1/* 2 * ADOBE CONFIDENTIAL 3 * 4 * Copyright 2024 Adobe Systems Incorporated 5 * All Rights Reserved. 6 * 7 * NOTICE: All information contained herein is, and remains 8 * the property of Adobe Systems Incorporated and its suppliers, 9 * if any. The intellectual and technical concepts contained 10 * herein are proprietary to Adobe Systems Incorporated and its 11 * suppliers and may be covered by U.S. and Foreign Patents, 12 * patents in process, and are protected by trade secret or copyright law. 13 * Dissemination of this information or reproduction of this material 14 * is strictly forbidden unless prior written permission is obtained 15 * from Adobe Systems Incorporated. 16 * 17 */ 18(function() { 19 "use strict"; 20 window.af = window.af || {}; 21 22 function waitForRumInitialization() { 23 return new Promise(function(resolve, reject){ 24 var timeout = 10000; // 10 seconds 25 var startTime = Date.now(); 26 function checkSampleRUM() { 27 // only execute forms runtime FT check if sampleRUM is defined via SITES FT 28 // adding check for forms specific feature toggle for RUM 29 if (window.hlx && window.hlx.sampleRUM) { 30 resolve(window.hlx.sampleRUM); 31 } else if (Date.now() - startTime >= timeout) { 32 // Reject the promise if the sampleRUM is not available within the timeout 33 reject(); 34 } else { 35 // If the rum is not set, wait and check again 36 setTimeout(checkSampleRUM, 50); 37 } 38 } 39 checkSampleRUM(); 40 }); 41 } 42 function initializeBridgeEvents(callback) { 43 var bridge; 44 var startTime = (new Date()).getTime(); 45 // this is for AF v1 46 if (window.guideBridge !== undefined) { 47 bridge = window.guideBridge; 48 if ('_guide' in bridge && bridge._guide != null) { 49 callback(bridge, null, bridge._guide.jcrPath, startTime); 50 } 51 } else { 52 window.addEventListener("bridgeInitializeStart", function(event) { 53 bridge = event.detail.guideBridge; 54 // this is only for AF v1, since in v2 we wont know all AF's, instead we rely on "AF_FormContainerInitialized" event 55 if ('_guide' in bridge) { 56 callback(bridge, null, null, startTime); 57 } 58 }); 59 } 60 // this is for AF v2 61 document.addEventListener("AF_FormContainerInitialised", function(event) { 62 callback(bridge, event, null, startTime); 63 }); 64 } 65 66 initializeBridgeEvents(function(bridge, e, _formContainerPath, startTime){ 67 var containerState = {}; 68 var CheckPoints = { 69 RENDER: "viewblock" 70 }; 71 72 var formContainerPath = e ? e.detail.getPath() : _formContainerPath; 73 if (formContainerPath != null) { 74 containerState[formContainerPath] = { 75 submitted: false, 76 formPath: formContainerPath 77 }; 78 } 79 bridge.connect(function() { 80 // special case for af v1 81 if (formContainerPath == null) { 82 formContainerPath = bridge._guide.jcrPath; 83 containerState[formContainerPath] = { 84 submitted: false, 85 formPath: formContainerPath 86 }; 87 } 88 89 waitForRumInitialization().then(function(sampleRUM) { 90 // form specific FT 91 if (window.FD && window.FD.isToggleEnabled("FT_FORMS-8965")) { 92 var timeToFormInteractivity = ((new Date()).getTime() - startTime) / 1000; 93 sampleRUM(CheckPoints.RENDER, 94 { 95 source: ".form", 96 target: bridge._guide != null ? "foundation" : "core", 97 } 98 ); 99 } 100 }) 101 .catch(function() { 102 // Handle the rejection without logging any error 103 }); 104 }, null, formContainerPath); 105 }); 106 107 108 // Attach functions to the window namespace 109 window.af.waitForRumInitialization = waitForRumInitialization; 110 111})(); 112 113/* 114 * *********************************************************************** 115 * ADOBE CONFIDENTIAL 116 * __________________ 117 * 118 * Copyright 2015 Adobe Systems Incorporated 119 * All Rights Reserved. 120 *
121 * NOTICE: All information contained herein is, and remains 122 * the property of Adobe Systems Incorporated and its suppliers, 123 * if any. The intellectual and technical concepts contained 124 * herein are proprietary to Adobe Systems Incorporated and its 125 * suppliers and may be covered by U.S. and Foreign Patents, 126 * patents in process, and are protected by trade secret or copyright law. 127 * Dissemination of this information or reproduction of this material 128 * is strictly forbidden unless prior written permission is obtained 129 * from Adobe Systems Incorporated. 130 * *********************************************************************** 131 */ 132 133(function ($) { 134 $.uaMatch = function( ua ) { 135 ua = ua.toLowerCase(); 136 var match = /(chrome)[ \/]([\w.]+)/.exec( ua ) || 137 /(webkit)[ \/]([\w.]+)/.exec( ua ) || 138 /(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) || 139 /(msie) ([\w.]+)/.exec( ua ) || 140 ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) || []; 141 return { 142 browser: match[ 1 ] || "", 143 version: match[ 2 ] || "0" 144 }; 145 }; 146 // Not clobbering any existing $.browser 147 if ( !$.browser ) { 148 var 149 matched = $.uaMatch( navigator.userAgent ), 150 browser = {}; 151 if ( matched.browser ) { 152 browser[ matched.browser ] = true; 153 browser.version = matched.version; 154 } 155 // Chrome is Webkit, but Webkit is also Safari. 156 if ( browser.chrome ) { 157 browser.webkit = true; 158 } else if ( browser.webkit ) { 159 browser.safari = true; 160 } 161 $.browser = browser; 162 } 163})($); 164/************************************************************************* 165 * ADOBE CONFIDENTIAL 166 * ___________________ 167 * 168 * Copyright 2013 Adobe Systems Incorporated 169 * All Rights Reserved. 170 *
171 * NOTICE: All information contained herein is, and remains 172 * the property of Adobe Systems Incorporated and its suppliers, 173 * if any. The intellectual and technical concepts contained 174 * herein are proprietary to Adobe Systems Incorporated and its 175 * suppliers and are protected by all applicable intellectual property 176 * laws, including trade secret and copyright laws. 177 * Dissemination of this information or reproduction of this material 178 * is strictly forbidden unless prior written permission is obtained 179 * from Adobe Systems Incorporated. 180 **************************************************************************/ 181 182 183/** 184 * @package xfalib.ut.Class 185 */ 186(function(_, xfalib){ 187 188 xfalib.ns = xfalib.ns || function (namespaceString) { 189 var parts = namespaceString.split('.'), 190 parent = window, 191 currentPart = ''; 192 193 for(var i = 0, length = parts.length; i < length; i++) { 194 currentPart = parts[i]; 195 parent[currentPart] = parent[currentPart] || {}; 196 parent = parent[currentPart]; 197 } 198 199 return parent; 200 }; 201 202 var Class = xfalib.ut.Class = function(options) { 203 this.options = _.extend({}, this.options, options); 204 if(!this.options.jsonModel) 205 this.options.jsonModel = {}; 206 //For perf reason, we are setting jsonModel as direct property instead of using property descriptor 207 this.jsonModel = this.options.jsonModel; 208 this.initialize.apply(this, arguments); 209 }; 210 211 _.extend(Class.prototype, { 212 initialize : function(){ 213 }, 214 215 xfaUtil :function(){ 216 return xfalib.ut.XfaUtil.prototype; 217 }, 218 219 copyArray : function(src,dst,options) { 220 var keepReference = this.getOrElse(options, "keepReference", true); 221 if(src instanceof Array) 222 { 223 for (var i = 0;i<src.length;i++) 224 { 225 var obj; 226 if(src[i] instanceof Array) 227 { 228 obj = this._createDestination(dst, i, keepReference, []); 229 this.copyArray(src[i],obj,options); 230 } 231 else if(typeof src[i] == "object") 232 { 233 obj = this._createDestination(dst, i, keepReference, {}); 234 this.copyObject(src[i],obj,options); 235 } else { 236 obj = src[i]; 237 } 238 dst[i] = obj; 239 } 240 if(dst.length > src.length){ 241 dst.splice(src.length, (dst.length - src.length)); //Remove ths rest of the extra destination items 242 } 243 } 244 }, 245 246 /** 247 * 248 * @param src 249 * @param dst 250 * @param options e.g. {keepReference: true, exceptions:["htmlId"], transformMaps: {"dataId", function(src, options){ return src "33"+src; }}} 251 */ 252 copyObject : function(src,dst,options) { 253 var keepReference = this.getOrElse(options, "keepReference", true); 254 var exceptions = this.getOrElse(options, "exceptions", []); 255 var transformMaps = this.getOrElse(options, "transformMaps", {}); 256 if(typeof src == "object") { 257 for (var child in src) { 258 if(exceptions.indexOf(child) == -1) { 259 if(src[child] instanceof Array) { 260 dst[child] = this._createDestination(dst, child, keepReference, []); 261 this.copyArray(src[child],dst[child],options); 262 } 263 else if(typeof src[child] == "object" && src[child] != null) { 264 dst[child] = this._createDestination(dst, child, keepReference, {}); 265 this.copyObject(src[child],dst[child],options); 266 } 267 else{ 268 if(!_.isUndefined(transformMaps[child])){ 269 dst[child] = transformMaps[child](src[child], options, src); 270 } 271 else 272 dst[child] = src[child]; 273 } 274 } 275 } 276 } 277 }, 278 279 _createDestination : function(obj, property, keepReference, defaultValue) { 280 if(!keepReference) 281 return defaultValue; 282 else if(_.isObject(obj) && !obj.hasOwnProperty(property)) 283 return defaultValue; 284 else 285 return obj[property] || defaultValue ; //Would handle both, Array and objects 286 }, 287 288 /** 289 * will replace functions in the object with noop function based on a predicate function's result. 290 * If no predicate is passed all functions will be disabled. 291 * Warning once disabled object cant be re-enabled. 292 * 293 * sample predicate to disable all 'public' functions : function (funcName) { return funcName[0] != '_'} 294 * 295 * @param predicate 296 * @private 297 */ 298 _disableFunctions: function (predicate) { 299 var noop = function () {}, 300 disableAll = !_.isFunction(predicate); 301 302 _.each(_.functions(this), function (funcName) { 303 if (disableAll || predicate(funcName)) { 304 this[funcName] = noop; 305 } 306 }, this); 307 }, 308 309 /** 310 * getOrElse can take multiple arguments. 311 * arg1(obj): base Object 312 * arg2: string representing property chain where properties are concatenated via dot 313 * arg3: default value 314 **/ 315 316 getOrElse : function(obj){ 317 var currObject = obj; 318 if(arguments.length < 2) 319 return currObject; 320 else if(arguments.length == 2) { 321 if(!_.isUndefined(currObject)){ 322 return currObject; 323 } else { 324 return _.clone(arguments[1]); 325 } 326 } 327 else { 328 var propChain = (arguments[1] || "").split("."); 329 var defaultValue = arguments[2]; 330 _.each(propChain, function(prop){ 331 if(_.isObject(currObject)) 332 currObject = currObject[prop]; 333 else 334 currObject = undefined; 335 }, this); 336 337 if(!_.isUndefined(currObject)) 338 return currObject; 339 else { 340 return _.clone(defaultValue) ; //May have to do deep clone in future. TODO: support for conditional clone 341 } 342 } 343 }, 344 345 jqId: function (id) { 346 return xfalib.ut.XfaUtil.prototype.jqId(id); 347 }, 348 349 logger : function(){ 350 return this.xfaUtil().getLogger(); 351 }, 352 353 validateInput : function(param, dataType,fallback){ 354 if(typeof param !== "undefined" && param !== null) { 355 switch(dataType) { 356 case "string": 357 param = param+""; 358 break; 359 case "object": 360 if(typeof param !== "object") 361 param = fallback; 362 break; 363 case "integer": 364 param = parseInt(param); 365 if(isNaN(param)) 366 param = fallback; 367 break; 368 case "measurement": 369 break; 370 default: 371 if(dataType instanceof Array) { 372 if(!~dataType.indexOf(param)) 373 param = fallback 374 } 375 } 376 } 377 return param; 378 } 379 380 }); 381 382 _.extend(Class, { 383 defineProps : function(propsMap){ 384 _.each(propsMap, function(propDesc, propName){ 385 //Check property can be resolved using resolveNode 386 if(propDesc.resolve) { 387 //Check whether prototype owns the object resolveProperties 388 if(!this.prototype.hasOwnProperty("resolveProperties")) { 389 //check whether prototype inherits the object resolveProperties 390 if(this.prototype.resolveProperties) { 391 //clone the object since we do not want to modify parent's prototype 392 this.prototype.resolveProperties = _.clone(this.prototype.resolveProperties); 393 } 394 else 395 this.prototype.resolveProperties = []; 396 } 397 this.prototype.resolveProperties.push(propName) 398 } 399 Object.defineProperty(this.prototype, propName, propDesc); 400 401 }, this); 402 }, 403 extend : function(props){ 404 var child = inherits(this, props); 405 child.extend = this.extend; 406 return child; 407 }, 408 addMixins : function(mixinBakers){ 409 if(!_.isArray(mixinBakers)){ 410 mixinBakers = [mixinBakers]; 411 } 412 _.each(mixinBakers, function(mixinBaker){ 413 if(mixinBaker.normalProperties){ 414 _.extend(this.prototype, mixinBaker.normalProperties); 415 } 416 if(mixinBaker.propertyDescriptors){ 417 this.defineProps(mixinBaker.propertyDescriptors); 418 } 419 }, this); 420 } 421 }); 422 423 // Shared empty constructor function to aid in prototype-chain creation. 424 var ctor = function(){}; 425 426 // Helper function to correctly set up the prototype chain, for subclasses. 427 // Similar to `goog.inherits`, but uses a hash of prototype properties and 428 // class properties to be extended. 429 function inherits(parent, protoProps, staticProps) { 430 var child; 431 var _super = parent.prototype; 432 // The constructor function for the new subclass is either defined by you 433 // (the "constructor" property in your `extend` definition), or defaulted 434 // by us to simply call the parent's constructor. 435 if (protoProps && protoProps.hasOwnProperty('constructor')) { 436 child = protoProps.constructor; 437 } else { 438 child = function(){ parent.apply(this, arguments); }; 439 } 440 441 // Inherit class (static) properties from parent. 442 _.extend(child, parent); 443 444 // Set the prototype chain to inherit from `parent`, without calling 445 // `parent`'s constructor function. 446 ctor.prototype = parent.prototype; 447 child.prototype = new ctor(); 448 child._super = parent.prototype; 449 child._superClass = parent; 450 451 // Add prototype properties (instance properties) to the subclass, 452 // if supplied.
453 if (protoProps) { //_.extend(child.prototype, protoProps); 454 // Copy the properties over onto the new prototype 455 for (var name in protoProps) { 456 if(name == "_defaults"){ 457 protoProps[name] = _.extend({}, _super[name], protoProps[name]); 458 } 459 child.prototype[name] = protoProps[name]; 460 } 461 } 462 463 464 // Add static properties to the constructor function, if supplied. 465 if (staticProps) _.extend(child, staticProps); 466 467 // Correctly set child's `prototype.constructor`. 468 child.prototype.constructor = child; 469 470 // Set a convenience property in case the parent's prototype is needed later. 471 child.__super__ = parent.prototype; 472 473 return child; 474 }; 475})(_, window.xfalib); 476/** 477 * Created by vdua on 2/18/2015. 478 */ 479(function (_, xfalib) { 480 var XMLUtils = { 481 dataSom2xpath: function (dataSom) { 482 var xpath = ""; 483 484 if (!_.isEmpty(dataSom)) { 485 // any dot preceded by ], takes care of dot-s in name, 486 // and remove constant prefix "xfa[0].datasets[0].data[0]" and form root name, then join using '/' 487 _.each(dataSom.split(/\]\./).slice(4), 488 function (part) { 489 var openBracketPos = part.lastIndexOf('['); 490 xpath += part.substring(0, openBracketPos + 1) + 491 (parseInt(part.substring(openBracketPos + 1)) + 1) + // increment index by 1 for xpath query 492 "]/"; 493 }); 494 495 if (_.isEmpty(xpath)) { 496 xpath = dataSom; 497 } else if (xpath[xpath.length - 1] === '/') { 498 xpath = xpath.slice(0, -1); 499 } 500 } 501 502 return xpath; 503 }, 504 505 /** 506 * Converts an xPathResult of type iterator to an array 507 * @param xPathResult 508 * @returns {Array} 509 */ 510 iteratorToArray: function (xPathResult) { 511 var result = []; 512 // in some browsers, if xpath is invalid xPath result is null whereas some browsers return XpathResult with empty iterator 513 var node = xPathResult ? xPathResult.iterateNext() : null; 514 while (node != null) { 515 result.push(node); 516 node = xPathResult.iterateNext(); 517 } 518 return result; 519 }, 520 /** 521 * Wrapper API for document.evaluate to provide cross-browser support. 522 * @param xpath 523 * @param node 524 * @param nsResolver 525 * @param resultType 526 * @param result 527 * @returns {Object|*} 528 */ 529 evaluateXPath: function (xpath, node, nsResolver, resultType, result) { 530 try { 531 if(_.isEmpty(xpath) || !_.isString(xpath) || !(node instanceof Node)) { 532 return null; 533 } 534 535 // Determine the appropriate document context for searching. 536 var searchContext = node instanceof Document ? node : node.ownerDocument; 537 // Check if the document.evaluate function is undefined or if we're in a server-side context. 538 var isEvaluateUndefined = typeof searchContext.evaluate === 'undefined'; 539 var isServerSide = window.guideBridge && window.guideBridge.hostName === "server"; 540 var needsXPathPolyfill = isEvaluateUndefined || isServerSide; 541 if (needsXPathPolyfill) { 542 // Install the wgxpath polyfill to provide evaluate functionality. 543 wgxpath.install(window, true); 544 // Assign the newly installed evaluate function to the search context. 545 searchContext.evaluate = window.document.evaluate; 546 } 547 548 var documentToEval = searchContext.evaluate ? searchContext : document; 549 xpath = this.sanitizeXPath(xpath); 550 551 return documentToEval.evaluate(xpath, node, nsResolver, resultType, result); 552 553 } catch (exception) { 554 xfalib.ut.XfaUtil.prototype.getLogger().error("Could not evaluate xpath: " + xpath + exception); 555 556 } 557 558 }, 559 /** 560 *Removes all [*] other than ['numeric'] from xpath 561 *@param xpath
562 *@returns xpath after removing "[*]" 563 */ 564 sanitizeXPath: function(xpath) { 565 var xpathArray=xpath.split("/"), 566 resultXpath = _.map(xpathArray, function (path) { 567 return path.replace(/\[(.*\D+.*)\]|\[\]/g,""); 568 }).join("/"); 569 return resultXpath; 570 }, 571 572 /** 573 * Creates all the Elements (if they don't exist) in the xpath leading to the node being searched for in the 574 * xpath relative to the element. Optionally creates the node as well if bParentsOnly is false 575 * @param xpath 576 * @param element 577 * @param bParentsOnly whether to create only the parents or the node as well 578 * @returns node that is being represented by the xpath relative to the element. 579 */ 580 createElementsFromXPath: function (xpath, element, bParentsOnly) { 581 if (xpath != null || element != null) { 582 var parts = xpath.split("/"), 583 actualParts = bParentsOnly ? _.initial(parts) : parts, 584 el = element; 585 _.each(actualParts, function (part, index) { 586 var som = part.match(/^([^[]+)(\[(\d+)\])?/), 587 childEl; 588 if (som == null) { 589 xfalib.ut.XfaUtil.prototype.getLogger().error("Unsupported expression in Bindref " + part); 590 return null; 591 } 592 //only the last element can be attribute 593 childEl = this.findOrCreateElement(part, el, index === actualParts.length - 1); 594 el = childEl; 595 }, this); 596 return el; 597 } 598 return null; 599 }, 600 601 /** 602 * Form an xpath part returns the index as well as the tagName. Index can be * as well 603 * @param xpathName 604 * @returns {*} 605 * @private 606 */ 607 _getElementNameAndIndexFromXPathPart: function (xpathName) { 608 var som = xpathName.match(/^([^[]+)(?:\[(\d+|\*)\])?/); 609 if (som !== null) { 610 return { 611 name: som[1], 612 index: som[2] || 0 613 }; 614 } 615 return null; 616 }, 617 618 /** 619 * create an element with the tagName elementName for the ownerDocument of element. 620 * @param elementName 621 * @param element 622 * @returns {HTMLElement} 623 */ 624 createElement: function (elementName, element) { 625 var el = element.ownerDocument.createElement(elementName); 626 return el; 627 }, 628 629 /** 630 * Searches for the nodeXpath relative to element. If it doesn't exists creates it and returns the node 631 * @param element 632 * @param nodeXpath 633 * @param bAttribute if true then check for attribute otherwise not. 634 * @returns {Node|*} 635 */ 636 findOrCreateElement: function (nodeXpath, element, bAttribute) { 637 try { 638 if (element == null) { 639 return null; 640 } 641 var result = this.evaluateXPath(nodeXpath, element, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null), 642 el = result.iterateNext(), 643 res; 644 if (el == null) { 645 res = this._getElementNameAndIndexFromXPathPart(nodeXpath); 646 if (res != null) { 647 if (bAttribute && res.name.match(/^@/)) { 648 var attrName = res.name.replace(/^@/, ""); 649 el = element.ownerDocument.createAttribute(attrName); 650 element.setAttributeNode(el); 651 } else { 652 el = element.ownerDocument.createElement(res.name); 653 element.appendChild(el); 654 } 655 } 656 } 657 return el; 658 659 } catch (exception) { 660 xfalib.ut.XfaUtil.prototype.getLogger().error("Following exception " 661 + "occurred while executing findOrCreateElement " + exception); 662 } 663 664 }, 665 666 /** 667 * Returns the Root Form Elment from the xmlDocumentElement 668 * @param xmlDocumentElement It can be a document or Element. If the root element is xdp element, it returns 669 * the grand grand child of that element. otherwise the root element is returned. The root 670 * Element can be either the element itself or documentElement of the element. 671 */ 672 getXFARootFormElementFromXML: function (xmlDocumentElement) { 673 if(_.isUndefined(document.evaluate)) { 674 wgxpath.install(); 675 } 676 var isElement = xmlDocumentElement instanceof Element, 677 docElemName = isElement ? xmlDocumentElement.nodeName : xmlDocumentElement.documentElement.nodeName, 678 rootElement = isElement ? xmlDocumentElement : xmlDocumentElement.documentElement, 679 nodeList; 680 681 if ("xdp:xdp" === docElemName || "xdp" === docElemName) { 682 if (xfalib.ut.XfaUtil.prototype.isIE()) { 683 //IE doesn't support evaluating namespace elements 684 var datasets = rootElement.firstElementChild, 685 data = datasets.firstElementChild; 686 rootElement = data.firstElementChild; 687 } else { 688 // assumption is that the xml will be of format <xdp><datasets><data><form1> 689 // TODO: change first * to xfa:datasets 690 nodeList = this.evaluateXPath("*/xfa:data/*", rootElement, formBridge.nsResolver, 691 XPathResult.ORDERED_NODE_ITERATOR_TYPE, null); 692 rootElement = nodeList.iterateNext(); 693 } 694 } 695 return rootElement; 696 }, 697 698 /**
699 * Returns an object containing the prefix and namespaces present in the rootElement. For default namespace the 700 * prefix is "_default" 701 * @param rootElement {Element} xml element which has to be looked for namespaces 702 * @returns {object} object whose keys are the prefix and values are the namespace 703 */ 704 getNamespaces: function (rootElement) { 705 var namespaces = { 706 "_default" : null 707 }; 708 _.each(rootElement.attributes, function (attr) { 709 var name = attr.name, 710 parsedAttrName = name.match(/^xmlns(?:\:(.*))?/), 711 isNamespace = parsedAttrName != null, 712 namespaceName = isNamespace ? parsedAttrName[1] || "_default" : null; 713 if (namespaceName) { 714 namespaces[namespaceName] = attr.value; 715 } 716 }); 717 return namespaces; 718 }, 719 720 /** 721 * Returns a namespace resolver given a element. The nsResolver returns the namespace given a prefix by 722 * using the namespaces mentioned in the element. 723 * @param rootElement element from which to create the nsResolver 724 * @returns {function} the function returns the namespace given a prefix. 725 */ 726 getNsResolver: function (rootElement) { 727 var namespaces = this.getNamespaces(rootElement), 728 nsResolver = (function (namespaces) { 729 return function (nsPrefix) { 730 var namespace = formBridge.nsResolver(nsPrefix) || namespaces[nsPrefix]; 731 return namespace; 732 }; 733 }(namespaces)); 734 return nsResolver; 735 }, 736 737 /** 738 * Removes default namespaces from xml, basically the namespace defined as xmlns="some namespace". The 739 * side-effect of the API is it removes the string "xmlns='some namespace'" from any attribute value as well. 740 * @param xml {string} 741 * @returns {string} 742 */ 743 removeDefaultNamespace: function (xml) { 744 var stringRegex = "(\\s+)" + // any number of spaces 745 "(xmlns=" + // then xmlns= 746 "('[^']*'|\"[^\"]*\"))" + // then value in single quotes ('[^']') or 747 // double quotes ("[^"]") 748 "(?=[^<>]*>)", // followed by closing tag (implies attribute) and before another 749 // opening tag(implies text) 750 regex = new RegExp(stringRegex, "g"); 751 return xml.replace(regex, "$1"); 752 } 753 }; 754 xfalib.ut.XMLUtils = XMLUtils; 755}(_, xfalib)); 756/** 757 * @package xfalib.ut.Logger 758 * @import xfalib.ut.Class 759 */ 760 761(function(_, xfalib, $){ 762 var categoryAcronyms = { 763 "a": "xfa", 764 "b": "xfaView", 765 "c": "xfaPerf" 766 }, 767 loggerTypes = ["off", "console", "server", "consoleServer"]; 768 var Logger = xfalib.ut.Logger = xfalib.ut.Class.extend({ 769 770// Count of log messages so far. 771 LOG_COUNT : { 772 level : { 773 "FATAL" : 0, 774 "ERROR" : 0, 775 "WARN" : 0, 776 "INFO" : 0, 777 "DEBUG" : 0, 778 "TRACE" : 0, 779 "ALL" : 0 780 }, 781 category : { 782 "xfa" : 0, 783 "xfaView" : 0, 784 "xfaPerf" : 0, 785 "Unknown" : 0 786 } 787 }, 788 789 /** 790 * Log level to turn logging off (default). 791 * @static 792 * @final 793 * @type Number 794 */ 795 OFF : 0, 796 797 /** 798 * Log level for fatal error messages. 799 * @static 800 * @final 801 * @type Number 802 */ 803 FATAL : 1, 804 805 /** 806 * Log level for error messages. 807 * @static 808 * @type Number 809 * @final 810 */ 811 ERROR : 2, 812 813 /** 814 * Log level for warning messages. 815 * @static 816 * @type Number 817 * @final 818 */ 819 WARN : 3, 820 821 /** 822 * Log level for info messages. 823 * @static 824 * @type Number 825 * @final 826 */ 827 INFO : 4, 828 829 /** 830 * Log level for debug messages. 831 * @static 832 * @type Number 833 * @final 834 */ 835 DEBUG : 5, 836 837 /** 838 * Log level for trace messages. 839 * @static 840 * @type Number 841 * @final 842 */ 843 TRACE : 6, 844 845 /** 846 * Log level for all messages. 847 * @static 848 * @type Number 849 * @final 850 */ 851 ALL : 7, 852 853 854 logLevelNames : ["OFF", "FATAL", "ERROR", "WARN", "INFO", "DEBUG", "TRACE", "ALL"], 855 856 initialize : function(){ 857 var str = "", 858 that =this; 859 Logger._super.initialize.call(this); 860 this.logs = {}; 861 this.logMessages = ""; 862 this.logServiceProxy = this.options.logServiceProxy; 863 this.contextPath = this.options.contextPath; 864 this.renderContext = this.options.renderContext;
865 if(this.jsonModel.logConfigString) { 866 _.extend(this.jsonModel, this.parse(this.jsonModel.logConfigString)); 867 } 868 _.each(this.jsonModel.category, function(category) { 869 that.LOG_COUNT.category[category] = 0; 870 }) 871 }, 872 873 /** 874 * parses a log config string of the form <0,1,2,3>-<category string><level integer>-<category string><level integer>.. 875 * and returns an a config object that logger uses. The function is a private and not to be called outside 876 * this function 877 * 878 * category can not contain numbers and only valid characters are a-zA-Z 879 * level can be any integer. 880 * 881 * category string is converted into actual category for the logger by using default categoryAcronyms 882 * [a : xfa, b: xfaView, c: xfaPerf} and the categoryAcronyms passed to the options while instantiating the 883 * object. If not found in both the acronyms then the value category string is used as actual category 884 * 885 * For example for the input string 1-a9-b9-c9 return object is 886 * {on: true, category: [xfa,xfaView, xfaPerf], level: [9, 9, 9], type: console} 887 * 888 * For the input string 1-a9-b9-c9-d9-e11 with options.categoryAcronyms {a:a, d:AF} return object is 889 * {on: true, category: [xfa,xfaView, xfaPerf, AF, e], level: [9, 9, 9, 9, 11], type: console} 890 */ 891 parse : function(configString) { 892 var arr = configString.split("-"), 893 logType = _.first(arr), 894 logConfig = _.rest(arr), 895 res = { 896 on: logType === "0" ? "false": "true", 897 category: [], 898 level:[], 899 type:loggerTypes[parseInt(logType)] 900 }; 901 _.each(logConfig, function(item, index) { 902 var config = item.match(/^([A-Za-z]+)(\d+)$/), 903 category; 904 if (config && config.length === 3) { 905 category = this.getOrElse(categoryAcronyms, config[1], 906 this.getOrElse(this.jsonModel, "categoryAcronyms." + config[1], config[1])); 907 res.category.push(category); 908 res.level.push(parseInt(config[2])); 909 } else { 910 //calling this because logger is not initialized as of now 911 this.consoleHandler(this.resolveMessage(xfalib.locale.LogMessages["ALC-FRM-901-020"], 912 [item, configString])) 913 } 914 }, this); 915 return res; 916 }, 917 918 /* 919 * 920 */ 921 resolveMessage : function(message, snippets) { 922 snippets = snippets || []; 923 return message.replace(/{(\d+)}/g, function(match, number) { 924 return typeof snippets[number] != 'undefined' 925 ? snippets[number] 926 : match 927 ; 928 }); 929 }, 930 931 /** 932 * Writes a message to the console. 933 * @private 934 * @param {Number} level The log level 935 * @param {String} message The log message 936 * @param {String/String[]} snippets (optional) The texts replacing 937 * <code>{n}</code> 938 * @return The log message
939 * @type String 940 */ 941 log : function(category, level, message, snippets) { 942 var d= new Date(); 943 var day = d.getDate(); 944 var month = d.getMonth() + 1; 945 var year = d.getFullYear(); 946 var mili = d.getMilliseconds(); 947 var sec = d.getSeconds(); 948 var min = d.getMinutes(); 949 var hour = d.getHours(); 950 var date = day + "." + month + "." + year +" " + hour + ":" + min + ":" + sec + ":" + mili; 951 if(this.jsonModel && this.jsonModel.category) { 952 for(var i = 0; i<this.jsonModel.category.length; i++) { 953 if (level != 0 && this.jsonModel.level[i] >= level && this.jsonModel.category[i] == category && this.jsonModel.on == "true") { 954 955 var resolvedMessage = message; 956 if(snippets){ 957 //resolve message with snippet 958 resolvedMessage = this.resolveMessage(message, snippets); 959 } 960 961 var text = ""; 962 text += date ; 963 text += " *" + this.logLevelNames[level] + "*"; 964 text += " [" + category + "]" ; 965 text += " " + resolvedMessage + "\r\n" ; 966 this.logMessages += text ; 967 if(this.jsonModel.type == "console" || this.jsonModel.type == "consoleServer" ) { 968 ++this.LOG_COUNT.category[category || 'Unknown']; 969 ++this.LOG_COUNT.level[this.logLevelNames[parseInt(level) < 8? level:7]]; 970 this.consoleHandler(text, level); 971 } 972 } 973 } 974 } 975 }, 976 977 consoleHandler : function(text, level){ 978 if(typeof console != "undefined") { 979 var levelName = typeof this.logLevelNames[level] === "string" 980 ? this.logLevelNames[level].toLowerCase() 981 : "log", 982 logFunction = console.log; 983 if (typeof console[levelName] === "function") { 984 logFunction = console[levelName] 985 } 986 logFunction.call(console, "\n\n\n" + text); 987 //Error log already shows the call stack for debugging. 988 if(levelName !== "error") { 989 try { 990 n.test 991 } catch (exception) { 992 if (exception.stack) { 993 logFunction.call(console, exception.stack.replace("ReferenceError: n is not defined", "")); 994 } 995 } 996 } 997 } 998 999 }, 1000 1001 /* 1002 * Helper function to ger submit service proxy url 1003 */ 1004 _getLogServiceProxyUrl: function() { 1005 var logServiceProxyUrl = ""; 1006 if(this.logServiceProxy) 1007 logServiceProxyUrl += this.logServiceProxy; 1008 else //finally hard code it 1009 logServiceProxyUrl += ((this.contextPath && this.contextPath != "/") ? this.contextPath : "") + "/libs/xfaforms/profiles/default.log.html"; 1010 return logServiceProxyUrl; 1011 }, 1012 1013 _invokeAtServer: function(options) { 1014 var localSubmitUrl = this._getLogServiceProxyUrl(); 1015 var params = { 1016 async: true, 1017 url: localSubmitUrl, 1018 type: 'POST', 1019 contentType: 'application/x-www-form-urlencoded; charset=UTF-8', 1020 data: options 1021 }; 1022 $.ajax(params); 1023 }, 1024 1025 isServerLoggingEnabled : function(){ 1026 if((this.jsonModel.on == "true") && (this.jsonModel.type == "server" || this.jsonModel.type == "consoleServer")) 1027 return true; 1028 else 1029 return false; 1030 }, 1031 1032 serverHandler :function() { 1033 var options = {'logMessages' : this.logMessages, 'renderContext' : this.renderContext}; 1034 this._invokeAtServer(options); 1035 this.logMessages = "" ; 1036 }, 1037 1038 /** 1039 * Writes a message to the console if log level is set to 1040 * {@link #FATAL} or higher. 1041 * @static 1042 * @param {String} message The log message 1043 * @param {String/String[]} snippets (optional) The texts replacing 1044 * <code>{n}</code> 1045 */ 1046 fatal : function(category, message, snippets) { 1047 this.log(category, this.FATAL, message, snippets); 1048 }, 1049 1050 /** 1051 * Writes a message to the console if log level is set to 1052 * {@link #ERROR} or higher. 1053 * @static 1054 * @param {String} message The log message 1055 * @param {String/String[]} snippets (optional) The texts replacing 1056 * <code>{n}</code> 1057 */ 1058 error : function(category, message, snippets) { 1059 this.log(category, this.ERROR, message, snippets); 1060 }, 1061 1062 /** 1063 * Writes a message to the console if log level is set to 1064 * {@link #WARN} or higher. 1065 * @static 1066 * @param {String} message The log message 1067 * @param {String/String[]} snippets (optional) The texts replacing 1068 * <code>{n}</code> 1069 */ 1070 warn : function(category, message, snippets) { 1071 this.log(category, this.WARN, message, snippets); 1072 }, 1073 1074 /** 1075 * Writes a message to the console if log level is set to 1076 * {@link #INFO} or higher. 1077 * @static 1078 * @param {String} message The log message 1079 * @param {String/String[]} snippets (optional) The texts replacing 1080 * <code>{n}</code> 1081 */ 1082 info : function(category, message, snippets) { 1083 this.log(category, this.INFO, message, snippets); 1084 }, 1085 1086 /** 1087 * Writes a message to the console if log level is set to 1088 * {@link #DEBUG} or higher. 1089 * @static 1090 * @param {String} message The log message 1091 * @param {String/String[]} snippets (optional) The texts replacing 1092 * <code>{n}</code> 1093 */ 1094 debug : function(category, message, snippets) { 1095 this.log(category, this.DEBUG, message, snippets); 1096 }, 1097 1098 /** 1099 * Writes a message to the console if log level is set to 1100 * {@link #TRACE} or higher. 1101 * @static 1102 * @param {String} message The log message 1103 * @param {String/String[]} snippets (optional) The texts replacing 1104 * <code>{n}</code> 1105 */ 1106 trace : function(category, message, snippets) { 1107 this.log(category, this.TRACE, message, snippets); 1108 }, 1109 1110 isLogEnabled : function(category, level) { 1111 if(this.jsonModel.on == "true") { 1112 var pos = this.jsonModel.category.indexOf(category) ; 1113 if(this.jsonModel.level[pos] >= level) 1114 return true; 1115 } 1116 return false;
1117 } 1118 1119 }); 1120})(_, xfalib, $); 1121/** 1122 * @package xfalib.ut.EventClass 1123 * @import xfalib.ut.Class 1124 */ 1125(function(_, xfalib){ 1126 // Regular expression used to split event strings 1127 // Regular expression used to split event strings 1128 var eventSplitter = /\s+/; 1129 1130 // A module that can be mixed in to *any object* in order to provide it with 1131 // custom events. You may bind with `on` or remove with `off` callback functions 1132 // to an event; trigger`-ing an event fires all callbacks in succession. 1133 // 1134 var EventClass = xfalib.ut.EventClass = xfalib.ut.Class.extend({ 1135 1136 // Bind one or more space separated events, `events`, to a `listener` 1137 // object. The object should implement `handleEvent` function which will be 1138 // called on event dispatch 1139 on: function(event, listener, context) { 1140 1141 var calls, list,retVal = true; 1142 var fnCallback = _.isFunction(listener) ? listener : null; 1143 if (!listener || (!listener["handleEvent"] && !fnCallback)) return false; 1144 1145 calls = this._callbacks || (this._callbacks = {}); 1146 1147 list = calls[event] || (calls[event] = []); 1148 if(fnCallback){ 1149 context = context || this; 1150 var found = _.find(list, function(callback){ 1151 return (callback.fn == fnCallback && callback.context == context); 1152 }, this); 1153 if(found) 1154 return false; 1155 else { 1156 list.push({"fn" : fnCallback, "context": context}); 1157 } 1158 } 1159 else{ 1160 if(~list.indexOf(listener)) 1161 return false; 1162 else 1163 list.push(listener); 1164 } 1165 1166 return true; 1167 }, 1168 1169 // Remove one or many callbacks. If `listener` is null, removes all listener for the 1170 // event. If `events` is null, removes all bound callbacks for all events. 1171 off: function(events, listener, context) { 1172 var event, calls, node; 1173 1174 // No events, or removing *all* events. 1175 if (!(calls = this._callbacks)) return; 1176 if (!(events || listener)) { 1177 delete this._callbacks; 1178 return this; 1179 } 1180 1181 var fnCallback = _.isFunction(listener) ? listener : null; 1182 // Loop through the listed events and contexts and remove the required ones. 1183 events = events ? events.split(eventSplitter) : _.keys(calls); 1184 while (event = events.shift()) { 1185 node = calls[event]; 1186 calls[event] = _.filter(calls[event],function(elem) { 1187 if(typeof(listener) !== "undefined"){ 1188 if(fnCallback && elem.fn == fnCallback && elem.context == context) 1189 return false; 1190 else if(!fnCallback && listener === elem) 1191 return false; 1192 } 1193 else{ 1194 return false; 1195 } 1196 return true; 1197 }); 1198 if(!calls[event].length) 1199 delete calls[event]; 1200 } 1201 1202 return this; 1203 }, 1204 1205 // Trigger one or many events, firing all bound callbacks. Callbacks are 1206 // passed the same arguments as `trigger` except the first 1207 trigger: function(events) { 1208 var event, calls, rest; 1209 if (!(calls = this._callbacks)) return this; 1210 events = events.split(eventSplitter); 1211 var payLoad = _.rest(arguments); 1212 while (event = events.shift()) { 1213 _.each(calls[event],function(callback) { 1214 if(callback.fn && callback.context){ 1215 callback.fn.apply(callback.context, payLoad); 1216 } 1217 else if (_.isFunction(callback.handleEvent)){ 1218 callback.handleEvent.apply(callback, payLoad); 1219 } 1220 }); 1221 } 1222 1223 return this; 1224 } 1225 1226 }); 1227 1228 1229})(_, xfalib); 1230 1231 1232(function (_, $, xfalib) { 1233 var XfaUtil = xfalib.ut.XfaUtil = function () { 1234 }, 1235 registeredLocaleProperties = null, 1236 timeoutListenerAttached = false, 1237 timeouts = [], 1238 attachClearTimeoutListener = function (timeout) { 1239 timeouts.push(timeout); 1240 if (timeoutListenerAttached === false) { 1241 $(window).one("destroy.xfa", function () { 1242 _.each(timeouts, function (_timeout) { 1243 clearTimeout(_timeout); 1244 }); 1245 timeouts = []; 1246 timeoutListenerAttached = false;
1247 }); 1248 timeoutListenerAttached = true; 1249 } 1250 }; 1251 _.extend(XfaUtil.prototype, { 1252 _globalUniqueId: (new Date()).getTime(), 1253 logger: null, 1254 1255 formScaleFactor: 1, // used to appropriately scale the form when contained inside an iframe 1256 1257 getOrElse: xfalib.ut.Class.prototype.getOrElse, 1258 //map of event names between XTG and Mobile Form 1259 //Mobile Form uses different names for some the event and let's fix those names before sending them to XTG. 1260 _xtgEventName: { 1261 "$formready": "ready", 1262 "$layoutready": "ready" 1263 }, 1264 1265 generateUID: function () { 1266 return "UID" + (++XfaUtil.prototype._globalUniqueId); 1267 }, 1268 1269 matchJsonType: function (jsonModel, _class) { //TODO: handle getOrElse 1270 return (jsonModel && _class && XfaUtil.prototype.getOrElse(jsonModel._class, "").toLowerCase() == ("" + _class).toLowerCase()); 1271 }, 1272 1273 $data: function (elem, name, data) { 1274 if (!$.data(elem, "_xfaInitialized")) { 1275 //Initialized data- attributes parse for once using this call. 1276 // Next onward don't use this. Instead use $.data which is cheap/ 1277 $(elem).data(); 1278 $.data(elem, "_xfaInitialized", true); //Mark the element to say that data has been initialized. 1279 } 1280 return $.data(elem, name, data); 1281 }, 1282 1283 /* 1284 * alternative to jQuery.css which sets style properties directly through element.style. This is much faster then 1285 * corresponding jQuery.css alternative. 1286 * 1287 * Warning: this only supports standard css property names and does not do any pre-processing of name and value. 1288 * So calling this, make sure the style names are compatible. 1289 */ 1290 $css: function (elem, stylesObj) { 1291 // Exclude the following css properties to add px. copied from jquery.cssNumber to add hyphenated style names 1292 var cssNumber = { 1293 "fillOpacity": true, 1294 "fill-opacity": true, 1295 "fontWeight": true, 1296 "font-weight": true, 1297 "lineHeight": true, 1298 "line-height": true, 1299 "zIndex": true, 1300 "z-index": true, 1301 "opacity": true, 1302 "orphans": true, 1303 "widows": true, 1304 "zoom": true 1305 }; 1306 1307 for (var prop in stylesObj) { 1308 var value = stylesObj[prop]; 1309 // If a number was passed in, add 'px' to the (except for certain CSS properties) 1310 if (_.isNumber(value) && !cssNumber[ prop ]) { 1311 value += "px"; 1312 } 1313 elem.style[prop] = value; 1314 } 1315 }, 1316 1317 isTableHF: function (iChildNode) { 1318 //model can be a Node object or simply a json 1319 var assistJson = _.find(iChildNode.children, function (jChild) { 1320 return jChild._class == "assist"; 1321 }, this); 1322 var childRole = (assistJson || {}).role; 1323 if (childRole == "TH" || childRole == "TF") 1324 return true; 1325 else 1326 return false; 1327 }, 1328 1329 getUiOneOfChildTag: function (uiParent) { 1330 var uiEl = _.find(uiParent.children, function (child) { 1331 return child._class == "ui"; 1332 }); 1333 if (!uiEl) 1334 return undefined; 1335 var uiOneOfChildMap = xfalib.runtime.xfa._templateSchema._getOneOfChild("ui"); 1336 var uiOneOfChild = _.find(uiEl.children, function (child) { 1337 return uiOneOfChildMap[child._class] == true; 1338 }); 1339 if (!uiOneOfChild) 1340 return undefined; 1341 return uiOneOfChild._class; 1342 }, 1343 1344 //TODO: this should be removed. One of the worst function. 1345 dIndexOf: function (searchArray, item2Find) { 1346 var ind = -1; 1347 _.find(searchArray, function (item, index) { 1348 return item == item2Find && (ind = index) 1349 }); 1350 return ind; 1351 }, 1352 1353 splitStringByWidth: function (value, width, refEl) { 1354 var i = value.length , expectedWidth; 1355 do { 1356 expectedWidth = xfalib.view.util.TextMetrics.measureExtent(value.slice(0, i), {"refEl": refEl, maxWidth: -1}).width; 1357 i--; 1358 } while (expectedWidth > width) 1359 if (i != value.length - 1) 1360 return value.slice(0, i + 1); 1361 return value; 1362 }, 1363 1364 isRepeatabeEl: function (elTag) { 1365 if (elTag == "subform" || elTag == "subformSet") 1366 return true; 1367 else 1368 return false;
1369 }, 1370 1371 /** 1372 * @function 1373 * stripOrCall(toStrip, diffFunc, fArgs) 1374 * @description 1375 * common utility function to handle final submission payload stripping 1376 * @param {bool} toStrip : flag to signify whether to optimize jsonModelDiff size, by stripping off unnecessary properties 1377 * @param {function} diffFunc : callback func. call in case submit is not on 1378 * @param {Array} fArgs : arguments to be passed to the diff func. 1379 * @returns {object} object containing the jsonDiff 1380 */ 1381 // should ALWAYS be called with a flag signifying if a submission is in progress, 1382 // and a callback function to compute the json to be sent back during submission, usually an apt '_computeJsonDiff' 1383 stripOrCall: function (toStrip, diffFunc, fArgs) { 1384 if (toStrip) { 1385 return { 1386 "changed": false, 1387 "jsonDifference": {} 1388 }; 1389 } 1390 else if (_.isFunction(diffFunc)) { 1391 return diffFunc.apply(this, fArgs); 1392 } 1393 }, 1394 1395 /** 1396 * @function 1397 * partialStripOrCall(stripLvl, diffFunc, fArgs) 1398 * @description 1399 * common utility function to handle final submission payload stripping or for output of getFormState. 1400 * @param {int} diff_level : flag to signify whether to optimize jsonModelDiff size, by stripping off unnecessary properties 1401 * must be 0,1, or 2, as with "diff_level" param of _computeJsonDiff. 1402 * @param {function} diffFunc : callback func. call in case submit is not on 1403 * @returns {object}
1403 object containing the jsonDiff 1404 */ 1405 partialStripOrCall: function (diff_level, diffFunc) { 1406 var diffObj = diffFunc.call(this, diff_level); 1407 1408 if (!diffObj.changed) { 1409 if(diff_level === 1) { 1410 diffObj = { 1411 "changed": true, 1412 "jsonDifference": { 1413 "_class": this.jsonModel._class, 1414 "name": this.jsonModel.name 1415 } 1416 }; 1417 } else { 1418 diffObj.jsonDifference = {}; // don't need stuff for other cases 1419 } 1420 } 1421 1422 return diffObj; 1423 }, 1424 1425 /** 1426 * @function 1427 * stripObject(obj, exceptionNames) 1428 * @description 1429 * Utility function to strip unnecessary properties from an object 1430 * @param {object} obj : the object to strip 1431 * @param {Array} exceptionNames : array holding names of important properties to preserve 1432 * @returns {boolean} : true if this obj, or any of it's descendant is returned un-stripped 1433 */ 1434 stripObject: function (obj, exceptionNames) { 1435 if (_.isEmpty(obj) || !_.isObject(obj)) { 1436 return true; 1437 } else { 1438 var dontStrip = false; 1439 _.each(_.keys(obj), function (propName) { 1440 var keepProp = false; 1441 if (!_.contains(exceptionNames, propName)) { 1442 if (_.isArray(obj[propName])) { 1443 _.each(obj[propName], function (arrElem) { 1444 var isUnStripped = XfaUtil.prototype.stripObject(arrElem, exceptionNames); 1445 keepProp = keepProp || isUnStripped; 1446 }); 1447 } else if (_.isObject(obj[propName])) { 1448 keepProp = XfaUtil.prototype.stripObject(obj[propName], exceptionNames); 1449 } 1450 1451 if (!keepProp) { 1452 delete obj[propName]; 1453 } else { 1454 dontStrip = true; 1455 } 1456 } else { 1457 dontStrip = true; 1458 } 1459 }); 1460 return dontStrip; 1461 } 1462 }, 1463 1464 computeDomJsonDiff: function (domNode, diff_level) { 1465 var changed = true; 1466 if (domNode.hasOwnProperty("_modelChanged")) { 1467 changed = domNode._modelChanged; 1468 } 1469 var jsonDiff = {}; 1470 if (changed) { 1471 this.copyObject(domNode.jsonModel, jsonDiff, {"exceptions": ["children", "{default}", "extras"]}); 1472 } else { 1473 jsonDiff = {_class: domNode.className}; 1474 } 1475 if (!changed && domNode.jsonModel.hasOwnProperty("name")) { 1476 jsonDiff.name = domNode.jsonModel.name; 1477 } 1478 if (domNode.name === "FS_EXTRAS" && diff_level === 3) { 1479 domNode._childModified = true; 1480 } 1481 return { 1482 "changed": changed, 1483 jsonDifference: jsonDiff 1484 }; 1485 }, 1486 1487 getLogger: function () { 1488 return XfaUtil.prototype.logger || XfaUtil.prototype.getOrElse(xfalib, "runtime.xfa.Logger", null); 1489 }, 1490 1491 getErrorManager: function () { 1492 return XfaUtil.prototype.getOrElse(xfalib, "runtime.xfa.ErrorManager", null); 1493 }, 1494 1495 XFA_CLICK_EVENT: "xfaclick", 1496 XFA_EXIT_EVENT: "xfaexit", 1497 XFA_ENTER_EVENT: "xfaenter", 1498 XFA_CHANGE_EVENT: "xfachange", 1499 XFA_PREOPEN_EVENT: "xfapreopen", 1500 1501 btwn: function (val, a, b) { 1502 return val > a && val < b; 1503 }, 1504 1505 // function to detect if Browser is chrome / safari (webkit) 1506 isWebkit: function () { 1507 return !!$.browser.webkit || /webkit/.test(navigator.userAgent.toLowerCase()) || !!window.chrome || !!$.browser.chrome || /chrom(e|ium)/.test(navigator.userAgent.toLowerCase()) || !!$.browser.safari || !!window.webkitURL || 1508 ( /safari/.test(navigator.userAgent.toLowerCase()) && 1509 /apple computer/.test(navigator.vendor.toLowerCase()) ); 1510 1511 // TODO : find a better way to do this as $.browser is deprecated and 1512 // userAgent may be spoofed 1513 }, 1514 1515 clearTimeoutOnDestroy: function (timeout) { 1516 attachClearTimeoutListener(timeout); 1517 }, 1518 1519 // function to detect if Browser is safari 1520 isSafari: function () { 1521 return ( /safari/.test(navigator.userAgent.toLowerCase()) && 1522 /apple computer/.test(navigator.vendor.toLowerCase()) ); 1523 }, 1524
1525 getLocaleStrings: function () { 1526 return xfalib.locale.Strings; 1527 }, 1528 1529 getLogMessages: function () { 1530 return xfalib.locale.LogMessages; 1531 }, 1532 1533 /* 1534 * This function should not be added in the prototype of any Object 1535 * as in the case of other functions 1536 */ 1537 registerLocaleProperties: function (props) { 1538 registeredLocaleProperties = props; 1539 }, 1540 1541 /* 1542 * This function should not be added in the prototype of any Object 1543 * as in the case of other functions 1544 */ 1545 getDefaultLocaleProperty: function (property) { 1546 var localeProps = registeredLocaleProperties || this.getOrElse(xfalib, "script.Xfa._defaultLocale", null); 1547 return this.getOrElse(localeProps, property, null); 1548 }, 1549 1550 /** 1551 * Encodes <script> and </script> with <script> and </script> 1552 * Does same with img, video and audio tags also. 1553 * These tags are being removed since scripts can be run through 1554 * <img onerror="script" /> (same for audio and video). 1555 */ 1556 encodeScriptableTags: function (str) { 1557 var index; 1558 if (_.isString(str)) { 1559 return str.replace(/<(\/?)(script[^<>]*)>/gi, '<$1$2>') 1560 .replace(/<(\/?)(img[^<>]*)>/gi, '<$1$2>') 1561 .replace(/<(\/?)(video[^<>]*)>/gi, '<$1$2>') 1562 .replace(/<(\/?)(audio[^<>]*)>/gi, '<$1$2>') 1563 } 1564 }, 1565 1566 /** 1567 * 1568 * @param id : a string representing an HTML element id. 1569 * 1570 * return after applying an escaping '\' before each # . : [ ] 1571 */ 1572 jqId: function(id) { 1573 return "#" + id.replace(/(#|:|\.|\[|\])/g, "\\$1"); 1574 }, 1575 1576 _triggerOnBridge: function (eventName, target, property, oldVal, newVal) { 1577 var evnt = xfalib.script.XfaModelEvent.createEvent(eventName, target, 1578 property, oldVal, newVal); 1579 if(formBridge){ 1580 window.formBridge.trigger(eventName, evnt); 1581 } 1582 }, 1583 1584 /* 1585 * pads the passed in String str by pre-pending padChars to convert it to a string of given width. 1586 * If string length is already greater that equal to given width, original string is returned. 1587 */ 1588 padString : function (str, width, padChar) { 1589 padChar = padChar || '0'; 1590 str = str + ''; 1591 return str.length >= width ? str : new Array(width - str.length + 1).join(padChar) + str; 1592 }, 1593 1594 /** 1595 * returns true if the browser is IE otherwise false 1596 * @returns {boolean} 1597 */ 1598 isIE: function () { 1599 return $.browser.msie || (navigator.appName === "Netscape" && navigator.userAgent.match(/Trident\//)) 1600 }, 1601 1602 /** 1603 * returns false if other browser 1604 * if ie tries to return browser version (non falsy) 1605 * @returns {*} 1606 */ 1607 1608 detectIE: function () { 1609 // 1st try jq 1610 if($.browser.msie) { 1611 if($.browser.version && parseInt($.browser.version, 10)) { 1612 return parseInt($.browser.version, 10); 1613 } 1614 } 1615 1616 var ua = window.navigator.userAgent; 1617 1618 // IE 10 1619 // ua = 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)'; 1620 1621 // IE 11 1622 // ua = 'Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko'; 1623 1624 // IE 12 / Spartan 1625 // ua = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36 Edge/12.0'; 1626 1627 // Edge (IE 12+) 1628 // ua = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Safari/537.36 Edge/13.10586'; 1629 1630 var msie = ua.indexOf('MSIE '); 1631 if (msie > 0) { 1632 // IE 10 or older => return version number 1633 return parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10); 1634 } 1635 1636 var trident = ua.indexOf('Trident/'); 1637 if (trident > 0) { 1638 // IE 11 => return version number 1639 var rv = ua.indexOf('rv:'); 1640 return parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10); 1641 } 1642 1643 var edge = ua.indexOf('Edge/'); 1644 if (edge > 0) { 1645 // Edge (IE 12+) => return version number
1646 return parseInt(ua.substring(edge + 5, ua.indexOf('.', edge)), 10); 1647 } 1648 1649 // other browser 1650 return false; 1651 }, 1652 /** 1653 * returns true if the browser is chrome otherwise false 1654 * @returns {boolean} 1655 */ 1656 detectChrome : function () { 1657 return (!!window.chrome || !!$.browser.chrome || /chrom(e|ium)/.test(navigator.userAgent.toLowerCase())); 1658 }, 1659 1660 /** 1661 * @param {String} val: value to be verified 1662 * @returns {boolean} 1663 * returns true if the provided string contains DOM element 1664 */ 1665 isHTML: function(val) { 1666 //check whether string contains tags, so that $val does not contain result of the val used as selector 1667 // eg: val = "a" will return result for $(val) which is not required 1668 if(val && /<[a-z][\s\S]*>/.test(val)) { 1669 try { 1670 var $val = $(val); 1671 return $val.length > 0; 1672 } catch (exception) { 1673 // if jquery throws exception that means string is not a proper HTML 1674 return false; 1675 } 1676 } else { 1677 return false; 1678 } 1679 }, 1680 1681 /** 1682 * returns true if passed key is non printable, false otherwise. 1683 * @param {String} key event.key property of a Keyboard event 1684 */ 1685 isNonPrintableKey : function (key) { 1686 return (key // In IE, event.key returns words instead of actual characters for some keys. 1687 && !_.contains(['MozPrintableKey','Divide','Multiply','Subtract','Add','Enter','Decimal','Spacebar','Del'],key) 1688 && key.length != 1 ) 1689 }, 1690 1691 /** 1692 * returns true for ipad 1693 * @returns {boolean} 1694 */ 1695 _isIpad : function () { 1696 return navigator.userAgent.match(/iPad/i) != null; 1697 }, 1698 1699 /** 1700 * returns true if the subform is table or having role table else false 1701 * @param {Object} view 1702 */ 1703 _tableCheckForAccessibility : function (view) { 1704 var assist = view.model.getElement("assist", 0, true); 1705 return this.getOrElse(view, "layoutModel.layout", null) == xfalib.view.LayoutConst.LAYOUT_TABLE 1706 || this.getOrElse(assist, "role", null) == "Table"; 1707 }, 1708 1709 /** 1710 * returns value of tooltip to be assigned as title based on values provided in accessibility 1711 * @param {Object} model 1712 * @returns toolTipText 1713 */ 1714 _getToolTipText : function (model) { 1715 var assist = model.getElement("assist", 0, true), 1716 toolTipText = ""; 1717 // going against xfa spec, on hover show tooltip or speak text or element name, don't show caption as it's already visible 1718 // assist priority doesn't matter, but selecting none will disable tooltip on hover 1719 if (this.getOrElse(assist, "speak.disable", 0) != 1) { // loose compare str
1719ing value 1720 toolTipText = this.getOrElse(assist, "toolTip.value", "") || 1721 this.getOrElse(assist, "speak.value", "") || 1722 this.getOrElse(model, "jsonModel.name", ""); 1723 } 1724 return toolTipText; 1725 }, 1726 1727 /** 1728 * returns value of mandatory message 1729 * @param {Object} model 1730 * @returns mandatoryMessage 1731 */ 1732 _getMandatoryMessage : function (model) { 1733 var defaultMessage = model._defaults.validate.message.defaultMessage, 1734 msg = this.getOrElse(model, "validate.message.nullTest", defaultMessage); 1735 return (msg && msg.value) ? msg.value : defaultMessage.value; 1736 }, 1737 /** 1738 * returns boolean based on val1, val2, checkEqual 1739 * For comparing date, use date object 1740 */ 1741 _compareVal : function (val1, val2, checkEqual) { 1742 if(!val1 || !val2) { 1743 return false; 1744 } 1745 1746 if(checkEqual) { 1747 return val1 >= val2; 1748 } else { 1749 return val1 > val2; 1750 } 1751 } 1752 }); 1753 1754 //Special handling for IE. 1755 if ($.browser.msie || $.browser.mozilla) { 1756 XfaUtil.prototype.$css = function (elem, stylesObj) { 1757 $(elem).css(stylesObj); 1758 } 1759 } 1760})(_, $, xfalib); 1761/************************************************************************* 1762 * 1763 * ADOBE CONFIDENTIAL 1764 * ___________________ 1765 * 1766 * Copyright 2013 Adobe Systems Incorporated 1767 * All Rights Reserved. 1768 *
1769 * NOTICE: All information contained herein is, and remains 1770 * the property of Adobe Systems Incorporated and its suppliers, 1771 * if any. The intellectual and technical concepts contained 1772 * herein are proprietary to Adobe Systems Incorporated and its 1773 * suppliers and are protected by trade secret or copyright law. 1774 * Dissemination of this information or reproduction of this material 1775 * is strictly forbidden unless prior written permission is obtained 1776 * from Adobe Systems Incorporated. 1777 **************************************************************************/ 1778 1779 1780 1781(function (_, $, xfalib) { 1782 xfalib.ut.Utilities = { 1783 1784 isIE11: function () { 1785 return !!navigator.userAgent.match(/Trident.*rv\:11\./); 1786 }, 1787 1788 checkMinMozillaVersion: function (version) { 1789 return (!this.isIE11() && $.browser.mozilla && parseInt($.browser.version) >= version); 1790 }, 1791 1792 getObjectFromKeyValueStringList: function (list) { 1793 var key, value, object = {}, tempArray; 1794 _.each(list, function (keyValuePair, index) { 1795 tempArray = keyValuePair.split("="); 1796 if (tempArray && tempArray.length > 1) { 1797 object[tempArray[0]] = tempArray[1]; 1798 } 1799 }); 1800 return object; 1801 }, 1802 1803 _getNameWithoutMarker: function (fileName) { 1804 var markerIndex = fileName.indexOf("__afAttachment__"); 1805 if (markerIndex !== -1) { 1806 fileName = fileName.substring(markerIndex + "__afAttachment__".length, fileName.length); 1807 } 1808 return fileName; 1809 }, 1810 1811 /* 1812 * This is to check support of multiple files selection in one add new dialog 1813 */ 1814 _isDataContainerSupported : function () { 1815 try { 1816 var dataContainer = new DataTransfer() || (new ClipboardEvent("")).clipboardData; 1817 if (dataContainer && dataContainer.items) { 1818 return true; 1819 } 1820 } catch(err) { 1821 // if err comes then dataContainer is not supported 1822 } 1823 return false; 1824 } 1825 }; 1826})(_, $, xfalib); 1827/** 1828 * @package xfalib.ut.Scanner 1829 * @fileOverview helper class to scan over a string. 1830 * @version 0.0.1 1831 */ 1832 1833/** 1834 * @constructor 1835 * @param Object {jsonModel:{_str: String}} 1836 */ 1837 1838(function(_,xfalib){ 1839 var Scanner = xfalib.ut.Scanner = xfalib.ut.Class.extend({ 1840 1841 initialize: function() { 1842 this._pos = 0; 1843 }, 1844 1845 isEOF : function(){ 1846 return (this.jsonModel._str.length <= this._pos); 1847 }, 1848 1849 peek : function(){ 1850 return (this.isEOF()) ? null : this.jsonModel._str.charAt(this._pos); 1851 }, 1852 1853 optionalConsumeChar : function(aChar){ 1854 if(this.jsonModel._str.charAt(this._pos) == aChar){ 1855 this._pos++; 1856 return aChar; 1857 }else{ 1858 return null; 1859 } 1860 }, 1861 1862 /** 1863 * Gets next char ignore quoted string. 1864 * | 1865 * abc returns c. 1866 * | 1867 * abc'de'f returns f. 1868 * @param aChar 1869 */ 1870 getNCharIQS : function(){ 1871 this._pos++; 1872 if(this.jsonModel._str.length <= this._pos){ 1873 var current = this.jsonModel._str.charAt(this._pos); 1874 if(current != '\''){ 1875 return current; 1876 }else{ 1877 if(moveNextExpectedChar('\'')){ 1878 return this.jsonModel._str.charAt(this._pos); 1879 } 1880 } 1881 } 1882 return null; 1883 }, 1884 1885 moveNextExpectedChar : function(aChar){ 1886 this._pos++;// currently point to ' 1887 while(this._pos< this.jsonModel._str.length && this.jsonModel._str.charAt(this._pos) != aChar){ 1888 this._pos++; 1889 } 1890 return this._pos < this.jsonModel._str.length; 1891 }, 1892 1893 readInteger : function(len){ 1894 if(this.pos+len >this.jsonModel._str.length){ 1895 return null; 1896 } 1897 var integer = xfalib.ut.PictureUtils.parseIntExact(this.jsonModel._str,this._pos,len); 1898 this._pos+=len; 1899 return integer; 1900 } 1901 }); 1902 1903 Scanner.lookupNext = function(pat, patPos, filter){ 1904 var patLen = pat.length; 1905 if(patPos >= patLen){ 1906 return null; 1907 } 1908 1909 var token = {}; 1910 token.startPos = patPos; 1911 1912 var firstChar = pat.charAt(patPos); 1913 var patValid = false;
1914 // 1915 if (firstChar == '\''){ 1916 for (var i = patPos+1; i < patLen;i++ ){ 1917 var chr = pat.charAt(i); 1918 if(chr =='\''){ 1919 token.type=1; 1920 token.len = i - patPos + 1; 1921 patValid = true; 1922 break; 1923 } 1924 } 1925 1926 }else if( ('a' <= firstChar && firstChar <= 'z' || 'A' <= firstChar && firstChar <= 'Z') || filter.call(null, firstChar)){ 1927 var endPos = patLen;//end is exclusive 1928 for (var i = 1; patPos+i < patLen;i++ ){ 1929 if(pat.charAt(patPos+i)!=firstChar){ 1930 endPos = patPos+i; 1931 break; 1932 } 1933 } 1934 token.type=2; 1935 token.len = endPos - patPos; 1936 token.patChar = firstChar; 1937 token.patPos = patPos; 1938 patValid = true; 1939 }else{ 1940 if (firstChar == '?' || firstChar == '+' || firstChar == '*') { 1941 token.type=3; 1942 token.len = 1; 1943 }else{ 1944 token.type=4; 1945 token.len = 1; 1946 } 1947 patValid = true; 1948 } 1949 if(patValid){ 1950 return token; 1951 }else{ 1952 throw "Picture is invalid."; 1953 } 1954 } 1955})(_,xfalib); 1956 1957 1958/** 1959 * @package xfalib.ut.PictureFmt 1960 * @fileOverview The file defines methods to parse and format data 1961 * according to XFA picture patterns. 1962 * @version 0.0.1 1963 */ 1964(function(_,xfalib) { 1965 1966 var PictureFmt = xfalib.ut.PictureFmt = function() {}; 1967 PictureFmt.DatePicturePattern = /^date(?:\([a-zA-Z]*_[a-zA-Z]*\))?\{([\w\W]*?)\}$/; 1968 PictureFmt.TimePicturePattern = /^time(?:\([a-zA-Z]*_[a-zA-Z]*\))?\{([\w\W]*?)\}$/; 1969 PictureFmt.TextPicturePattern = /^text\{([\w\W]*?)\}$/; 1970 PictureFmt.NumPicturePattern = /^num\{([\w\W]*?)\}$/; 1971 1972 /** 1973 * Parses a given data source according to the given picture. 1974 * @param sSource {string} 1975 * @param sPicture {string} 1976 * @param sLocale {string} 1977 * @returns {object} 1978 */ 1979 PictureFmt.parse = function(sSource, sPicture,sLocale){ 1980 var PictureEngine = new xfalib.ut.PictureEngine({jsonModel:{locale:sLocale}}); 1981 1982 var match = PictureFmt.DatePicturePattern.exec(sPicture); 1983 if(match && match[1]){ 1984 return PictureEngine.parseDate(sSource, match[1]); 1985 } 1986 match = PictureFmt.TimePicturePattern.exec(sPicture); 1987 if(match && match[1]){ 1988 return PictureEngine.parseTime(sSource, match[1]); 1989 } 1990 match = PictureFmt.TextPicturePattern.exec(sPicture); 1991 if(match && match[1]){ 1992 return PictureEngine.parseText(sSource, match[1]); 1993 } 1994 match = PictureFmt.NumPicturePattern.exec(sPicture); 1995 if(match && match[1]){ 1996 return PictureEngine.parseNumeric(sSource, match[1]); 1997 } 1998 throw "Invalid picture clause "+sPicture; 1999 }; 2000 2001 /** 2002 * Formats a given data source according to the given picture. 2003 * @param date {object} 2004 * @param sPicture {string} 2005 * @param sLocale {string} 2006 * @returns {string} 2007 */ 2008 PictureFmt.format = function(sSource, sPicture, sLocale,bRelaxed,bFormatNumberFromasDefaultPC){ 2009 var PictureEngine = new xfalib.ut.PictureEngine({jsonModel:{locale:sLocale}}); 2010 2011 var match = PictureFmt.DatePicturePattern.exec(sPicture); 2012 if(match && match[1]){ 2013 return PictureEngine.formatDate(sSource, match[1]); 2014 } 2015 match = PictureFmt.TimePicturePattern.exec(sPicture); 2016 if(match && match[1]){ 2017 return PictureEngine.formatTime(sSource, match[1]); 2018 } 2019 match = PictureFmt.TextPicturePattern.exec(sPicture); 2020 if(match && match[1]){ 2021 return PictureEngine.formatText(sSource, match[1],bRelaxed); 2022 } 2023 match = PictureFmt.NumPicturePattern.exec(sPicture); 2024 if(match && match[1]){ 2025 return PictureEngine.formatNumeric(sSource, match[1],sLocale,bRelaxed,bFormatNumberFromasDefaultPC); 2026 } 2027 throw "Invalid picture clause "+sPicture; 2028 }; 2029 2030 /** 2031 * Checks if a given data source is formatted according to the given picture. 2032 * @param date {object} 2033 * @param sPicture {string} 2034 * @param sLocale {string} 2035 * @returns {boolean} 2036 */ 2037 PictureFmt.formatTest = function (sSource, sPicture, sLocale, bRelaxed, bFormatNumberFromasDefaultPC) { 2038 var formattedData; 2039 try { 2040 formattedData = PictureFmt.format(sSource, sPicture, sLocale, bRelaxed, bFormatNumberFromasDefaultPC); 2041 }catch(e) { 2042 return false;
2043 } 2044 2045 if(!_.isString(formattedData)) { 2046 return false; 2047 } else { 2048 var parsedData; 2049 try { 2050 parsedData = PictureFmt.parse(formattedData, sPicture, sLocale); 2051 } catch (e) { 2052 return false; 2053 } 2054 if(!_.isString(parsedData) && parsedData !== formattedData) { 2055 return false; 2056 } 2057 } 2058 return true; 2059 }; 2060 2061 /** 2062 * Parses a given data source according to the given date picture 2063 * under the given sLocale. 2064 * @param sSource {string} 2065 * @param sPicture {string} 2066 * @param sLocale {string} 2067 * @returns {string} 2068 */ 2069 PictureFmt.parseDate = function(sSource, sPicture,sLocale){ 2070 var picRegexp = PictureFmt.DatePicturePattern; 2071 var match = picRegexp.exec(sPicture); 2072 var PictureEngine = new xfalib.ut.PictureEngine({jsonModel:{locale:sLocale}}); 2073 if(match && match[1]){ 2074 return PictureEngine.parseDate(sSource, match[1]); 2075 }else{ 2076 return PictureEngine.parseDate(sSource, sPicture); 2077 } 2078 }; 2079 2080 2081 /** 2082 * Formats a given data source according to the given date picture 2083 * * under the given sLocale. 2084 * @param date {string} 2085 * @param sPicture {string} 2086 * @param sLocale {string} 2087 * @returns {string} 2088 */ 2089 PictureFmt.formatDate = function(date, sPicture, sLocale){ 2090 var picRegexp = PictureFmt.DatePicturePattern; 2091 var match = picRegexp.exec(sPicture); 2092 var PictureEngine = new xfalib.ut.PictureEngine({jsonModel:{locale:sLocale}}); 2093 if(match && match[1]){ 2094 return PictureEngine.formatDate(date, match[1]); 2095 }else{ 2096 return PictureEngine.formatDate(date, sPicture); 2097 } 2098 }; 2099 2100 /** 2101 * Parses a given data source according to the given date picture 2102 * under the given sLocale. 2103 * @param sSource {string} 2104 * @param sPicture {string} 2105 * @param sLocale {string} 2106 * @returns {date} 2107 */ 2108 PictureFmt.parseTime = function(sSource, sPicture,sLocale){ 2109 var picRegexp = PictureFmt.TimePicturePattern; 2110 var match = picRegexp.exec(sPicture); 2111 var PictureEngine = new xfalib.ut.PictureEngine({jsonModel:{locale:sLocale}}); 2112 if(match && match[1]){ 2113 return PictureEngine.parseTime(sSource, match[1]); 2114 }else{ 2115 return PictureEngine.parseTime(sSource, sPicture); 2116 } 2117 return null; 2118 }; 2119 2120 2121 /** 2122 * Formats a given data source according to the given date picture 2123 * * under the given sLocale. 2124 * @param date {string} 2125 * @param sPicture {string} 2126 * @param sLocale {string} 2127 * @returns {string} 2128 */ 2129 PictureFmt.formatTime = function(date, sPicture, sLocale){ 2130 var picRegexp = PictureFmt.TimePicturePattern; 2131 var match = picRegexp.exec(sPicture); 2132 var PictureEngine = new xfalib.ut.PictureEngine({jsonModel:{locale:sLocale}}); 2133 if(match && match[1]){ 2134 return PictureEngine.formatTime(date, match[1]); 2135 }else{ 2136 return PictureEngine.formatTime(date, sPicture); 2137 } 2138 }; 2139 2140 /** 2141 * Parses a given data source according to the given text picture 2142 * under the given sLocale. 2143 * @param sSource {string} 2144 * @param sPicture {string} 2145 * @param sLocale {string} 2146 * @returns {string} 2147 */ 2148 PictureFmt.parseText = function(sSource, sPicture,sLocale){ 2149 var picRegexp = PictureFmt.TextPicturePattern; 2150 var match = picRegexp.exec(sPicture); 2151 var PictureEngine = new xfalib.ut.PictureEngine({jsonModel:{locale:sLocale}}); 2152 if(match && match[1]){ 2153 return PictureEngine.parseText(sSource, match[1]); 2154 }else{ 2155 return PictureEngine.parseText(sSource, sPicture); 2156 } 2157 }; 2158 2159 /** 2160 * Formats a given data source according to the given text picture 2161 * under the given sLocale. 2162 * @param sSource {string} 2163 * @param sPicture {string} 2164 * @param sLocale {string} 2165 * @returns {string} 2166 */ 2167 PictureFmt.formatText = function(sSource, sPicture, sLocale,bRelaxed){ 2168 var picRegexp = PictureFmt.TextPicturePattern; 2169 var match = picRegexp.exec(sPicture); 2170 var PictureEngine = new xfalib.ut.PictureEngine({jsonModel:{locale:sLocale}}); 2171 if(match && match[1]){ 2172 return PictureEngine.formatText(sSource, match[1],bRelaxed); 2173 }else{ 2174 return PictureEngine.formatText(sSource, sPicture,bRelaxed); 2175 } 2176 return null; 2177 }; 2178 2179 /** 2180 * Parses a given data source according to the given numeric picture 2181 * under the given sLocale. 2182 * @param sSource {string} 2183 * @param sPicture {string} 2184 * @param sLocale {string} 2185 * @returns {string} 2186 */ 2187 PictureFmt.parseNumeric = function(sSource, sPicture,sLocale){ 2188 var picRegexp = PictureFmt.NumPicturePattern; 2189 var match = picRegexp.exec(sPicture); 2190 var PictureEngine = new xfalib.ut.PictureEngine({jsonModel:{locale:sLocale}}); 2191 if(match && match[1]){ 2192 return PictureEngine.parseNumeric(sSource, match[1]); 2193 }else{ 2194 return PictureEngine.parseNumeric(sSource, sPicture); 2195 } 2196 return null; 2197 }; 2198 2199 /** 2200 * Formats a given data source according to the given numeric picture 2201 * under the given sLocale. 2202 * @param sSource {string} 2203 * @param sPicture {string} 2204 * @param sLocale {string} 2205 * @returns {string} 2206 */ 2207 PictureFmt.formatNumeric = function(sSource, sPicture, sLocale){ 2208 var picRegexp = PictureFmt.NumPicturePattern; 2209 var match = picRegexp.exec(sPicture); 2210 var PictureEngine = new xfalib.ut.PictureEngine({jsonModel:{locale:sLocale}}); 2211 if(match && match[1]){ 2212 return PictureEngine.formatNumeric(sSource, match[1]); 2213 }else{ 2214 return PictureEngine.formatNumeric(sSource, sPicture); 2215 } 2216 }; 2217 2218 2219 2220 2221 /** 2222 * Parses a given data source according to the given datetime picture 2223 * under the given sLocale. 2224 * @param sSource {string} 2225 * the source data. 2226 * @param sPicture {string} 2227 * the datetime picture. 2228 * @param sDateMask {string} 2229 * the date sub-picture. 2230 * @param sTimeMask {string} 2231 * the time sub-picture. 2232 * @param sLocale 2233 * the locale name. 2234 * 2235 */ 2236 PictureFmt.parseDateTime = function(sSource, sPicture, sDateMask, sTimeMask, sLocale){ 2237 2238 }; 2239 /** 2240 * Formats a given data source according to the given datetime picture 2241 * under the given locale. 2242 * 2243 * @param sSource {string} 2244 * the source data. 2245 * @param sPicture {string} 2246 * the datetime picture. 2247 * @param sDateMask {string} 2248 * the date sub-picture. 2249 * @param sTimeMask {string} 2250 * the time sub-picture. 2251 * @param sLocale {string} 2252 * the locale name. 2253 */ 2254 PictureFmt.formatDateTime = function(sSource, sPicture, sDateMask, sTimeMask, sLocale){ 2255 2256 }; 2257 2258})(_,xfalib); 2259/** 2260 * @package xfalib.ut.PictureUtils 2261 * @fileOverview The file defines static utilities methods. 2262 * @version 0.0.1 2263 */ 2264 2265(function(_,xfalib){ 2266 var PictureUtils = xfalib.ut.PictureUtils = function() {} 2267 2268 PictureUtils.padding = function(number, digits, isFw, zero){ 2269 var leading = ["0","00","000","0000"]; 2270 var numStr = leading[digits-1] + number; 2271 return numStr.slice(- digits); 2272 }; 2273 2274 PictureUtils.parseIntAggressive = function(dateString, startPos,len){ 2275 var result = new Object(); 2276 var parsedNum = 0; //The number value parsed from dateString 2277 var parsedLen = -1; //How many chars parsed according to this pattern; 2278 for(var idx=0; idx<len && (startPos + idx) < dateString.length; idx++){ 2279 var chr = dateString.charAt(startPos + idx); 2280 if(chr >='0' && chr <='9'){ 2281 parsedNum = parsedNum *10 + (chr- '0'); 2282 }else{ 2283 parsedLen = idx; 2284 break; 2285 } 2286 } 2287 if(parsedLen == -1) { 2288 parsedLen = len; 2289 } 2290 result.value = parsedNum; 2291 result.len = parsedLen; 2292 return result; 2293 }; 2294 2295 PictureUtils.parseIntExact = function(dateString, startPos,len){ 2296 var result = 0; 2297 PictureUtils.assert(startPos+ len <= dateString.length, "mismatch"); 2298 for(var idx=0; idx<len ; idx++){ 2299 var chr = dateString.charAt(startPos + idx); 2300 if(chr >='0' && chr <='9'){ 2301 result = result *10 + (chr- '0'); 2302 }else{ 2303 throw "unexpected currentChar in PictureUtils.parseInt"; 2304 } 2305 } 2306 return result; 2307 }; 2308 2309 PictureUtils.isDigit = function(chr){ 2310 return /[0-9]/.test(chr) ; 2311 }; 2312 2313 PictureUtils.inString = function(chr,aString){ 2314 return (aString.indexOf(chr) >=0) ; 2315 }; 2316 2317 2318 var regExpIsLetter = /[\u0041-\u005a\u0061-\u007a\u00aa-\u00aa\u00b5-\u00b5\u00ba-\u00ba\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u0236\u0250-\u02
2318c1\u02c6-\u02d1\u02e0-\u02e4\u02ee-\u02ee\u037a-\u037a\u0386-\u0386\u0388-\u038a\u038c-\u038c\u038e-\u03a1\u03a3-\u03ce\u03d0-\u03f5\u03f7-\u03fb\u0400-\u0481\u048a-\u04ce\u04d0-\u04f5\u04f8-\u04f9\u0500-\u050f\u0531-\u0556\u0559-\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0621-\u063a\u0640-\u064a\u066e-\u066f\u0671-\u06d3\u06d5-\u06d5\u06e5-\u06e6\u06ee-\u06ef\u06fa-\u06fc\u06ff-\u06ff\u0710-\u0710\u0712-\u072f\u074d-\u074f\u0780-\u07a5\u07b1-\u07b1\u0904-\u0939\u093d-\u093d\u0950-\u0950\u0958-\u0961\u0985-\u098c\u098f-\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2-\u09b2\u09b6-\u09b9\u09bd-\u09bd\u09dc-\u09dd\u09df-\u09e1\u09f0-\u09f1\u0a05-\u0a0a\u0a0f-\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32-\u0a33\u0a35-\u0a36\u0a38-\u0a39\u0a59-\u0a5c\u0a5e-\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2-\u0ab3\u0ab5-\u0ab9\u0abd-\u0abd\u0ad0-\u0ad0\u0ae0-\u0ae1\u0b05-\u0b0c\u0b0f-\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32-\u0b33\u0b35-\u0b39\u0b3d-\u0b3d\u0b5c-\u0b5d\u0b5f-\u0b61\u0b71-\u0b71\u0b83-\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99-\u0b9a\u0b9c-\u0b9c\u0b9e-\u0b9f\u0ba3-\u0ba4\u0ba8-\u0baa\u0bae-\u0bb5\u0bb7-\u0bb9\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c60-\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd-\u0cbd\u0cde-\u0cde\u0ce0-\u0ce1\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d28\u0d2a-\u0d39\u0d60-\u0d61\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd-\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32-\u0e33\u0e40-\u0e46\u0e81-\u0e82\u0e84-\u0e84\u0e87-\u0e88\u0e8a-\u0e8a\u0e8d-\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5-\u0ea5\u0ea7-\u0ea7\u0eaa-\u0eab\u0ead-\u0eb0\u0eb2-\u0eb3\u0ebd-\u0ebd\u0ec0-\u0ec4\u0ec6-\u0ec6\u0edc-\u0edd\u0f00-\u0f00\u0f40-\u0f47\u0f49-\u0f6a\u0f88-\u0f8b\u1000-\u1021\u1023-\u1027\u1029-\u102a\u1050-\u1055\u10a0-\u10c5\u10d0-\u10f8\u1100-\u1159\u115f-\u11a2\u11a8-\u11f9\u1200-\u1206\u1208-\u1246\u1248-\u1248\u124a-\u124d\u1250-\u1256\u1258-\u1258\u125a-\u125d\u1260-\u1286\u1288-\u1288\u128a-\u128d\u1290-\u12ae\u12b0-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0-\u12c0\u12c2-\u12c5\u12c8-\u12ce\u12d0-\u12d6\u12d8-\u12ee\u12f0-\u130e\u1310-\u1310\u1312-\u1315\u1318-\u131e\u1320-\u1346\u1348-\u135a\u13a0-\u13f4\u1401-\u166c\u166f-\u1676\u1681-\u169a\u16a0-\u16ea\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7-\u17d7\u17dc-\u17dc\u1820-\u1877\u1880-\u18a8\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1d00-\u1d6b\u1e00-\u1e9b\u1ea0-\u1ef9\u1f00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59-\u1f59\u1f5b-\u1f5b\u1f5d-\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe-\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071-\u2071\u207f-\u207f\u2102-\u2102\u2107-\u2107\u210a-\u2113\u2115-\u2115\u2119-\u211d\u2124-\u2124\u2126-\u2126\u2128-\u2128\u212a-\u212d\u212f-\u2131\u2133-\u2139\u213d-\u213f\u2145-\u2149\u3005-\u3006\u3031-\u3035\u303b-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312c\u3131-\u318e\u31a0-\u31b7\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fa5\ua000-\ua48c\uac00-\ud7a3\uf900-\ufa2d\ufa30-\ufa6a\ufb00-\ufb06\ufb13-\ufb17\ufb1d-\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e-\ufb3e\ufb40-\ufb41\ufb43-\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]/ 2319 2320 /** 2321 * TODO Implement method equivalent to Character.isLetter. 2322 */ 2323 PictureUtils.isLetter = function(chr){ 2324 return regExpIsLetter.test(chr); 2325 }; 2326 2327 PictureUtils.isLetterOrDigit = function(chr){ 2328 return this.isLetter(chr) || this.isDigit(chr); 2329 }; 2330 2331 /** 2332 * Scan this string for the first character in the given set. Similar to 2333 * strcspn(). 2334 * 2335 * @param src{String} 2336 * the string to scan 2337 * @param sSkip{String} 2338 * the characters to scan for 2339 * @param nOffset{number} 2340 * the position where to start the scan. Default = 0. 2341 * @return The position, relative to nOffset, for the first character found 2342 * in the given set 2343 */ 2344 PictureUtils.skipUntil = function(srcStr, sSkip, nOffset) { 2345 var nCharsSkipped = nOffset; 2346 2347 // starting at the offset position, scan the characters in this string 2348 // until it matches one of the characters in the given set. 2349 while (nCharsSkipped < srcStr.length) { 2350 var i = nCharsSkipped; 2351 if (sSkip.indexOf(srcStr.charAt(i++)) >= 0) 2352 break; 2353 nCharsSkipped = i; 2354 } 2355 2356 return nCharsSkipped - nOffset; 2357 }; 2358 2359 PictureUtils.matchString = function(str, startPos, target){ 2360 if(startPos + target.length > str.length){ 2361 return false;
2362 }else{ 2363 for(var idx = 0; idx<target.length; idx++){ 2364 if(target.charAt(idx) != str.charAt(startPos + idx)) return false; 2365 } 2366 return true; 2367 } 2368 }; 2369 2370 PictureUtils.assert = function(condition, message){ 2371 if(!condition){ 2372 throw message; 2373 } 2374 }; 2375 2376 PictureUtils.getLocaleObject = function(locale,property) { 2377 if(locale !== null && xfalib.runtime.xfa) { 2378 return xfalib.runtime.xfa._getLocaleSymbols(locale, property); 2379 } else { 2380 return xfalib.ut.XfaUtil.prototype.getDefaultLocaleProperty(property) 2381 } 2382 } 2383 2384 PictureUtils.getHashOfLocaleObject = function(locale,property) { 2385 if(!PictureUtils.getHashOfLocaleObject[locale+"_"+property]) { 2386 var hashObj = {}; 2387 _.each(PictureUtils.getLocaleObject(locale,property), function(val) { 2388 var sVal = (val+"").toLowerCase(); 2389 var hash = 0; 2390 for(var i =0;i<sVal.length;i++) { 2391 hash+=(i+1)*sVal.charCodeAt(i) 2392 } 2393 hashObj[hash] = hashObj[hash] || []; 2394 hashObj[hash].push(sVal); 2395 }) 2396 PictureUtils.getHashOfLocaleObject[locale+"_"+property] = hashObj; 2397 } 2398 return PictureUtils.getHashOfLocaleObject[locale+"_"+property] 2399 } 2400 2401 PictureUtils.convertNumberToLocale = function(locale,number) { 2402 var zero = PictureUtils.getLocaleObject(locale,"numberSymbols.zero"); 2403 var zeroCode = zero.charCodeAt(0); 2404 number += ""; 2405 var newNumber = []; 2406 for(var i = 0;i < number.length;i++) { 2407 newNumber.push(String.fromCharCode(zeroCode + parseInt(number.charAt(i)))); 2408 } 2409 return newNumber.join(""); 2410 } 2411 2412 PictureUtils.parsePictureClause = function (clause){ 2413 if(clause === null || clause === undefined) { 2414 return []; 2415 } 2416 var insidePattern = false, 2417 insideQuote=false, 2418 insideLocale = false, 2419 locale = "", 2420 type = "", 2421 pattern = "", 2422 flag = false, 2423 currentChar = "", 2424 result = [], 2425 matchType = /^num$|^text$|^date$/, 2426 matchLocale = /^[a-zA-Z]*_[a-zA-Z]*$/, 2427 i = 0, 2428 bracketOpenCount = 0; 2429 for(;i<clause.length;i++) { 2430 currentChar = clause.charAt(i); 2431 if(insideQuote && currentChar !== "'") { 2432 pattern += currentChar; 2433 continue; 2434 } 2435 switch(currentChar) { 2436 case "'": 2437 if(!insidePattern) { 2438 // ' is not allowed except insidePattern 2439 return null; 2440 } 2441 insideQuote = !insideQuote; 2442 pattern += currentChar; 2443 break; 2444 case "{": 2445 if(insidePattern || insideLocale || type === "") { 2446 // { is not allowed insidePattern or insideLocale 2447 return null; 2448 } 2449 insidePattern = true; 2450 break; 2451 case "}": 2452 if(!insidePattern || (insideLocale && pattern === "") || type === "") { 2453 // { is allowed only insidePattern and not insideLocale 2454 return null; 2455 } else { 2456 bracketOpenCount = 0; 2457 insidePattern = false; 2458 if(matchType.exec(type) === null) { 2459 return null; 2460 } 2461 if(locale !== "" && matchLocale.exec(locale) === null) { 2462 return null; 2463 } 2464 result.push({ 2465 category: type, 2466 mask: pattern, 2467 locale: locale 2468 }) 2469 } 2470 break; 2471 case "|": 2472 if(type === "" || insidePattern || insideLocale) { 2473 return null; 2474 } else { 2475 type = pattern = locale = ""; 2476 insidePattern = insideLocale = false;
2477 } 2478 break; 2479 case "(" : 2480 if(type === "" || bracketOpenCount === 1) { 2481 // ( is not allowed inside Locale 2482 return null; 2483 } else { 2484 if(!insidePattern) { 2485 insideLocale = true; 2486 } else { 2487 pattern += currentChar; 2488 } 2489 bracketOpenCount++; 2490 } 2491 break; 2492 case ")" : 2493 if((!insideLocale && !insidePattern) || bracketOpenCount === 0) { 2494 return null; 2495 } else { 2496 if(insidePattern) { 2497 pattern += currentChar; 2498 } 2499 insideLocale = false; 2500 bracketOpenCount--; 2501 } 2502 break; 2503 default: 2504 if(insidePattern) { 2505 pattern += currentChar; 2506 } else if(insideLocale) { 2507 locale += currentChar; 2508 } else if(type !== "" && (pattern !== "" || locale !== "")){ 2509 return null; 2510 } else { 2511 type += currentChar; 2512 } 2513 break; 2514 } 2515 } 2516 if(insidePattern || insideLocale || insideQuote || bracketOpenCount !== 0) { 2517 return null; 2518 } 2519 return result; 2520 } 2521 2522})(_,xfalib); 2523 2524/** 2525 * @package xfalib.ut.VisitorBase 2526 * @import xfalib.ut.Class 2527 * @fileOverview Base class for visitor 2528 * @version 0.0.1 2529 */ 2530 2531/** 2532 * @constructor 2533 * @param Object {jsonModel: {_sPicture: String}} 2534 */ 2535 2536(function(_,xfalib) { 2537 var VisitorBase = xfalib.ut.VisitorBase = xfalib.ut.Class.extend({ 2538 consume : function(token){ 2539 switch (token.type) 2540 { 2541 case 1: 2542 this.consumeStringLiteral(token); 2543 break; 2544 case 2: 2545 this.consumeSubPattern(token); 2546 break; 2547 case 3: 2548 this.consumeStringWildCard(token); 2549 break; 2550 case 4: 2551 this.consumeCharLiteral(token); 2552 break; 2553 } 2554 }, 2555 acceptPatternChar : function(chr){ 2556 return false; 2557 }, 2558 getPicture : function(){ 2559 return this.jsonModel._sPicture; 2560 }, 2561 abstractMethod : function(){ 2562 throw "Not implemented"; 2563 }, 2564 consumeStringWildCard : this.abstractMethod, 2565 consumeStringLiteral: this.abstractMethod, 2566 consumeCharLiteral: this.abstractMethod, 2567 consumeSubPattern: this.abstractMethod, 2568 getResult: this.abstractMethod 2569 }); 2570})(_,xfalib); 2571 2572/** 2573 * @package xfalib.ut.NumPictureDesc 2574 * @import xfalib.ut.Class 2575 * @fileOverview Pre-process Numeric Picture. 2576 * @version 0.0.1 2577 */ 2578 2579/** 2580 * @constructor 2581 * @param Object {jsonModel: {_sPicture: String}} 2582 */ 2583 2584(function(_,xfalib){ 2585 var NumPictureDesc = xfalib.ut.NumPictureDesc = xfalib.ut.Class.extend({ 2586 2587 initialize: function() { 2588 this.hasRadix = false; 2589 this.hasExpon = false; 2590 this.hasSign = false; 2591 this.hasPercent = false; 2592 this.fracDigit = 0; 2593 this.intDigit = 0; 2594 2595 this._mbLeftParenSeen = false; 2596 this._mbRightParenSeen = false; 2597 this._compactPattern(); 2598 this._xlatePattern(); 2599 NumPictureDesc._super.initialize.call(this); 2600 }, 2601 2602 getPicture : function(){ 2603 return this.jsonModel._sPicture; 2604 }, 2605 2606 _match2Char : function (char1, char2, idx){ 2607 if(idx+1 < this.jsonModel._sPicture.length){ 2608 return (this.jsonModel._sPicture.charAt(idx) ==char1 && this.jsonModel._sPicture.charAt(idx+1) ==char2); 2609 }else{ 2610 return false;
2611 } 2612 }, 2613 2614 _xlatePattern : function(){ 2615 var patPos = 0; 2616 for(var token = xfalib.ut.Scanner.lookupNext(this.jsonModel._sPicture, patPos, this._acceptPatternChar); token != null; ){ 2617 this._consume(token); 2618 patPos = patPos + token.len; 2619 token = xfalib.ut.Scanner.lookupNext(this.jsonModel._sPicture, patPos, this._acceptPatternChar); 2620 } 2621 }, 2622 2623 _compactPattern : function(){ 2624 var buf = new Array(); 2625 for(var index =0, len = this.jsonModel._sPicture.length; index <len; index++){ 2626 if(this._match2Char('D','B',index)){ 2627 buf.push('D'); 2628 index++; 2629 }else if(this._match2Char('d','b',index)){ 2630 buf.push('d'); 2631 index++; 2632 }else if(this._match2Char('C','R',index)){ 2633 buf.push('C'); 2634 index++; 2635 }else if(this._match2Char('c','r',index)){ 2636 buf.push('c'); 2637 index++; 2638 }else{ 2639 buf.push(this.jsonModel._sPicture.charAt(index)); 2640 } 2641 } 2642 this.jsonModel._sPicture = buf.join(""); 2643 }, 2644 2645 _acceptPatternChar : function(chr){ 2646 return xfalib.ut.PictureUtils.inString(chr, "(%$,.)89BCDERSVZbcdrsvzt"); 2647 }, 2648 2649 _consume : function(token){ 2650 if(token.type == 2){ 2651 this._subConsume(token.patChar, token.len); 2652 }// else not a pattern 2653 }, 2654 2655 _subConsume : function(chr, chrCnt){ 2656 switch (chr) { 2657 case'E' : 2658 if (chrCnt > 1 || this.hasExpon || (this.fracDigit + this.intDigit)==0) 2659 throw "Illegal Numeric Picture: more than one Expon"; 2660 this.hasExpon = true; 2661 break; 2662 case '(': 2663 if (chrCnt > 1 || this._mbLeftParenSeen || this.fracDigit + this.intDigit >0 ) 2664 throw "Illegal Numeric Picture: ()"; 2665 this._mbLeftParenSeen = true; 2666 break; 2667 2668 case ')': 2669 if (chrCnt > 1 || ! this._mbLeftParenSeen || this._mbRightParenSeen) 2670 throw "Illegal Numeric Picture: ()"; 2671 this._mbRightParenSeen = true; 2672 if(this.fracDigit + this.intDigit >0) this.hasSign = true; 2673 break; 2674 case 'S': 2675 case 's': 2676 case 'C': //CR 2677 case 'c': //cr 2678 case 'D': //DB 2679 case 'd': //db 2680 this.hasSign = true; 2681 break; 2682 case '%' : 2683 this.hasPercent = true; 2684 break; 2685 case '.': 2686 case 'V': 2687 case 'v': 2688 if (chrCnt > 1 || this.hasRadix) 2689 throw "Illegal Numeric Picture: too many vV."; 2690 this.hasRadix = true; 2691 this._mbFracStartSeen = true; 2692 break; 2693 case '8' : 2694 case '9' : 2695 case 'Z': 2696 case 'z': 2697 if (this.hasRadix){ 2698 this.fracDigit += chrCnt; 2699 } else{ 2700 this.intDigit += chrCnt; 2701 } 2702 break; 2703 } 2704 }, 2705 2706 parseNumberInfo : function(msText){ 2707 var text=msText, 2708 num = Number(text), 2709 negative = false 2710 if(num < 0){ 2711 negative = true; 2712 num = -num; 2713 text = text.replace("-",""); 2714 } 2715 if(this.hasPercent){ 2716 num *= 100; 2717 text = ""+num; 2718 } 2719 var shift = 0; 2720 if(this.hasExpon){ 2721 var threshold = Math.pow(10,this.intDigit); 2722 if(num < threshold){ 2723 while(num*10 < threshold) { 2724 num *= 10; 2725 shift--; 2726 } 2727 }else{ 2728 while(num > threshold){ 2729 num /= 10; 2730 shift++; 2731 } 2732 } 2733 text = num+""; 2734 } 2735 var radixPos = text.indexOf(".", 0), 2736 fractionDigit = radixPos<0 ? 0 : text.length - radixPos - 1 2737 2738 if(this.fracDigit < fractionDigit) { 2739 num = num.toFixed(this.fracDigit); 2740 text = num +"" 2741 } 2742 2743 if(text.indexOf("0") == 0 && msText.indexOf("0") != 0) { 2744 text = text.substring(1); 2745 } 2746 2747 radixPos = text.indexOf(".", 0) 2748 var integerDigit = radixPos < 0 ? text.length : radixPos, 2749 offset = this.intDigit - integerDigit 2750 2751 if(offset <0 ){ 2752 throw "Exit: most significant " + offset +" digit lost"; 2753 } 2754 return { 2755 "integerDigit" : integerDigit, 2756 "radixPos" : radixPos , 2757 "fractionDigit" : radixPos<0 ? 0 : text.length - radixPos - 1, 2758 "msText" : text, 2759 "shift" : shift, 2760 "isNegative" : negative, 2761 "padding" :offset 2762 }; 2763 } 2764 }); 2765 2766 NumPictureDesc.gsDB = "DB"; 2767 NumPictureDesc.gsCR = "CR"; 2768 NumPictureDesc.gsE = "E"; 2769 NumPictureDesc.gsDSP = " "; 2770 NumPictureDesc.gsSSP = " "; 2771 2772})(_,xfalib); 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 /** 2785 * @package xfalib.ut.TimeInfo 2786 * @import xfalib.ut.Class 2787 * @fileOverview A wrapper class for date related information. 2788 * @version 0.0.1 2789 */ 2790
2791/** 2792 * @constructor 2793 */ 2794(function(_,xfalib){ 2795 var TimeInfo = xfalib.ut.TimeInfo = xfalib.ut.Class.extend({ 2796 2797 initialize: function() { 2798 this.mHourOfMeriDiem = -1; 2799 this.mHourOfDay = -1; 2800 this.mMinuteOfHour = -1; 2801 this.mSecondOfMinute = -1; 2802 this.mThousandthOfSecond = -1; 2803 }, 2804 2805 getISOTime : function(){ 2806 var timeStr = ""; 2807 if(this.mThousandthOfSecond>0){ 2808 timeStr = "-" + this.formatNum(this.mThousandthOfSecond,3); 2809 } 2810 if(this.mSecondOfMinute>0 || timeStr!=""){ 2811 timeStr = this.formatNum(this.mSecondOfMinute,2)+timeStr; 2812 timeStr = ":"+timeStr; 2813 } 2814 if(this.mMinuteOfHour>0 || timeStr!=""){ 2815 timeStr = this.formatNum(this.mMinuteOfHour,2)+timeStr; 2816 timeStr = ":"+timeStr; 2817 } 2818 timeStr = this.formatNum(this.mHourOfDay,2) + timeStr; 2819 2820 return timeStr; 2821 }, 2822 2823 formatNum : function(num, digits){ 2824 if(num<0){ 2825 num = 0; 2826 } 2827 return xfalib.ut.PictureUtils.padding(num, digits); 2828 }, 2829 2830 getDate : function(){ 2831 var date = new Date(); 2832 this.setTime(date); 2833 return date; 2834 }, 2835 2836 setTime : function(date){ 2837 date.setHours(this.mHourOfDay); 2838 date.setMinutes(this.mMinuteOfHour); 2839 date.setSeconds(this.mSecondOfMinute); 2840 date.setMilliseconds(this.mThousandthOfSecond); 2841 } 2842 }); 2843 2844 /** 2845 * 2846 * <p>Valid ISO8601/XFA time strings are in any one 2847 * of the following time patterns: 2848 * <ul> 2849 * <li> HH[MM[SS[.FFF][z]]] 2850 * <li> HH[MM[SS[.FFF][+HH[MM]]]] 2851 * <li> HH[MM[SS[.FFF][-HH[MM]]]] 2852 * <li> HH[:MM[:SS[.FFF][z]]] 2853 * <li> HH[:MM[:SS[.FFF][+HH[:MM]]]] 2854 * <li> HH[:MM[:SS[.FFF][-HH[:MM]]]] 2855 * </ul> 2856 */ 2857 TimeInfo.Parse = function(isoDateStr, locale){ 2858 var scanner = new xfalib.ut.Scanner({jsonModel:{_str:isoDateStr}}); 2859 var hours = scanner.readInteger(2); 2860 var minitues = -1; 2861 if(!scanner.isEOF()){ 2862 scanner.optionalConsumeChar(':'); 2863 minitues = scanner.readInteger(2); 2864 } 2865 var seconds = -1; 2866 if(!scanner.isEOF()){ 2867 scanner.optionalConsumeChar(':'); 2868 seconds = scanner.readInteger(2); 2869 } 2870 var milliseconds = -1; 2871 if(!scanner.isEOF()){ 2872 scanner.optionalConsumeChar('-'); 2873 milliseconds = scanner.readInteger(3); 2874 } 2875 //TODO timezone 2876 var info = new xfalib.ut.TimeInfo(); 2877 TimeInfo.setPropertyIfNotNull(info,hours,"mHourOfDay"); 2878 TimeInfo.setPropertyIfNotNull(info,minitues,"mMinuteOfHour"); 2879 TimeInfo.setPropertyIfNotNull(info,seconds,"mSecondOfMinute"); 2880 TimeInfo.setPropertyIfNotNull(info,milliseconds,"mThousandthOfSecond"); 2881 return info; 2882 }; 2883 2884 /** 2885 * 2886 * static method 2887 */ 2888 TimeInfo.setPropertyIfNotNull = function(object, value, proName){ 2889 if(value!=null){ 2890 var d = Number(value); 2891 if(!isNaN(d)){ 2892 object[proName] = d; 2893 } 2894 } 2895 }; 2896 2897})(_,xfalib); 2898/** 2899 * @package xfalib.ut.DateInfo 2900 * @import xfalib.ut.Class 2901 * @fileOverview A wrapper class for date related information. 2902 * @version 0.0.1 2903 */ 2904 2905/** 2906 * @constructor 2907 */ 2908 2909(function(_,xfalib) { 2910 var DateInfo = xfalib.ut.DateInfo = xfalib.ut.Class.extend({ 2911 2912 initialize: function(options) { 2913 if (options && !options.isParsingCall ) { // skip setting internal values when called while parsing date formats 2914 this.date = new Date(); 2915 this._year = this.date.getFullYear(); 2916 this._month = this.date.getMonth() + 1; 2917 this._day = this.date.getDay(); 2918 } 2919 DateInfo._super.initialize.call(this); 2920 }, 2921 2922 formatNum : function(num, digits){ 2923 if(num<0) 2924 num = 0; 2925 return xfalib.ut.PictureUtils.padding(num, digits); 2926 }, 2927 2928 getDate : function(){ 2929 return this.date; 2930 }, 2931 setDate : function() { 2932 this.date = new Date(this._year,this._month-1,this._day) 2933 }, 2934 getISODate : function(){ 2935 var isoDate = []; 2936
2937 isoDate.push(this.formatNum(this._year, 4)); 2938 isoDate.push("-"); 2939 isoDate.push(this.formatNum(this._month, 2)); 2940 isoDate.push("-"); 2941 isoDate.push(this.formatNum(this._day, 2)); 2942 2943 return isoDate.join(""); 2944 }, 2945 2946 year : function(y) { 2947 if(y && y > 0 && y <= 9999) 2948 this._year = y; 2949 else 2950 throw "undefined year"; 2951 }, 2952 2953 month : function(m) { 2954 if(m && m>0 && m < 13) { 2955 this._month = m; 2956 } 2957 else 2958 throw "Invalid month " + m; 2959 }, 2960 2961 _leapYear : function() { 2962 var year = this._year; 2963 return year % 400 == 0 || (year % 100 != 0 && year % 4 == 0); 2964 }, 2965 2966 _maxDate : function(m) { 2967 if(this._leapYear() && m == 2) 2968 return 29; 2969 else return DateInfo.dates[m-1]; 2970 }, 2971 2972 day : function(d) { 2973 if(d && d > 0 && d <= this._maxDate(this._month || 0)) 2974 this._day = d; 2975 else 2976 throw "Invalid Date "+ d + " for the month "+(this._month); 2977 }, 2978 2979 validate : function(y, m, d) { 2980 this.year(y); 2981 this.month(m); 2982 this.day(d); 2983 } 2984 }); 2985 2986 DateInfo.ParseIsoString = function(isoDateStr, locale){ 2987 var isDateRegexp = /^(\d{4})(?:-?(\d{1,2})(?:-?(\d{1,2}))?)?(?:T((\d{2}):(\d{2}):(\d{2}))Z)?$/; 2988 var match = isDateRegexp.exec(isoDateStr); 2989 if(match && match.length >= 4){ 2990 var dateInfo = new DateInfo(); 2991 var date = new Date(isoDateStr); 2992 // TODO - check if date is invalid. 2993 if(match[4] && date != null) { // if time is available then use date object for conversion otherwise use previous approach to support invalid date like 2012-10-101, 2010-02-29 etc for RTC CQ-4201274 2994 dateInfo.year(date.getFullYear()); 2995 dateInfo.month(date.getMonth()+1); 2996 dateInfo.day(date.getDate()); 2997 } else { 2998 try { 2999 dateInfo.year(Number(match[1])); 3000 dateInfo.month(Number(match[2])); 3001 dateInfo.day(Number(match[3])); 3002 } catch(e) { 3003 return null; 3004 } 3005 } 3006 dateInfo.setDate(); 3007 return dateInfo; 3008 } 3009 return null; 3010 }; 3011 3012 DateInfo.Parse = function(dateStr, locale, validateWithDefaultPatterns){ 3013 locale = locale || "en_US"; 3014 var patterns = xfalib.ut.PictureUtils.getLocaleObject(locale,"datePatterns"), 3015 isoDate = this.ParseIsoString(dateStr, locale); 3016 if(!_.isEmpty(isoDate)) { 3017 return isoDate; // in case edit pattern is present, it'll be parsed by the widget during input and return an iso date string. 3018 } 3019 //if edit pattern is present then don't try to match it from default locale patterns. 3020 if(validateWithDefaultPatterns === false){ 3021 _.find(patterns, function(pattern) { 3022 try { 3023 isoDate = xfalib.ut.PictureFmt.parseDate(dateStr,pattern,locale); 3024 return true; 3025 } catch(exception) { 3026 return false; 3027 } 3028 }); 3029 } 3030 isoDate = isoDate || dateStr; 3031 return DateInfo.ParseIsoString(isoDate); 3032 }; 3033 3034 DateInfo.dates = [31,28,31,30,31,30,31,31,30,31,30,31]; 3035 DateInfo.daysOfWeek = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]; 3036})(_,xfalib); 3037/** 3038 * @package xfalib.ut.PictureEngine 3039 * @import xfalib.ut.Scanner 3040 * @fileOverview The file is a facade to assembly all components together. 3041 * @version 0.0.1 3042 */ 3043(function(_,xfalib) { 3044 3045 var PictureEngine = xfalib.ut.PictureEngine = xfalib.ut.Class.extend({ 3046 3047 _lookupNext: xfalib.ut.Scanner.lookupNext, 3048 3049 MAX_XFA_PREC : 8, // Max no. of fractional digits in XFA. 3050 MAX_DBL_DIG :18, // Max no. of significant digits in a double. 3051 MAX_INT_DIG :10, // Max no. of significant digits in an integer. 3052 MAX_DBL_WIDTH :15, // Max width before precision loss in a double. 3053 INTEGRAL_FMT : 0, 3054 DECIMAL_FMT : 1, 3055 CURRENCY_FMT : 2, 3056 PERCENT_FMT : 3, 3057 3058 parseDate : function(sSource, sPicture, locale){ 3059 return this._acceptVisitor(new xfalib.ut.DateParsingVisitor({jsonModel:{_sPicture:sPicture,_dataString:sSource,_locale:this.jsonModel.locale}})); 3060 }, 3061 3062 formatDate : function(dDate, sPicture){
3063 var validateWithDefaultPatterns = typeof sPicture !== 'undefined'; 3064 var dateInfo = xfalib.ut.DateInfo.Parse(dDate, this.jsonModel.locale, validateWithDefaultPatterns); 3065 if(dateInfo == null){ 3066 return null; 3067 }else{ 3068 return this._acceptVisitor(new xfalib.ut.DateFormattingVisitor({jsonModel:{_sPicture:sPicture,_dateInfo:dateInfo,_locale:this.jsonModel.locale}})); 3069 } 3070 }, 3071 3072 parseTime : function(sSource, sPicture){ 3073 return this._acceptVisitor(new xfalib.ut.TimeParsingVisitor({jsonModel:{_sPicture:sPicture,_dataString:sSource}})); 3074 }, 3075 3076 formatTime : function(dDate, sPicture){ 3077 var timeInfo = xfalib.ut.TimeInfo.Parse(dDate, this.jsonModel.locale); 3078 if(timeInfo == null){ 3079 return null; 3080 }else{ 3081 return this._acceptVisitor(new xfalib.ut.TimeFormattingVisitor({jsonModel:{_sPicture:sPicture,_timeInfo:timeInfo}})); 3082 } 3083 }, 3084 3085 parseText : function(sSource, sPicture){ 3086 return this._acceptVisitor(new xfalib.ut.TextParsingVisitor({jsonModel:{_sPicture:sPicture,_dataString:sSource}})); 3087 }, 3088 3089 formatText : function(sSource, sPicture,bRelaxed){ 3090 return this._acceptVisitor(new xfalib.ut.TextFormattingVisitor({jsonModel:{_sPicture:sPicture,_text:sSource,relaxed:bRelaxed}})); 3091 }, 3092
3093 parseNumeric : function(sSource, sPicture){ 3094 var visitor = new xfalib.ut.NumParsingVisitor({jsonModel:{_sPicture:sPicture,_dataString:sSource,_locale:this.jsonModel.locale}}); // TODO : Is locale required 3095 visitor.parse(); 3096 return visitor.getResult(); 3097 }, 3098 3099 formatNumeric : function(sSource, sPicture,locale,bRelaxed,bFormatNumberFromasDefaultPC){ 3100 3101 var sFormatPicture =sPicture; 3102 if( bRelaxed && bFormatNumberFromasDefaultPC){ 3103 sFormatPicture = this.getNumberFormat(sPicture,1, {formatOption: "WITH_GROUPINGS", 3104 "precision" : this.getNumberPrecision(sSource), 3105 "width" : sSource.length 3106 }); 3107 } 3108 return this._acceptVisitor(new xfalib.ut.NumFormattingVisitor({jsonModel:{_sPicture:sFormatPicture,_locale:this.jsonModel.locale},text:sSource})); 3109 }, 3110 3111 _acceptVisitor : function(visitor){ 3112 this._scanPattern(visitor); 3113 return visitor.getResult(); 3114 }, 3115 3116 _scanPattern : function(visitor){ 3117 var patPos = 0; 3118 var sPicture = visitor.getPicture(); 3119 for(var token = this._lookupNext(sPicture, patPos, visitor.acceptPatternChar); token != null; ){ 3120 visitor.consume(token); 3121 patPos = patPos + token.len; 3122 token = this._lookupNext(sPicture, patPos, visitor.acceptPatternChar); 3123 } 3124 }, 3125 3126 /** 3127 * Removes n bytes from this string starting at position nOffset. 3128 * 3129 * @param nOffset - start position for the remove 3130 * @param nLength - the number of characters to remove 3131 * @return This string 3132 */ 3133 3134 _swallow : function(sString , nOffset, nLenToSwallow) 3135 { 3136 if(_.isEmpty(sString) || nLenToSwallow ==0){ 3137 return sString; 3138 } 3139 3140 if( (nOffset + nLenToSwallow)> sString.length ) { 3141 nLenToSwallow = (nOffset + nLenToSwallow) - sString.length; 3142 } 3143 var subStr = sString.substr(0,nOffset) + sString.substr(offset + nLenToSwallow); 3144 3145 return subStr 3146 }, 3147 /** 3148 * Replace some portion of one string with another String. 3149 * @param sString - the String where it has to be replaced. 3150 * @param sReplacement - the replacement string. 3151 * @param nOffset - start position for the replacement. Default value = 0. 3152 * @param nCutLength - the number of bytes to remove from the 3153 * original string. 3154 */ 3155 3156 _replaceAll : function(sString ,sReplacement , nOffset ,nCutlength) { 3157 return sString.substr(0,nOffset) + sReplacement + sString.substr(nOffset + nCutlength) 3158 }, 3159 3160 //---------------------------------------------------------------------- 3161 // SkipOver 3162 // 3163 // Scan this string for the first byte of the character not in the given set. 3164 // Similar to strspn(). 3165 //---------------------------------------------------------------------- 3166 _skipOver : function(fromString,sSkip, nOffset) 3167 { 3168 // starting at the offset position, scan the characters in this string 3169 // until it does not match any of the characters in the given set. 3170 var nCharsSkipped = nOffset; 3171 var i = 0; 3172 while (nCharsSkipped < fromString.length) 3173 { 3174 i = nCharsSkipped; 3175 if (sSkip.indexOf(fromString[i]) ==-1) { 3176 break; 3177 } 3178 i++; 3179 nCharsSkipped = i; 3180 } 3181 3182 return nCharsSkipped - nOffset; 3183 }, 3184 3185 /* 3186 * Get the numeric format in the given style. 3187 * @param style in the range of values 0-2, 3188 * where (0 = integral, 1 = decimal, 2 = currency). 3189 * @param option in the set of format options: 3190 */ 3191 getNumberFormat : function(format , style, option) 3192 { 3193 if (style < this.INTEGRAL_FMT || this.PERCENT_FMT < style) { 3194 style = this.DECIMAL_FMT; 3195 } 3196 3197 var sFormat = format; 3198 3199 // 3200 // Use any alternate part because they handle negative values. 3201 // 3202 var nBar = 0; 3203 if ((nBar = sFormat.indexOf('|')) != -1) { 3204 sFormat = this._swallow(sFormat, 0, nBar + 1); 3205 } 3206 // 3207 // Determine position of radix (or anything like it) 3208 // and the replicating part of the pattern, i.e., from 3209 // the separator to this radix. 3210 // 3211 var nDot; 3212 if ( (nDot = sFormat.indexOf('.')) == -1) { 3213 if ((nDot = sFormat.indexOf('v')) == -1) { 3214 if ((nDot = sFormat.indexOf('V')) == -1) { 3215 if ((nDot = sFormat.indexOf('E')) == -1) { 3216 if ((nDot = sFormat.indexOf(' ')) == -1) { 3217 if ((nDot = sFormat.indexOf('%')) == -1) { 3218 nDot = sFormat.length; 3219 } 3220 } 3221 } 3222 } 3223 } 3224 } 3225 if (nDot) { 3226 if (this._skipOver(sFormat,"89zZ", nDot - 1) != 1) { 3227 nDot = sFormat.length; 3228 } 3229 } 3230 var sZZZ; 3231 var nZed; 3232 if ( (nZed = sFormat.indexOf("z,")) != -1) { 3233 // 3234 // Watson 1230768. Handle locales, like India, that have 3235 // pictures with more than one grouping symbol. 3236 // 3237 var nSep = nDot; 3238 var nComma; 3239 if ((nComma = sFormat.indexOf(',', nZed + 2)) !=-1) { 3240 nSep = nComma; 3241 } 3242 if (nSep > nZed + 2) { 3243 sZZZ = Array(nSep - nZed).join('z'); 3244 } 3245 else { 3246 sZZZ = Array(1).join('z'); 3247 } 3248 } 3249 else { 3250 nZed = 0; 3251 } 3252 // 3253 // If non-integral styles Then determine width and precision. 3254 // 3255 var nPrec = 0; 3256 var nWidth = this.MAX_INT_DIG; 3257 if (style != this.INTEGRAL_FMT) { 3258 nPrec = option.precision; // (option >> 8) & 0xff;
3259 var trim = ((nPrec & 0x80) == 0); 3260 nPrec &= 0x7f; 3261 if (nPrec == 0x7f) { 3262 nPrec = this._skipOver(sFormat, "89zZ", nDot + 1); 3263 } 3264 if ((option.width) != undefined) { 3265 nWidth = option.width; 3266 } 3267 else { 3268 nWidth = this.MAX_DBL_DIG; 3269 } 3270 // 3271 // Fix for Watson 1229423. If the locale's format contains 3272 // any sign pictures Then widen accordingly. Also widen if 3273 // precision of locale's picture format is greater than requested. 3274 // 3275 if (sFormat.indexOf('s')!=-1) { 3276 nWidth += 1; 3277 } 3278 if (sFormat.indexOf('(')!=-1) { 3279 nWidth += 1; 3280 } 3281 if (sFormat.indexOf(')') !=-1) { 3282 nWidth += 1; 3283 } 3284 var nFmtPrec = this._skipOver(sFormat,"89zZ", nDot + 1); 3285 if (0 < nPrec && nPrec < nFmtPrec) { 3286 nWidth += nFmtPrec - nPrec; 3287 } 3288 3289 // 3290 // Pare down the precision if the width is big enough to yield 3291 // IEEE 754 64-bit double precision errors, which appears to be 3292 // anything over 14 significant digits. 3293 // 3294 if (trim && nPrec > 0 && nWidth > nPrec) { 3295 // 3296 // Fix for Watson 1211481. If the given precision is less 3297 // than what the locale's format dictates then widen the given 3298 // width. 3299 // 3300 if (nPrec <= sFormat.length - 1 - nDot) { 3301 nWidth += sFormat.length - 1 - nDot - nPrec; 3302 } 3303 for (var i = nWidth - 1; i > this.MAX_DBL_WIDTH; i--) { 3304 // 3305 // Never pare down the precision below what the locale's 3306 // format dictates. 3307 // 3308 if (nPrec <= sFormat.length - 1 - nDot) 3309 break; 3310 nPrec--; 3311 } 3312 } 3313 } 3314 //Watson 1483675 - If the locale's format contains 3315 // a dollar sign or a space then widen accordingly. 3316 if (style == this.CURRENCY_FMT) { 3317 if (sFormat.indexOf('$')!=-1) { 3318 nWidth++; 3319 } 3320 3321 if (sFormat.indexOf(' ')!=-1) { 3322 nWidth += 1; 3323 } 3324 } 3325 3326 // 3327 // If percent style was wanted Then truncate after the percent character. 3328 // 3329 if (style == this.PERCENT_FMT) { 3330 var nTrim = this._skipOver(sFormat,"89zZ", nDot + 1); 3331 sFormat = this._replaceAll(sFormat,"",nTrim,0) 3332 //sFormat.Replace(jfString::EmptyString(), nDot + 1, nTrim); 3333 3334 //Watson 1483675 - If the locale's format contains 3335 // a percent sign then widen accordingly. 3336 if (sFormat.indexOf('%')!=-1) { 3337 nWidth++; 3338 } 3339 } 3340 // 3341 // Else if integral style was wanted Then truncate at the radix character. 3342 // 3343 // 3344 // If integral style was wanted Then truncate at the radix character. 3345 // 3346 else if (style == this.INTEGRAL_FMT || nPrec == 0){// && option.formatOption == "WITHOUT_RADIX") { 3347 var nTrim = this._skipOver(sFormat,"89zZ", nDot + 1); 3348 sFormat = this._replaceAll(sFormat,"",nDot,nTrim+1); 3349 } 3350 // 3351 // Otherwise for decimal and currency styles Do 3352 // replace fractional 'z' pictures with '8's to requested precision, 3353 // 3354 else if (option.formatOption == "WITH_EIGHTS") { 3355 var nEight = nDot + 1; 3356 while ((nEight =sFormat.indexOf('z'))!=-1) { 3357 this._replaceAll(sFormat, '8', nEight,'8'.length); 3358 } 3359 while (sFormat.Length() - nDot <= nPrec) { 3360 sFormat = this._replaceAll(sFormat, "8", nDot + 1, 0); 3361 } 3362 } 3363 // 3364 // Or replace fractional '9' pictures with 'z's to requested precision 3365 // Watson 1322850 - add option to keep nines, previously this function 3366 // would force frac. digits to be either z's or 8's with no option for 9's. 3367 // 3368 else if ((option.formatOption) == "WITH_ZEDS" && !((option.formatOption) == "KEEP_NINES")) { 3369 var nNine = nDot + 1; 3370 while ((nNine = sFormat.indexOf('9'))!=-1) { 3371 this._replaceAll(sFormat, 'z', nNine,1); 3372 } 3373 while (sFormat.Length() - nDot <= nPrec) {
3374 this._replaceAll(sFormat, "z", nDot + 1, 0); 3375 } 3376 } 3377 // 3378 // Replicate section from separator to radix to requested width. 3379 // 3380 if (!sZZZ) { 3381 sZZZ = "z"; 3382 } 3383 else if ((option.formatOption) == "WITHOUT_GROUPINGS" ) { 3384 // 3385 // Watson 1230768. Handle locales, like India, that have 3386 // pictures with more than one grouping symbol. 3387 // 3388 var nComma = nZed + 1 ; 3389 this._replaceAll(sFormat, 'z' ,nComma,1); 3390 while ( nComma!= -1 && (nComma < nDot)) { 3391 nComma = sFormat.indexOf(','); 3392 sFormat = this._replaceAll(sFormat,'z',nComma,1); 3393 } 3394 } 3395 else if ((option.formatOption == "WITH_GROUPINGS")) { 3396 sZZZ = this._replaceAll(sZZZ,',',0,1); 3397 nWidth += (nWidth + sZZZ.length) / sZZZ.length; 3398 } 3399 while (sFormat.length < nWidth) { 3400 sFormat = this._replaceAll(sFormat, sZZZ, nZed + 1, 0); 3401 } 3402 return sFormat; 3403 }, 3404 3405 /** 3406 * Get the decimal precision of the given numeric string. 3407 * @return the decimal precision or 0 for integral values. 3408 */ 3409 getNumberPrecision: function(sVal) 3410 { 3411 var nRadix = 0; 3412 var i = -1; 3413 // Reason for not using the commented line. We are always storing the value in model with . as decimal separator 3414 // Passing field locale/ browser locale would lead to precision width being zero for non-english locales where 3415 // decimal separater may be different. 3416 // var rIndex = xfalib.ut.PictureUtils.getLocaleObject(this.jsonModel.locale,"numberSymbols").decimal; 3417 // so hardcoding . for now 3418 var rIndex = "."; 3419 if( (nRadix = sVal.indexOf(rIndex))!=-1) 3420 { 3421 for(; nRadix <=sVal.length ;nRadix++) { 3422 i++; 3423 } 3424 3425 return i; 3426 } 3427 return 0; 3428 } 3429 }) 3430})(_,xfalib); 3431/** 3432 * @package xfalib.ut.FormattingVisitorBase 3433 * @import xfalib.ut.VisitorBase 3434 * @fileOverview Base class for visitor 3435 * @version 0.0.1 3436 */ 3437 3438/** 3439 * @constructor 3440 * @param Object {jsonModel: {_sPicture: String]} 3441 */ 3442 3443(function(_,xfalib) { 3444 var FormattingVisitorBase = xfalib.ut.FormattingVisitorBase = xfalib.ut.VisitorBase.extend({ 3445 3446 initialize: function() { 3447 this._buffer = []; //TODO: ASK Ren where does this _buffer comes from 3448 FormattingVisitorBase._super.initialize.call(this); 3449 }, 3450 3451 consumeStringWildCard : function(token){ 3452 //'?' '*' '+ 3453 this._buffer.push(" "); 3454 }, 3455 3456 consumeStringLiteral : function(token){ 3457 this._buffer.push(this.jsonModel._sPicture.substr(token.startPos+1,token.len-2)); 3458 }, 3459 3460 consumeCharLiteral : function(token){ 3461 this._buffer.push(""+ this.jsonModel._sPicture.charAt(token.startPos)); 3462 } 3463 }) 3464 3465})(_,xfalib); 3466/** 3467 * @package xfalib.ut.ParsingVisitorBase 3468 * @import xfalib.ut.VisitorBase 3469 * @fileOverview Base class for visitor 3470 * @version 0.0.1 3471 */ 3472 3473/** 3474 * @constructor 3475 * @param Object {jsonModel: {_sPicture: String,_dataString: String}} 3476 */ 3477 3478(function(_,xfalib){ 3479 var ParsingVisitorBase = xfalib.ut.ParsingVisitorBase = xfalib.ut.VisitorBase.extend({ 3480 3481 initialize: function() { 3482 this._strLen = this.jsonModel._dataString.length; 3483 this._strPos = 0; 3484 ParsingVisitorBase._super.initialize.call(this); 3485 }, 3486 3487 consumeStringWildCard : function(token){ 3488 if (chr == '?') { 3489 if (this._strPos < this._strLen)//&& Character.isDefined(str.charAt(strPos)) 3490 this._strPos += 1; 3491 } else if (chr == '+') { 3492 if (this._strPos >= this._strLen)// || ! Character.isWhitespace(str.charAt(strPos))) 3493 throw "Mismatch"; 3494 this._strPos += 1; 3495 while (this._strPos < this._strLen)// && Character.isWhitespace(str.charAt(strPos))) 3496 this._strPos += 1; 3497 } else if (chr == '*') { 3498 while (this._strPos < this._strLen)// && Character.isWhitespace(str.charAt(strPos))) 3499 this._strPos += 1; 3500 } 3501 3502 }, 3503 3504 consumeStringLiteral : function(token){ 3505 for(var offset=0; offset<token.len-2 ;offset++){ //-2, heading and trailing quote 3506 if(this.jsonModel._sPicture.charAt(token.startPos+offset+1) != this.jsonModel._dataString.charAt(this._strPos+offset)){ 3507 throw ("Mismatch" + this.jsonModel._sPicture.substr(token.startPos, token.len)); 3508 } 3509 } 3510 this._strPos += token.len-2; 3511 3512 }, 3513 3514 consumeCharLiteral : function(token){ 3515 if(this.jsonModel._sPicture.charAt(token.startPos) == this.jsonModel._dataString.charAt(this._strPos)){ 3516 this._strPos += 1; 3517 }else{ 3518 throw "Mismatch"; 3519 } 3520 } 3521 }) 3522})(_,xfalib); 3523 3524/** 3525 * @package xfalib.ut.DateFormattingVisitor 3526 * @import xfalib.ut.FormattingVisitorBase 3527 * @fileOverview The file provides formating logic on date pattern characters. 3528 * @version 0.0.1 3529 */ 3530 3531 3532/** 3533 * @constructor 3534 * @param object {jsonModel: {_sPicture:String,_dateInfo: xfalib.ut.DateInfo}} 3535 */ 3536 3537(function(_,xfalib) { 3538 var PictureUtils = xfalib.ut.PictureUtils; 3539 var DateFormattingVisitor = xfalib.ut.DateFormattingVisitor = xfalib.ut.FormattingVisitorBase.extend({ 3540 3541 consumeSubPattern : function(token){ 3542 var chr = token.patChar; 3543 var chrCnt = token.len; 3544 3545 switch (chr) { 3546 case 'D': 3547 var dayOfMonth=this.jsonModel._dateInfo.date.getDate(); 3548 switch(chrCnt){ 3549 case 1: 3550 break; 3551 case 2: 3552 dayOfMonth = PictureUtils.padding(dayOfMonth,2); 3553 break; 3554 } 3555 this._buffer.push(PictureUtils.convertNumberToLocale(this.jsonModel._locale,dayOfMonth)); 3556 break; 3557 case 'J': 3558 3559 //this._mDayOfYear; 3560 break; 3561 case 'M': 3562 var monthOfYear = this.jsonModel._dateInfo.date.getMonth(); 3563 switch(chrCnt){ 3564 case 1: 3565 this._buffer.push(PictureUtils.convertNumberToLocale(this.jsonModel._locale,monthOfYear+1)); 3566 break; 3567 case 2: 3568 this._buffer.push(PictureUtils.convertNumberToLocale(this.jsonModel._locale,PictureUtils.padding(monthOfYear+1,2))); 3569 break; 3570 case 3: 3571 var monthNames = PictureUtils.getLocaleObject(this.jsonModel._locale,"calendarSymbols.abbrmonthNames"); 3572 this._buffer.push(monthNames[monthOfYear]); 3573 break; 3574 case 4: 3575 var monthNames = PictureUtils.getLocaleObject(this.jsonModel._locale,"calendarSymbols.monthNames"); 3576 this._buffer.push(monthNames[monthOfYear]); 3577 break; 3578 } 3579 3580 break; 3581 case 'E': 3582 var dayOfWeek = this.jsonModel._dateInfo.date.getDay(); 3583 var dayNames; 3584 switch(chrCnt) { 3585 case 1: 3586 this._buffer.push(dayOfWeek); 3587 break; 3588 case 3: 3589 dayNames = PictureUtils.getLocaleObject(this.jsonModel._locale,"calendarSymbols.abbrdayNames"); 3590 this._buffer.push(dayNames[dayOfWeek]); 3591 break; 3592 case 4: 3593 dayNames = PictureUtils.getLocaleObject(this.jsonModel._locale,"calendarSymbols.dayNames"); 3594 this._buffer.push(dayNames[dayOfWeek]); 3595 break; 3596 default: 3597 throw "unsupported Picture Clause "; 3598 } 3599 break; 3600 case 'e': 3601 break; 3602 case 'G': 3603 break; 3604 case 'Y': 3605 3606 var yearOfEra = this.jsonModel._dateInfo.date.getFullYear() 3607 switch(chrCnt){ 3608 case 2: 3609 if(yearOfEra>2029 || yearOfEra < 1930){ 3610 throw "unsupported " + yearOfEra + " by pattern YY"; 3611 } 3612 yearOfEra = PictureUtils.padding(yearOfEra % 100, 2); 3613 break; 3614 case 4: 3615 yearOfEra = PictureUtils.padding(yearOfEra, 4); // 2 digit(0000-9999) 3616 break; 3617 } 3618 this._buffer.push(PictureUtils.convertNumberToLocale(this.jsonModel._locale,yearOfEra)); 3619 break; 3620 case 'w': 3621 break; 3622 case 'W': 3623 break; 3624 default: throw "Unsupported pattern"; 3625 } 3626 3627 }, 3628 /** 3629 * 3630 * @override 3631 */ 3632 getResult : function(){ 3633 return this._buffer.join(""); 3634 } 3635 3636 }); 3637})(_,xfalib); 3638 3639 3640/** 3641 * @package xfalib.ut.TextFormattingVisitor 3642 * @import xfalib.ut.FormattingVisitorBase 3643 * @fileOverview Formats a string according to Text Picture. 3644 * @version 0.0.1 3645 */ 3646
3647/** 3648 * @constructor 3649 * @param Object { jsonModel:{_sPicture: String, _text: String}} 3650 */ 3651(function(_,xfalib){ 3652 var TextFormattingVisitor = xfalib.ut.TextFormattingVisitor = xfalib.ut.FormattingVisitorBase.extend({ 3653 3654 initialize: function() { 3655 this._textPos = 0; 3656 this._relaxed = typeof this.jsonModel.relaxed === "undefined" ? true: this.jsonModel.relaxed; 3657 TextFormattingVisitor._super.initialize.call(this); 3658 }, 3659 3660 consumeSubPattern : function(token){ 3661 var chr = token.patChar; 3662 var chrCnt = token.len; 3663 for(var index = 0; index < chrCnt && (!this._relaxed || this._textPos < this.jsonModel._text.length); index++){ 3664 switch (chr) { 3665 case '9': // Numeric 3666 var cUni = this.jsonModel._text.charAt(this._textPos++); 3667 if(!xfalib.ut.PictureUtils.isDigit(cUni)){ 3668 throw "TextFormatting: not a digit as expected"; 3669 } 3670 this._buffer.push(cUni); 3671 break; 3672 case 'A': // Alphebetic 3673 var cUni = this.jsonModel._text.charAt(this._textPos++); 3674 if(!xfalib.ut.PictureUtils.isLetter(cUni)){ 3675 throw "TextFormatting: not a character as expected"; 3676 } 3677 this._buffer.push(cUni); 3678 break; 3679 case 'O': // Alphanumeric 3680 case '0': 3681 var cUni = this.jsonModel._text.charAt(this._textPos++); 3682 // cUni === "" is a hack for LC-6152 3683 // To prevent extra loop[one more time than the length of the string] for which cUni was "" 3684 // which was neither a letter nor a digit 3685 // so we were getting textformatting error 3686 //which caused email id validation to fail for chars less than picture clause 3687 if(!(cUni ==="" || xfalib.ut.PictureUtils.isLetter(cUni) || xfalib.ut.PictureUtils.isDigit(cUni))){ 3688 throw "TextFormatting: not a character or digit as expected"; 3689 } 3690 this._buffer.push(cUni); 3691 break; 3692 case 'X': 3693 var cUni = this.jsonModel._text.charAt(this._textPos++); 3694 this._buffer.push(cUni); 3695 break; 3696 case 't': 3697 this._buffer.push("\t"); 3698 break; 3699 default: this._buffer.push(chr); 3700 } 3701 } 3702 3703 }, 3704 3705 /** 3706 * 3707 * @override 3708 */ 3709 getResult : function(){ 3710 if(this._textPos < this.jsonModel._text.length) 3711 throw "TextFormatting: picture clause smaller than input Text"; 3712 return this._buffer.join(""); 3713 }, 3714 3715 /** 3716 * 3717 * @override 3718 */ 3719 acceptPatternChar : function(chr){ 3720 return xfalib.ut.PictureUtils.inString(chr, "9AO0Xt"); 3721 }, 3722 3723 consumeCharLiteral : function(token){ 3724 this._buffer.push(""+ this.jsonModel._sPicture.charAt(token.startPos)); 3725 // LC-3869 : forward the text pointer after literal is present and matched with the picture. 3726 if(this.jsonModel._sPicture.charAt(token.startPos) == this.jsonModel._text.charAt(token.startPos)) 3727 this._textPos++; 3728 } 3729 }) 3730 3731})(_,xfalib); 3732 3733 3734/** 3735 * @package xfalib.ut.TextFormattingVisitor 3736 * @import xfalib.ut.FormattingVisitorBase 3737 * @fileOverview The file provides formating logic on date pattern characters. 3738 * @version 0.0.1 3739 */ 3740 3741/** 3742 * @constructor 3743 * @param object {jsonModel: {_sPicture:String,_timeInfo: xfalib.ut.TimeInfo}} 3744 */ 3745 3746(function(_,xfalib){ 3747 var TimeFormattingVisitor = xfalib.ut.TimeFormattingVisitor= xfalib.ut.FormattingVisitorBase.extend({ 3748 3749 consumeSubPattern : function(token){ 3750 var chr = token.patChar; 3751 var chrCnt = token.len; 3752 3753 switch (chr) { 3754 case 'H': 3755 case 'K': 3756 var hourOfDay = this.jsonModel._timeInfo.mHourOfDay; 3757 if(chr=='K'){ 3758 hourOfDay += 1; 3759 } 3760 switch(chrCnt){ 3761 case 1: 3762 this._buffer.push(hourOfDay); 3763 break; 3764 case 2: 3765 this._buffer.push(xfalib.ut.PictureUtils.padding(hourOfDay,2)); 3766 break; 3767 } 3768 break; 3769 3770 case 'M': 3771 var minuteOfHour = this.jsonModel._timeInfo.mMinuteOfHour; 3772 switch(chrCnt){ 3773 case 1: 3774 this._buffer.push(minuteOfHour); 3775 break; 3776 case 2: 3777 this._buffer.push(xfalib.ut.PictureUtils.padding(minuteOfHour,2)); 3778 break; 3779 } 3780 3781 break; 3782 case 'S': 3783 var secondOfMinute = this.jsonModel._timeInfo.mSecondOfMinute; 3784 switch(chrCnt){ 3785 case 1: 3786 this._buffer.push(secondOfMinute); 3787 break; 3788 case 2: 3789 this._buffer.push(xfalib.ut.PictureUtils.padding(secondOfMinute,2)); 3790 break; 3791 } 3792 break; 3793 case 'F': 3794 var Milliseconds =this.jsonModel._timeInfo.mThousandthOfSecond; 3795 this._buffer.push(xfalib.ut.PictureUtils.padding(Milliseconds,3)); 3796 break; 3797 3798 default: throw "Unsupported pattern"; 3799 }; 3800 3801 }, 3802 3803 /** 3804 * 3805 * @override 3806 */ 3807 getResult : function(){ 3808 return this._buffer.join(""); 3809 } 3810 3811 }); 3812 3813})(_,xfalib); 3814 3815 3816/** 3817 * @package xfalib.ut.NumFormattingVisitor 3818 * @import xfalib.ut.FormattingVisitorBase 3819 * @fileOverview Formats a string according to Text Picture. 3820 * @version 0.0.1 3821 */ 3822
3823/** 3824 * @constructor 3825 * @param Object { jsonModel:{_sPicture: String}, text: String} 3826 */ 3827 3828(function(_,xfalib){ 3829 var PictureUtils = xfalib.ut.PictureUtils; 3830 var NumFormattingVisitor = xfalib.ut.NumFormattingVisitor = xfalib.ut.FormattingVisitorBase.extend({ 3831 3832 initialize: function(options) { 3833 NumFormattingVisitor._super.initialize.call(this); 3834 this._textPos = 0; 3835 3836 //boolean value used for internal state track 3837 this._mbDigitAddedToOutput = false; // at least one digit has been added to output 3838 this._mbSignAddedToOutput = false; 3839 this._nScannedPatternDigit = 0; //how many digit(98Zz) characters scanned in pattern, reset to 0 after '.Vv' 3840 this._mbRadixSeen = false; 3841 3842 this._pictureDesc = new xfalib.ut.NumPictureDesc({jsonModel:{_sPicture:this.jsonModel._sPicture}}); 3843 this.jsonModel._sPicture= this._pictureDesc.getPicture(); 3844 this._numberInfo = this._pictureDesc.parseNumberInfo(options.text); 3845 3846 this._mbNegative = this._numberInfo.isNegative; 3847 this._msText = this._numberInfo.msText; 3848 this._leadingPadding = this._numberInfo.padding; 3849 // 3850 this._mNumberSymbols = xfalib.ut.PictureUtils.getLocaleObject(this.jsonModel._locale,"numberSymbols"); 3851 this._mCurrencySymbols = xfalib.ut.PictureUtils.getLocaleObject(this.jsonModel._locale,"currencySymbols"); 3852 }, 3853 3854 _checkAndAddDecimalPoint: function(fw) { 3855 if(this._mAddRadix) { 3856 this._buffer.push(this._fmtStr(this._mNumberSymbols.decimal, fw)); 3857 this._mAddRadix = false; 3858 } 3859 }, 3860 3861 consumeSubPattern : function(token){ 3862 var chr = token.patChar, 3863 chrCnt = token.len; 3864 switch (chr) { 3865 case '9': 3866 case '8': 3867 case 'Z': // Digit or space if zero. 3868 case 'z':// Digit or nothing if zero. 3869 if(!this._mbSignAddedToOutput) 3870 this._ensureSignIsAdded(); 3871 while (chrCnt-- > 0 ) { 3872 if(!this._mbRadixSeen){ 3873 if(this._leadingPadding > this._nScannedPatternDigit++){ 3874 var placeHolder = null; 3875 if(this._mbDigitAddedToOutput){ 3876 placeHolder = this._mNumberSymbols.zero; 3877 }else{ 3878 if(chr == '9' || chr =='8') { 3879 placeHolder = this._mNumberSymbols.zero; 3880 this._mbDigitAddedToOutput = true; 3881 }else if(chr == 'Z'){ 3882 placeHolder = " "; 3883 } 3884 } 3885 if(placeHolder){ 3886 this._buffer.push(this._matchChr(placeHolder)); 3887 } 3888 }else { 3889 var cValue = this._msText.charAt(this._textPos++); 3890 this._ensureCharIsDigit(cValue); 3891 this._buffer.push(PictureUtils.convertNumberToLocale(this.jsonModel._locale,cValue)); 3892 this._mbDigitAddedToOutput = true; 3893 } 3894 }else{ //handling fractional part 3895 if(this._nScannedPatternDigit++ < this._numberInfo.fractionDigit ){ 3896 var cValue = this._msText.charAt(this._textPos++); 3897 this._ensureCharIsDigit(cValue); 3898 this._checkAndAddDecimalPoint(); 3899 this._buffer.push(PictureUtils.convertNumberToLocale(this.jsonModel._locale,cValue)); 3900 this._mbDigitAddedToOutput = true; 3901 }else{ 3902 if(chr == '9'|| chr =='Z') { 3903 this._checkAndAddDecimalPoint(); 3904 this._buffer.push(this._matchChr(this._mNumberSymbols.zero)); 3905 } else if(chr == '8') { 3906 var cValue = this._msText.charAt(this._textPos++); 3907 if(cValue != '' && this._ensureCharIsDigit(cValue)) { 3908 this._checkAndAddDecimalPoint(); 3909 this._buffer.push(PictureUtils.convertNumberToLocale(this.jsonModel._locale,cValue)); 3910 this._mbDigitAddedToOutput = true; 3911 } 3912 } 3913 } 3914 } 3915 3916 } 3917 3918 break; 3919 case 'E': // Exponent. 3920 this._buffer.push('E'); 3921 this._buffer.push("" + this._numberInfo.shift); 3922 break; 3923 case 'C': // CR symbol if negative and spaces if positive. 3924 this._buffer.push((this._mbNegative) ? xfalib.ut.NumPictureDesc.gsCR : xfalib.ut.NumPictureDesc.gsDSP); 3925 break; 3926 case 'c': // CR symbol if negative and nothing if positive. 3927 if (this._mbNegative){ 3928 this._buffer.push(xfalib.ut.NumPictureDesc.gsCR); 3929 } 3930 break; 3931 case 'D': // DB symbol if negative and spaces if positive. 3932 this._buffer.push((this._mbNegative) ? xfalib.ut.NumPictureDesc.gsDB : xfalib.ut.NumPictureDesc.gsDSP); 3933 break; 3934 case 'd': // DB symbol if negative and nothing if positive. 3935 if (this._mbNegative){ 3936 this._buffer.push(xfalib.ut.NumPictureDesc.gsDB); 3937 } 3938 break; 3939 case 'S': // Minus sign if negative and a space if positive. 3940 case 's': 3941 if (this._mbNegative){ 3942 this._buffer.push(this._fmtStr( this._mNumberSymbols.minus)); 3943 }else{ 3944 if('S' == chr){ 3945 this._buffer.push(this._matchChr(' ')); 3946 } 3947 } 3948 break; 3949 case 'V': // Implied decimal sign if parsing. 3950 case '.': 3951 case 'v': // Implied decimal sign. 3952 if (this._textPos < this._msText.length && this._msText.charAt(this._textPos) == '.'){ 3953 this._textPos++; //consume a '.' 3954 } 3955 if (chr == 'V' || chr == '.'){ 3956 this._mAddRadix = true; 3957 //this._buffer.push(this._fmtStr(this._mNumberSymbols.decimal, )); 3958 } 3959 this._mbRadixSeen = true; 3960 this._nScannedPatternDigit = 0; 3961 break; 3962 3963 case 0xFF0C: // Fullwidth ','. 3964 case ',': // Grouping separator. 3965 while (chrCnt-- > 0) { 3966 if (this._mbDigitAddedToOutput){ 3967 this._buffer.push(this._fmtStr( this._mNumberSymbols.grouping )); 3968 } 3969 this._mbCommaSeen = true; 3970 } 3971 break; 3972 case 0xFF04: // Fullwidth '$'. 3973 case '$': // Currency name or symbol. 3974 while (chrCnt-- > 0) { 3975 this._buffer.push(this._fmtStr( this._mCurrencySymbol
3975s.symbol )); 3976 } 3977 break; 3978 case 0xFF05: // Fullwidth '%'. 3979 case '%': // Percent symbol. 3980 while (chrCnt-- > 0) { 3981 this._buffer.push(this._fmtStr( this._mNumberSymbols.percent)); 3982 } 3983 break; 3984 case 0xFF08: // Fullwidth '('. 3985 case 0xFF09: // Fullwidth ')'. 3986 case '(': // Left parenthesis. 3987 case ')': // Right parenthesis. 3988 this._buffer.push(this._matchChr((this._mbNegative) ? chr : ' ')); 3989 break; 3990 default: 3991 } 3992 }, 3993 3994 _ensureCharIsDigit : function(cValue){ 3995 if ('0' > cValue || cValue > '9'){ 3996 throw "Nuberic Formatting: not a digit as expected " + cValue; 3997 } 3998 }, 3999 4000 4001 _fmtStr : function(str){ 4002 return str; 4003 }, 4004 4005 _matchStr : function(str){ 4006 return str; 4007 }, 4008 4009 _matchChr : function(str){ 4010 return str; 4011 }, 4012 4013 _ensureSignIsAdded : function(){ 4014 if (this._mbNegative && ! this._mbDigitAddedToOutput && ! this._pictureDesc.hasSign) { 4015 this._buffer.push(this._mNumberSymbols.minus); 4016 this._mbSignAddedToOutput = true; 4017 } 4018 }, 4019 4020 /** 4021 * 4022 * @override 4023 */ 4024 getResult : function(){ 4025 return this._buffer.join(""); 4026 }, 4027 4028 /** 4029 * 4030 * @override 4031 */ 4032 acceptPatternChar : function(chr){ 4033 return xfalib.ut.PictureUtils.inString(chr, "(%$,.)89BCDERSVZbcdrsvzt"); 4034 } 4035 4036 }); 4037 4038})(_,xfalib); 4039 4040 4041/** 4042 * @package xfalib.ut.TimeParsingVisitor 4043 * @import xfalib.ut.ParsingVisitorBase 4044 * @fileOverview The file provides parsing/formating logic on date pattern characters. 4045 * @version 0.0.1 4046 */ 4047 4048/** 4049 * @constructor 4050 * @param Object {jsonModel: {_sPicture: String, _dataString: String]} 4051 */ 4052 4053(function(_,xfalib){ 4054 var TimeParsingVisitor = xfalib.ut.TimeParsingVisitor = xfalib.ut.ParsingVisitorBase.extend({ 4055 4056 initialize: function() { 4057 this._timeInfo = new xfalib.ut.TimeInfo(); 4058 TimeParsingVisitor._super.initialize.call(this); 4059 }, 4060 4061 consumeSubPattern : function(token){ 4062 var chr = token.patChar; 4063 var chrCnt = token.len; 4064 var curPos = this._strPos; 4065 var scannedChar = chrCnt; 4066 this._assert(curPos+chrCnt <=this.jsonModel._dataString.length, "Mismatch"); 4067 4068 switch (chr) { 4069 case 'h': 4070 if(this._timeInfo.mHourOfMeriDiem != -1 || this._timeInfo.mHourOfDay != -1){ 4071 throw "ambiguity time string"; 4072 } 4073 var hourOfMeriDiem=-1; 4074 switch(chrCnt){ 4075 case 1: 4076 var parsed = this.parseIntAggressive(this.jsonModel._dataString, curPos, 2); // 1-2 digit(1-12) 4077 hourOfMeriDiem = parsed.value; 4078 scannedChar = parsed.len; 4079 break; 4080 case 2: 4081 hourOfMeriDiem = this.parseIntExact(this.jsonModel._dataString, curPos, 2); // 1-2 digit(1-12) 4082 break; 4083 } 4084 4085 this._timeInfo.mHourOfMeriDiem = hourOfMeriDiem -1; 4086 this._assert(this._timeInfo.mHourOfMeriDiem>=0 && this._timeInfo.mHourOfMeriDiem<=11, "Invalid Hour Of MeriDiem value."); 4087 break; 4088 4089 case 'k': 4090 if(this._timeInfo.mHourOfMeriDiem != -1 || this._timeInfo.mHourOfDay != -1){ 4091 throw "ambiguity time string"; 4092 } 4093 var hourOfMeriDiem=-1; 4094 switch(chrCnt){ 4095 case 1: 4096 var parsed = this.parseIntAggressive(this.jsonModel._dataString, curPos, 2); // 1-2 digit(0-11) 4097 hourOfMeriDiem = parsed.value; 4098 scannedChar = parsed.len; 4099 break; 4100 case 2: 4101 hourOfMeriDiem = this.parseIntExact(this.jsonModel._dataString, curPos, 2); // 1-2 digit(0-11) 4102 break; 4103 } 4104 4105 this._timeInfo.mHourOfMeriDiem = hourOfMeriDiem; 4106 this._assert(this._timeInfo.mHourOfMeriDiem>=0 && this._timeInfo.mHourOfMeriDiem<=11, "Invalid hour of meriDiem value."); 4107 break; 4108 4109 case 'H': 4110 if(this._timeInfo.mHourOfMeriDiem != -1 || this._timeInfo.mHourOfDay != -1){ 4111 throw "ambiguity time string"; 4112 } 4113 var hourOfDay=-1; 4114 switch(chrCnt){ 4115 case 1: 4116 var parsed = this.parseIntAggressive(this.jsonModel._dataString, curPos, 2); // 1-2 digit(0-23) 4117 hourOfDay = parsed.value; 4118 scannedChar = parsed.len; 4119 break; 4120 case 2: 4121 hourOfDay = this.parseIntExact(this.jsonModel._dataString, curPos, 2); // 1-2 digit(0-23) 4122 break; 4123 } 4124 4125 this._timeInfo.mHourOfDay = hourOfDay; 4126 this._assert(this._timeInfo.mHourOfDay>=0 && this._timeInfo.mHourOfDay<=23, "Invalid hour of day value."); 4127 break; 4128 4129 case 'K': 4130 if(this._timeInfo.mHourOfMeriDiem != -1 || this._timeInfo.mHourOfDay != -1){ 4131 throw "ambiguity time string"; 4132 } 4133 var hourOfDay=-1; 4134 switch(chrCnt){ 4135 case 1: 4136 var parsed = this.parseIntAggressive(this.jsonModel._dataString, curPos, 2); // 1-2 digit(0-23) 4137 hourOfDay = parsed.value; 4138 scannedChar = parsed.len; 4139 break; 4140 case 2: 4141 hourOfDay = this.parseIntExact(this.jsonModel._dataString, curPos, 2); // 1-2 digit(0-23) 4142 break; 4143 } 4144 4145 this._timeInfo.mHourOfDay = hourOfDay - 1; 4146 this._assert(this._timeInfo.mHourOfDay>=0 && this._timeInfo.mHourOfDay<=23, "Invalid hour of day value."); 4147 break; 4148 case 'M': 4149 if(this._timeInfo.mMinuteOfHour != -1){ 4150 throw "ambiguity time string"; 4151 } 4152 var minuteOfHour=-1; 4153 switch(chrCnt){ 4154 case 1: 4155 var parsed = this.parseIntAggressive(this.jsonModel._dataString, curPos, 2); // 1-2 digit(0-59) 4156 minuteOfHour = parsed.value; 4157 scannedChar = parsed.len; 4158 break; 4159 case 2: 4160 minuteOfHour = this.parseIntExact(this.jsonModel._dataString, curPos, 2); // 1-2 digit(0-59) 4161 break; 4162 } 4163 4164 this._timeInfo.mMinuteOfHour = minuteOfHour; 4165 this._assert(this._timeInfo.mMinuteOfHour>=0 && this._timeInfo.mMinuteOfHour<=59, "Invalid minute of hour."); 4166 break; 4167 case 'S': 4168 if(this._timeInfo.mSecondOfMinute != -1){ 4169 throw "ambiguity time string"; 4170 } 4171 var secondOfMinute=-1; 4172 switch(chrCnt){ 4173 case 1: 4174 var parsed = this.parseIntAggressive(this.jsonModel._dataString, curPos, 2); // 1-2 digit(0-59) 4175 secondOfMinute = parsed.value; 4176 scannedChar = parsed.len; 4177 break; 4178 case 2: 4179 secondOfMinute = this.parseIntExact(this.jsonModel._dataString, curPos, 2); // 1-2 digit(0-59) 4180 break; 4181 } 4182 4183 this._timeInfo.mSecondOfMinute = secondOfMinute; 4184 this._assert(this._timeInfo.mSecondOfMinute>=0 && this._timeInfo.mSecondOfMinute<=59, "Invalid second of minute."); 4185 break; 4186 case 'F': 4187 4188 this._assert(chrCnt==3, "Invalid pattern F."); 4189 this._timeInfo.mThousandthOfSecond = this.parseIntExact(this.jsonModel._dataString, curPos, 3); 4190 this._assert(this._timeInfo.mThousandthOfSecond>=0 && this._timeInfo.mThousandthOfSecond<=999, "Invalid thousand of second."); 4191 break; 4192 4193 default: throw "Unsupported pattern"; 4194 } 4195 4196 this._strPos += scannedChar; 4197 }, 4198 4199 parseIntAggressive : xfalib.ut.PictureUtils.parseIntAggressive, 4200 4201 parseIntExact : xfalib.ut.PictureUtils.parseIntExact, 4202 4203 getResult : function(){ 4204 return this._timeInfo.getISOTime(); 4205 }, 4206 4207 getTimeInfo : function(){ 4208 return this._timeInfo; 4209 }, 4210 4211 _assert : function(condition, message){ 4212 if(!condition){ 4213 throw message; 4214 } 4215 } 4216 }); 4217})(_,xfalib); 4218 4219 4220 4221/** 4222 * @package xfalib.ut.TextParsingVisitor 4223 * @import xfalib.ut.ParsingVisitorBase 4224 * 4225 * @fileOverview Parses a string according to Text Picture. 4226 * @version 0.0.1 4227 */ 4228
4229/** 4230 * @constructor 4231 * @param Object {jsonModel: {_sPicture: String, _dataString: String]} 4232 */ 4233(function(_,xfalib){ 4234 var TextParsingVisitor = xfalib.ut.TextParsingVisitor = xfalib.ut.ParsingVisitorBase.extend({ 4235 4236 initialize: function() { 4237 TextParsingVisitor._super.initialize.call(this); 4238 this._buffer = []; 4239 }, 4240 4241 consumeSubPattern : function(token){ 4242 var chr = token.patChar; 4243 var chrCnt = token.len; 4244 for(var index = 0; index < chrCnt; index++){ 4245 switch (chr) { 4246 case '9': // Numeric 4247 var cUni = this.jsonModel._dataString.charAt(this._strPos++); 4248 if(!xfalib.ut.PictureUtils.isDigit(cUni)){ 4249 throw "TextParsing: not a digit as expected"; 4250 } 4251 this._buffer.push(cUni); 4252 break; 4253 case 'A': // Alphebetic 4254 var cUni = this.jsonModel._dataString.charAt(this._strPos++); 4255 if(!xfalib.ut.PictureUtils.isLetter(cUni)){ 4256 throw "TextParsing: not a character as expected"; 4257 } 4258 this._buffer.push(cUni); 4259 break; 4260 case 'O': // Alphanumeric 4261 case '0': 4262 var cUni = this.jsonModel._dataString.charAt(this._strPos++); 4263 if(!xfalib.ut.PictureUtils.isLetterOrDigit(cUni)){ 4264 throw "TextParsing: not a character or digit as expected"; 4265 } 4266 this._buffer.push(cUni); 4267 break; 4268 case 'X': 4269 var cUni = this.jsonModel._dataString.charAt(this._strPos++); 4270 this._buffer.push(cUni); 4271 break; 4272 case 't': 4273 if(this.jsonModel._dataString.charAt(this._strPos++)=="\t"){ 4274 this._buffer.push("\t"); 4275 }else{ 4276 throw "TextParsing: not a Tab as expected"; 4277 } 4278 break; 4279 default: 4280 if(this.jsonModel._dataString.charAt(this._strPos++)== chr){ 4281 this._buffer.push(chr); 4282 }else{ 4283 throw "TextParsing: not '" + chr+"' as expected"; 4284 } 4285 } 4286 } 4287 4288 }, 4289 /** 4290 * 4291 * @override 4292 */ 4293 getResult : function(){ 4294 if(this._strPos < this.jsonModel._dataString.length) 4295 throw "TextParsing: picture clause smaller than input Text"; 4296 return this._buffer.join(""); 4297 }, 4298 /** 4299 * 4300 * @override 4301 */ 4302 acceptPatternChar : function(chr){ 4303 return xfalib.ut.PictureUtils.inString(chr, "9AO0Xt"); 4304 } 4305 4306 }); 4307})(_,xfalib); 4308 4309 4310/** 4311 * @package xfalib.ut.NumParsingVisitor 4312 * @import xfalib.ut.ParsingVisitorBase 4313 * @fileOverview Parses a string according to Text Picture. 4314 * @version 0.0.1 4315 */ 4316 4317/** 4318 * @constructor 4319 * @param Object {jsonModel: {_sPicture: String,_dataString: String}} 4320 */ 4321 4322(function(_,xfalib){ 4323 var NumParsingVisitor = xfalib.ut.NumParsingVisitor = xfalib.ut.ParsingVisitorBase.extend({ 4324 4325 initialize: function(options) { 4326 this._pictureDesc = new xfalib.ut.NumPictureDesc({jsonModel:{_sPicture:this.jsonModel._sPicture}}); 4327 this.jsonModel._sPicture = this._pictureDesc.getPicture(); 4328 this._buffer = []; 4329 this._strPos = 0; 4330 this._hasRadix = false; 4331 this._mbNegative = false; 4332 this._mbDigitSeen = false; // at least one digit has been added to output 4333 this._mbSignSeen = false; 4334 this._mBacktrack = null; 4335 this._hasPercent = false; 4336 this._mbExponSeen = false; 4337 4338 this._mNumberSymbols = xfalib.ut.PictureUtils.getLocaleObject(this.options._locale,"numberSymbols");
4339 this._mCurrencySymbols = xfalib.ut.PictureUtils.getLocaleObject(this.options._locale,"currencySymbols"); 4340 }, 4341 4342 _lookupNext : xfalib.ut.Scanner.lookupNext, 4343 4344 parse : function(){ 4345 var patPos = 0; 4346 while(true){ 4347 try{ 4348 for(var token = this._lookupNext(this.jsonModel._sPicture, patPos, this.acceptPatternChar); token != null; ){ 4349 this.consume(token); 4350 patPos = patPos + token.len; 4351 token = this._lookupNext(this.jsonModel._sPicture, patPos, this.acceptPatternChar); 4352 } 4353 }catch(e){ 4354 //mismatch, try again! 4355 if(this._mBacktrack){ 4356 patPos = this._mBacktrack.patPos; 4357 this._buffer.length = 0; 4358 this._strPos = this._mBacktrack.strPos; 4359 this._mbDigitSeen = false; 4360 this._mBacktrack = null; 4361 continue; 4362 } 4363 } 4364 break; 4365 } 4366 }, 4367 consumeSubPattern : function(token){ 4368 4369 var chr = token.patChar; 4370 var chrCnt = token.len; 4371 var fw = false; 4372 switch (chr) { 4373 case '9': 4374 case '8': 4375 case 'Z': // Digit or space if zero. 4376 case 'z':// Digit or nothing if zero. 4377 while (chrCnt-- > 0 ) { 4378 if(!this._mbDigitSeen){ 4379 var cUni = this.jsonModel._dataString.charAt(this._strPos); 4380 if(cUni == '-'){ 4381 this._mbNegative = true; 4382 cUni = this.jsonModel._dataString.charAt(++this._strPos); 4383 } 4384 if(chr== '9' || chr == '8'){ 4385 if(!xfalib.ut.PictureUtils.isDigit(cUni)){ 4386 throw "TextParsing: not a digit as expected"; 4387 } 4388 this._buffer.push(cUni); 4389 this._mbDigitSeen =true; 4390 }else if(chr =='Z'){ 4391 if(xfalib.ut.PictureUtils.isDigit(cUni)){ 4392 this._buffer.push(cUni); 4393 this._mbDigitSeen =true; 4394 }else if(cUni != ' '){ 4395 throw "TextParsing: not a digit or space as expected"; 4396 } 4397 }else { 4398 // has to be 'z', eagerly try to match a digit, if a mismatch is latterly found, backtrack 4399 if(xfalib.ut.PictureUtils.isDigit(cUni)){ 4400 this._buffer.push(cUni); 4401 this._mbDigitSeen =true; 4402 this._mBacktrack = { 4403 "patPos" : token.patPos + token.len - chrCnt, //new position from next char after 'z' 4404 "strPos" : this._strPos 4405 }; 4406 }else { 4407 throw "TextParsing: not a digit or space as expected"; 4408 } 4409 } 4410 ++this._strPos; 4411 }else{ 4412 var cUni = this.jsonModel._dataString.charAt(this._strPos); 4413 if(xfalib.ut.PictureUtils.isDigit(cUni)){ 4414 this._buffer.push(cUni); 4415 ++this._strPos; 4416 }else{ 4417 if(chr !='z'){ 4418 throw "TextParsing: not a digit as expected"; 4419 }else{ 4420 ++this._strPos; 4421 } 4422 } 4423 } 4424 } 4425 4426 break; 4427 case 'V' : 4428 case 'v' : 4429 case '.' : 4430 if(this._matchStr(this._mNumberSymbols.decimal)){ 4431 this._hasRadix = true; 4432 this._buffer.push('.'); 4433 this._mbDigitSeen =true; 4434 }else{ 4435 throw "TextParsing: not a radix as expected"; 4436 } 4437 break; 4438 case 'E': // Exponent. 4439 if(this._matchStr('E')){ 4440 this._buffer.push('E'); 4441 if(this._matchStr('+')){ 4442 // 4443 }else if(this._matchStr('-')){ 4444 this.jsonModel._buffer.push('-'); 4445 } 4446 var strLen = this.jsonModel._dataString.length; 4447 while(this._strPos < strLen && 4448 xfalib.ut.PictureUtils.isDigit(this.jsonModel._dataString.charAt(this._strPos))){ 4449 this._buffer.push(this.jsonModel._dataString.charAt(this._strPos++)); 4450 } 4451 } 4452 break; 4453 4454 case 'C': // CR symbol if negative and spaces if positive. 4455 if(this._matchStr(xfalib.ut.NumPictureDesc.gsCR)){ 4456 this._mbNegative = true; 4457 }else if(!this._matchStr(xfalib.ut.NumPictureDesc.gsDSP)){ 4458 throw "TextParsing: not a CR as expected"; 4459 } 4460 break; 4461 case 'c': // CR symbol if negative and nothing if positive. 4462 if(this._matchStr(xfalib.ut.NumPictureDesc.gsCR)){ 4463 this._mbNegative = true; 4464 } 4465 break; 4466 case 'D': // DB symbol if negative and spaces if positive. 4467 if(this._matchStr(xfalib.ut.NumPictureDesc.gsDB)){ 4468 this._mbNegative = true; 4469 }else if(!this._matchStr(xfalib.ut.NumPictureDesc.gsDSP)){ 4470 throw "TextParsing: not a CR as expected"; 4471 } 4472 break; 4473 case 'd': // DB symbol if negative and nothing if positive. 4474 if(this._matchStr(xfalib.ut.NumPictureDesc.gsDB)){ 4475 this._mbNegative = true; 4476 } 4477 break; 4478 case 'S': // Minus sign if negative and a space if positive. 4479 if(this._matchStr(this._mNumberSymbols.negative,fw)){ 4480 this._mbNegative = true; 4481 }else if(!this._matchStr(" ")){ 4482 throw "TextParsing: not a CR as expected"; 4483 } 4484 break; 4485 case 's': 4486 if(this._matchStr(this._mNumberSymbols.negative,fw)){ 4487 this._mbNegative = true; 4488 } 4489 break; 4490 case 0xFF0C: // Fullwidth ','. 4491 case ',': // Grouping separator. 4492 while (chrCnt-- > 0) { 4493 if(!this._matchStr(this._mNumberSymbols.grouping, fw)){ 4494 throw "TextParsing: not a grouping symbol as expected"; 4495 } 4496 } 4497 break; 4498 case 0xFF04: // Fullwidth '$'. 4499 case '$': // Currency name or symbol. 4500 while (chrCnt-- > 0) { 4501 if(!this._matchStr(this._mCurrencySymbol
4501s.symbol, fw)){ 4502 throw "TextParsing: not a grouping symbol as expected"; 4503 } 4504 } 4505 break; 4506 case 0xFF05: // Fullwidth '%'. 4507 case '%': // Percent symbol. 4508 while (chrCnt-- > 0) { 4509 if(!this._matchStr(this._mNumberSymbols.percent, fw)){ 4510 throw "TextParsing: not a grouping symbol as expected"; 4511 } 4512 } 4513 this._hasPercent = true; 4514 break; 4515 case 0xFF08: // Fullwidth '('. 4516 case 0xFF09: // Fullwidth ')'. 4517 case '(': // Left parenthesis. 4518 case ')': // Right parenthesis. 4519 if(this._matchStr(chr,fw)){ 4520 this._mbNegative = true; 4521 }else if(!this._matchStr(" ")){ 4522 throw "TextParsing: not parentesis as expected"; 4523 } 4524 break; 4525 case 't': // tab. 4526 while (chrCnt-- > 0) this._matchStr('\t',fw); 4527 } 4528 }, 4529 getResult : function(){ 4530 var stringNum = this._buffer.join(""); 4531 if(this._hasPercent) { 4532 var buf = new Array(); 4533 stringNum = Number(stringNum).toString(); 4534 var dot = stringNum.indexOf('.'); 4535 4536 var pos = dot-2; 4537 if(pos ==0) buf.push("0"); 4538 else if(pos ==-1) buf.push("0.0"); 4539 else if(pos ==-3) pos = stringNum.length - 2; 4540 for(var index=0;index < stringNum.length; index++){ 4541 if(index == pos){ 4542 buf.push("."); 4543 } 4544 if(index != dot){ 4545 buf.push(stringNum.charAt(index)); 4546 } 4547 } 4548 stringNum = buf.join(""); 4549 } 4550 var number = Number(stringNum); 4551 if(this._mbNegative) number = -number; 4552 return number.toString(); 4553 }, 4554 4555 _matchStr : function(target){ 4556 if(xfalib.ut.PictureUtils.matchString(this.jsonModel._dataString, this._strPos, target)){ 4557 this._strPos+= target.length; 4558 return true; 4559 }else{ 4560 return false; 4561 } 4562 }, 4563 4564 /** 4565 * 4566 * @override 4567 */ 4568 acceptPatternChar : function(chr){ 4569 return xfalib.ut.PictureUtils.inString(chr, "(%$,.)89BCDERSVZbcdrsvzt"); 4570 } 4571 }); 4572})(_,xfalib); 4573/** 4574 * @package xfalib.ut.DateParsingVisitor 4575 * @import xfalib.ut.ParsingVisitorBase 4576 * @fileOverview The file provides parsing/formating logic on date pattern characters. 4577 * @version 0.0.1 4578 */ 4579 4580/** 4581 * @constructor 4582 * @param Object {jsonModel: {_sPicture: String, _dataString: String]} 4583 */ 4584 4585(function(_,xfalib) { 4586 var DateParsingVisitor = xfalib.ut.DateParsingVisitor = xfalib.ut.ParsingVisitorBase.extend({ 4587 4588 initialize: function() { 4589 this._dateInfo = new xfalib.ut.DateInfo({isParsingCall : true}); 4590 this._dayOfMonth = this._monthOfYear = this._yearOfEra = null; // used to validate date once all sub patterns are consumed 4591 DateParsingVisitor._super.initialize.call(this); 4592 }, 4593 4594 consumeSubPattern : function(token){ 4595 var chr = token.patChar; 4596 var chrCnt = token.len; 4597 var curPos = this._strPos; 4598 var scannedChar = chrCnt; 4599 4600 //TODO: need to remove this assert. 4601 this._assert(curPos+chrCnt <=this.jsonModel._dataString.length, "Mismatch"); 4602 4603 switch (chr) { 4604 case 'D': 4605 switch(chrCnt){ 4606 case 1: 4607 var parsed = xfalib.ut.PictureUtils.parseIntAggressive(this.jsonModel._dataString, curPos, 2); // 1-2 digit(1-31) 4608 this._dayOfMonth = parsed.value; 4609 scannedChar = parsed.len; 4610 break; 4611 case 2: 4612 this._dayOfMonth = xfalib.ut.PictureUtils.parseIntExact(this.jsonModel._dataString, curPos, 2); // 1-2 digit(1-31) 4613 break; 4614 } 4615 this._assert(this._dayOfMonth <= 31 && this._dayOfMonth >0, "Invalid date string1"); 4616 break; 4617 case 'J': 4618 4619 //this._mDayOfYear; 4620 break; 4621 case 'M': 4622 var symbol = ""; 4623 switch(chrCnt){ 4624 case 1: 4625 var parsed = xfalib.ut.PictureUtils.parseIntAggressive(this.jsonModel._dataString, curPos, 2); // 1-2 digit(1-12) 4626 this._monthOfYear = parsed.value; 4627 scannedChar = parsed.len; 4628 break; 4629 case 2: 4630 this._monthOfYear = xfalib.ut.PictureUtils.parseIntExact(this.jsonModel._dataString, curPos, 2); // 2 digit(01-12) 4631 break; 4632 case 3: 4633 symbol = "calendarSymbols.abbrmonthNames"; 4634 break; 4635 case 4: 4636 symbol = "calendarSymbols.monthNames" 4637 break; 4638 4639 } 4640 if(symbol) { 4641 var hashObj = xfalib.ut.PictureUtils.getHashOfLocaleObject(this.jsonModel._locale,symbol), 4642 str = this.jsonModel._dataString.toLowerCase(), 4643 hash = 0, 4644 curStr = "" 4645 scannedChar = 0; 4646 while(curPos+scannedChar < str.length) { 4647 hash += (scannedChar+1)*str.charCodeAt(curPos+scannedChar) 4648 curStr+= str.charAt(curPos+scannedChar); 4649 scannedChar++; 4650 if(hashObj[hash] && hashObj[hash].indexOf(curStr) > -1 ) break; 4651 } 4652 var monthNames = _.map(xfalib.ut.PictureUtils.getLocaleObject(this.jsonModel._locale, symbol), function (str) { 4653 return str.toLowerCase(); 4654 }); 4655 this._monthOfYear = monthNames.indexOf(curStr) + 1; // months are from 1 to 12 4656 } 4657 //TODO: remove this assert 4658 this._assert(this._monthOfYear <= 12 && this._monthOfYear >0, "Invalid date string2"); 4659 break; 4660 case 'E': 4661 var symbol = "" 4662 switch(chrCnt) { 4663 case 1: 4664 scannedChar = 1; 4665 break; 4666 case 3: 4667 symbol = "calendarSymbols.abbrdayNames"; 4668 break; 4669 case 4: 4670 symbol = "calendarSymbols.dayNames" 4671 break; 4672 default: 4673 throw "unsupported Picture Clause "; 4674 } 4675 if(symbol) { 4676 var hashObj = xfalib.ut.PictureUtils.getHashOfLocaleObject(this.jsonModel._locale,symbol); 4677 scannedChar = 0; 4678 var str = this.jsonModel._dataString.toLowerCase(); 4679 var hash = 0; 4680 var curStr = ""; 4681 while(curPos+scannedChar < str.length) { 4682 hash += (scannedChar+1)*str.charCodeAt(curPos+scannedChar) 4683 curStr+= str.charAt(curPos+scannedChar); 4684 scannedChar++; 4685 if(hashObj[hash] && hashObj[hash].indexOf(curStr) > -1) break; 4686 } 4687 } 4688 break; 4689 4690 case 'e': 4691 break; 4692 case 'G': 4693 break; 4694 case 'Y': 4695 4696 switch(chrCnt){ 4697 case 2: 4698 this._yearOfEra = xfalib.ut.PictureUtils.parseIntExact(this.jsonModel._dataString, curPos, 2); // 2 digit(00-99) 4699 this._yearOfEra+=2000; 4700 if(this._yearOfEra >= 2029){ 4701 this._yearOfEra -=100; 4702 } 4703 break; 4704 case 4: 4705 this._yearOfEra = xfalib.ut.PictureUtils.parseIntExact(this.jsonModel._dataString, curPos, 4); // 2 digit(0000-9999) 4706 break; 4707 } 4708 4709 this._assert(this._yearOfEra <= 9999 && this._yearOfEra >=0, "Invalid date string3"); 4710 break; 4711 case 'w': 4712 break; 4713 case 'W': 4714 break; 4715 default: throw "Unsupported pattern"; 4716 } 4717 4718 if(this._yearOfEra && this._monthOfYear && this._dayOfMonth){ 4719 this._dateInfo.validate(this._yearOfEra, this._monthOfYear, this._dayOfMonth); 4720 } 4721 4722 this._strPos += scannedChar; 4723 }, 4724 4725 getDate : function(){ 4726 return this._dateInfo.date; 4727 }, 4728 4729 getResult: function(){ 4730 if (this._strPos < this.jsonModel._dataString.length) { 4731 throw "DateParsing: picture clause smaller than input Date"; 4732 } 4733 return this._dateInfo.getISODate(); 4734 }, 4735 4736 _assert : function(condition, message){ 4737 if(!condition){ 4738 throw message; 4739 } 4740 } 4741 }); 4742})(_,xfalib); 4743 4744/************************************************************************* 4745 * 4746 * ADOBE CONFIDENTIAL 4747 * ___________________ 4748 * 4749 * Copyright 2013 Adobe Systems Incorporated 4750 * All Rights Reserved. 4751 *
4752 * NOTICE: All information contained herein is, and remains 4753 * the property of Adobe Systems Incorporated and its suppliers, 4754 * if any. The intellectual and technical concepts contained 4755 * herein are proprietary to Adobe Systems Incorporated and its 4756 * suppliers and are protected by trade secret or copyright law. 4757 * Dissemination of this information or reproduction of this material 4758 * is strictly forbidden unless prior written permission is obtained 4759 * from Adobe Systems Incorporated. 4760 **************************************************************************/ 4761 4762 4763 4764(function(_, $, xfalib){ 4765 4766 var LocalizationUtil = xfalib.ut.LocalizationUtil = xfalib.ut.Class.extend({ 4767 4768 getLocalizedMessage: function(category, message, snippets){ 4769 var resolvedMessage = message; 4770 if(snippets){ 4771 //resolve message with snippet 4772 resolvedMessage = resolvedMessage.replace(/{(\d+)}/g, function(match, number) { 4773 return typeof snippets[number] != 'undefined' 4774 ? snippets[number] 4775 : match 4776 ; 4777 }); 4778 } 4779 var text = ""; 4780 if (category) { 4781 text += " [" + category + "]"; 4782 } 4783 text += " " + resolvedMessage + "\r\n" ; 4784 return text; 4785 } 4786 4787 }); 4788})(_, $, xfalib); 4789 4790 4791/************************************************************************* 4792 * ADOBE CONFIDENTIAL 4793 * ___________________ 4794 * 4795 * Copyright 2013 Adobe Systems Incorporated 4796 * All Rights Reserved. 4797 *
4798 * NOTICE: All information contained herein is, and remains 4799 * the property of Adobe Systems Incorporated and its suppliers, 4800 * if any. The intellectual and technical concepts contained 4801 * herein are proprietary to Adobe Systems Incorporated and its 4802 * suppliers and are protected by all applicable intellectual property 4803 * laws, including trade secret and copyright laws. 4804 * Dissemination of this information or reproduction of this material 4805 * is strictly forbidden unless prior written permission is obtained 4806 * from Adobe Systems Incorporated. 4807 **************************************************************************/ 4808 4809 4810 4811 4812(function(_, $, xfalib){ 4813 xfalib.view.util.TextMetrics = { 4814 xfaUtil : xfalib.ut.XfaUtil.prototype, 4815 ERROR_MARGIN : 1, 4816 $measureEl : null, 4817 initialize : function(divEl){ 4818 if(!divEl){ 4819 var $div = $("<div></div>"); 4820 $div.attr("id", "textMetrics"); 4821 var divStyles = {}; 4822 divStyles.left = -1000; 4823 divStyles.top = -1000; 4824 divStyles.position = "absolute"; 4825 divStyles.visibility = "hidden"; 4826 this.xfaUtil.$css($div.get(0), divStyles); 4827 this.$measureEl = $div; 4828 $("body").append(this.$measureEl); 4829 }else{ 4830 this.$measureEl = divEl; 4831 } 4832 }, 4833 4834 measureExtent : function(text, options){ 4835 text = text + " "; 4836 if(!this.$measureEl){ 4837 this.initialize(); 4838 } 4839 options = options || {}; 4840 var textStyles = {}; 4841 var $refEl = $(options.refEl || "<div></div>") ; 4842 var refEl = $refEl.get(0); 4843 textStyles.fontSize = $refEl.css("fontSize") || options["font-size"] || options["fontSize"]; 4844 textStyles.fontStyle = $refEl.css("fontStyle") || options["font-style"] || options["fontStyle"]; 4845 textStyles.fontWeight = $refEl.css("fontWeight") || options["font-weight"] || options["fontWeight"]; 4846 textStyles.fontFamily = $refEl.css("fontFamily") || options["font-family"] || options["fontFamily"]; 4847 textStyles.lineHeight = refEl.style.lineHeight || options["line-height"] || options["lineHeight"]; 4848 textStyles.letterSpacing = $refEl.css("letterSpacing") || options["letter-spacing"] || options["letterSpacing"]; 4849 textStyles.whiteSpace = $refEl.css("whiteSpace") || options["white-space"] || options["whiteSpace"] || "pre-wrap"; 4850 if( $.browser.mozilla && $refEl.is("textarea")) // for Bug #3621180 4851 textStyles.whiteSpace = "pre-wrap"; 4852 textStyles.wordBreak = $refEl.css("wordBreak") || options["word-break"] || options["wordBreak"] || "break-all"; 4853 textStyles.wordWrap = $refEl.css("wordWrap") || options["word-wrap"] || options["wordWrap"] || "break-word"; 4854 textStyles.width = this._elWidth(refEl, options); 4855 textStyles.height = this._elHeight(refEl, options); 4856 textStyles.minWidth = this._elMinWidth(refEl, options); 4857 textStyles.minHeight = this._elMinHeight(refEl, options); 4858 textStyles.maxWidth = this._elMaxWidth(refEl, options); 4859 textStyles.maxHeight = this._elMaxHeight(refEl, options); 4860 this.xfaUtil.$css(this.$measureEl.get(0), textStyles); 4861 // for text fields/areas and draw requiring rich text support 4862 if(options.contentType === "text/html"){ 4863 // retaining for future use . If we use the above property for other rich text 4864 if(options.skipXSSProtection) { 4865 this.$measureEl.html(text); 4866 } else { 4867 this.$measureEl.html(xfalib.ut.XfaUtil.prototype.encodeScriptableTags(text)); 4868 } 4869 }else { 4870 text = text.replace(/\n\r/g,"\n").replace(/\r\n/g,"\n").replace(/\r/g, "\n"); 4871 this.$measureEl.text(text); 4872 } 4873 var measuredWidth = this.$measureEl.width(); 4874 var measuredHeight = this.$measureEl.height(); 4875 4876 if(measuredWidth == Math.ceil(options["width"]) || measuredWidth == Math.floor(options["width"])){ 4877 measuredWidth = options["width"]; 4878 } 4879 /* 4880 FORMS-11363 : fix for height calculation of table cell 4881 Enable this toggle for old behaviour (if any regression comes) 4882 */ 4883 else if ((window.FD && window.FD.isToggleEnabled("FT_FORMS-11363")) && (options["maxWidth"] > measuredWidth || (measuredWidth > options["minWidth"] > 0 && (options["maxWidth"] || -1) < 0))) { 4884 //complicated, please simplify if below hurts you: Add error margin if there is scope of further extension of extent 4885 measuredWidth = measuredWidth + 1; 4886 } else if (options["maxWidth"] > measuredWidth || (measuredWidth > options["minWidth"] > 0 && (options["maxWidth"] || -1) < 0)) { 4887 //complicated, please simplify if below hurts you: Add error margin if there is scope of further extension of extent 4888 measuredWidth = measuredWidth; 4889 } 4890 4891 if(measuredHeight == Math.ceil(options["height"]) || measuredHeight == Math.floor(options["height"])){ 4892 measuredHeight = options["height"]; 4893 } 4894 else if( $refEl.is("textarea") && (options["maxHeight"] > measuredHeight || (measuredHeight > options["minHeight"] > 0 && (options["maxHeight"] || -1) < 0))){ 4895 measuredHeight = measuredHeight +1; 4896 } 4897 this.$measureEl.empty(); 4898 return {width : measuredWidth, height : measuredHeight}; 4899 }, 4900 4901 _elWidth : function(refEl, options){ 4902 if(options["minWidth"] && options["minWidth"] > -1) 4903 return "auto"; 4904 else if(options["maxWidth"] && options["maxWidth"] > -1) 4905 return "auto"; 4906 else 4907 return options["width"] || "auto"; 4908 }, 4909 4910 _elHeight : function(refEl, options){ 4911 // TODO: check for calculations here for floating field and other cases. 4912 if(options["contentType"] === "text/html") 4913 return "auto"; 4914 if(options.isDraw) { // for handling the case of draw having floating fields 4915 return "auto"; 4916 } 4917 if(!$(refEl).is("textarea")) 4918 return options["height"] || "auto"; 4919 if(options["minHeight"] && options["minHeight"] > -1) 4920 return "auto"; 4921 else if(options["maxHeight"] && options["maxHeight"] > -1) 4922 return "auto"; 4923 else 4924 return options["height"] || "auto"; 4925 }, 4926 4927 _elMinWidth : function(refEl, options){ 4928 if(options["minWidth"] && options["minWidth"] > -1) 4929 return options["minWidth"]; 4930 else 4931 return "0"; //default css value 4932 }, 4933 4934 _elMinHeight : function(refEl, options){ 4935 if(options["minHeight"] && options["minHeight"] > -1) 4936 return options["minHeight"]; 4937 else 4938 return "0"; //default css value 4939 }, 4940 4941 _elMaxWidth : function(refEl, options){ 4942 if(options["maxWidth"] && options["maxWidth"] > -1) 4943 return options["maxWidth"]; 4944 else 4945 return "none"; //default css value 4946 }, 4947 4948 _elMaxHeight : function(refEl, options){ 4949 if(options["maxHeight"] && options["maxHeight"] > -1) 4950 return options["maxHeight"]; 4951 else 4952 return "none"; //default css value 4953 }, 4954 4955 _destroy : function() { 4956 $("#textMetrics").remove(); 4957 this.$measureEl = null; 4958 } 4959 } 4960})(_, $, xfalib); 4961(function($, _) { 4962 4963 $.alertBox = { 4964 4965 verticalOffset: -75, 4966 horizontalOffset: 0, 4967 repositionOnResize: true, 4968 overlayOpacity: 0.01,
4969 overlayColor: '#FFF', 4970 draggable: false, 4971 dialogClass: null, 4972 imageDirectory: "..", 4973 images: ["A_Warning_Lg_N.png", "A_Alert2_Lg_N.png", "C_QuestionBubble_Xl_N.png", "A_InfoBlue_32x32_N.png"], 4974 4975 alert: function(img, message, title, callback) { 4976 this._show(img, title, message, null, 'OK', function(result) { 4977 if( callback ) callback(result); 4978 }); 4979 }, 4980 4981 okCancel: function(img, message, title, callback) { 4982 this._show(img, title, message, null, 'OK-Cancel', function(result) { 4983 if( callback ) callback(result); 4984 }); 4985 }, 4986 yesNo: function(img, message, title, callback) { 4987 this._show(img, title, message, null, 'Yes-No', function(result) { 4988 if( callback ) callback(result); 4989 }); 4990 }, 4991 4992 yesNoCancel: function(img, message, title, callback) { 4993 this._show(img, title, message, null, 'Yes-No-Cancel', function(result) { 4994 if( callback ) callback(result); 4995 }); 4996 }, 4997 4998 _createBox: function(msgBox_message,buttons,callback) { 4999 var that = this; 5000 $("#"+msgBox_message).after("<div id='msgBox_panel'>"); 5001 _.each(buttons.split("-"),function(val,i) { 5002 var dispval = xfalib.locale.Strings[val.toLowerCase()] ? xfalib.locale.Strings[val.toLowerCase()] : val; // keys in loaclization files are in lower-case 5003 $("#msgBox_panel").append("<input type='button' value='"+dispval+"' id = 'msgBox_"+val+"' class=msgbox_input />"); 5004 $("#msgBox_"+val).click( function() { 5005 that._hide(); 5006 callback(!i); 5007 }); 5008 if(!i) $("msgBox_"+val).focus(); 5009 }); 5010 }, 5011 5012 _show: function(img, title, msg, value, type, callback) { 5013 5014 this._hide(); 5015 this._overlay('show'); 5016 5017 $("BODY").append( 5018 '<div id="msgBox_container">' + 5019 '<h1 id="msgBox_title"></h1>' + 5020 '<div id="msgBox_content">' + 5021 '<div id="msgBox_message"></div>' + 5022 '</div>' + 5023 '</div>'); 5024 5025 if( this.dialogClass ) $("#msgBox_container").addClass($.alertBox.dialogClass); 5026 5027 $("#msgBox_container").css({ 5028 position: 'absolute', 5029 zIndex: 99999, 5030 padding: 0, 5031 margin: 0 5032 }); 5033 5034 $("#msgBox_title").text(title); 5035 $("#msgBox_content").addClass("msgBoxType"+img);//css("background-image","url("+this.imageDirectory+ this.images[img]+")"); 5036 msg = xfalib.ut.XfaUtil.prototype.encodeScriptableTags(msg.replace(/\n/g, '<br />')); 5037 $("#msgBox_message").html(msg); 5038 5039 $("#msgBox_container").css({ 5040 minWidth: $("#msgBox_container").outerWidth(), 5041 maxWidth: $("#msgBox_container").outerWidth() 5042 }); 5043 5044 this._reposition(); 5045 this._maintainPosition(true); 5046 5047 this._createBox("msgBox_message",type,callback); 5048 5049 //TODO: Make keyboard input work 5050 /*$("#msgBox_ok").keypress( function(e) { 5051 if( e.keyCode == 13 || e.keyCode == 27 ) $("#msgBox_ok").trigger('click'); 5052 }); 5053 $("#msgBox_cancel").keypress( function(e) { 5054 if( e.keyCode == 13 ) $("#msgBox_ok").trigger('click'); 5055 if( e.keyCode == 27 ) $("#msgBox_cancel").trigger('click'); 5056 }); 5057 $("#msgBox_yes, #msgBox_no").keypress( function(e) { 5058 if( e.keyCode == 13 ) $("#msgBox_yes").trigger('click'); 5059 if( e.keyCode == 27 ) $("#msgBox_no").trigger('click'); 5060 });*/ 5061 5062 }, 5063 5064 _hide: function() { 5065 $("#msgBox_container").remove(); 5066 this._overlay('hide'); 5067 this._maintainPosition(false); 5068 }, 5069 5070 _overlay: function(status) { 5071 switch( status ) { 5072 case 'show': 5073 this._overlay('hide'); 5074 $("BODY").append('<div id="msgBox_overlay"></div>'); 5075 $("#msgBox_overlay").css({ 5076 position: 'absolute', 5077 zIndex: 99998, 5078 top: '0px', 5079 left: '0px', 5080 width: '100%', 5081 height: $(document).height(), 5082 background: this.overlayColor, 5083 opacity: this.overlayOpacity 5084 }); 5085 break; 5086 case 'hide': 5087 $("#msgBox_overlay").remove(); 5088 break; 5089 } 5090 }, 5091 5092 _reposition: function() { 5093 var windowHeight = $(window).height() / xfalib.ut.XfaUtil.prototype.formScaleFactor, 5094 windowWidth = $(window).width() / xfalib.ut.XfaUtil.prototype.formScaleFactor, 5095 windowScrollTop = $(window).scrollTop() / xfalib.ut.XfaUtil.prototype.formScaleFactor, 5096 windowScrollLeft = $(window).scrollLeft() / xfalib.ut.XfaUtil.prototype.formScaleFactor, 5097 top = ((windowHeight / 2) - ($("#msgBox_container").outerHeight() / 2)) + this.verticalOffset, 5098 left = ((windowWidth / 2) - ($("#msgBox_container").outerWidth() / 2)) + this.horizontalOffset; 5099 if( top < 0 ) top = 0; 5100 if( left < 0 ) left = 0; 5101 5102 // IE6 fix 5103 if( $.browser.msie && parseInt($.browser.version) <= 6 ) top = top + windowScrollTop; 5104 5105 $("#msgBox_container").css({ 5106 top: top + windowScrollTop + 'px', 5107 left: left + windowScrollLeft + 'px' 5108 }); 5109 $("#msgBox_overlay").height( $(document).height() ); 5110 }, 5111 5112 _maintainPosition: function(status) { 5113 if( this.repositionOnResize ) { 5114 switch(status) { 5115 case true: 5116 $(window).on('resize', this._reposition); 5117 break; 5118 case false: 5119 $(window).off('resize', this._reposition); 5120 break; 5121 } 5122 } 5123 } 5124 5125 }; 5126})($, window._);/************************************************************************* 5127 * ADOBE CONFIDENTIAL 5128 * ___________________ 5129 * 5130 * Copyright 2016 Adobe Systems Incorporated 5131 * All Rights Reserved. 5132 *
5133 * NOTICE: All information contained herein is, and remains 5134 * the property of Adobe Systems Incorporated and its suppliers, 5135 * if any. The intellectual and technical concepts contained 5136 * herein are proprietary to Adobe Systems Incorporated and its 5137 * suppliers and are protected by all applicable intellectual property 5138 * laws, including trade secret and copyright laws. 5139 * Dissemination of this information or reproduction of this material 5140 * is strictly forbidden unless prior written permission is obtained 5141 * from Adobe Systems Incorporated. 5142 **************************************************************************/ 5143 5144 5145(function(_, $, xfalib){ 5146 xfalib.view.util.HtmlUtil = { 5147 /* 5148 * Most of the time it returns undefined while accessing an undefined attribute of a dom element. 5149 * But some browsers can throw specific exceptions while accessing an attribute which is un-supported for a specific case. 5150 * This API is to make this behaviour consistent across browsers and return undefined for un-supported attributes. 5151 * */ 5152 getHTMLSupportedAttr : function($domElement, attr){ 5153 try{ 5154 return $domElement[attr]; 5155 } 5156 catch (err){ 5157 return undefined; 5158 } 5159 }, 5160 5161 /** 5162 * Checks if the attribute is supported for the given HTML element. 5163 * This is primarily useful to support HTML5 features in widgets 5164 * @param element name of HTML element 5165 * @param attribute attribute to check on the element 5166 * @returns {boolean} 5167 */ 5168 elementSupportsAttribute : function (element, attribute) { 5169 var test = document.createElement(element); 5170 if (attribute in test) { 5171 $(test).remove(); 5172 test = null; 5173 return true; 5174 } else { 5175 $(test).remove(); 5176 test = null; 5177 return false; 5178 } 5179 } 5180 } 5181})(_, $, xfalib); 5182/************************************************************************* 5183* 5184* ADOBE CONFIDENTIAL 5185* ___________________ 5186* 5187* Copyright 2013 Adobe Systems Incorporated 5188* All Rights Reserved. 5189*
5190* NOTICE: All information contained herein is, and remains 5191* the property of Adobe Systems Incorporated and its suppliers, 5192* if any. The intellectual and technical concepts contained 5193* herein are proprietary to Adobe Systems Incorporated and its 5194* suppliers and are protected by trade secret or copyright law. 5195* Dissemination of this information or reproduction of this material 5196* is strictly forbidden unless prior written permission is obtained 5197* from Adobe Systems Incorporated. 5198**************************************************************************/ 5199 5200 5201 5202(function(_, $, xfalib){ 5203 xfalib.view.util.Styles = { 5204 xfaUtil : xfalib.ut.XfaUtil.prototype, 5205 _deviceResolution : 144.0, //DPI 5206 _in2mmFactor : 25.4, 5207 _pdfResolution : 72.0 , 5208 getStyleForEdge : function (edgeElement, str, cssStyleObj){ 5209 var style = { "raised" : "outset" , 5210 "dashDot" : "dashed" , 5211 "dashDotDot" : "dashed" , 5212 "dashed" : "dashed" , 5213 "dotted" : "dotted" , 5214 "embossed" : "groove" , 5215 "etched" : "inset" , 5216 "lowered" : "ridge", 5217 "solid" : "solid"}; 5218 if(edgeElement && edgeElement.jsonModel.presence != "hidden" && edgeElement.jsonModel.presence !="invisible") { 5219 cssStyleObj['border'+str+'width'] = this._subPixelValue(this._convertToPx(edgeElement.getAttribute('thickness'))) || "1px"; 5220 if(edgeElement.getElement("color") && edgeElement.getElement("color").getAttribute("value") !="") { 5221 var color = edgeElement.getElement("color").getAttribute("value"); 5222 color = "rgb(" + color + ")"; 5223 cssStyleObj['border'+str+'color'] = color ; 5224 } 5225 else { 5226 cssStyleObj['border'+str+'color'] = "rgb(0,0,0)" ; 5227 } 5228 cssStyleObj['border'+str+'style'] = style[edgeElement.getAttribute('stroke')] || "solid" ; 5229 } else { 5230 cssStyleObj['border'+str+'width'] = "0px"; 5231 return 1; 5232 } 5233 5234 }, 5235 5236 getStyleForBorder : function (border) { 5237 if(border) { 5238 var edge = border.getElement('edge', 0, true), 5239 edge1 = border.getElement('edge', 1, true), 5240 edge2 = border.getElement('edge', 2, true), 5241 edge3 = border.getElement('edge', 3, true); 5242 if(edge || edge1 || edge2 || edge3) { 5243 var cssStyleObj = {} ; 5244 var e0 = this.getStyleForEdge(edge, "-top-",cssStyleObj); 5245 var e1 = this.getStyleForEdge(edge1 || edge,"-right-",cssStyleObj); 5246 var e2 = this.getStyleForEdge(edge2|| edge,"-bottom-",cssStyleObj); 5247 var e3 = this.getStyleForEdge(edge3 || edge,"-left-",cssStyleObj); 5248 if(e0 !=1|| e1 !=1|| e2 !=1|| e3!=1) 5249 return cssStyleObj ; 5250 } 5251 } 5252 return null; 5253 }, 5254 5255 _convertToPx : function(size){ 5256 if(!size) 5257 return 0; 5258 size = "" + size; 5259 var pxSize = size; 5260 if(size.indexOf("in") >=0){ 5261 pxSize = this._mm2px(parseFloat(size) * this._in2mmFactor); 5262 } 5263 else if(size.indexOf("mm") >=0){ 5264 pxSize = this._mm2px(size); 5265 } 5266 else if(size.indexOf("cm") >=0){ 5267 pxSize = this._mm2px(parseFloat(size) * 10); 5268 } 5269 else if(size.indexOf("pt") >=0){ 5270 pxSize = parseFloat(size) * (this._deviceResolution/this._pdfResolution); 5271 } 5272 else if(size.indexOf("px") >=0){ 5273 pxSize = parseFloat(size); 5274 } 5275 return pxSize; 5276 }, 5277 5278 _mm2px : function(mmSize){ 5279 var mmSizeNum = 0; 5280 if(_.isNumber(mmSize)) 5281 mmSizeNum = mmSize; 5282 else{ 5283 mmSizeNum = parseFloat(mmSize) 5284 } 5285 var mm2in = 1/25.4 ; 5286 var pxSize = mmSizeNum*mm2in*this._deviceResolution; 5287 return pxSize; 5288 }, 5289 5290 _subPixelValue : function(value){ 5291 if(value > 0.01) 5292 return Math.max(value, 1.0); 5293 else 5294 return value; 5295 } 5296 } 5297})(_, $, xfalib); 5298/************************************************************************* 5299 * ADOBE CONFIDENTIAL 5300 * ___________________ 5301 * 5302 * Copyright 2017 Adobe Systems Incorporated 5303 * All Rights Reserved. 5304 *
5305 * NOTICE: All information contained herein is, and remains 5306 * the property of Adobe Systems Incorporated and its suppliers, 5307 * if any. The intellectual and technical concepts contained 5308 * herein are proprietary to Adobe Systems Incorporated and its 5309 * suppliers and are protected by all applicable intellectual property 5310 * laws, including trade secret and copyright laws. 5311 * Dissemination of this information or reproduction of this material 5312 * is strictly forbidden unless prior written permission is obtained 5313 * from Adobe Systems Incorporated. 5314 **************************************************************************/ 5315 5316 5317 5318 5319(function(_, $, xfalib){ 5320 xfalib.view.util.traversalManager = { 5321 5322 // compute tabIndex for the provided page 5323 _computTabIndex : function (pageView) { 5324 var pageNum = pageView._pageNumber(), 5325 tabIndex = this._tabIndexBasedOnRange(pageNum); 5326 this.geographicalOrder = []; 5327 this._createGeographicalOrder(pageView); 5328 this._createFinalTraversalOrder(tabIndex); // assign tab index using traversal element and geographicalOrder 5329 // keep tracks of the last field on the page to get tab index so that handler to render next page can be added on getting focus through tabbing 5330 this._lastFieldTabbed = null; 5331 }, 5332 5333 _tabIndexBasedOnRange : function (pageNum) { 5334 var behaviorConfig = new xfalib.ut.Version(formBridge.userConfig["behaviorConfig"]), 5335 tabIndexConfig = (behaviorConfig.isOn('mfRangeTabIndex')|| behaviorConfig.isOn('rangeTabIndex')), 5336 /*assuming single page can not have more than 1000 fields.[index -> 0 to 999] 5337 this is also configurable by passing the maximum number of fields allowable in the page 5338 in the config parameter */ 5339 maxFieldInPageForTabIndex = tabIndexConfig? parseInt(tabIndexConfig):1000; 5340 5341 return pageNum * maxFieldInPageForTabIndex; 5342 }, 5343 5344 // to create geographical order array which will be containing all the views in the geographical order 5345 _createGeographicalOrder : function (currentView) { 5346 var sortedChildViewWrapper = this._sortViewGeographically(currentView.childViews); 5347 _.each(sortedChildViewWrapper, function (wrapper) { 5348 var currentView = wrapper.view, 5349 instanceCheckMap = this._getMapOfInstanceCheck(currentView), 5350 isViewEligibleForTabbing = this._isViewEligibleForTabbing(currentView); 5351 // If the child view is fieldView, drawView, exclGroupView or subformView then we will push these views in this.geographicalOrder array, 5352 // as we need their traverse object during final traversing 5353 if (((instanceCheckMap.isField && !instanceCheckMap.isChildOfExclGroup) || instanceCheckMap.isSubform || instanceCheckMap.isDraw 5354 || instanceCheckMap.isExclGroup) && isViewEligibleForTabbing) { 5355 this.geographicalOrder.push({ 5356 view : currentView, 5357 visited : false 5358 }); 5359 } 5360 if (instanceCheckMap.isContainer && isViewEligibleForTabbing) { 5361 this._createGeographicalOrder(currentView); 5362 } 5363 }, this); 5364 }, 5365 5366 // to sort provided views in geographical order 5367 _sortViewGeographically : function (views) { 5368 var viewsWrapper = []; // wrapper of view and their geographical reference 5369 _.each(views, function(view) { 5370 var position = view.$el.offset(), 5371 paddedX = xfalib.ut.XfaUtil.prototype.padString(parseInt(position.left), 5, '0'), 5372 marginTop = view._marginTop(), 5373 paddedY = position.top - parseFloat(marginTop), 5374 positionalReference = parseInt("" + parseInt(paddedY) + paddedX); 5375 viewsWrapper.push({ 5376 positionalReference: positionalReference, 5377 view: view 5378 }); 5379 }); 5380 return _.sortBy(viewsWrapper, function(viewWrapper){ return viewWrapper.positionalReference; }); 5381 }, 5382 5383 // Walk through views in geographical order and assign tab index honouring traversal object if present 5384 _createFinalTraversalOrder : function (tabIndex) { 5385 var geographicalOrderLength = this.geographicalOrder.length, 5386 currentWrappedObj = null, 5387 index = -1, 5388 traversalIndex = 0, // index of the element to be traversed 5389 viewTraversed = 0; // counter of view traversed 5390 5391 while (1) { 5392 if (traversalIndex >= geographicalOrderLength) { 5393 traversalIndex = 0; 5394 } 5395 currentWrappedObj = this.geographicalOrder[traversalIndex]; 5396 5397 if (!currentWrappedObj || currentWrappedObj.visited) { // if the wrapped object does not exist or it has been visited move to the next one 5398 traversalIndex++; 5399 } else { 5400 currentWrappedObj.visited = true; 5401 viewTraversed++; 5402 var currentView = currentWrappedObj.view, 5403 instanceCheckMap = this._getMapOfInstanceCheck(currentView), 5404 currentModel = currentView.model, 5405 nextView = null, 5406 nextViewSom = null; 5407 5408 // get the first traversal of the subform if traversal object is present, else move to the next geographical element 5409 // next of the subform will be taken care when we will be finding the next view to be traversed, 5410 // as we will be checking if the ancestor contain next before moving to geographically next view 5411 if (instanceCheckMap.isSubform) { 5412 if (currentModel && currentModel.getTraversalObject()) { 5413 // get the first element to be traversed and update traversalIndex 5414 nextViewSom = currentModel.getNextTraversalSom(xfalib.template.Constants.firstTraversal); 5415 index = this._findViewInGeographicalOrderArray(nextViewSom); 5416 traversalIndex = index != -1 ? index : traversalIndex + 1; 5417 } else { 5418 traversalIndex++; 5419 } 5420 // get the next traversal for the field/draw if traversal object is present, else move to the next geographical element 5421 // update the tabindex for the field 5422 } else if (instanceCheckMap.isField || instanceCheckMap.isDraw) { 5423 if (instanceCheckMap.isField) { 5424 currentView.updateTabIndex(tabIndex); 5425 this._lastFieldTabbed = currentView; 5426 tabIndex++; 5427 } 5428 if (currentModel && currentModel.getTraversalObject()) { 5429 //get next element to be traversed and update traversalIndex 5430 nextViewSom = currentModel.getNextTraversalSom(xfalib.template.Constants.nextTraversal); 5431 index = this._findViewInGeographicalOrderArray(nextViewSom); 5432 traversalIndex = index != -1 ? index : traversalIndex + 1; 5433 } else { 5434 traversalIndex = this._findNextViewToBeTraversed(traversalIndex); 5435 } 5436 // if traversal object present get the next element to be traversed, if first is also present then update tab index of the first element 5437 // else look for the traversal element in the children 5438 } else if (instanceCheckMap.isExclGroup) { 5439 if (currentModel && currentModel.getTraversalObject()) { 5440 // get next element to be traversed and update traversalIndex 5441 nextViewSom = currentModel.getNextTraversalSom(xfalib.template.Constants.nextTraversal); 5442 index = this._findViewInGeographicalOrderArray(nextViewSom); 5443 traversalIndex = index != -1 ? index : traversalIndex + 1; 5444 // if first is also present assign tab index to that referred child else assign same tab index to all child 5445 nextViewSom = currentModel.getNextTraversalSom(xfalib.template.Constants.firstTraversal); 5446 tabIndex = this._updateTabIndexOfExclGroupChildren(currentView, tabIndex, nextViewSom); 5447 } else { 5448 tabIndex = this._updateTabIndexOfExclGroupChildren(currentView, tabIndex); 5449 traversalIndex = this._findTraversalInExclGroupChildren(currentView, traversalIndex); 5450 } 5451 } else { 5452 traversalIndex++; 5453 } 5454 } 5455 5456 // if all the view are traversed, we have assigned tab index to all the views 5457 if (viewTraversed >= geographicalOrderLength) { 5458 this._renderNextPageFuture(); 5459 break; 5460 } 5461 } 5462 }, 5463 5464 // Check if the nextView is a sibling of the currentView (shares the same parent) 5465 // if it is not a sibling, check if the parent has a NEXT traversal. 5466 // if so get the node traversed to else recurse to see if nextView is a sibling of our parent 5467 // return -1 if the provided next node is sibling of current node or if no ancestor contain next traversal 5468 // else return index of the next traversal object of parent 5469 _getParentNextTraversal : function (currentView, nextView, traversalIndex) { 5470 var parentView = currentView.parentView, 5471 parentModel = parentView.model, 5472 nextViewParentModel = nextView.parentView.model, 5473 traversalObj = null, 5474 nextIndex = -1; 5475 5476 if (parentModel && nextViewParentModel && parentModel.somExpression != nextViewParentModel.somExpression) { 5477 if(parentView && parentView instanceof xfalib.view.SubformView) { 5478 if (parentModel.getTraversalObject()) { 5479 var nextViewSom = parentModel.getNextTraversalSom(xfalib.template.Constants.nextTraversal); 5480 nextIndex = this._findViewInGeographicalOrderArray(nextViewSom); 5481 if (nextIndex != -1 && !this.geographicalOrder[
5481nextIndex].visited) { 5482 return nextIndex; 5483 } else { 5484 return traversalIndex++; 5485 } 5486 } else { 5487 this._getParentNextTraversal(parentView, nextView, traversalIndex); 5488 } 5489 } else { // parentView is not a subform so skip up a level and re-check sibling 5490 this._getParentNextTraversal(parentView, nextView, traversalIndex); 5491 } 5492 } else { 5493 return -1; //provided currentView and nextView are sibling 5494 } 5495 return traversalIndex++; 5496 }, 5497 5498 // return the index of the view having provided somExpression in the geographicalOrder array 5499 _findViewInGeographicalOrderArray : function (somExpression) { 5500 return _.findIndex(this.geographicalOrder, function (viewWrapper) { 5501 var currentViewModel = viewWrapper.view.model; 5502 return (currentViewModel && currentViewModel.somExpression == somExpression); 5503 }); 5504 }, 5505 5506 // find the next element to be traversed based on the provided traversalIndex 5507 _findNextViewToBeTraversed : function (traversalIndex) { 5508 var currentView = this.geographicalOrder[traversalIndex].view, 5509 index = this._getNextUnvisited(traversalIndex), //get next unvisited based on geographical location 5510 nextView = null, 5511 nextIndex = -1; 5512 5513 if (index != -1) { 5514 nextView = this.geographicalOrder[index].view; 5515 //check if both are sibling and if not find the next of the parent and update traversalIndex 5516 nextIndex = this._getParentNextTraversal(currentView, nextView, traversalIndex); 5517 return nextIndex != -1 ? nextIndex : index; 5518 } 5519 return traversalIndex++; 5520 }, 5521 5522 // return the next unvisited node based on geographical location 5523 // starting from the traversalIndex and wraps around to check all the views 5524 _getNextUnvisited : function (traversalIndex) { 5525 var geographicalOrderLength = this.geographicalOrder.length, 5526 index = 0, 5527 actualIndex = 0; 5528 while(index < geographicalOrderLength) { 5529 actualIndex = (index + traversalIndex) % geographicalOrderLength; 5530 if(!this.geographicalOrder[actualIndex].visited) { 5531 return actualIndex; 5532 } 5533 index++; 5534 } 5535 return -1; 5536 }, 5537 5538 // assign same tab index to all the child of exclude group 5539 // if exclude group contain first traverse object, then the child being referred as first should have less tabindex 5540 // compared to other child 5541 _updateTabIndexOfExclGroupChildren : function (exclGroupView, tabIndex, firstChildSom) { 5542 _.each(exclGroupView.childViews, function(child){ 5543 if (this._isViewEligibleForTabbing(child)) { 5544 if(firstChildSom && child.model.somExpression == firstChildSom) { 5545 tabIndex++; 5546 child.updateTabIndex(tabIndex-1); 5547 this._lastFieldTabbed = child; 5548 } else { 5549 child.updateTabIndex(tabIndex); 5550 } 5551 } 5552 }, this); 5553 if (!firstChildSom) { 5554 this._lastFieldTabbed = exclGroupView.childViews[0]; 5555 } 5556 return ++tabIndex; 5557 }, 5558 5559 // find if any child contains next pointer and update traversal index 5560 // start with the last in the geographical order of the children and find child which have next traversal 5561 _findTraversalInExclGroupChildren : function (exclGroupView, traversalIndex) { 5562 var sortedChildView = this._sortViewGeographically(exclGroupView.childViews), 5563 tempObj = null, 5564 childView = null, 5565 childModel = null, 5566 traversalObj = null, 5567 nextViewSom = null, 5568 index = -1; 5569 5570 sortedChildView.reverse(); 5571 tempObj = _.find(sortedChildView, function(child) { 5572 childView = child.view; 5573 childModel = childView.model; 5574 if(childModel && (traversalObj = childModel.getTraversalObject())) { 5575 return traversalObj.length > 0; 5576 } 5577 }); 5578 5579 if (tempObj) { 5580 nextViewSom = tempObj.model.getNextTraversalSom(xfalib.template.Constants.nextTraversal); 5581 index = this._findViewInGeographicalOrderArray(nextViewSom); 5582 traversalIndex = index != -1 ? index : traversalIndex + 1; 5583 } else { // else get next unvisited based on geographical location 5584 traversalIndex = this._findNextViewToBeTraversed(traversalIndex); 5585 } 5586 return traversalIndex; 5587 }, 5588 5589 // check if the view is initialized and visible 5590 _isViewEligibleForTabbing : function (view) { 5591 if (view._initialized && view.$el.css("visibility") != "hidden") { 5592 return true; 5593 } 5594 return false;
5595 }, 5596 5597 // return map of whethter provided view is instance of the various views 5598 _getMapOfInstanceCheck : function (view) { 5599 var instanceCheckMap = {}; 5600 instanceCheckMap.isSubform = view instanceof xfalib.view.SubformView; 5601 instanceCheckMap.isField = view instanceof xfalib.view.FieldView; 5602 instanceCheckMap.isDraw = view instanceof xfalib.view.XfaDrawView; 5603 instanceCheckMap.isExclGroup = view instanceof xfalib.view.ExclGroupView; 5604 instanceCheckMap.isChildOfExclGroup = view.parentView instanceof xfalib.view.ExclGroupView; 5605 instanceCheckMap.isContainer = view instanceof xfalib.view.ContainerView; 5606 5607 return instanceCheckMap; 5608 }, 5609 5610 // add event handler for rendering next page on tabbing on last field of the page 5611 _renderNextPageFuture : function () { 5612 if (this._lastFieldTabbed) { 5613 this._lastFieldTabbed.$el.one('focusin.traversalManager', function() { 5614 var pagingManager = window.formBridge ? window.formBridge.pagingManager() : null; 5615 $(window).on( "keyup.traversalManager", function (e) { 5616 var code = (e.keyCode ? e.keyCode : e.which); 5617 if (code == 9 && pagingManager && pagingManager.hasMorePages()) { 5618 pagingManager.renderNextPage(); 5619 $(window).off("keyup.traversalManager"); 5620 } 5621 }); 5622 }); 5623 } 5624 }, 5625 _destroy : function() { 5626 this.geographicalOrder = null; 5627 } 5628 } 5629})(_, $, xfalib); 5630/************************************************************************* 5631* 5632* ADOBE CONFIDENTIAL 5633* ___________________ 5634* 5635* Copyright 2013 Adobe Systems Incorporated 5636* All Rights Reserved. 5637*
5638* NOTICE: All information contained herein is, and remains 5639* the property of Adobe Systems Incorporated and its suppliers, 5640* if any. The intellectual and technical concepts contained 5641* herein are proprietary to Adobe Systems Incorporated and its 5642* suppliers and are protected by trade secret or copyright law. 5643* Dissemination of this information or reproduction of this material 5644* is strictly forbidden unless prior written permission is obtained 5645* from Adobe Systems Incorporated. 5646**************************************************************************/ 5647 5648 5649 5650(function(_, $, xfalib){ 5651 5652 var ErrorManager = xfalib.view.util.ErrorManager = xfalib.ut.Class.extend({ 5653 5654 options: { 5655 warningMessageVisible:false, 5656 errorMessageVisible: false 5657 }, 5658 5659 initialize: function () { 5660 $(window).on("destroy.xfa", function () { 5661 $("#error-msg").hide(); 5662 $("#warning-msg").hide(); 5663 }); 5664 }, 5665 5666 onFieldEnter: function (jqWidget) { 5667 var element = jqWidget.element; 5668 if (jqWidget.option("errorMessage")|| jqWidget.option("warningMessage")) { 5669 var pos = $(element).offset(), 5670 styles = {}; 5671 styles.left = (pos.left * (1 / xfalib.ut.XfaUtil.prototype.formScaleFactor) + element.width() + 5) + "px"; 5672 styles.top = pos.top * (1 / xfalib.ut.XfaUtil.prototype.formScaleFactor) + "px"; 5673 if (jqWidget.option("errorMessage")) { 5674 jqWidget.$css($("#error-msg").get(0), styles); 5675 $("#error-msg").text(jqWidget.option("errorMessage")).show(); 5676 jqWidget.option("errorMessageVisible",true); 5677 } 5678 else if (jqWidget.option("warningMessage")) { 5679 jqWidget.$css($("#warning-msg").get(0), styles); 5680 $("#warning-msg").text(jqWidget.option("warningMessage")).show(); 5681 jqWidget.option("warningMessageVisible",true); 5682 } 5683 } 5684 }, 5685 5686 onFieldExit: function (jqWidget) { 5687 if (jqWidget.option("errorMessageVisible")) { 5688 $("#error-msg").hide(); 5689 jqWidget.option("errorMessageVisible",false); 5690 } else if (jqWidget.option("warningMessageVisible")) { 5691 $("#warning-msg").hide(); 5692 jqWidget.option("warningMessageVisible",false); 5693 } 5694 }, 5695 5696 markError: function (jqWidget, msg, type) { 5697 // assigning role="alert" so that JAWS reads-out the validation message 5698 if (type != "warning") { 5699 if ($("#error-msg").length < 1) 5700 $("<div id='error-msg' role='alert'></div>").appendTo('body'); 5701 jqWidget.option("errorMessage",msg); 5702 jqWidget.element.addClass("dataInvalid"); 5703 } else { 5704 if ($("#warning-msg").length < 1) 5705 $("<div id='warning-msg' role='alert'></div>").appendTo('body'); 5706 jqWidget.option("warningMessage",msg); 5707 } 5708 5709 }, 5710 5711 clearError: function (jqWidget) { 5712 this.onFieldExit(jqWidget); 5713 jqWidget.element.removeClass("dataInvalid"); 5714 jqWidget.option("errorMessage",null); 5715 jqWidget.option("warningMessage",null); 5716 } 5717 }); 5718})(_, $, xfalib); 5719(function(_,$, xfalib) { 5720 var xfaUtil = xfalib.ut.XfaUtil.prototype, 5721 BUFFER_SPC = 20; 5722 5723 /* template for the clear Button */ 5724 var clearButtonTemplate = '<div class="dp-clear">' + 5725 '<a></a>' + 5726 '</div>'; 5727 5728 /* template for the calendar 5729 * header contains the navigation icons (left and right arrows) 5730 * and the current caption (which can be date, year or month) 5731 * 5732 * monthview displays the grid for showing the dates for a particular 5733 * month 5734 * 5735 * yearview displays all the months of that year 5736 * 5737 * yearsetview displays a grid of 16 years. This can be configured 5738 * through the option: yearsPerView 5739 * 5740 */ 5741 var calendarTemplate = '<div class="dp-header">' + 5742 '<div class="dp-leftnav"></div>' + 5743 '<div class="dp-caption"></div>' + 5744 '<div class="dp-rightnav"></div>' + 5745 '</div>' + 5746 '<div role="table" class="view dp-monthview"></div>' + 5747 '<div role="table" class="view dp-yearview"></div>' + 5748 '<div role="table" class="view dp-yearsetview"></div>'; 5749 5750 /*template for the timer: not implemented yet */ 5751 var watchTemplate = '<div class="dp-header">' + 5752 '<div class="dp-leftnav"></div>' + 5753 '<div class="dp-caption"></div>' + 5754 '<div class="dp-rightnav"></div>' + 5755 '</div>' + 5756 '<div class="view dp-monthview"></div>' + 5757 '<div class="view dp-yearview"></div>' + 5758 '<div class="view dp-yearsetview"></div>'; 5759 5760 /** default configuration options 5761 * 5762 * container: the html element where the datepicker template will be added 5763 *
5764 * yearsPerView: number of years to show in the yearset view 5765 * 5766 * width: with of the widget 5767 * 5768 * viewHeight: Height of the month,year and yearset view. This doesn't include 5769 * the height of the header 5770 * 5771 * locale: locale information for the locale in which to show the datepicker which comprises of 5772 * days: day names to display in the monthview 5773 * months: month names to display in the yearview 5774 * zero: string representation of zero in the locale. Numbers will be 5775 * displayed in that locale only 5776 * clearText: Text to display for the reset button 5777 * name: name of the locale 5778 * 5779 * format: input format for the datepicker (not implemented) 5780 * 5781 * pickerType: type of the datetimepicker (date, datetime and time) 5782 * 5783 * positioning: element around which datepicker will be displayed. if null then it 5784 * will be displayed around the input element 5785 * 5786 * showCalendarIcon: to show the Calendar on the right of the text field or not 5787 */ 5788 5789 var defaults = { 5790 container: "body", 5791 yearsPerView: 16, 5792 width: 340, 5793 viewHeight: 248, 5794 locale: { 5795 days:["S","M","T","W","T","F","S"], 5796 months: ["January","February","March","April","May","June","July","August","September","October","November","December"], 5797 zero: "0", 5798 clearText: "Clear", 5799 name:"en_US" 5800 }, 5801 format:"YYYY-MM-DD", 5802 pickerType:"date", 5803 positioning: null, 5804 showCalendarIcon: false 5805 }, 5806 dates = [31,28,31,30,31,30,31,31,30,31,30,31], 5807 /* 5808 * Actions to perform when clicked on the datepicker buttons 5809 * for different views 5810 * caption: view to show when clicked on caption 5811 * (Year/YearSet/Month/null) null means don't change the view 5812 * li: view to show when clicked on date, month or year element 5813 * upDown: add(up key) or subtract(down key) current date (for monthview), 5814 * month(Year View) or year(YearSetView) with the number provided 5815 * key: identifies the key that needs to be changed for that view 5816 */ 5817 viewAction = { 5818 Month: { 5819 caption: 'Year', 5820 li: null, 5821 key:"day", 5822 upDown:7 5823 }, 5824 Year: { 5825 caption: "Yearset", 5826 li: "Month", 5827 key:"month", 5828 upDown:3 5829 }, 5830 Yearset: { 5831 caption: null, 5832 li: "Year", 5833 key:"year", 5834 upDown:4 5835 } 5836 }, 5837 headerClass = "header", 5838 5839 DateTimePicker = function() { 5840 this.initialized = false; 5841 } 5842 5843 $.extend(DateTimePicker.prototype, { 5844 /* 5845 * create the widget using the provided options 5846 */ 5847 create: function(options) { 5848 var $dp,self = this,html="",prevNavWidth,nextNavWidth; 5849 if (window.FD && window.FD.isToggleEnabled("FT_FORMS-13599")) { 5850 defaults.width = 433; 5851 } 5852 this.options = $.extend({},defaults,options); 5853 // prevent memory leak since options.positioning holds reference to HTML DOM 5854 this.options.positioning = null; 5855 // If width of date-picker exceeds screen width then it'll take up the entire screen width in AF 5856 if(window.guideBridge && this.options.width > window.innerWidth && window.innerWidth > 0) { 5857 this.options.width=window.innerWidth - BUFFER_SPC; // buffer 5858 } 5859 if(this.options.pickerType.match(/date/)) { 5860 html += calendarTemplate; 5861 } 5862 5863 if(this.options.pickerType.match(/time/)) { 5864 html += watchTemplate; 5865 } 5866 5867 html += clearButtonTemplate; 5868 5869 $.extend(this, { 5870 selectedDay:0, 5871 selectedMonth:0, 5872 selectedYear:0, 5873 currentDay:0, 5874 currentMonth:0, 5875 currentYear:0, 5876 touchSupported : xfalib.ut.TouchUtil.TOUCH_ENABLED, 5877 _visible:false, 5878 _defaultView:"Month", 5879 _keysEnabled:false, 5880 focusedOnDatepickerItem : false, 5881 keyboardAccessibility : true, 5882 $dp:$("<div></div>").addClass("datetimepicker") 5883 .width(this.options.width) 5884 .append(html) 5885 .addClass("datePickerTarget") 5886 .appendTo(this.options.container) 5887 .toggleClass("datetimepicker-notouch",this.touchSupported), 5888 $month: $(".dp-monthview",this.$dp).height(this.options.viewHeight),
5889 $year: $(".dp-yearview",this.$dp).height(this.options.viewHeight), 5890 $yearset : $(".dp-yearsetview",this.$dp).height(this.options.viewHeight) 5891 }); 5892 this.actualWidth = Math.floor(this.$dp.width()); 5893 this.$clear = $('.dp-clear a', this.$dp).on("click", $.proxy(this._clearDate, this)); 5894 this.$prevNavWidthBtn = $(".dp-leftnav", this.$dp).on("click", 5895 function(evnt) { 5896 self._adjustDate(-1, self.view, false) 5897 }); 5898 this.$nextNavWidthBtn = $(".dp-rightnav", this.$dp).on("click", 5899 function(evnt) { 5900 self._adjustDate(1, self.view, false) 5901 }); 5902 prevNavWidth = this.$prevNavWidthBtn.outerWidth(true); 5903 nextNavWidth = this.$nextNavWidthBtn.outerWidth(true); 5904 this.$caption = $(".dp-caption", this.$dp).width(this.actualWidth - prevNavWidth - nextNavWidth) 5905 .on("click", 5906 function(evnt) { 5907 if(!self.$caption.hasClass("disabled")) { 5908 self._layout(viewAction[self.view].caption); 5909 } 5910 }); 5911 if (this.keyboardAccessibility) { 5912 _.each([this.$prevNavWidthBtn, this.$caption, this.$nextNavWidthBtn, this.$clear], function (elem, i) { 5913 elem.attr("tabIndex", i + 1); 5914 }); 5915 } 5916 // attach click event on entire datePicker popup 5917 $(this.$dp).on("click", 5918 function(evnt) { 5919 //focus only if the device doesn't support touch 5920 // input otherwise on screen keyboard will popup 5921 if(!self.touchSupported) 5922 self._curInstance.$field.focus(); 5923 }); 5924 5925 $(window).on("touchstart.datetimepicker mousedown.datetimepicker",self._checkWindowClicked); 5926 this._curInstance = null; 5927 }, 5928 5929 /* 5930 * attaches the date picker to the field. This is a one time operation 5931 * First creates a configuration object and stores it in the field data attributes 5932 * then attaches event handlers on click, focus (to show the picker) and blur (to hide) events 5933 */ 5934 _attachField: function($field,options, value) { 5935 var inst = this._newInst($field,options, value), 5936 self = this, 5937 activateField = function(evnt) { 5938 var data = xfaUtil.$data(evnt.target,"datetimepicker"); 5939 if(data.access == false) { 5940 return; 5941 } 5942 if(!self._curInstance) 5943 self._activateField(evnt); 5944 5945 if(self.options.showCalendarIcon) { 5946 if (evnt.type === self.getEvent()) { 5947 if (self._iconClicked) { 5948 self._iconClicked = false; 5949 if (self._visible) { 5950 self._hide(); // hide the calendar popup if visible when calendar icon is clicked 5951 self._curInstance.$field.focus(); // bring back focus in field 5952 } else { 5953 self._show(); //// show the calendar popup if not visible when calendar icon is clicked 5954 } 5955 } 5956 } 5957 } else { 5958 /*show the popup only if 5959 1. click/touch event 5960 2. focus event in case of non-touch devices and focus is not done using script 5961 */ 5962 if (evnt.type === self.getEvent() || (evnt.type === "focus" && !self.touchSupported && !self.scriptFocus)) { 5963 self._show(evnt); 5964 } 5965 } 5966 5967 self._clickedWindow = true; 5968 self.scriptFocus = false;
5969 }, 5970 deactivateField = function(evnt) { 5971 //deactivate only if clicked outside window 5972 // on touch devices only keyboard or calander should be active at once, touching keyboard should deactivate calendar 5973 if ((self._clickedWindow && !self.focusedOnDatepickerItem) && (self.options.showCalendarIcon || !self.touchSupported)) { 5974 self._hide(); 5975 self._deactivateField(); 5976 self._clickedWindow = true; 5977 } 5978 }; 5979 5980 xfaUtil.$data($field[0],"datetimepicker",inst); 5981 5982 $field.on(this.getEvent(),activateField) 5983 .focus(activateField) 5984 .blur(deactivateField); 5985 if(options.showCalendarIcon) { 5986 var calendarIcon = $("<div></div>") 5987 .addClass("datepicker-calendar-icon") 5988 .css({ 5989 "width": options.iconWidth + "px", 5990 "height": options.iconHeight + "px" 5991 }); 5992 calendarIcon.insertAfter($field); 5993 5994 if (this.keyboardAccessibility) { 5995 calendarIcon.attr("tabindex", 0); 5996 } 5997 5998 calendarIcon.on(this.getEvent(), function (evnt) { 5999 self._iconClicked = true; 6000 $field.click(); 6001 }) 6002 .on("keydown", function (event) { 6003 if (event.keyCode === 32 || event.keyCode === 13) { 6004 $field.click(); 6005 } 6006 }); 6007 } 6008 }, 6009 6010 _newInst: function($f,options, value) { 6011 return { 6012 $field:$f, 6013 locale: options.locale, 6014 positioning: options.positioning || $f, 6015 access:options.access, 6016 selectedDate:options.value, 6017 editValue :options.editValue, 6018 minValidDate : options.minValidDate, 6019 maxValidDate : options.maxValidDate, 6020 exclMinDate : options.exclMinDate, 6021 exclMaxDate : options.exclMaxDate 6022 } 6023 }, 6024 6025 /* 6026 * To check where the click happened, if happened outside the datepicker 6027 * then hide the picker. This is checked whether any ancestor of clicked target 6028 * has a class datePickerTarget. This class is added to the attached element as well 6029 */ 6030 _checkWindowClicked : function(evnt) { 6031 var self = adobeDateTimePicker; 6032 if(self._curInstance) { 6033 // datepickerTarget class depicts that the component is a part of the Date Field 6034 // and on click of that class, we should not hide the datepicker or fire exit events. 6035 if(!$(evnt.target).closest(".datePickerTarget").length) { 6036 //non-touch devices do not deactivate on blur. Hence needs to be done here 6037 if(self.touchSupported) { 6038 self._hide() 6039 //clicking outside a field doesn't blur the field in IPad. Doing it by script 6040 self._curInstance.$field[0].blur() 6041 self._deactivateField() 6042 } else{ 6043 self._clickedWindow = true; 6044 // set focusedOnDatepickerItem to false, it hides the datepicker see method deactivateField. 6045 self.focusedOnDatepickerItem = false; 6046 self._curInstance.$field.blur() 6047 } 6048 } 6049 else { 6050 self._clickedWindow = false; 6051 } 6052 } 6053 }, 6054 6055 /* 6056 * handling of key strokes. All the key strokes prevent the default browser action 6057 * unless specified otherwise 6058 * tab: set focus on calendar icon when dateinput field is active, navigates through date picker buttons when datepicker is open, 6059 * otherwise perform default browser action 6060 * escape: hides the datepicker 6061 * down arrow key: navigate the picker downwards by the number specified in actionView.upDown of the current View 6062 * up arrow key: navigate the picker upwards by the number specified in actionView.upDown of the current View 6063 * left arrow key: navigate the picker one unit of that view backward 6064 * right arrow key: navigate the picker one unit of that view forward 6065 * shift + up: perform the action that happens on clicking the caption (as specified in actionView.caption) 6066 * shift + left: perform the action that happens on clicking the left navigation button 6067 * shift + right: perform the action that happens on clicking the right navigation button 6068 * space/enter: triggers the click event for the current focused element from datepicker/ opens datepicker when calendar icon is focused. 6069 */ 6070 _hotKeys: function(evnt) { 6071 var handled = false, date; 6072 switch(evnt.keyCode) { 6073 case 9: //tab 6074 // CQ-4239352 : Setting clickedWindow property to true on tabbing so that deactivateField logic gets executed 6075 // When clicking on "x" on input field in in IE and when selecting the content and releasing the mouse select outside the field 6076 // the click event is not trigerred on the field and hence activateField is not executed, so clickedWindow remains as fal
6076se 6077 adobeDateTimePicker._clickedWindow = true; 6078 handled = false; 6079 break; 6080 case 27://escape 6081 if(this._visible) { 6082 adobeDateTimePicker._hide(); 6083 this._curInstance.$field.focus(); 6084 handled = true; 6085 } 6086 break; 6087 case 32: //space 6088 case 13: // enter 6089 if($(evnt.target).hasClass("datepicker-calendar-icon")){ 6090 if(!this._visible) { 6091 this._show(); 6092 return; 6093 } 6094 this.$focusedDate.addClass("dp-focus"); 6095 } 6096 break; 6097 case 40: //down arrow key 6098 if(!this._visible) { 6099 this._show(); 6100 return; 6101 } 6102 this.$focusedDate.addClass("dp-focus"); 6103 break; 6104 } 6105 6106 if(adobeDateTimePicker._visible && this._keysEnabled) { 6107 var v = viewAction[this.view].key, 6108 updown=viewAction[this.view].upDown; 6109 switch(evnt.keyCode) { 6110 case 9: // tab 6111 if (evnt.shiftKey) { 6112 if ($(evnt.target).hasClass("dp-leftnav") || $(evnt.target).hasClass("dp-focus")) { 6113 this._hide(); 6114 this._curInstance.$field.focus(); 6115 handled = true; 6116 } else { 6117 handled = false; 6118 } 6119 } else { 6120 var buttonTabindex = $(evnt.target).attr("tabindex"); 6121 if (buttonTabindex === '0') { 6122 if (evnt.target.tagName.toLocaleLowerCase() === "input") { 6123 this._hide(); 6124 handled = false; 6125 } else { 6126 this.$prevNavWidthBtn.focus(); 6127 handled = true; 6128 } 6129 } else if (buttonTabindex === '4') { 6130 this._hide(); 6131 this._curInstance.$field.focus(); 6132 handled = true; 6133 } else { 6134 handled = false; 6135 } 6136 } 6137 break; 6138 case 32: //select on space 6139 case 13: // select on enter 6140 this.hotKeyPressed = true; 6141 this.focusedOnDatepickerItem = false; 6142 if (!this.focusedOnDatepickerItem) { 6143 $(evnt.target, this.$dp).triggerHandler("click"); 6144 } else { 6145 if (this.$focusedDate) { 6146 this.$focusedDate.trigger("click"); 6147 } 6148 } 6149 this.hotKeyPressed = false; 6150 handled = true; 6151 break; 6152 case 37: //left arrow key 6153 if (evnt.shiftKey) { 6154 $(".dp-leftnav", this.$dp).triggerHandler("click"); 6155 } else { 6156 this._adjustDate(-1, v, true); 6157 } 6158 handled = true; 6159 break; 6160 case 38: //up arrow key 6161 if (evnt.shiftKey) { 6162 this.$caption.triggerHandler("click"); 6163 } else { 6164 this._adjustDate(-updown, v, true); 6165 } 6166 handled = true; 6167 break; 6168 case 39: //right arrow key
6169 if (evnt.shiftKey) { 6170 $(".dp-rightnav", this.$dp).triggerHandler("click"); 6171 } else { 6172 this._adjustDate(+1, v, true); 6173 } 6174 handled = true; 6175 break; 6176 case 40: //down arrow key 6177 this._adjustDate(updown, v, true); 6178 handled = true; 6179 break; 6180 default: 6181 } 6182 } 6183 if(handled) { 6184 evnt.preventDefault(); 6185 } 6186 }, 6187 6188 /* 6189 * show the datepicker. 6190 */ 6191 _show: function() { 6192 if(this._curInstance.access == false) 6193 return; 6194 this.options.locale = this._curInstance.locale; 6195 if(!this._visible) { 6196 var self = this, 6197 date = new Date(), 6198 val, 6199 maxDateInfo, 6200 minDateInfo, 6201 validDate; 6202 //Bug#3607735: 6203 // Date constructor in ipad 5.1 doesn't support "YYYY-MM-DD", hence parsing the date on our own 6204 validDate = xfalib.ut.DateInfo.ParseIsoString(this._curInstance.selectedDate); 6205 date = (validDate != null)? validDate.getDate(): new Date(); 6206 this.selectedDay = this.currentDay = date.getDate(); 6207 this.selectedMonth = this.currentMonth = date.getMonth(); 6208 this.selectedYear = this.currentYear = date.getFullYear(); 6209 maxDateInfo = this.options.maxValidDate ? xfalib.ut.DateInfo.ParseIsoString(this._curInstance.maxValidDate) : null; 6210 this.maxValidDate = maxDateInfo ? maxDateInfo.getDate() : null; 6211 minDateInfo = this.options.minValidDate ? xfalib.ut.DateInfo.ParseIsoString(this._curInstance.minValidDate) : null; 6212 this.minValidDate = minDateInfo ? minDateInfo.getDate() : null; 6213 this.exclMaxDate = this._curInstance.exclMaxDate; 6214 this.exclMinDate = this._curInstance.exclMinDate; 6215 $('.dp-clear a',this.$dp).text(this.options.locale.clearText); 6216 this._layout('Month'); 6217 this._position(); 6218 this.$dp.show(); 6219 // if li element of datepicker is focused then set focusedOnDatepickerItem to true, it manages the visibility of the datepicker. 6220 this.focusedOnDatepickerItem = false; 6221 this._visible = true; 6222 if (this.options.showCalendarIcon) { 6223 this._curInstance.$field.attr('readonly', true); // when the datepicker is active, deactivate the field 6224 } 6225 } 6226 6227 // Disabling the focus on ipad due to a bug where value of 6228 // date picker is not being set 6229 // Removing this code will only hamper one use case 6230 // where on ipad if you click on the calander then 6231 // the field becomes read only so 6232 // there is no indication where the current focus is 6233 // And if you remove this foucs code all together 6234 // then what happens is that on desktop MF in iframe the exit event 6235 // is not getting called hence calander getting remained open even 6236 // when you click somewhere on window or focus into some other field 6237 if (this.options.showCalendarIcon && !this.touchSupported) { 6238 if(this.$focusedDate && this.$focusedDate.length > 0) { 6239 this.$focusedDate.focus(); // shift focus on current date or selected date. 6240 } else { 6241 this._curInstance.$field.focus(); // field loses focus after being marked readonly, causing blur event not to be fired later 6242 } 6243 } 6244 }, 6245 6246 /* 6247 * position the datepicker around the positioning element 6248 * provided in the options 6249 */ 6250 _position: function() { 6251 var $elem = this._curInstance.positioning, 6252 windowScrollX = window.scrollX/ xfalib.ut.XfaUtil.prototype.formScaleFactor,
6253 windowScrollY = window.scrollY/ xfalib.ut.XfaUtil.prototype.formScaleFactor, 6254 windowInnerHeight = window.innerHeight/ xfalib.ut.XfaUtil.prototype.formScaleFactor, 6255 windowInnerWidth = window.innerWidth/ xfalib.ut.XfaUtil.prototype.formScaleFactor, 6256 height = $elem.outerHeight(true), 6257 width = $elem.outerWidth(true), 6258 top = $elem.offset().top / xfalib.ut.XfaUtil.prototype.formScaleFactor + height, 6259 left = $elem.offset().left / xfalib.ut.XfaUtil.prototype.formScaleFactor, 6260 styles = {"top": (top+"px"), "left": (left+"px")}, 6261 diffBottom = top + this.$dp.outerHeight(true) - windowInnerHeight - windowScrollY, 6262 newLeft, 6263 newTop; 6264 if(diffBottom > 0) { 6265 //can't appear at the bottom 6266 //check top 6267 newTop = top - height - this.$dp.outerHeight(true) - BUFFER_SPC; 6268 if(newTop < windowScrollY) { 6269 //can't appear at the top as well ... the datePicker pop up overlaps the date field 6270 newTop = top - diffBottom; 6271 // Fix for BUG #3626974 6272 if(xfaUtil.isWebkit() && !this.options.showCalendarIcon) { 6273 this._curInstance.$field.trigger("onoverlap.datetimepicker"); 6274 } 6275 } 6276 styles.top = newTop + "px"; 6277 } 6278 if(left + this.$dp.outerWidth(true) > windowScrollX + windowInnerWidth ) { 6279 //align with the right edge 6280 newLeft = windowScrollX + windowInnerWidth - this.$dp.outerWidth(true) - BUFFER_SPC; 6281 styles.left = newLeft + "px"; 6282 } 6283 xfaUtil.$css(this.$dp.get(0), styles); 6284 return this; 6285 }, 6286 6287 /* 6288 * layout the nextView. if nextView is null return 6289 * 6290 */ 6291 _layout: function(nextView) { 6292 if(nextView == null) { 6293 this._hide(); 6294 } else { 6295 if(this.view) 6296 this['$'+this.view.toLowerCase()].hide(); 6297 this.view = nextView; 6298 this.$caption.toggleClass("disabled",!viewAction[this.view].caption); 6299 this['$'+this.view.toLowerCase()].show(); 6300 this["show"+this.view](); 6301 } 6302 return this; 6303 }, 6304 6305 /* 6306 * show the month view 6307 */ 6308 showMonth: function() { 6309 var self = this, 6310 curDate = new Date(this.currentYear, this.currentMonth), 6311 maxDay = this._maxDate(this.currentMonth), 6312 prevMaxDay = this._maxDate((this.currentMonth + 11)%12), 6313 day1 = new Date(this.currentYear,this.currentMonth,1).getDay(), 6314 data,display; 6315 6316 this.tabulateView( 6317 { 6318 caption: this.options.locale.months[this.currentMonth] + ", "+ this._convertNumberToLocale(this.currentYear), 6319 header:this.options.locale.days, 6320 numRows:7, 6321 numColumns:7, 6322 elementAt: function(row,col) { 6323 var day = (row-1)*7 + col - day1 + 1; 6324 var monthVal = self.currentMonth + 1; 6325 display = self._convertNumberToLocale(day); 6326 data = day; 6327 if(day < 1) { 6328 display = self._convertNumberToLocale(prevMaxDay + day); 6329 data = -1; 6330 monthVal = self.currentMonth; 6331 } 6332 else if(day > maxDay) { 6333 display = self._convertNumberToLocale(day-maxDay); 6334 data = -1; 6335 monthVal = self.currentMonth + 2; 6336 } 6337 else { 6338 curDate.setDate(day); 6339 var compareFn = xfalib.ut.XfaUtil.prototype._compareVal; 6340 // check if the currentdate is valid based on max and min valid date 6341 if(compareFn(curDate, self.maxValidDate, self.exclMaxDate) || compareFn(self.minValidDate, curDate, self.exclMinDate)) { 6342 data = -1; 6343 } 6344 } 6345 return { 6346 data : data, 6347 display : display, 6348 ariaLabel : self.options.editValue(self.currentYear+"-"+self._pad2(monthVal)+"-"+self._pad2(display)) 6349 }; 6350 } 6351 }); 6352 }, 6353 6354 6355 6356 /* 6357 * show the year view 6358 */ 6359 showYear: function() { 6360 var self = this, 6361 minDate = this.minValidDate ? new Date(this.minValidDate.getFullYear(), this.minValidDate.getMonth()) : null, 6362 maxDate = this.maxValidDate ? new Date(this.maxValidDate.getFullYear(), this.maxValidDate.getMonth()) : null, 6363 curDate = new Date(this.currentYear, 0), //can't omit month, if only one param present it is treated as millisecond 6364 data, 6365 month; 6366 this.tabulateView( 6367 { 6368 caption : this._convertNumberToLocale(this.currentYear), 6369 numRows : 4, 6370 numColumns : 3, 6371 elementAt : function(row,col) { 6372 data = month = row*3 + col; 6373 curDate.setMonth(month); 6374 if ((minDate && curDate < minDate) || (maxDate && curDate > maxDate)) { 6375 data = -1; 6376 } 6377 return { 6378 data : data, 6379 display : self.options.locale.months[month], 6380 ariaLabel : self.options.locale.months[month] + " " +self.currentYear 6381 }; 6382 } 6383 }); 6384 }, 6385 6386 /* 6387 * show the year set view 6388 */ 6389 showYearset: function() { 6390 var year, 6391 minDate = this.minValidDate ? new Date(this.minValidDate.getFullYear(), 0
6391) : null , 6392 maxDate = this.maxValidDate ? new Date(this.maxValidDate.getFullYear() + 1, 0) : null, 6393 curDate = new Date(), 6394 data, 6395 self = this; 6396 this.tabulateView( 6397 { 6398 caption: this._convertNumberToLocale(this.currentYear - this.options.yearsPerView/2) +"-"+this._convertNumberToLocale(this.currentYear - this.options.yearsPerView/2 + this.options.yearsPerView - 1), 6399 numRows:4, 6400 numColumns:4, 6401 elementAt: function(row,col) { 6402 data = year = self.currentYear - 8 + (row*4 + col); 6403 curDate.setFullYear(year); 6404 if ((minDate && curDate < minDate) || (maxDate && curDate > maxDate)) { 6405 data = -1; 6406 } 6407 return { 6408 "data" : data, 6409 "display" : self._convertNumberToLocale(year), 6410 ariaLabel : year 6411 }; 6412 } 6413 }); 6414 }, 6415 6416 insertRow : function(rowNum,rowArray,isHeader,height) { 6417 var $view = this["$"+this.view.toLowerCase()], 6418 width = (this.actualWidth)/rowArray.length, 6419 $row = $("ul",$view).eq(rowNum), 6420 items,$li,element,$tmp, 6421 self= this; 6422 if(!$row.length) 6423 $row = $("<ul></ul>").attr("aria-label", "").attr("role", "row").appendTo($view).toggleClass(headerClass,isHeader); 6424 $row.height(height); 6425 items = $("li",$row).length; 6426 while(items++ < rowArray.length) { 6427 $tmp = $("<li></li>").attr("role", "cell").appendTo($row); 6428 if(!isHeader) 6429 $tmp.on("click", $.proxy(this._selectDate,this)); 6430 } 6431 6432 _.each(rowArray, function(el,index) { 6433 $li = $("li",$row).eq(index); 6434 if(isHeader) 6435 $li.text(rowArray[index]); 6436 else { 6437 element = rowArray[index]; 6438 xfaUtil.$data($li.get(0), "value", element.data); 6439 if(self._checkDateIsFocussed(element.data)) { 6440 if(self.$focusedDate) { 6441 self.$focusedDate.removeClass("dp-focus"); 6442 self.$focusedDate.attr("tabindex", "-1"); 6443 } 6444 self.$focusedDate = $li; 6445 if(self._keysEnabled) 6446 self.$focusedDate.addClass("dp-focus") 6447 } 6448 $li.toggleClass("dp-selected",self._checkDateIsSelected(element.data)) 6449 .toggleClass("disabled", element.data == -1).text(element.display) 6450 .attr("title", element.ariaLabel) 6451 .attr("aria-label", element.ariaLabel) 6452 .attr("tabindex", -1); 6453 } 6454 $li.css( {"height":height+"px","width":width+"px","line-height":height+"px"}); 6455 }); 6456 return $row; 6457 }, 6458 6459 /* 6460 * creates a tabular view based on the options provided. The options that can be passed are 6461 * numRows: number of rows that needs rendering 6462 * numCols: number of columns that needs rendering 6463 * caption: text for the datepickers caption element 6464 * header: an array of elements that identifies the header row 6465 * elementAt: a function(row, column) that returns an object (data: <data>, display: <display>) where 6466 * <data> is the value to set for that view when the element at (row,column) is clicked and 6467 * <display> is the value that will be visible to the user 6468 */ 6469 tabulateView : function(options) { 6470 var r = 0,rows = 0, 6471 row = [], 6472 ht = this.options.viewHeight/options.numRows, 6473 c; 6474 this.$caption.text(options.caption); 6475 if(options.header) { 6476 this.insertRow(r++,options.header,true,ht); 6477 } 6478 while(r < options.numRows) { 6479 c = 0; 6480 while(c < options.numColumns) { 6481 row[c] = options.elementAt(r,c); 6482 c++; 6483 } 6484 this.insertRow(r++,row,false,ht); 6485 } 6486 }, 6487 6488 _activateField : function(evnt) { 6489 this._curInstance = xfaUtil.$data(evnt.target,"datetimepicker"); 6490 this._curInstance.$field.trigger("onfocus1.datetimepicker").addClass("datePickerTarget"); 6491 // Issue LC-7049: 6492 // datepickerTarget should be added when activate the field and should be removed 6493 // after the fields gets deactivated. 6494 if (this.options.showCalendarIcon) { 6495 this._curInstance.$field.parent().addClass("datePickerTarget"); 6496 } 6497 //enable hot keys only for non touch devices 6498 if(!this.touchSupported && !this._keysEnabled) { 6499 $(window).on("keydown.datetimepicker", $.proxy(this._hotKeys,this)); 6500 this._keysEnabled = true; 6501 } 6502 }, 6503 6504 _deactivateField: function() { 6505 if(this._curInstance) { 6506 if(this._keysEnabled) { 6507 $(window).off("keydown.datetimepicker") 6508 this._keysEnabled = false;
6509 } 6510 //Bug#3607499: on deactivate check the value in the input box, if that is 6511 // different than the selected Date, change the selectedDate 6512 //if (this._curInstance.selectedDate != this._curInstance.$field.val()) { 6513 // this._curInstance.selectedDate = this._curInstance.$field.val(); 6514 //} 6515 this._curInstance.$field.trigger("onfocusout.datetimepicker").removeClass("datePickerTarget"); 6516 // Issue LC-7049: 6517 // datepickerTarget should be added when activate the field and should be removed 6518 // after the fields gets deactivated. Otherwise clicking on any other datefield 6519 // will not hide the existing datepicker 6520 if (this.options.showCalendarIcon) { 6521 this._curInstance.$field.parent().removeClass("datePickerTarget"); 6522 } 6523 this._curInstance = null; 6524 } 6525 }, 6526 6527 _hide: function() { 6528 if(this._visible) { 6529 this.$dp.hide(); 6530 this._curInstance.$field.trigger("onclose.datetimepicker"); 6531 this._visible = false; 6532 if (this.options.showCalendarIcon) { 6533 this._curInstance.$field.attr('readonly', false); // when the datepicker is deactivated, activate the field 6534 } 6535 } 6536 }, 6537 6538 _adjustDate: function(step, view, focus) { 6539 var maxDate,prevMaxDate; 6540 var _focus = focus || false; 6541 switch(view.toLowerCase()) { 6542 case "day": 6543 this.currentDay += step; 6544 maxDate = this._maxDate(this.currentMonth) 6545 if(this.currentDay < 1) { 6546 prevMaxDate = this._maxDate((this.currentMonth - 1 + 12)%12); 6547 this.currentDay = prevMaxDate + this.currentDay; 6548 return this._adjustDate(-1, "month", _focus); 6549 } 6550 if(this.currentDay > maxDate) { 6551 this.currentDay -= maxDate; 6552 return this._adjustDate(+1, "month", _focus); 6553 } 6554 break; 6555 case "month": 6556 this.currentMonth += step; 6557 if(this.currentMonth > 11) { 6558 this.currentYear++; 6559 this.currentMonth = 0; 6560 } 6561 if(this.currentMonth < 0) { 6562 this.currentYear--; 6563 this.currentMonth = 11; 6564 } 6565 break; 6566 case "year": 6567 this.currentYear += step; 6568 break;
6569 case "yearset": 6570 this.currentYear += step*this.options.yearsPerView; 6571 break; 6572 } 6573 this._layout(this.view); 6574 if (_focus) { 6575 this.focusedOnDatepickerItem = true; 6576 this.$focusedDate.attr("tabindex", 0)[0].focus(); 6577 } 6578 }, 6579 6580 _checkDateIsSelected: function(data) { 6581 switch(this.view.toLowerCase()) { 6582 case "month": 6583 return this.currentYear == this.selectedYear && this.currentMonth == this.selectedMonth && data == this.selectedDay; 6584 case "year": 6585 return this.currentYear == this.selectedYear && this.selectedMonth == data; 6586 case "yearset": 6587 return this.selectedYear == data; 6588 } 6589 }, 6590 6591 _checkDateIsFocussed: function(data) { 6592 switch(this.view.toLowerCase()) { 6593 case "month": 6594 return data == this.currentDay; 6595 case "year": 6596 return this.currentMonth == data;
6597 case "yearset": 6598 return this.currentYear == data; 6599 } 6600 }, 6601 6602 _convertNumberToLocale : function(number) { 6603 var zeroCode = this.options.locale.zero.charCodeAt(0); 6604 number += ""; 6605 var newNumber = []; 6606 for(var i = 0;i < number.length;i++) { 6607 newNumber.push(String.fromCharCode(zeroCode + parseInt(number.charAt(i)))); 6608 } 6609 return newNumber.join(""); 6610 }, 6611 6612 _clearDate: function() { 6613 var isDateEmpty = this._curInstance.$field.val() ? false : true; 6614 this.selectedYear 6615 = this.selectedMonth 6616 = this.selectedYear 6617 = -1; 6618 this._curInstance.selectedDate = ""; 6619 this._curInstance.$field.val(""); 6620 if (!isDateEmpty) { 6621 this._curInstance.$field.trigger("onvaluechange.datetimepicker", [ 6622 {selectedDate: ""} 6623 ]); 6624 } 6625 $(".dp-selected",this['$'+this.view.toLowerCase()]).removeClass("dp-selected"); 6626 }, 6627 6628 getEvent : function() { 6629 return "click";//this.touchSupported ? "touchstart" : "click"; 6630 }, 6631 6632 _pad2: function(m) { 6633 return m = m < 10 ?"0"+m:m; 6634 }, 6635 6636 toString : function() { 6637 return this.selectedYear +"-"+this._pad2(this.selectedMonth + 1)+"-"+this._pad2(this.selectedDay); 6638 }, 6639 6640 _selectDate : function(evnt) { 6641 var val = xfaUtil.$data(evnt.target, "value"), 6642 nextView = viewAction[this.view].li, 6643 editVal; 6644 //disabled dates have a value of -1. Do nothing in that case 6645 if(val == -1) 6646 return; 6647 switch(this.view.toLowerCase()) { 6648 case "month": 6649 this.selectedMonth = this.currentMonth; 6650 this.selectedYear = this.currentYear; 6651 this.selectedDay = val; 6652 this._curInstance.selectedDate = this.toString(); 6653 editVal = this._curInstance.editValue(this.toString()); 6654 this._curInstance.$field.val(editVal).focus(); 6655 this._curInstance.$field.trigger("onvaluechange.datetimepicker", [ 6656 {selectedDate: editVal} 6657 ]); 6658 $(".dp-selected",this['$'+this.view.toLowerCase()]).removeClass("dp-selected"); 6659 $(evnt.target).addClass("dp-selected"); 6660 break; 6661 case "year": 6662 this.currentMonth = val; 6663 break;
6664 case "yearset": 6665 this.currentYear = val; 6666 break; 6667 } 6668 this._layout(nextView); 6669 //manually focus on the field if clicked on the popup buttons for non-touch device 6670 if(!this.touchSupported) { 6671 //No need to focus if selection is made by pressing space. 6672 if(!this.hotKeyPressed) { 6673 this.scriptFocus = true; 6674 if(nextView == null) { 6675 this.focusedOnDatepickerItem = false; 6676 } 6677 } 6678 } else if(nextView == null){ 6679 //For touch devices, deactivate the field if a selection is made 6680 this.focusedOnDatepickerItem = false; 6681 this._deactivateField() 6682 } 6683 }, 6684 6685 _leapYear : function() { 6686 return this.currentYear % 400 == 0 || (this.currentYear % 100 != 0 && this.currentYear % 4 == 0); 6687 }, 6688 6689 _maxDate : function(m) { 6690 if(this._leapYear() && m == 1) 6691 return 29; 6692 else return dates[m]; 6693 }, 6694 6695 _access: function(val) { 6696 if(typeof val == "undefined") 6697 return this.access 6698 this.access = val; 6699 }, 6700 6701 _value:function(val) { 6702 if(typeof val == "undefined") 6703 return this.$field.val() 6704 else { 6705 this.selectedDate = val; 6706 var editValue = this.editValue(val); 6707 // update the field val with provided value instead of null 6708 if (!editValue) { 6709 editValue = val; 6710 } 6711 this.$field.val(editValue); 6712 } 6713 } 6714 }); 6715 6716 var adobeDateTimePicker = new DateTimePicker(); 6717 6718 $.fn.adobeDateTimePicker = function(options, value) { 6719 if(!adobeDateTimePicker.initialized) { 6720 adobeDateTimePicker.create(options); 6721 adobeDateTimePicker.initialized = true; 6722 } 6723 if(typeof options === "object") { 6724 adobeDateTimePicker._attachField(this, options); 6725 } 6726 else if(typeof options === "string") { 6727 if(arguments.length == 2) 6728 adobeDateTimePicker["_"+options].apply(xfaUtil.$data(this[0],"datetimepicker"),[value]) 6729 else 6730 return adobeDateTimePicker["_"+options].apply(xfaUtil.$data(this[0],"datetimepicker")) 6731 } 6732 return this; 6733 } 6734})(_, $, xfalib); 6735(function (xfalib) { 6736 xfalib.ut.TouchUtil = (function () { 6737 var touchAvailable = !!("ontouchstart" in window || window.DocumentTouch && document instanceof DocumentTouch) , 6738 pointerEnabled = !!(window.MSPointerEvent || window.PointerEvent) , 6739 POINTER_DOWN_EVENT = "mousedown", 6740 POINTER_MOVE_EVENT = "mousemove", 6741 POINTER_UP_EVENT = "mouseup", 6742 EVENT_TYPE = "MouseEvent"; 6743 6744 if (window.PointerEvent) { //> IE11 6745 POINTER_DOWN_EVENT = "pointerdown"; 6746 POINTER_MOVE_EVENT = "pointermove"; 6747 POINTER_UP_EVENT = "pointerup"; 6748 EVENT_TYPE = "PointerEvent"; 6749 6750 } else if (window.MSPointerEvent) { // IE10 6751 POINTER_DOWN_EVENT = "MSPointerDown"; 6752 POINTER_MOVE_EVENT = "MSPointerMove"; 6753 POINTER_UP_EVENT = "MSPointerUp"; 6754 EVENT_TYPE = "MSPointerEvent" ; 6755 6756 } else if (touchAvailable) { // other touch devices 6757 POINTER_DOWN_EVENT = "touchstart"; 6758 POINTER_MOVE_EVENT = "touchmove"; 6759 POINTER_UP_EVENT = "touchend"; 6760 EVENT_TYPE = "TouchEvent"; 6761 } 6762 return { 6763 TOUCH_ENABLED: touchAvailable, 6764 // new MS Pointer Events 6765 POINTER_EVENT: EVENT_TYPE, 6766 POINTER_ENABLED: pointerEnabled, 6767 POINTER_DOWN: POINTER_DOWN_EVENT, 6768 POINTER_MOVE: POINTER_MOVE_EVENT, 6769 POINTER_UP: POINTER_UP_EVENT, 6770 getTouchEvent: function (evt) { 6771 var target; 6772 if (pointerEnabled) { 6773 target = evt.originalEvent; 6774 } else if (touchAvailable) { 6775 target = evt.originalEvent || evt; 6776 target = target.touches[0]; 6777 //if (evt.originalEvent && evt.originalEvent.changedTouches && evt.originalEvent.changedTouches[0]) { 6778 // te = evt.originalEvent.changedTouches[0]; 6779 //} 6780 } 6781 6782 return target || evt; 6783 }, 6784 getPointerEvent: function (eventType) { 6785 var event = null; 6786 if ((typeof PointerEvent) === "function") { 6787 event = new PointerEvent(eventType, { 6788 bubbles: true, 6789 cancelable: true 6790 }); 6791 } else { 6792 event = document.createEvent(EVENT_TYPE); 6793 event.initEvent(eventType, true, true); 6794 } 6795 return event; 6796 }, 6797 getTouches:function(evt){ 6798 var touches = []; 6799 if(touchAvailable && evt.originalEvent && evt.originalEvent.touches ){ 6800 touches = evt.originalEvent.touches; 6801 } 6802 return touches; 6803 } 6804 }; 6805 })(); 6806})(xfalib); 6807(function ($, _) { 6808 $.widget("xfaWidget.abstractWidget", { 6809 6810 $userControl: null, 6811 6812 $data: xfalib.ut.XfaUtil.prototype.$data, 6813 6814 $css: xfalib.ut.XfaUtil.prototype.$css, 6815 6816 getOrElse: xfalib.ut.Class.prototype.getOrElse, 6817 6818 dIndexOf: xfalib.ut.XfaUtil.prototype.dIndexOf, 6819 6820 btwn: xfalib.ut.XfaUtil.prototype.btwn, 6821 6822 logger: xfalib.ut.XfaUtil.prototype.getLogger, 6823
6824 localeStrings: xfalib.ut.XfaUtil.prototype.getLocaleStrings, 6825 6826 logMsgs: xfalib.ut.XfaUtil.prototype.getLogMessages, 6827 6828 errorManager: xfalib.ut.XfaUtil.prototype.getErrorManager, 6829 6830 _widgetName: "abstractWidget", 6831 6832 // if there are any specific black listed attributes, each widget should define their own 6833 _blackListedAttributes : ["type"], 6834 6835 options: { 6836 name: "", 6837 value: null, 6838 commitProperty: "value", 6839 displayValue: null, 6840 screenReaderText: null, 6841 tabIndex: 0, 6842 role: null, 6843 paraStyles: null, 6844 dir: null, 6845 errorMessage: null, 6846 warningMessage: null, 6847 hScrollDisabled: false, 6848 placeholder:"", 6849 isValid:true, 6850 mandatory: false 6851 }, 6852 6853 getOptionsMap: function () { 6854 return { 6855 "tabIndex": function (val) { 6856 this.$userControl.attr("tabindex", val); 6857 }, 6858 "role": function (val) { 6859 if (val) 6860 this.$userControl.attr("role", val); 6861 }, 6862 "screenReaderText": function (val) { 6863 if (val) 6864 this.$userControl.attr("aria-label", val) 6865 }, 6866 "paraStyles": function (val) { 6867 if (val) 6868 this.$css(this.$userControl.get(0), val); 6869 }, 6870 "dir": function (val) { 6871 if (val) 6872 this.$userControl.attr("dir", this.options.dir); 6873 }, 6874 "height": function (val) { 6875 if (val) { 6876 this.$css(this.$userControl[0], {"height": val}) 6877 } 6878 }, 6879 "width": function (val) { 6880 if (val) 6881 this.$css(this.$userControl[0], {"width": val}) 6882 }, 6883 "isValid": function (val) { 6884 if(val){ 6885 this.$userControl.removeAttr("aria-invalid"); 6886 } else { 6887 this.$userControl.attr("aria-invalid",true); 6888 } 6889 }, 6890 "color" : function(value) { 6891 if(!_.isEmpty(value)) { 6892 var color = "rgb(" + value + ")"; 6893 this.$css(this.$userControl[0], {"color": color}); 6894 } 6895 }, 6896 "font-style" : function (value) { 6897 if (!_.isEmpty(value)) { 6898 this.$css(this.$userControl[0], {"font-style": value}); 6899 } 6900 }, 6901 "mandatory" : function (value) { 6902 if(value){ 6903 this.$userControl.attr("aria-required", true); 6904 } else { 6905 this.$userControl.removeAttr("aria-required"); 6906 } 6907 } 6908 }; 6909 }, 6910 6911 getEventMap: function () { 6912 return { 6913 "focus": xfalib.ut.XfaUtil.prototype.XFA_ENTER_EVENT, 6914 "blur": xfalib.ut.XfaUtil.prototype.XFA_EXIT_EVENT, 6915 "click": xfalib.ut.XfaUtil.prototype.XFA_CLICK_EVENT 6916 }; 6917 }, 6918 6919 /** 6920 * Copies all the attributes from source jquery object to destination jquery object 6921 * @param $src source jquery object 6922 * @param $dest destination jquery object 6923 */ 6924 copyAttributesFromSrcToDest : function($src, $dest){ 6925 var that = this; 6926 // let's get all the attribute from the src element and copy it to dest jquery object 6927 if($src != null && $src[0] && $src[0].attributes && $dest != null){ 6928 $.each($src[0].attributes, function() { 6929 // we don't add the black listed set of attributes 6930 if(this.specified && this.value != null && _.isString(this.value) && this.value.length > 0 && that._blackListedAttributes.indexOf(this.name) === -1) { 6931 $dest.attr(this.name, this.value); 6932 } 6933 }); 6934 } 6935 }, 6936 6937 _create: function () { 6938 this.widgetEventPrefix = ""; 6939 this.element.addClass(this._widgetName); 6940 this.$userControl = this.render(); 6941 this.optionsHandler = this.getOptionsMap(); 6942 this.eventMap = this.getEventMap(); 6943 this._initializeOptions(); 6944 this._initializeEventHandlers(); 6945 this.errObj = this.errorManager(); 6946 //call it only after render 6947 // Dirty hack to prevent this being called in Guide 6948 if (typeof guidelib === "undefined") { 6949 this.$css(this.$userControl.get(0), { 6950 "box-sizing": "border-box", 6951 "position": "absolute" 6952 }); 6953 } 6954 }, 6955 6956 _initializeEventHandlers: function () { 6957 xfalib.ut.XfaUtil.prototype.getLogger().debug("xfa", "initialize event handlers for " + this._widgetName); 6958 _.each(this.eventMap, function (xfaevent, htmlevent) { 6959 var self = this; 6960 if (xfaevent) { 6961 if (!(xfaevent instanceof Array)) { 6962 xfaevent = [xfaevent]; 6963 } 6964 for (var i = 0; i < xfaevent.length; i++) { 6965 xfalib.ut.XfaUtil.prototype.getLogger().debug("xfa", "binding " + htmlevent + " with " + xfaevent[i]); 6966 this.$userControl.on(htmlevent, 6967 (function (xfevnt) { 6968 return function (evnt) { 6969 xfalib.ut.XfaUtil.prototype.getLogger().debug("xfa", "trigger " + evnt.type + 6970 " xfa-event " + xfevnt); 6971 self._preProcessEvent.apply(self, [xfevnt, evnt]); 6972 //since the fix https://github.com/jquery/jquery/pull/972, Fix for keeping namespace when triggering an event using an Event #972 6973 //we need to clear the namespace and its regular expression of triggering event, as the listeners are registered on un-namespaced events 6974 evnt.namespace = ""; 6975 evnt.namespace_re = ""; 6976 self._trigger(xfevnt, evnt); 6977 self._postProcessEvent.apply(self, [xfevnt, evnt]); 6978 } 6979 })(xfaevent[i]) 6980 ) 6981 6982 } 6983 } 6984 }, this) 6985 }, 6986 6987 _preProcessEvent: function (xfaevent, htmlevent) { 6988 if (xfaevent == this.options.commitEvent) { 6989 this.preProcessCommit(htmlevent); 6990 } 6991 switch (xfaevent) { 6992 case xfalib.ut.XfaUtil.prototype.XFA_ENTER_EVENT: 6993 this.preProcessEnter(htmlevent); 6994 break; 6995 case xfalib.ut.XfaUtil.prototype.XFA_EXIT_EVENT: 6996 this.preProcessExit(htmlevent); 6997 break; 6998 case xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT: 6999 this.preProcessChange(htmlevent); 7000 break; 7001 case xfalib.ut.XfaUtil.prototype.XFA_CLICK_EVENT: 7002 this.preProcessClick(htmlevent); 7003 break; 7004 } 7005 7006 }, 7007 7008 _postProcessEvent: function (xfaevent, htmlevent) { 7009 if (xfaevent == this.options.commitEvent) { 7010 this.postProcessCommit(htmlevent); 7011 } 7012 switch (xfaevent) { 7013 case xfalib.ut.XfaUtil.prototype.XFA_ENTER_EVENT: 7014 this.postProcessEnter(htmlevent); 7015 break; 7016 case xfalib.ut.XfaUtil.prototype.XFA_EXIT_EVENT: 7017 this.postProcessExit(htmlevent); 7018 break; 7019 case xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT: 7020 this.postProcessChange(htmlevent); 7021 break; 7022 case xfalib.ut.XfaUtil.prototype.XFA_CLICK_EVENT: 7023 this.postProcessClick(htmlevent); 7024 break; 7025 } 7026 }, 7027 7028 _initializeOptions: function () { 7029 _.each(this.optionsHandler, function (value, key) { 7030 if (typeof value === "function") 7031 value.apply(this, [this.options[key]]); // TODO: check whether it is needed for initialization or not 7032 }, this) 7033 }, 7034 7035 _setOption: function (key, value) { 7036 if (this.options[key] != value) { 7037 this.options[ key ] = value; 7038 if (typeof this.optionsHandler[key] === "function") { 7039 this.optionsHandler[key].apply(this, [this.options[key]]) 7040 } 7041 } 7042 }, 7043 7044 /** 7045 * @override 7046 */ 7047 option: function (key, value) { 7048 if (arguments.length === 1 && 7049 typeof key === "string" && 7050 this.options.hasOwnProperty(key) && 7051 this.options[key] === undefined) { 7052 return undefined; 7053 } 7054 return $.Widget.prototype.option.apply(this, arguments) 7055 }, 7056 7057 destroy: function () { 7058 this.$userControl.removeClass(this._widgetName); 7059 }, 7060 7061 7062 render: function () { 7063 var control; 7064 if (this.element.children().length > 0) { 7065 control = $(this.element.children().get(0)); 7066 } 7067 else 7068 control = this.element; 7069 control.attr("name", this.options.name) 7070 return control; 7071 }, 7072 7073 7074 preProcessCommit: function (evnt) { 7075 this.options.value = this.getCommitValue(); 7076 xfalib.ut.XfaUtil.prototype.getLogger().debug("xfa", "passing commit value " + this.options.value + 7077 "to model "); 7078 }, 7079 7080 getCommitValue: function () { 7081 7082 }, 7083 7084 preProcessExit: function (evnt) { 7085 7086 }, 7087 7088 preProcessEnter: function (evnt) { 7089 //Only focus the enabled widgets 7090 if (this.options.access === "open") { 7091 this._showError(); 7092 this.showValue(); 7093 } 7094 }, 7095 7096 preProcessChange: function (evnt) { 7097 7098 }, 7099 7100 preProcessClick: function (evnt) { 7101 7102 }, 7103 7104 postProcessCommit: function (evnt) { 7105 this.showDisplayValue(); 7106 }, 7107 7108 postProcessExit: function (evnt) { 7109 //Only for the enabled widgets 7110 if (this.options.access === "open") { 7111 this.showDisplayValue(); 7112 this._hideError(); 7113 } 7114 }, 7115 7116 postProcessEnter: function (evnt) { 7117 }, 7118 7119 postProcessChange: function (evnt) { 7120 7121 }, 7122 7123 postProcessClick: function (evnt) { 7124 7125 }, 7126 7127 showDisplayValue: function () { 7128 this.$userControl.val(this.options.displayValue) 7129 }, 7130 7131 /** 7132 * Checks if the edit value is same as value present in the user control(html form element) 7133 * @returns {boolean} 7134 */ 7135 _isValueSame : function(){ 7136 return (((this.options.value === null) && (this.$userControl.val() === "")) || (this.options.value === this.$userControl.val())); 7137 }, 7138 7139 showValue: function () { 7140 // May be $userControl doesn't have val(), using it as of now 7141 // If the value of the field is not same as edit value, only then set the value, this also solves IE bug of cursor 7142 // moving to the end of field on click 7143 if(!this._isValueSame()) { 7144 this.$userControl.val(this.options.value) 7145 } 7146 }, 7147 7148 focus: function () { 7149 var that = this; 7150 // setTimeout added to fix CQ-51141 7151 // While using setFocus API in adaptive form, the focus was not being set in TextBox on chrome 7152 // and also on click of caption of RadioButton/Checkbox, due to fast event execution, he
7152nce adding delay during focus. 7153 setTimeout(function(){ 7154 that.$userControl[0].focus(); 7155 }, 1); 7156 }, 7157 7158 click: function () { 7159 this.focus(); 7160 this.$userControl.triggerHandler("click"); // we do not want the exact click as might bubble up to the field. 7161 }, 7162 7163 /* widget specific code */ 7164 7165 _showError: function () { 7166 if(this.errObj && _.isFunction(this.errObj.onFieldEnter)) { 7167 this.errObj.onFieldEnter(this); 7168 } 7169 }, 7170 7171 _calculatePaddingForVAlign:function(diff){ 7172 var flagForMoz = $.browser.mozilla && !xfalib.ut.Utilities.isIE11() && 7173 this.options.multiLine, 7174 vAlignBottomOrTop = this.options.paraStyles && 7175 (this.options.paraStyles["vertical-align"] == "bottom" || 7176 this.options.paraStyles["vertical-align"] == "top"); 7177 7178 if(flagForMoz && vAlignBottomOrTop || $.browser.msie && this.options.multiLine) { 7179 return; 7180 } 7181 // to handle the edge cases, if the diff is like -0.01 the whole operation is getting aborted 7182 // this diff comes mainly due to scroll height getting rounded off when widgetHeight is like x.999999 7183 diff = (diff > -0.01) ? Math.abs(diff) : diff; 7184 if (this.options.paraStyles && diff > 0) { 7185 var vAlign = this.options.paraStyles["vertical-align"]; 7186 if (vAlign == "bottom") { 7187 diff = diff - this.options.paraStyles["padding-bottom"]; 7188 this.$userControl.css("padding-top", diff); 7189 this.padding = this.$userControl.css("padding-top"); 7190 } 7191 else if (vAlign == "top" || (vAlign != "middle" && vAlign == undefined)) { 7192 if (this.options.paraStyles["padding-top"]) 7193 diff = diff - this.options.paraStyles["padding-top"]; 7194 this.$userControl.css("padding-bottom", diff); 7195 this.padding = this.$userControl.css("padding-bottom"); 7196 } 7197 else if (this.options.multiLine && vAlign == "middle") { 7198 var newDiff = diff / 2; 7199 newDiff = newDiff - this.options.paraStyles["padding-bottom"]; 7200 if (this.options.paraStyles["padding-top"]) 7201 newDiff = newDiff + this.options.paraStyles["padding-top"]; 7202 this.$userControl.css("padding-top", newDiff); 7203 } 7204 } 7205 }, 7206 7207 _handleVAlignOnExit: function (evnt) { 7208 7209 if (!this.options.paraStyles) { 7210 //vAlign has to be handled only if there is paraStyles 7211 return; 7212 } 7213 var value = this.options.displayValue, 7214 lineHeight = xfalib.view.util.TextMetrics.measureExtent(value, {refEl: this.$userControl.get(0), maxHeight: -1}).height, 7215 widgetHeight = this.options.height, 7216 diff = widgetHeight - lineHeight; 7217 this._calculatePaddingForVAlign(diff); 7218 7219 }, 7220 7221 _handleVAlignOnEnter: function (evnt) { 7222 //Only align the enabled widgets 7223 var flagForIE = $.browser.msie && this.options.multiLine; 7224 if (this.options.paraStyles && !flagForIE) { 7225 var vAlign = this.options.paraStyles["vertical-align"]; 7226 if (vAlign == "bottom" && this.padding) 7227 this.$userControl.css("padding-top", this.padding); 7228 else if (vAlign == "top" && this.padding) 7229 this.$userControl.css("padding-bottom", this.padding); 7230 } 7231 }, 7232 7233 _hideError: function () { 7234 if(this.errObj && _.isFunction(this.errObj.onFieldExit)) { 7235 this.errObj.onFieldExit(this); 7236 } 7237 }, 7238 7239 markError: function (msg, type) { 7240 if(this.errObj && _.isFunction(this.errObj.markError)) { 7241 this.errObj.markError(this, msg, type); 7242 } 7243 }, 7244 7245 clearError: function () { 7246 if(this.errObj && _.isFunction(this.errObj.clearError)) { 7247 this.errObj.clearError(this); 7248 } 7249 }, 7250 7251 getEditValue: function(value) { 7252 if(this.options.editPattern == null) { 7253 return value; 7254 } 7255 try { 7256 return xfalib.ut.PictureFmt.format(value, this.options.editPattern); 7257 } catch(e) { 7258 return null; 7259 } 7260 }, 7261 7262 parseEditValue: function(value) { 7263 if(this.options.editPattern == null) { 7264 return value; 7265 } 7266 try { 7267 return xfalib.ut.PictureFmt.parse(value, this.options.editPattern); 7268 } catch(e) { 7269 return value; 7270 } 7271 } 7272 }); 7273})($, window._); 7274(function($) { 7275 $.widget( "xfaWidget.defaultWidget", $.xfaWidget.abstractWidget, { 7276 7277 _widgetName: "defaultWidget", 7278 7279 getOptionsMap: function() { 7280 var parentOptionsMap = $.xfaWidget.abstractWidget.prototype.getOptionsMap.apply(this,arguments); 7281 return $.extend({},parentOptionsMap,{ 7282 "access": function(val) { 7283 switch(val) { 7284 case "open" : 7285 this.$userControl.removeAttr("readOnly"); 7286 this.$userControl.removeAttr("aria-readonly"); 7287 this.$userControl.removeAttr("disabled"); 7288 this.$userControl.removeAttr("aria-disabled"); 7289 break; 7290 case "nonInteractive" : 7291 case "protected" : 7292 this.$userControl.attr("disabled", "disabled"); 7293 this.$userControl.attr("aria-disabled", "true"); 7294 break; 7295 case "readOnly" : 7296 this.$userControl.attr("readOnly", "readOnly"); 7297 this.$userControl.attr("aria-readonly", "true"); 7298 break; 7299 default : 7300 this.$userControl.removeAttr("disabled"); 7301 this.$userControl.removeAttr("aria-disabled"); 7302 break; 7303 } 7304 }, 7305 7306 "displayValue": function(val) { 7307 if(this.options.commitProperty) { 7308 if($.browser.mozilla && this.options.commitProperty == "value") { 7309 // on submitting form firefox does not remember autocomplete values, if updated through attr() 7310 this.$userControl.val(this._displayEmptyStringForIE(this.options.displayValue)); 7311 } else { 7312 this.$userControl.prop(this.options.commitProperty, this._displayEmptyStringForIE(this.options.displayValue)); 7313 this.$userControl.attr(this.options.commitProperty, this._displayEmptyStringForIE(this.options.displayValue)); 7314 } 7315 } else { 7316 this.logger().debug("xfaView", "[DefaultWidget._update], User Control or Commit Property is null"); 7317 } 7318 }, 7319 7320 "placeholder": function(value){ 7321 this.$userControl.attr("placeholder", value); 7322 } 7323 }); 7324 }, 7325 7326 _displayEmptyStringForIE: function(value){ 7327 /*CQ-69417: By default "null" is displayed in the comments text box 7328 "null" values shown in IE */ 7329 // CQ-69107 included check for edge as well 7330 return (value == null && xfalib.ut.XfaUtil.prototype.detectIE()) ? '' : value; 7331 }, 7332 7333 render : function() { 7334 var control = $.xfaWidget.abstractWidget.prototype.render.apply(this,arguments) 7335 this._attachEventHandlers(control) 7336 return control 7337 }, 7338 7339 getCommitValue: function() { 7340 var value = this.$userControl.val(); 7341 if(this.options.hScrollDisabled && !this.options.multiLine) 7342 var value = xfalib.ut.XfaUtil.prototype.splitStringByWidth(this.$userControl.val(),this.$userControl.width(),this.$userControl.get(0)) ; 7343 return value; 7344 }, 7345 7346 _attachEventHandlers: function($control) {
7347 $control.keydown($.proxy(this._handleKeyDown,this)); 7348 $control.keypress($.proxy(this._handleKeyPress,this)); 7349 $control.on('paste',$.proxy(this._handlePaste,this)); 7350 $control.on('cut',$.proxy(this._handleCut,this)); 7351 }, 7352 7353 _compositionUpdateCallback : function (event) { 7354 return false; 7355 }, 7356 7357 _attachCompositionEventHandlers : function($control) { 7358 var isComposing = false; // IME Composing going on 7359 var hasCompositionJustEnded = false; // Used to swallow keyup event related to compositionend 7360 // IME specific handling, to handle japanese languages max limit 7361 // since enter can also be invoked during composing, a special handling is done here 7362 var that = this, 7363 changeCaratPosition = function() { 7364 // change the carat selection position to further limit input of characters 7365 var range = window.getSelection(); 7366 range.selectAllChildren(that.$userControl[0]); 7367 range.collapseToEnd(); 7368 }; 7369 $control.keyup(function(event) { 7370 if (/*isComposing || */hasCompositionJustEnded) { 7371 if (that._compositionUpdateCallback(event)) { 7372 changeCaratPosition(); 7373 } 7374 // IME composing fires keydown/keyup events 7375 hasCompositionJustEnded = false; 7376 } 7377 }); 7378 $control.on("compositionstart", 7379 function(event) { 7380 isComposing = true; 7381 }) 7382 .on("compositionupdate", 7383 function(event) { 7384 // event.originalEvent.data refers to the actual content 7385 if (that._compositionUpdateCallback(event)) { 7386 changeCaratPosition(); 7387 } 7388 }) 7389 .on("compositionend", 7390 function(event) { 7391 isComposing = false; 7392 // some browsers (IE, Firefox, Safari) send a keyup event after 7393 // compositionend, some (Chrome, Edge) don't. This is to swallow 7394 // the next keyup event, unless a keydown event happens first 7395 hasCompositionJustEnded = true; 7396 }) 7397 .on("keydown", 7398 function(event) { 7399 // Safari on OS X may send a keydown of 229 after compositionend 7400 if (event.which !== 229) { 7401 hasCompositionJustEnded = false; 7402 } 7403 }); 7404 }, 7405 7406 _handleKeyDown : function(event){ 7407 if(event.keyCode == 13 || event.charCode == 13 || event.which == 13) // touch devices may return charCode 7408 event.preventDefault(); 7409 }, 7410 7411 _handleKeyPress : function(event){ 7412 if(event.keyCode == 13 || event.charCode == 13 || event.which == 13) // touch devices may return charCode 7413 event.preventDefault(); 7414 } 7415 }); 7416})($); 7417(function($, _) { 7418 var xfaUtil = xfalib.ut.XfaUtil.prototype; 7419 $.widget( "xfaWidget.dateTimeEdit", $.xfaWidget.defaultWidget, { 7420 7421 _widgetName : "dateTimeEdit", 7422 7423 getEventMap: function() { 7424 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getEventMap.apply(this,arguments); 7425 if(this._nativeWidget === false) { 7426 return $.extend({}, parentOptionsMap, { 7427 "onfocus1.datetimepicker": xfalib.ut.XfaUtil.prototype.XFA_ENTER_EVENT, 7428 "onvaluechange.datetimepicker": xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT, 7429 "onfocusout.datetimepicker": xfalib.ut.XfaUtil.prototype.XFA_EXIT_EVENT, 7430 "onoverlap.datetimepicker": xfalib.ut.XfaUtil.prototype.XFA_CLICK_EVENT, // Custom Event to fix BUG #3626974 7431 "input": xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT, // TODO : add handler for xfa.event.change 7432 "focus": null, 7433 "blur": null 7434 }) 7435 } else { 7436 return $.extend({}, parentOptionsMap, { 7437 "change": xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT 7438 }) 7439 } 7440 }, 7441 7442 _getAdobeDatePickerOptionsMap : function(parentOptionsMap) { 7443 return { 7444 "access" : function (val) { 7445 switch (val) { 7446 case "open" : 7447 this.$userControl.adobeDateTimePicker("access", true); 7448 break; 7449 case "nonInteractive" : 7450 case "protected" : 7451 case "readOnly" : 7452 this.$userControl.adobeDateTimePicker("access", false); 7453 break; 7454 } 7455 parentOptionsMap.access.apply(this, arguments); 7456 }, 7457 "displayValue" : function (val) { 7458 // set the value in the datepicker plugin 7459 this.$userControl.adobeDateTimePicker("value", this.options.value); 7460 // show the display value 7461 this.showDisplayValue(); 7462 } 7463 } 7464 }, 7465 7466 _getNativeDatePickerOptionsMap: function (parentOptionsMap) { 7467 return { 7468 "displayValue": function (val) { 7469 this.showDisplayValue(); 7470 } 7471 } 7472 }, 7473 7474 7475 getOptionsMap: function() { 7476 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this,arguments), 7477 datePickerOptions = this._nativeWidget === false ? this._getAdobeDatePickerOptionsMap(parentOptionsMap) 7478 : this._getNativeDatePickerOptionsMap(parentOptionsMap), 7479 commonOptions = { 7480 "paraStyles": function (paraStyles) { 7481 parentOptionsMap.paraStyles.apply(this, arguments); 7482 this._handleVAlignOnExit(); 7483 }, 7484 7485 "access": function(val) { 7486 // update width on change of access (as width of widget is dependent on access) 7487 // The calender icon should be hidden, and widget should take full space when readOnly 7488 parentOptionsMap.access.apply(this, arguments); 7489 this.getOptionsMap().width.apply(this,[this.options.width]); 7490 }, 7491 "width": function (val) { 7492 parentOptionsMap.width.apply(this, arguments); 7493 if (this.options.showCalendarIcon && val && this.options.access == "open") { 7494 var effectiveWidth = val > this.options.calendarIconWidth ? val - this.options.calendarIconWidth : val; 7495 this.$userControl.width(effectiveWidth); // leave space for the cal icon 7496 } 7497 }, 7498 7499 "height": function(val) { 7500 parentOptionsMap.height.apply(this, arguments); 7501 this._handleVAlignOnExit(); 7502 }, 7503 "screenReaderText": function (val) { 7504 var editPattern = this.options.editPattern; 7505 var defaultEditPattern = this._nativeWidget ? "mm/dd/yyyy" : "YYYY-MM-DD"; 7506 var regex = /(?:date){0,1}{(.*)}/;
7506 // date{<pattern>} or {<pattern>} both are valid as per xfa spec 7507 editPattern = typeof editPattern === "string" ? editPattern.match(regex)[1] : defaultEditPattern; 7508 var defaultLabel = "Please Enter date in {0} format only"; 7509 if (editPattern) { 7510 var ariaLabel = xfalib.ut.LocalizationUtil.prototype.getLocalizedMessage("", 7511 xfalib.locale.Strings.datePickerAriaLabel || defaultLabel, [editPattern]) 7512 } 7513 var finalVal = val !== undefined ? val + " " + ariaLabel : val; 7514 this.$userControl.attr("aria-label", finalVal); 7515 } 7516 }; 7517 return $.extend({},parentOptionsMap,datePickerOptions, commonOptions); 7518 }, 7519 7520 postProcessExit: function(evnt) { 7521 $.xfaWidget.defaultWidget.prototype.postProcessExit.apply(this,arguments); 7522 this._handleVAlignOnExit (); 7523 }, 7524 7525 preProcessEnter: function(evnt) { 7526 $.xfaWidget.defaultWidget.prototype.preProcessEnter.apply(this,arguments); 7527 this._handleVAlignOnEnter(); 7528 }, 7529 7530 preProcessChange: function(evnt) { 7531 //CQ-46332:loss of date value in date-picker , setting the value here or else 7532 //it gets lost during focus 7533 if(this._nativeWidget === true){ 7534 this.options.value = this.$userControl.val(); 7535 } 7536 }, 7537 7538 showDisplayValue: function() { 7539 if(this._nativeWidget === false) { 7540 $.xfaWidget.defaultWidget.prototype.showDisplayValue.apply(this, arguments); 7541 } else { 7542 this.showValue(); 7543 } 7544 }, 7545 7546 7547 showValue: function () { 7548 if (this._nativeWidget == false) { 7549 this.$userControl.adobeDateTimePicker("value", this.options.value); 7550 } else { 7551 $.xfaWidget.defaultWidget.prototype.showValue.apply(this, arguments); 7552 } 7553 $.xfaWidget.textField.prototype._selectOnFocusInIE.apply(this, arguments); 7554 }, 7555 7556 getCommitValue: function() { 7557 if (this._nativeWidget === false) { 7558 var value = this.$userControl.adobeDateTimePicker("value"), 7559 parsedValue = this.parseEditValue(value); 7560 return parsedValue; 7561 } 7562 return $.xfaWidget.defaultWidget.prototype.getCommitValue.apply(this, arguments); 7563 }, 7564 7565 render: function() { 7566 var self = this, 7567 textStyle = this.getOrElse(this.$data(this.element.get(0), "xfamodel"), "textstyle", ""), 7568 $control = $.xfaWidget.abstractWidget.prototype.render.apply(this, arguments), 7569 $source = $control, 7570 id, 7571 existingInlineStyleAttributeValues, 7572 newInlineStyleAttributeValues, 7573 combinedInlineStyleAttributeValues; 7574 existingInlineStyleAttributeValues = this.element.find("input").attr("style") || ''; 7575 this._nativeWidget = true; 7576 if(this.options.useNativeWidget === false || $control[0].type !== "date") { 7577 this._nativeWidget = false; 7578 id = this.element.find("input")[0].id; 7579 this.element.children().remove(); 7580 $("<div></div>").css({position: "relative", width: "100%", height: "100%"}) // want to fill entire width of containing table cell 7581 .append($("<input type='text'/>")) 7582 .appendTo(this.element); 7583 $control = $("input", this.element). 7584 attr("style", textStyle). 7585 attr("name", this.options.name). 7586 attr("id", id). 7587 adobeDateTimePicker({ 7588 positioning: this.element, 7589 locale: { 7590 months: this.options.months, 7591 days: this.options.days, 7592 zero: this.options.zero, 7593 clearText: this.options.clearText 7594 }, 7595 access: this.options.access, 7596 value: this.options.value, 7597 showCalendarIcon: this.options.showCalendarIcon, 7598 iconWidth: this.options.calendarIconWidth, 7599 minValidDate : this.options.minValidDate, 7600 maxValidDate : this.options.maxValidDate, 7601 exclMinDate : this.options.exclMinDate, 7602 exclMaxDate : this.options.exclMaxDate, 7603 editValue: function (value) { 7604 return self.getEditValue(value); 7605 } 7606 }); 7607 } 7608 this._attachEventHandlers($control); 7609 newInlineStyleAttributeValues = this.element.find("input").attr("style") || ''; 7610 //append the previous inlineStyleAttributeValues to newInlineStyleAttributeValues so that the inline styles 7611 //added from the dialog are applied. 7612 combinedInlineStyleAttributeValues = newInlineStyleAttributeValues + existingInlineStyleAttributeValues; 7613 this.element.find("input").attr("style", combinedInlineStyleAttributeValues); 7614 // only in case of adaptive form, we would copy the attributes back 7615 if(window.guideBridge) { 7616 // restore the original attribute back to destination object 7617 this.copyAttributesFromSrcToDest($source, this.element.find("input")); 7618 } 7619 return $control; 7620 } 7621 }) ; 7622 7623})($, _); 7624(function($, _) { 7625$.widget("xfaWidget.numericInput", $.xfaWidget.defaultWidget, { 7626 7627 _widgetName: "numericInput", 7628 7629 options : { 7630 value : null, 7631 curValue: null, 7632 pos: 0, 7633 lengthLimitVisible: true, 7634 zero:"0",
7635 decimal:".", 7636 minus:"-" 7637 }, 7638 7639 //TODO: to support writing in different locales \d should be replaced by [0-9] for different locales 7640 _matchArray : { 7641 "integer":"^[+-]?{digits}*$", 7642 "decimal":"^[+-]?{digits}{leading}({decimal}{digits}{fraction})?$", 7643 "float":"^[+-]?{digits}*({decimal}{digits}*)?$" 7644 }, 7645 7646 _regex : null, 7647 7648 _engRegex : null, 7649 7650 _writtenInLocale : false, 7651 7652 _previousCompositionVal : "", 7653 7654 7655 _toLatinForm : function (halfOrFullWidthStr) { 7656 // refer http://www.fileformat.info/info/unicode/block/halfwidth_and_fullwidth_forms/utf8test.htm 7657 return halfOrFullWidthStr.replace( 7658 /[\uff00-\uffef]/g, 7659 function(ch) { return String.fromCharCode(ch.charCodeAt(0) - 0xfee0); } 7660 ); 7661 }, 7662 7663 getOptionsMap: function() { 7664 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this,arguments); 7665 return $.extend({},parentOptionsMap,{ 7666 "paraStyles": function(paraStyles){ 7667 parentOptionsMap.paraStyles.apply(this,arguments); 7668 this._handleVAlignOnExit (); 7669 } , 7670 7671 "height": function(val) { 7672 if(val) { 7673 this.$css(this.$userControl[0],{"height" :val}); 7674 this._handleVAlignOnExit(); // To Handle the case of expandable Fields 7675 } 7676 } 7677 7678 }) 7679 }, 7680 7681 getEventMap: function() { 7682 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getEventMap.apply(this,arguments); 7683 return $.extend({},parentOptionsMap,{ 7684 "onKeyInput.numericInput" : xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT 7685 }) 7686 }, 7687 7688 _getDigits: function() { 7689 var zeroCode = this.options.zero.charCodeAt(0), 7690 digits = ""; 7691 for(var i = 0;i < 10;i++) { 7692 digits += String.fromCharCode(zeroCode + i); 7693 } 7694 return "["+digits+"]" 7695 }, 7696 7697 _escape: function(str) { 7698 return str.replace(".","\\.") 7699 }, 7700 7701 postProcessExit: function(evnt) { 7702 $.xfaWidget.defaultWidget.prototype.postProcessExit.apply(this,arguments); 7703 this._handleVAlignOnExit (); 7704 }, 7705 7706 preProcessEnter: function(evnt) { 7707 $.xfaWidget.defaultWidget.prototype.preProcessEnter.apply(this,arguments); 7708 this._handleVAlignOnEnter(); 7709 }, 7710 7711 render : function() { 7712 var matchStr = this._matchArray[this.options.dataType]; 7713 if(matchStr) { 7714 var ld = this.options.leadDigits, 7715 fd = this.options.fracDigits, 7716 ldstr = ld && ld != -1 ? "{0,"+ld+"}" 7717 : "*", 7718 fdstr = fd && fd != -1 ? "{0,"+fd+"}" 7719 : "*", 7720 matchStr = matchStr.replace("{leading}",ldstr) 7721 .replace("{fraction}",fdstr), 7722 localeStr = matchStr.replace(/{digits}/g,this._getDigits()) 7723 .replace("{decimal}",this._escape(this.options.decimal)), 7724 engStr = matchStr.replace(/{digits}/g,"[0-9]") 7725 .replace("{decimal}","\\.") 7726 this._processValue = !(this._getDigits() == "[0123456789]" && this.options.decimal == ".") 7727 this._regex = new RegExp(localeStr, "g"); 7728 this._engRegex = new RegExp(engStr, "g"); 7729 } 7730 return $.xfaWidget.defaultWidget.prototype.render.apply(this, arguments); 7731 }, 7732 7733 getCommitValue: function() { 7734 var value = $.xfaWidget.defaultWidget.prototype.getCommitValue.apply(this, arguments); 7735 // we support full width, half width and locale specific numbers 7736 value = this._toLatinForm(value); 7737 if(value.length > 0 && this._processValue && !value.match(this._engRegex)) { 7738 this._writtenInLocale = true; 7739 value = this._convertValueFromLocale(value); 7740 } else { 7741 this._writtenInLocale = false 7742 } 7743 if(value && value.length >= this.options.combCells ) 7744 value = value.slice(0,this.options.combCells); 7745 this._previousCompositionVal = value; 7746 return value; 7747 }, 7748 7749 _compositionUpdateCallback : function (event) { 7750 var that = this; 7751 var flag = false;
7752 var leadDigits = that.options.leadDigits; 7753 var fracDigits = that.options.fracDigits; 7754 // we don't check use-case where just fracDigits is set since in case of composition update, the value to update is not known 7755 if (leadDigits !== -1) { 7756 var val = that.$userControl.val(); 7757 if (event.type === "compositionupdate" && event.originalEvent.data) { 7758 val = val + event.originalEvent.data.substr(event.originalEvent.data.length - 1); 7759 } 7760 // can't use the existing regex (since current regex checks for english digits), rather doing leadDigit compare 7761 var totalLength = leadDigits + (fracDigits !== -1 ? (fracDigits + that.options.decimal.length) : 0); 7762 if (val.indexOf(that.options.decimal) === -1) { 7763 totalLength = leadDigits; 7764 } 7765 var latinVal = this._toLatinForm(val); 7766 // match both since we support full width, half width and locale specific input 7767 var match = latinVal.match(that._regex)|| latinVal.match(this._engRegex); 7768 flag = !match; 7769 if (match === null) { 7770 // entered invalid character, revert to previous value 7771 that.$userControl.val(that._previousCompositionVal); 7772 flag = true; 7773 } else if (flag) { 7774 // if max reached 7775 var newVal = val.substr(0, totalLength); 7776 that.$userControl.val(newVal); 7777 that._previousCompositionVal = newVal; 7778 flag = true; 7779 } else { 7780 that._previousCompositionVal = val; 7781 } 7782 } 7783 return flag; 7784 }, 7785 7786 _attachEventHandlers : function($control) { 7787 $.xfaWidget.defaultWidget.prototype._attachEventHandlers.apply(this, arguments); 7788 // IME specific handling, to handle japanese languages max limit 7789 $.xfaWidget.defaultWidget.prototype._attachCompositionEventHandlers.apply(this, arguments); 7790 }, 7791 7792 _handleKeyInput : function(event, character, code){ 7793 if(event.ctrlKey && !_.contains(['paste', 'cut'], event.type)) { 7794 return true; 7795 } 7796 7797 $.xfaWidget.defaultWidget.prototype._handleKeyDown.apply(this,arguments); 7798 this.options.lengthLimitVisible = true; 7799 7800 var val = this.$userControl.prop(this.options.commitProperty) || '', 7801 // if selectionStart attribute isn't supported then its value will be undefined 7802 selectionStart = xfalib.view.util.HtmlUtil.getHTMLSupportedAttr(this.$userControl[0], "selectionStart"), 7803 isSelectionAttrSupported = !(selectionStart === undefined || selectionStart === null), 7804 selectionStart = selectionStart || 0, 7805 selectionEnd = xfalib.view.util.HtmlUtil.getHTMLSupportedAttr(this.$userControl[0], "selectionEnd") || 0, 7806 combCells = parseInt(this.options.combCells) || 0, 7807 current, 7808 change = character; 7809 7810 if (combCells > 0 ) { 7811 change = character.substr(0, combCells - val.length + selectionEnd - selectionStart); 7812 } 7813 7814 current = val.substr(0, selectionStart) + change + val.substr(selectionEnd); 7815 // done to handle support for both full width, half width or mixed input in number field 7816 var latinCurrentValue = this._toLatinForm(current); 7817 7818 // we want to check regex first and then see whether it was numeric or not. 7819 if (!(this._regex == null || latinCurrentValue.match(this._regex) || latinCurrentValue.match(this._engRegex))) { 7820 event.preventDefault(); 7821 return false; 7822 } 7823 7824 // CQ-4245407 : selectionStart and selectionEnd attributes aren't supported in case of input type = number 7825 // it is used for providing native HTML5 implementation for numeric field, so no further processing is required 7826 // As it is specific to AF and AF doesn't support change event on each keypress, so this change should be fine 7827 if (!isSelectionAttrSupported) { 7828 return true; 7829 } 7830 7831 if (!_.contains(['keydown', 'cut'], event.type) && combCells && (val.length >= combCells || current.length > combCells) && selectionStart === selectionEnd) { 7832 event.preventDefault(); 7833 return false;
7834 } 7835 7836 this.options.curValue = val; 7837 this._previousCompositionVal = val; 7838 this.options.pos = selectionStart; 7839 7840 if(this.options.hScrollDisabled && !_.contains(['keydown', 'cut'], event.type)) { 7841 var expectedWidth = xfalib.view.util.TextMetrics.measureExtent(current, {refEl: this.$userControl[0], maxWidth:-1}).width; 7842 if(!event.ctrlKey && expectedWidth > this.$userControl.width() - 5){ 7843 event.preventDefault(); 7844 this.options.lengthLimitVisible = false; 7845 } 7846 } 7847 7848 this.$userControl.trigger({ 7849 type : "onKeyInput.numericInput", 7850 originalType : event.type, 7851 character : character, // contains the pasted string or pressed key 7852 keyCode : event.keyCode || 0, 7853 charCode : event.charCode || 0, 7854 which : event.which || 0, 7855 ctrlKey : event.ctrlKey || event.metaKey || false, 7856 shiftKey : event.shiftKey || false, 7857 keyDown : false, // This property is available only for list boxes and drop-down lists 7858 selectionStart: selectionStart, 7859 selectionEnd: selectionEnd 7860 }); 7861 }, 7862 7863 _handleKeyDown : function(event){ 7864 if (event) { 7865 var code = event.charCode || event.which || event.keyCode || 0; 7866 if(code == 8 || code == 46) // backspace and del 7867 this._handleKeyInput(event, "", code); 7868 else if(code == 32) { // suppress space 7869 event.preventDefault(); 7870 return false; 7871 } 7872 } 7873 }, 7874 7875 _isValidChar: function (character) { 7876 character = this._toLatinForm(character); 7877 var lastSingleDigitChar = String.fromCharCode(this.options.zero.charCodeAt(0) + 9); 7878 // we only full width, half width and also locale specific if customer has overlayed the i18n file 7879 return (character >= "0" && character <= "9") || (character>=this.options.zero && character<=lastSingleDigitChar) || character===this.options.decimal || character===this.options.minus; 7880 }, 7881 7882 _handleKeyPress : function(event){ 7883 if (event) { 7884 var code = event.charCode || event.which || event.keyCode || 0, 7885 character = String.fromCharCode(code); 7886 7887 if(xfalib.ut.XfaUtil.prototype.isNonPrintableKey(event.key)) { // mozilla also generates a keypress, along with keydown 7888 return true; // for all keys, so only handling printable keys in keypress 7889 } 7890 7891 if (this._isValidChar(character)) 7892 this._handleKeyInput(event, character, code); 7893 else if (!event.ctrlKey){ 7894 event.preventDefault(); 7895 return false; 7896 } 7897 } 7898 }, 7899 7900 _handlePaste : function(event){ 7901 if (event) { 7902 var pastedChar = undefined; 7903 if (window.clipboardData && window.clipboardData.getData) { // IE 7904 pastedChar = window.clipboardData.getData('Text'); 7905 } else if (event.originalEvent.clipboardData && event.originalEvent.clipboardData.getData) { 7906 pastedChar = event.originalEvent.clipboardData.getData('text/plain'); 7907 } 7908 7909 if(pastedChar) { 7910 var allPastedCharsValid = _.every(pastedChar.split(''), function (character) { 7911 return this._isValidChar(character); 7912 }, this); 7913 if (allPastedCharsValid) { 7914 // during paste we support both half width, full width and locale specific numbers 7915 pastedChar = this._toLatinForm(pastedChar); 7916 this._handleKeyInput(event, pastedChar, 0); 7917 } 7918 else if (!event.ctrlKey) { 7919 event.preventDefault(); 7920 return false; 7921 } 7922 } 7923 } 7924 }, 7925 7926 _handleCut : function(event) { 7927 if (event) { 7928 this._handleKeyInput(event, "", 0); 7929 } 7930 }, 7931 // CQ-107886 : added handling for negative values, as for '-', '-3' was getting returned 7932 _convertValueToLocale: function(val) { 7933 var zeroCode = this.options.zero.charCodeAt(0); 7934 return _.map(val,function(c) { 7935 if(c == ".") { 7936 return this.options.decimal; 7937 } else if(c == "-") { 7938 return this.options.minus; 7939 } else { 7940 return String.fromCharCode(parseInt(c) + zeroCode); 7941 } 7942 },this).join(""); 7943 }, 7944 7945 _convertValueFromLocale: function(val) { 7946 val = this._toLatinForm(val); 7947 var zeroCode = this.options.zero.charCodeAt(0); 7948 return _.map(val,function(c) { 7949 if(c == this.options.decimal) { 7950 return "."; 7951 } else if(c == this.options.minus) { 7952 return "-"; 7953 } else { 7954 return (c.charCodeAt(0) - zeroCode).toString(); 7955 } 7956 },this).join(""); 7957 }, 7958 7959 showValue : function() { 7960 // if the value is same, don't do anything 7961 if(!this._isValueSame()){ 7962 if(this.options.value && this._writtenInLocale) { 7963 this.$userControl.val(this._convertValueToLocale(this.options.value)) 7964 } else { 7965 this.$userControl.val(this.options.value) 7966 } 7967 } 7968 //IE doesn't show selected text if we focus and set its value all the time so force selection 7969 $.xfaWidget.textField.prototype._selectOnFocusInIE.apply(this, arguments); 7970 } 7971}); 7972})($, window._);(function ($, _) { 7973 $.widget("xfaWidget.dropDownList", $.xfaWidget.defaultWidget, { //commitEvent: change; commitProperty: value<Array> 7974 7975 _widgetName: "dropDownList", 7976 7977 options: { 7978 value: [], 7979 items: [], 7980 editable: false, 7981 placeholder: "", 7982 displayValue: [] 7983 }, 7984 7985 widgetSkeleton: '<select name="" style="" size = "1"></select>', 7986 optionSkeleton: '<option data-user-option></option>', 7987 optGroupSkeleton: '<optgroup label=""></optgroup>', 7988 AF_OPTGROUP_NAME: "afOptGroupName", 7989 PLACE_HOLDER_STYLE_CLASS : "placeHolder", 7990 7991 getOptionsMap: function () { 7992 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this, arguments); 7993 return $.extend({}, parentOptionsMap, { 7994 "value": function (val) { 7995 if (!_.isArray(val)) { 7996 val = [val]; 7997 } 7998 var selectedOptionFound = false, 7999 that = this; 8000 //sync option selection as per new values 8001 $("option", this.$userControl).each(function (index) { 8002 var selectValue = $(this).val(); 8003 //Check if this value is present in options value array 8004 if (_.contains(val, selectValue)) { 8005 $(this).prop("selected", true); 8006 selectedOptionFound = true; 8007 } else { 8008 $(this).prop("selected", false); 8009 if (this.id === "emptyValue") { 8010 $(this).val("").html(that.options.placeholder); 8011 //Hiding emptyValue with no placeholder text configured. 8012 if(that.options.placeholder.length == 0) { 8013 $(this).hide(); 8014 } 8015 } 8016 } 8017 }); 8018 8019 /* Add default option if : 8020 / 1. If placeholder add an extra option 8021 / 2. If the value is set anything other than the options (and null/"") create a new option 8022 */ 8023 if ((!selectedOptionFound && val.length != 0 && val[0] != null) || that.options.placeholder.length != 0) { 8024 if (this.$userControl.children('[data-empty-option]').length == 0) { 8025 var extraOption = document.createElement("option"); 8026 extraOption.setAttribute("data-empty-option", ""); 8027 extraOption.setAttribute("role", "none"); 8028 extraOption.setAttribute("value", "") 8029 this.$userControl[0].insertBefore(extraOption, this.$userControl[0].firstChild); 8030 } 8031 // If placeholder is present the set value of empty option to placeholder 8032 if (that.options.placeholder.length != 0) { 8033 this.$userControl.children('[data-empty-option]').text(that.options.placeholder); 8034 } 8035 // If placeholder is present and value is not present then select placeholder 8036 if (val.length == 0 || val[0] == null) { 8037 this.$userControl.children('[data-empty-option]').prop("selected", true); 8038 } // If value is set anything other than option then set empty option to value 8039 else if (!selectedOptionFound && val.length != 0 && val[0] != null) { 8040 this.$userControl.children('[data-empty-option]').text(val[0]). 8041 prop("selected", true). 8042 val(_.escape(val[0])). 8043 show(); 8044 } 8045 8046 } 8047 else if (that.options.placeholder.length == 0) { 8048 // Delete default option if value is found in options while adding options 8049 if (selectedOptionFound && this.$userControl.children('[data-empty-option]').val() != that.options.displayValue) { 8050 if (this.$userControl.children('[data-empty-option]').length > 0) { 8051 this.$userControl[0].removeChild(this.$userControl.children('[data-empty-option]')[0]); 8052 } 8053 } 8054 // Reset the value of dropdown based on rule 8055 else if (!selectedOptionFound && (val.length == 0 || val == null || val[0] == null)) { 8056 this.$userControl[0].value = ""; 8057 } 8058 } 8059 this.$userControl.toggleClass(this.PLACE_HOLDER_STYLE_CLASS, val.length == 0 || val == null); 8060 }, 8061 8062 "items": function (val) { 8063 if (!_.isArray(val)) { 8064 val = [val]; 8065 } 8066 8067 var AF_OPTGROUP_NAME = "afOptGroupName"; 8068 var i, j, optgroupOptions = [], element, $viewOptgroup, $preOptgroup; 8069 var viewOptgroups = $("optgroup", this.$userControl); 8070 // Removes all options which earlier didn't belong to any optgroup. 8071 if (viewOptgroups.length == 0) { 8072 // save selected value because when value is set before items in setWidgetOptions 8073 // the selected value would get lost in html 8074 var selectedOption = this.$userControl.find('[selected]'); 8075 this.$userControl.children("option[data-user-option]").remove(); 8076 } 8077 for (i = 0, j = 0; j < val.length; j++) { 8078 element = val[j]; 8079 if (element.save != AF_OPTGROUP_NAME) { 8080 // Add options to String[] which will be later synced to the optgroup. 8081 optgroupOptions.push(element); 8082 } else { 8083 $viewOptgroup = viewOptgroups[i++]; 8084 // When optgroup is less than the required optgroups. 8085 if (i > viewOptgroups.length) { 8086 $viewOptgroup = this.addGroup(element.display); 8087 } 8088 // Undefined as it may not occur even once when list is purely of options. 8089 if (!_.isUndefined($viewOptgroup) && $viewOptgroup.label != element.display) { 8090 $viewOptgroup.label = element.display || ''; 8091 } 8092 // Check to skip the first optgroup. 8093 if (j != 0) { 8094 // Syncs options to the prev optgroup. 8095 // Prev optgroup because current optgroup marks the end of options of prev. 8096 this.handleOptions($preOptgroup, optgroupOptions); 8097 // Clear options of the optgroup for next optgroup. 8098 optgroupOptions = []; 8099 } 8100 $preOptgroup = $viewOptgroup; 8101 } 8102 } 8103 // Removes all extra optgroups. 8104 while (i < viewOptgroups.length) { 8105 $viewOptgroup = viewOptgroups[i++]; 8106 this.deleteGroup($viewOptgroup.label); 8107 } 8108 //Add remaining options to respective optgroup. 8109 if (optgroupOptions.length != 0) { 8110 this.handleOptions($preOptgroup, optgroupOptions, selectedOption); 8111 } 8112 8113 //Intentionally left the selection check -> I am relying on the fact that "value" sync event is called after "items" sync. 8114 }, 8115 8116 "displayValue": function () { 8117 }, 8118 "placeholder": function(value){ 8119 // overriding the default handling of place holder options setter 8120 }, 8121 "access": function (val) { 8122 switch (val) { 8123 case "open" : 8124 this.$userControl.removeAttr("disabled"); 8125 this.$userControl.removeAttr("aria-disabled"); 8126 break; 8127 case "nonInteractive" : 8128 case "protected" : 8129 case "readOnly" : 8130 this.$userControl.attr("disabled", "disabled"); 8131 this.$userControl.attr("aria-disabled", "true"); 8132 break; 8133 default : 8134 this.$userControl.removeAttr("disabled"); 8135 this.$userControl.removeAttr("aria-disabled"); 8136 break; 8137 } 8138 } 8139 }) 8140 }, 8141 8142 getEventMap: function () { 8143 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getEventMap.apply(this, arguments); 8144 return $.extend({}, parentOptionsMap, { 8145 "focus": [xfalib.ut.XfaUtil.prototype.XFA_ENTER_EVENT, xfalib.ut.XfaUtil.prototype.XFA_PREOPEN_EVENT], 8146 "change": xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT 8147 }) 8148 }, 8149 8150 render: function () { 8151 var existingInlineStyleAttributeValues = this.element.find("select").attr("style"), 8152 newInlineStyleAttributeValues, 8153 combinedInlineStyleAttributeValues, 8154 size = 1; 8155 8156 this.element.addClass(this._widgetName); 8157 this.element.children().remove(); 8158 8159 var inputName = _.uniqueId("select"), //Unique Id 8160 textStyle = this.getOrElse(this.$data(this.element.get(0), "xfamodel"), "textstyle", ""), 8161 $widgetSkeleton = $(this.widgetSkeleton) 8162 .attr('style', textStyle) 8163 .attr('name', inputName); 8164 if(this.options.editable) { 8165 $widgetSkeleton.addClass('combobox'); 8166 } 8167 8168 if(this.options.items && this.options.items.length>0){ 8169 size = this.options.items.length 8170 } 8171 if(this.options.multiSelect) { 8172 $widgetSkeleton.addClass('multiDropdown'); 8173
8173 $widgetSkeleton.attr('multiple','multiple'); 8174 $widgetSkeleton.attr('size',size); 8175 $widgetSkeleton.attr('data-multiple-selection',"true"); 8176 } 8177 8178 var $parEl = $widgetSkeleton; 8179 _.each(this.options.items, function(item){ 8180 var saveItem = _.isString(item.save) ? item.save.replace(/\"/g, """) : ""; 8181 if (saveItem === this.AF_OPTGROUP_NAME){ // assuming optgroups appear before options 8182 $parEl = $(this.optGroupSkeleton).attr('label', item.display).appendTo($widgetSkeleton); 8183 } else { 8184 $(this.optionSkeleton).val(saveItem).text(item.display).appendTo($parEl); 8185 } 8186 },this); 8187 8188 this.element.append($widgetSkeleton); 8189 8190 var control = this.element.children().eq(0).attr("name", this.options.name); 8191 this._attachEventHandlers(control); 8192 newInlineStyleAttributeValues = this.element.find("select").attr("style"); 8193 //append the previous inlineStyleAttributeValues to newInlineStyleAttributeValues so that the inline styles 8194 //added from the dialog are applied. 8195 combinedInlineStyleAttributeValues = newInlineStyleAttributeValues + existingInlineStyleAttributeValues; 8196 this.element.find("select").attr("style", combinedInlineStyleAttributeValues); 8197 return control; 8198 }, 8199 8200 //syncs the options to the optgroup dynamically. 8201 handleOptions : function ($viewOptgroup, val, selectedOption) { 8202 //When the list so far consists purely of options. 8203 if (_.isUndefined($viewOptgroup)) { 8204 $viewOptgroup = this.$userControl[0]; 8205 } 8206 var viewOptions = $("option[data-user-option]", $viewOptgroup); 8207 //Syncs the value of options. 8208 for (var i = 0, j = 0; i < viewOptions.length && j < val.length; i++, j++) { 8209 var $viewOption = viewOptions[i]; 8210 var element = val[j]; 8211 if ($viewOption.text != element.display) { 8212 $viewOption.text = element.display || ''; 8213 } 8214 if ($viewOption.value != element.save) { 8215 $viewOption.value = element.save || ''; 8216 } 8217 } 8218 //Deletes options if count is more than required. 8219 while (i < viewOptions.length) { 8220 this.deleteOption(viewOptions[i++]) 8221 } 8222 //Add options if count is less than required. 8223 while (j < val.length) { 8224 this.addOption($viewOptgroup, val[j++], selectedOption); 8225 } 8226 // Set empty value to dropdown if placeholder and default value is not present 8227 if (this.options.placeholder.length == 0) { 8228 if (this.checkForEmptyValue(this.options.value)) { 8229 this.$userControl[0].value = ""; 8230 } 8231 } 8232 }, 8233 8234 addOption : function ($viewOptgroup, element, selectedOption) { 8235 var $newOption = $(this.optionSkeleton).val(element.save).text(element.display); 8236 $newOption.appendTo($viewOptgroup); 8237 if(selectedOption) { 8238 if(element.save === selectedOption.val() && element.display === selectedOption.text()) { 8239 $newOption.prop("selected", true); 8240 } 8241 } 8242 // Since the displayValue is a '\n' separated string of selected values in case of multiSelect, 8243 // we convert it to an array and check whether that array contains the save value of the element 8244 var values; 8245 if (this.options.value && _.isString(this.options.value)) { 8246 values = this.options.value.split('\n'); 8247 } else if (_.isArray(this.options.value)) { 8248 // In the case of AF we have value/displayValue as an array 8249 values = this.options.value 8250 } 8251 if (values && values.indexOf(element.save) >= 0) { 8252 //Delete emptyValue with no placeholder text configured and value is found in options 8253 if (this.options.placeholder.length == 0 && this.$userControl.children('[data-empty-option]').length > 0) { 8254 this.$userControl[0].removeChild(this.$userControl.children('[data-empty-option]')[0]); 8255 } 8256 this.$userControl.children().filter(function() { 8257 return this.value == element.save; 8258 }).prop("selected", true); 8259 } 8260 }, 8261 8262 deleteOption: function ($viewOption) { 8263 this.$userControl.find('option[value='+$viewOption.value+']').remove(); 8264 }, 8265 8266 checkForEmptyValue: function(value) { 8267 if ((value && _.isArray(value) && value[0] == null) || (this.options.value == null)) 8268 return true; 8269 else 8270 return false;
8271 }, 8272 8273 addGroup: function(label) { 8274 //Creates a optgroup Node. 8275 var optionGroup = document.createElement("OPTGROUP"); 8276 optionGroup.label = label; 8277 this.$userControl[0].appendChild(optionGroup); 8278 return optionGroup; 8279 }, 8280 8281 deleteGroup: function(label) { 8282 this.$userControl.children().remove('optgroup[label='+label+']'); 8283 }, 8284 8285 addItem: function(itemValues) { 8286 var newOption = new Option(itemValues.sDisplayVal || '', itemValues.sSaveVal || ''), 8287 val = this.options.value; 8288 8289 this.$userControl[0].add(newOption, null); 8290 8291 // if item has same value as present in options then mark it as selected 8292 if (_.contains(val, itemValues.sSaveVal)) { 8293 this.$userControl.find("option[value=" + itemValues.sSaveVal + "]").prop("selected", true); 8294 var emptyValue = this.$userControl.children('[data-empty-option]'); 8295 if (emptyValue.length > 0 && emptyValue.val() === itemValues.sSaveVal) { 8296 this.$userControl[0].removeChild(emptyValue[0]); 8297 } 8298 } else if ((val == null || val.length == 0 || val[0] == null) && this.options.placeholder.length == 0) { 8299 // Value should remain empty if option is not already selected & placeholder is empty 8300 this.$userControl[0].value = ""; 8301 } 8302 }, 8303 8304 clearItems: function () { 8305 //Deleting all the options including optGroup except the empty value. 8306 this.$userControl.children().not('[data-empty-option]').remove(); 8307 }, 8308 8309 deleteItem: function (nIndex) { 8310 //check for emptyValue instead of blindly doing + 1 8311 if (this.$userControl[0].item(0) && this.$userControl[0].item(0).id == "emptyValue") 8312 nIndex = nIndex + 1; 8313 //if there is emptyValue element then just delete one index higher 8314 //this check is must instead of blindly increasing the index by 1 because NWKListBox extends this class and that doesn't maintain emptyValue 8315 this.$userControl[0].remove(nIndex); 8316 }, 8317 8318 getCommitValue: function (event) { 8319 var value = $("option:selected", this.$userControl).map(function () { 8320 return $(this).val(); 8321 }).get(); 8322 return value; 8323 }, 8324 8325 showDisplayValue: function () { 8326 }, 8327 8328 destroy: function () { 8329 this.element. 8330 removeClass(this._widgetName). 8331 children().remove(). 8332 text(""); 8333 8334 // call the base destroy function 8335 $.xfaWidget.defaultWidget.prototype.destroy.apply(this, arguments); 8336 }, 8337 8338 _handleKeyDown: function (event) { 8339 8340 if (event.keyCode == 13) { 8341 //do nothing 8342 //just override the return key behaviour and over to defaultWidget for rest of the stuff. 8343 //return key is intercepted to avoid submission of form which is default behavior of html form element 8344 //but as a side effect it also stops the closing of drop down only in IE -> probably I should use IE condition but 8345 // this code works fine in chrome as well so keeping it that way. 8346 //watson bug#3675141 8347 } 8348 else 8349 $.xfaWidget.defaultWidget.prototype._handleKeyDown.apply(this, arguments); 8350 }, 8351 8352 // CQ-51462 : focus and commit event (change) happen together hence first selection was modifying the value 8353 // we do not want focus to modify the value that is about to be committed 8354 showValue : function() { 8355 8356 } 8357 }); 8358})($, _); 8359(function($, _){ 8360 $.widget( "xfaWidget.listBox", $.xfaWidget.defaultWidget, { 8361 8362 _widgetName: "listBoxWidget", 8363 8364 options : { 8365 value : [], 8366 items : [], 8367 multiSelect : false 8368 }, 8369 8370 getOptionsMap: function() { 8371 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this,arguments); 8372 return $.extend({},parentOptionsMap,{ 8373 "width" : function(val) { 8374 //Bug#3597771. setting the height more than 0.95 brings scrollbar 8375 this.options.width = val*0.95 8376 parentOptionsMap.width.apply(this,[this.options.width]) 8377 }, 8378 "access" : function() {}, 8379 "value": function(val) { 8380 var newValues = this.options.value, 8381 self = this, 8382 tabSet = false;
8383 if(!_.isArray(newValues)) 8384 newValues = [newValues]; 8385 var tabSet 8386 this.$userControl.children().each(function(){ 8387 var saveVal = $(this).attr("data-save"); 8388 8389 // Check if this value is present in options value array 8390 if(newValues && _.contains(newValues, saveVal)){ 8391 self._selectListItem($(this)); 8392 tabSet = true; 8393 8394 // Set the selected data attribute to true. 8395 if (!$.data(this, "_xfaInitialized")) { 8396 //Initialized data- attributes parse for once using this call. 8397 // Next onward don't use this. Instead use $.data which is cheap/ 8398 $(this).data(); 8399 $.data(this, "_xfaInitialized", true); //Mark the element to say that data has been initialized. 8400 } 8401 $.data(this, "selected", true); 8402 8403 } 8404 else{ 8405 $(this).removeClass("item-selected"); 8406 $(this).addClass("item-selectable"); 8407 $(this).attr("tabIndex", "-1"); 8408 } 8409 }); 8410 if(!tabSet) { 8411 $(this.$userControl.children().get(0)).attr("tabIndex", this.options.tabIndex); 8412 } 8413 }, 8414 8415 "items" : function(val) { 8416 if(!_.isArray(val)) 8417 val = [val]; 8418 var viewItems = this.$userControl.children(); 8419 8420 //if number of items are not same in model and view then balance it 8421 if((viewItems.length) > val.length){ 8422 for(var i=viewItems.length; i > val.length; i--){ 8423 this.deleteItem(i-1); 8424 } 8425 } 8426 else if((viewItems.length) < val.length){ 8427 for(var i=viewItems.length; i < (val.length); i++){ 8428 this.addItem({sDisplayVal: val[i].display, sSaveVal: val[i].save}); 8429 } 8430 } 8431 8432 _.each(val, function(element, index){ 8433 var $viewItem = $(viewItems[index]); 8434 if( $viewItem.text() != element.display){ 8435 $viewItem.text(element.display || ''); 8436 } 8437 8438 if( $viewItem.attr("data-save") != element.save){ 8439 $viewItem.attr("data-save", element.save || ''); 8440 } 8441 }); 8442 8443 //Intentionally left the selection check -> I am relying on the fact that "value" sync event is called after "items" sync. 8444 }, 8445 8446 "displayValue" : function(){;}, 8447 8448 "tabIndex": function() { 8449 var selectedItem = this.$userControl.children(".item-selected"), 8450 children =this.$userControl.children() 8451 if(selectedItem.length) { 8452 selectedItem.eq(0).attr("tabIndex", this.options.tabIndex); 8453 } 8454 else if(children.length > 0) { 8455 children.eq(0).attr("tabIndex", this.options.tabIndex); 8456 } 8457 } 8458 }) 8459 }, 8460 8461 getEventMap: function() { 8462 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getEventMap.apply(this,arguments); 8463 return $.extend({},parentOptionsMap,{ 8464 "listboxenter":xfalib.ut.XfaUtil.prototype.XFA_ENTER_EVENT, 8465 "listboxexit":xfalib.ut.XfaUtil.prototype.XFA_EXIT_EVENT, 8466 "listboxchange":xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT, 8467 "focus":null, 8468 "blur":null 8469 }) 8470 }, 8471 8472 showDisplayValue : function() { 8473 }, 8474 8475 render : function() { 8476 this.element.addClass( this._widgetName); 8477 this.element.children().remove(); 8478 8479 //TODO: add a function for geting textStyle 8480 var textStyle = this.getOrElse(this.$data(this.element.get(0), "xfamodel"), "textstyle", ""), 8481 that = this, 8482 //Bug#3597771 width and height are provided by the view itself. 8483 listElTemplate = 8484 '<ol style="position:absolute;<%=textStyle%>" role="listbox">' + 8485 '<% _.each(items, function(item){ %>' + 8486 '<% var saveItem = item.save ? item.save.replace(/\"/g,"""):null %>'+ 8487 '<li role="option" data-save="<% print(saveItem) %>" data-selected="false"><% print(item.display) %></li>'+ 8488 '<%})%>'+ 8489 '</ol>', 8490 compiledListElTemplate = _.template(listElTemplate), 8491 templateOptions = _.extend({ 8492 "textStyle" : textStyle 8493 }, this.options), 8494 resolvedListEl = compiledListElTemplate(templateOptions); 8495 that.element.html(xfalib.ut.XfaUtil.prototype.encodeScriptableTags(resolvedListEl)); 8496 var control = $(that.element.children().get(0)).attr("name",this.options.name); 8497 this._attachEventHandlers(control); 8498 return control 8499 }, 8500 8501 focus: function() { 8502 if(this.$userControl.children(".item-selected").length > 0) { 8503 this.$userControl.children(".item-selected")[0].focus(); 8504 } 8505 else if(this.$userControl.children().length > 0) { 8506 this.$userControl.children()[0].focus(); 8507 } 8508 }, 8509 8510 addItem : function(itemValues){ 8511 $("<li></li>") 8512 .attr("data-save", itemValues.sSaveVal || '') 8513 .text(itemValues.sDisplayVal || '') 8514 .appendTo(this.$userControl)
8515 .click($.proxy(this._handleItemClick, this)) 8516 .focus($.proxy(this._handleItemFocus, this)); 8517 8518 // add new item as selected if the value is already present in options 8519 if (_.contains(this.options.value, itemValues.sSaveVal)) { 8520 this._selectListItem(this.$userControl.find("[data-save=" + itemValues.sSaveVal+ "]")); 8521 } 8522 }, 8523 8524 clearItems : function(){ 8525 $(this.$userControl).empty(); 8526 }, 8527 8528 deleteItem : function(nIndex){ 8529 $(this.$userControl).children('li').each(function(index,element){ 8530 if(index==nIndex){ 8531 $(element).off("click").off("focus").remove(); 8532 } 8533 }) 8534 }, 8535 8536 8537 _attachEventHandlers : function($control){ 8538 var self = this; 8539 $control.keydown($.proxy(this._hotKeys,this)) 8540 .children().on("mousedown",function() { 8541 if(self.inFocus == true) { 8542 self.mouseDown = true; 8543 } 8544 }) 8545 .click($.proxy(this._handleItemClick, this)) 8546 .focus($.proxy(this._handleItemFocus, this)) 8547 .blur($.proxy(this._handleFocusOut,this)) 8548 8549 }, 8550 8551 _hotKeys : function(event){ 8552 if(this.options.access != "open") 8553 return; 8554 if(this.itemInFocus){ 8555 switch(event.which) { 8556 case 38: //arrow up 8557 var prevSibling = $(this.itemInFocus).prev(); 8558 if(prevSibling){ 8559 this.keyDown = true; 8560 prevSibling.focus(); 8561 this.keyDown = false; 8562 } 8563 event.preventDefault(); 8564 break; 8565 case 40: //arrow down 8566 var nextSibling = $(this.itemInFocus).next(); 8567 if(nextSibling){ 8568 this.keyDown = true; 8569 nextSibling.focus(); 8570 this.keyDown = false; 8571 } 8572 event.preventDefault(); 8573 break; 8574 case 91: //left arrow 8575 case 92: //right arrow 8576 event.preventDefault(); 8577 break; 8578 case 32: 8579 this._toggleItem(this.itemInFocus); 8580 event.preventDefault(); 8581 break; 8582 default: 8583 } 8584 } 8585 }, 8586 8587 _toggleItem: function(item) { 8588 var $item = $(item), 8589 multiMode = this.options.multiSelect, // && event.ctrlKey ; 8590 that = this; 8591 //toggle selected state of this item 8592 this.$data(item, "selected", !this.$data(item, "selected")); 8593 var state = this.$data(item, "selected") 8594 8595 if(!multiMode) { 8596 var $selectedItem = this.$userControl.children(".item-selected") 8597 if($selectedItem.length) {
8598 this.$data($selectedItem[0],"selected",false) 8599 $selectedItem.removeClass("item-selected").addClass("item-selectable") 8600 } 8601 } 8602 $item.toggleClass("item-selectable",!state). 8603 toggleClass("item-selected",state) 8604 8605 this.$userControl.trigger("listboxchange"); 8606 }, 8607 8608 getCommitValue: function() { 8609 var that = this, 8610 multiMode = this.options.multiSelect; 8611 8612 8613 return this.$userControl.children().map(function(){ 8614 // intentionally using $this.attr("data-save") instead of $this.data("data") 8615 return that.$data(this, "selected") ? $(this).attr("data-save") : null; 8616 }).get(); 8617 }, 8618 8619 _handleItemFocus : function(event){ 8620 if(this.options.access != "open") 8621 return; 8622 var item = event.target; 8623 this.itemInFocus = item; 8624 8625 // overriding default widgets handleFocus 8626 if(!(this.keyDown || this.mouseDown)) { //we do not need to fire focus event if 8627 this.$userControl.trigger("listboxenter") // clicked on another li element or pressed a key to move the selectio 8628 } 8629 this.mouseDown = false; 8630 this.inFocus = true; 8631 }, 8632 8633 _handleItemClick : function(event){ 8634 // Bug#3501811 If clicked onlistbox entry more than once, exit event is not fired 8635 // Clicking on the same entry does not call focus and hence we were not resetting the state. Doing it in onClick 8636 if(this.mouseDown == true) 8637 this.mouseDown = false; 8638 if(this.options.access != "open") 8639 return; 8640 this._toggleItem(event.target) 8641 }, 8642 8643 _handleFocusOut: function(){ 8644 if(!(this.keyDown || this.mouseDown)) { 8645 this.$userControl.trigger("listboxexit"); 8646 this.inFocus = false 8647 } 8648 }, 8649 8650 _selectListItem : function ($elem) { 8651 if ($elem && $elem.length) { 8652 $elem.removeClass("item-selectable") 8653 .addClass("item-selected") 8654 .attr("tabIndex", this.options.tabIndex); 8655 } 8656 }, 8657 8658 destroy: function() { 8659 this.element. 8660 removeClass(this._widgetName). 8661 children().remove(). 8662 text(""); 8663 8664 $.xfaWidget.defaultWidget.prototype.destroy.apply(this, arguments); 8665 } 8666}); 8667})($, window._); 8668(function($) { 8669 $.widget( "xfaWidget.nwkListBox", $.xfaWidget.dropDownList, { //non-webkit listbox 8670 8671 _widgetName : "nwkListBox", 8672 8673 options : { 8674 value : [], 8675 multiSelect : false 8676 }, 8677 8678 render : function() { 8679 var $control = $.xfaWidget.dropDownList.prototype.render.apply(this, arguments); 8680 if($control){ 8681 $control.children("#emptyValue").remove(); 8682 if(this.options.multiSelect) 8683 $control.attr("multiple", "multiple"); 8684 } 8685 this._updateSelectSize($control); 8686 return $control; 8687 }, 8688 8689 addItem : function(itemValues){ 8690 $.xfaWidget.dropDownList.prototype.addItem.apply(this, arguments); 8691 this._updateSelectSize(); 8692 }, 8693 8694 clearItems : function(){ 8695 $.xfaWidget.dropDownList.prototype.clearItems.apply(this, arguments); 8696 this._updateSelectSize(); 8697 }, 8698 8699 deleteItem : function(nIndex){ 8700 $.xfaWidget.dropDownList.prototype.deleteItem.apply(this, arguments); 8701 this._updateSelectSize(); 8702 }, 8703 8704 _updateSelectSize : function($control){ 8705 $control = $control || this.$userControl; 8706 $control.attr("size", (this.options.items || []).length); 8707 }, 8708 8709 // Bug#3597771 8710 // focus and commit event happen together hence first selection was modifying the value 8711 // we do not want focus to modify the value that is about to be committed 8712 showValue : function() { 8713 8714 } 8715 8716 }); 8717})($); 8718(function ($) { 8719 $.widget("xfaWidget.xfaButton", $.xfaWidget.defaultWidget, { //commitEvent: change; commitProperty: value<Array> 8720 8721 _widgetName: "xfaButton", 8722 8723 options: { 8724 value: null, 8725 svgCaption: false //option to indicate if button already has an SVG caption 8726 }, 8727 8728 getOptionsMap: function () { 8729 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this, arguments); 8730 return $.extend({}, parentOptionsMap, { 8731 "access": function (val) { 8732 switch (val) { 8733 case "open" : 8734 this.$userControl.removeAttr("disabled"); 8735 this.$userControl.removeAttr("aria-disabled"); 8736 break; 8737 case "nonInteractive" : 8738 case "protected" : 8739 case "readOnly" : 8740 this.$userControl.attr("disabled", "disabled"); 8741 this.$userControl.attr("aria-disabled", "true"); 8742 break; 8743 default : 8744 this.$userControl.removeAttr("disabled"); 8745 this.$userControl.removeAttr("aria-disabled"); 8746 break; 8747 } 8748 }, 8749 "value": function () { 8750 }, 8751 "displayValue": function () { 8752 }, 8753 "svgCaption": function (val) { 8754 if (val) { 8755 this.$userControl.removeAttr("value"); 8756 } 8757 } 8758 }) 8759 }, 8760 8761 _attachEventHandlers: function ($control) { 8762 $control.click(function () { 8763 this.focus() 8764 }); 8765 }, 8766 8767 getCommitValue: function () { 8768 return this.options.value; 8769 }, 8770 8771 showValue: function () { 8772 }, 8773 8774 showDisplayValue: function () { 8775 } 8776 }); 8777})($);(function ($) { 8778 $.widget("xfaWidget.XfaCheckBox", $.xfaWidget.defaultWidget, { //commitEvent: change; commitProperty: value<Array> 8779 8780 _widgetName: "XfaCheckBox", 8781 8782 options: { 8783 value: null, 8784 state: -1, 8785 states: 2, 8786 values: [], 8787 mandatory: false 8788 }, 8789 8790 checkedState: false, 8791 clickPending: false, 8792 8793 getOptionsMap: function () { 8794 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this, arguments); 8795 return $.extend({}, parentOptionsMap, { 8796 "access": function (val) { 8797 switch (val) { 8798 case "open" : 8799 this.$userControl.removeAttr("disabled"); 8800 this.$userControl.removeAttr("aria-disabled"); 8801 break; 8802 case "nonInteractive" : 8803 case "protected" : 8804 case "readOnly" : 8805 this.$userControl.attr("disabled", "disabled"); 8806 this.$userControl.attr("aria-disabled", "true"); 8807 break; 8808 default : 8809 this.$userControl.removeAttr("disabled"); 8810 this.$userControl.removeAttr("aria-disabled"); 8811 break; 8812 } 8813 }, 8814 8815 "displayValue": function (val) { 8816 this.$userControl.attr(this.options.commitProperty, this.options.value); 8817 this._state(this.dIndexOf(this.options.values, this.options.value)); 8818 this.$userControl.attr("checked", this.checkedState ? "checked" : null); 8819 this.$userControl.prop("checked", this.checkedState ? "checked" : null); 8820 //for accessibility 8821 this.$userControl.attr("aria-checked", this.checkedState); 8822 if (this.options.state == 2) 8823 this.$userControl.addClass("neutral"); 8824 else if (this.options.states == 3) 8825 this.$userControl.removeClass("neutral"); // since current state != neutral 8826 }, 8827 8828 "allowNeutral": function (val) { 8829 var intVal = parseInt(val); 8830 if (intVal == 0 || intVal == 1) { 8831 this.options.states = 2 + intVal; 8832 } 8833 }, 8834 8835 "paraStyles": function (paraStyles) { 8836 parentOptionsMap.paraStyles.apply(this, arguments); 8837 this._handleVAlignOnExit(); 8838 } 8839 }) 8840 }, 8841 8842 getEventMap: function () { 8843 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getEventMap.apply(this, arguments); 8844 return $.extend({}, parentOptionsMap, { 8845 "xfacheckboxchange" : xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT, 8846 "xfacheckboxclick" : xfalib.ut.XfaUtil.prototype.XFA_CLICK_EVENT, 8847 "change": null, 8848 "click" : null 8849 }) 8850 }, 8851 8852 _attachEventHandlers: function ($control) { 8853 var that = this; 8854 var focusFunc = function (evnt) { 8855 if (!that.inFocus) { 8856 that.focus(); 8857 that.inFocus = true; 8858 } 8859 } 8860 var focusOutFunc = function (evnt) { 8861 that.inFocus = false;
8862 } 8863 $control.click(focusFunc).change(focusFunc).blur(focusOutFunc); 8864 $control.change($.proxy(this._handleChange,this)).click($.proxy(this._handleClick,this)); //LC-5106 8865 }, 8866 8867 getCommitValue: function () { 8868 this._state((this.options.state + 1) % this.options.states); 8869 this.$userControl.attr("checked", this.checkedState ? "checked" : null); 8870 //for accessibility 8871 this.$userControl.attr("aria-checked", this.checkedState) 8872 if (this.options.state == 2) { 8873 this.$userControl.addClass("neutral"); 8874 } 8875 else if (this.options.states == 3) 8876 this.$userControl.removeClass("neutral"); // since current state != neutral 8877 8878 return this.options.values[this.options.state]; 8879 }, 8880 8881 _handleVAlignOnExit: function (evnt) { 8882 //--this is being kept empty as no other browser (i.e Mozilla and Chrome) take the padding-bottom or padding-top into account. 8883 // the only browser to take it into consideration is IE. And moreover the alignment and padding considerations have already been taken into account in 8884 // calculations in CheckButtonFieldView.js. And on removing the entire function it takes up the _handleVAlignOnExit() of AbstractWidget. 8885 8886 }, 8887 8888 _handleChange: function (evnt) { 8889 this.$userControl.trigger("xfacheckboxchange"); //change is always fired 8890 if(this.clickPending === true) { 8891 this.clickPending = false; 8892 this.$userControl.trigger("xfacheckboxclick"); 8893 } else { 8894 // handling of this.clickPending is added to handle the case when clicked on checkbox/radiobutton label/caption 8895 this.clickPending = true; 8896 } 8897 }, 8898 8899 _handleClick: function (evnt) { 8900 var isChrome = xfalib.ut.XfaUtil.prototype.detectChrome(), 8901 isIE = xfalib.ut.XfaUtil.prototype.detectIE(), 8902 isSafari = xfalib.ut.XfaUtil.prototype.isSafari(), 8903 userControlType = this.$userControl.attr("type"); 8904 // click will not be fired if the previous state of the radiobutton is 'on'. 8905 // CQ-4312095: Checkbox movement - Click event works fine on chrome but not in iOS safari for collapsible fields 8906 // CQ-103023 : Click Event on Radio Button not working correctly in Chrome 53 8907 // CQ-103715 : CQ-103715 : Click Event on Check Box not working correctly in Chrome and Firefox, added handling for checkbox also 8908 // handling of this.clickPending is added to handle the case when clicked on checkbox/radiobutton label/caption 8909 if(($.browser.mozilla || isChrome || isSafari) && !isIE && this.clickPending === false && ((userControlType === "radio" && this.checkedState === false) || (userControlType === "checkbox"))) { 8910 this.clickPending = true; 8911 } 8912 else { 8913 this.$userControl.trigger("xfacheckboxclick"); 8914 this.clickPending = false; 8915 } 8916 }, 8917 8918 _state: function (newState) { 8919 if (newState == undefined) 8920 return this.options.state; 8921 else 8922 this.options.state = newState; 8923 this.checkedState = (newState == 0 || newState == 2); 8924 }, 8925 8926 click: function () { 8927 // trigger change for check box and for radio only if it is not selected 8928 // otherwise radio button will go in deselected state 8929 if (this.$userControl.attr("type") !== "radio" || this.options.state !== 0) { 8930 this.$userControl.trigger("change"); 8931 } 8932 //we should call only the handler since calling click will trigger change. 8933 this.$userControl.triggerHandler("click"); 8934 } 8935 }); 8936})($); 8937(function($, _){ 8938 $.widget( "xfaWidget.textField", $.xfaWidget.defaultWidget, { 8939 8940 _widgetName: "textField", 8941 8942 options: { 8943 curValue : null , 8944 pos:0, 8945 lengthLimitVisible: true, 8946 maxChars:0 , 8947 flag:"", 8948 // by default html5Type is set to true 8949 // we leverage pattern, maxLength support from HTML5 browser for mobile forms 8950 html5Type : "text", 8951 length : null, 8952 minLength : 0, 8953 totalLengthMessage : "", 8954 minimumLengthMessage : "", 8955 }, 8956 8957 getOptionsMap: function() { 8958 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this,arguments); 8959 return $.extend({},parentOptionsMap,{ 8960 "maxChars": function(maxchars) { 8961 if(this._maxCharsReached(this.options.value)) { 8962 var value = this.options.value.slice(0,maxchars) 8963 this._setOption("value", value); 8964 this._setOption("displayValue", value); 8965 } 8966 8967 }, 8968 8969 "multiLine ": function(val) { 8970 if(this.options.multiLine) 8971 this.$userControl.attr("aria-multiline", "true"); 8972 else 8973 this.$userControl.removeAttr("aria-multiline", "false"); 8974 }, 8975 8976 "height": function(val) { 8977 if(val) {
8978 this.$css(this.$userControl[0],{"height" :val}) 8979 this._handleVAlignOnExit(); // To Handle the case of expandable Fields 8980 } 8981 }, 8982 "width": function(val){ 8983 parentOptionsMap.width.apply(this,arguments); 8984 // handle valign on width change as well 8985 // as content height(scrollHeight) varies according to width 8986 this._handleVAlignOnExit(); 8987 }, 8988 "paraStyles": function(paraStyles){ 8989 parentOptionsMap.paraStyles.apply(this,arguments); 8990 this._handleVAlignOnExit(); 8991 } 8992 8993 }) 8994 }, 8995 8996 render : function() { 8997 var control = $.xfaWidget.defaultWidget.prototype.render.apply(this, arguments); 8998 // use the control to set HTML5 attributes 8999 if (control && control.length > 0 && this.options.html5Type) { 9000 var minLength = this.options.minLength, 9001 maxLength = this.options.maxChars, 9002 length = this.options.length; 9003 isMinLengthSet = minLength != null && minLength > 0, 9004 isMaxLengthSet = maxLength != null && maxLength > 0, 9005 isLengthSet = length != null && length > 0, 9006 isMultiline = this.options.multiLine, 9007 minLengthMsg = this.options.minimumLengthMessage, 9008 totLengthMsg = this.options.totalLengthMessage, 9009 pattern = ""; // html5 pattern is not supported for textarea 9010 9011 // order of execution matters for the below code snippet 9012 if (isMinLengthSet) { 9013 // add minLength though it is not fully supported in all browsers 9014 // hence also adding pattern attribute 9015 control.attr("minlength", parseInt(minLength)); 9016 if(minLengthMsg && minLengthMsg.length > 0) { 9017 control.attr("title", this.options.minimumLengthMessage); // html5 supported message on pattern validation failure 9018 } 9019 } 9020 9021 if (isMaxLengthSet) { 9022 control.attr("maxlength", parseInt(maxLength)); 9023 } 9024 9025 // if both min and max length is set 9026 if(isMinLengthSet && isMaxLengthSet){ 9027 pattern += ".{" + minLength + "," + maxLength + "}"; 9028 } else if(isMinLengthSet) { 9029 // if only min length set 9030 pattern += ".{" + minLength + ",}"; 9031 } 9032 9033 // if length is set then set min and max length in pattern equal to length 9034 if (isLengthSet) { 9035 if(isMultiline){ // set both min and maxlength as pattern is not supported 9036 control.attr("minlength", parseInt(length)); 9037 control.attr("maxlength", parseInt(length)); 9038 } 9039 if(totLengthMsg && totLengthMsg.length > 0) { 9040 control.attr("title", this.options.totalLengthMessage); 9041 } 9042 // reset the pattern string 9043 pattern = ".{" + length + "," + length + "}"; 9044 } 9045 // if required is set, set the required attribute, it is necessary else an empty value will be excluded from constraint validation 9046 if (this.options.required) { 9047 control.attr("required", true); 9048 } 9049 // set the pattern if not empty and check if this is not multiline, since pattern is not supported for textarea 9050 if (pattern && pattern.length > 0 && !isMultiline) { 9051 control.attr("pattern", pattern); 9052 } 9053 } 9054 return control; 9055 }, 9056 9057 /* This function aligns vAlign when: 9058 1. parastyles is present and the widget contains a value. 9059 2. During initial rendering if no content present fallback to the previous logic. 9060 3. Presence of content in widget. 9061 */ 9062 _handleVAlignOnExit: function(){ 9063 var value = this.options.displayValue, 9064 noContentPresent = _.isEmpty(this.$userControl.val() || this.options.displayValue), 9065 contentHeight,widgetHeight,diff,tempCSS; 9066 9067 //the widget doesn't have value as yet but content exists [ Rendering of widget] 9068 if (!this.options.paraStyles || noContentPresent) { 9069 //vAlign has to be handled only if there is paraStyles and widget has content 9070 return; 9071 } 9072 9073 // mozilla results in vAlign regression hence made this change only for textarea 9074 if($(this.element[0]).find("textarea").length >0 && !noContentPresent) { 9075 /* measureExtent not returning correct height of content in textarea even with all 9076 css values */ 9077 tempCSS={'height':this.$userControl.css('height'),'padding':this.$userControl.css('padding')};
9078 this.$css(this.$userControl[0],{'height':'1px','padding':'0px'}); 9079 9080 contentHeight = this._getContentHeight(); 9081 this.$css(this.$userControl[0],tempCSS); 9082 widgetHeight = this.options.height; 9083 diff = widgetHeight - contentHeight; 9084 this._calculatePaddingForVAlign(diff); 9085 } else { 9086 // widget has no initial content or is a textfield.Proceed as before. 9087 $.xfaWidget.defaultWidget.prototype._handleVAlignOnExit.apply(this,arguments); 9088 } 9089 }, 9090 9091 getEventMap: function() { 9092 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getEventMap.apply(this,arguments); 9093 return $.extend({},parentOptionsMap,{ 9094 "onKeyInput.textField" : xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT 9095 }) 9096 }, 9097 9098 _maxCharsReached: function(val) { 9099 var isMaxLengthSupported = false, 9100 elementName = this.options.multiLine ? "textarea" : "input"; 9101 // in browsers, where max length is supported, we don't custom javascript checks, we let HTML do the validation of max length 9102 if(this.options.html5Type && xfalib.view.util.HtmlUtil.elementSupportsAttribute(elementName, "maxLength")){ 9103 isMaxLengthSupported = true; 9104 } 9105 return !isMaxLengthSupported && this.options.maxChars 9106 && this.options.maxChars!=="0" 9107 && val 9108 && val.length >= this.options.maxChars 9109 }, 9110 9111 _handleKeyInput : function(event, character, code) { 9112 if(event.ctrlKey && !_.contains(['paste', 'cut'], event.type)) { 9113 return true; 9114 } 9115 9116 if(!this.options.multiLine) { 9117 $.xfaWidget.defaultWidget.prototype._handleKeyDown.apply(this, arguments); 9118 character = (code == 13) ? '' : character ; 9119 } 9120 9121 var val = this.$userControl.val(), 9122 selectionStart = xfalib.view.util.HtmlUtil.getHTMLSupportedAttr(this.$userControl[0], "selectionStart") || 0, 9123 selectionEnd = xfalib.view.util.HtmlUtil.getHTMLSupportedAttr(this.$userControl[0], "selectionEnd") || 0, 9124 pos = selectionStart, 9125 // CQ-4260239 : " " taking space of 5 chars for restricting the length to visible area 9126 newVal = (val.substr(0, selectionStart) + character + val.substr(selectionEnd)); 9127 this.options.curValue = val; 9128 if(!this.options.multiLine) { //TODO:looks like a bug 9129 this.options.lengthLimitVisible = true; 9130 this.options.pos = pos; 9131 if(this.options.hScrollDisabled && !_.contains(['keydown', 'cut'], event.type)) { 9132 var expectedWidth = xfalib.view.util.TextMetrics.measureExtent(newVal, {refEl: this.$userControl[0], maxWidth:-1}).width; 9133 if(!event.ctrlKey && expectedWidth > this.$userControl.width()){ // Why allowance of 5 required?? 9134 this.options.lengthLimitVisible = false; 9135 event.preventDefault(); 9136 return false; 9137 } 9138 } 9139 } else if (this.options.multiLine && this.options.hScrollDisabled) { // LC-4656 : wait till user input, if it causes an overflow revert to old text 9140 var $textArea = this.$userControl; 9141 $textArea.css("padding", "0px 0px 0px"); // TODO : take care of multiline selection & padding later 9142 9143 // TODO : find a scheme to avoid attaching and detaching listeners, currently $.val() causes 'input' to fire, resulting in an infinite loop 9144 $textArea.one("input", function () { 9145 if ($textArea.prop('scrollHeight') > $textArea.prop('offsetHeight')) { 9146 $textArea.val(val) 9147 .prop("selectionStart", selectionEnd) 9148 .prop("selectionEnd", selectionEnd); // LC-4656 : reset the cursor pos, afterwards 9149 character = null; 9150 code = 0; 9151 } 9152 }); 9153 } 9154 9155 if (!_.contains(['keydown', 'cut'], event.type) && this._maxCharsReached(val) && selectionStart === selectionEnd) { 9156 event.preventDefault(); 9157 return false;
9158 } 9159 9160 this.$userControl.trigger({ 9161 type : "onKeyInput.textField", 9162 originalType : event.type, 9163 character : character, // contains the pasted string or pressed key 9164 keyCode : event.keyCode || 0, 9165 charCode : event.charCode || 0, 9166 which : event.which || 0, 9167 ctrlKey : event.ctrlKey || event.metaKey || false, 9168 shiftKey : event.shiftKey || false, 9169 keyDown: false, // This property is available only for list boxes and drop-down lists 9170 selectionStart: selectionStart, 9171 selectionEnd: selectionEnd 9172 }); 9173 }, 9174 9175 _handleKeyDown : function(event){ 9176 if (event) { 9177 var code = event.charCode || event.which || event.keyCode || 0; 9178 if(code == 8 || code == 46) // backspace and del 9179 this._handleKeyInput(event, "", code); 9180 } 9181 }, 9182 9183 _handleKeyPress : function(event){ 9184 if (event) { 9185 var code = event.charCode || event.which || event.keyCode || 0, 9186 character = (code == 13) ? "\n" : String.fromCharCode(code); // modified '\r\n' -> '\n' 9187 9188 if(xfalib.ut.XfaUtil.prototype.isNonPrintableKey(event.key)) { // mozilla also generates a keypress, along with keydown 9189 return true; // for all keys, so only handling printable keys in keypress 9190 } 9191 9192 this._handleKeyInput(event, character, code); 9193 } 9194 }, 9195 9196 _compositionUpdateCallback : function (event) { 9197 var that = this; 9198 var val = that.$userControl.val(); 9199 if (event.type === "compositionupdate" && event.originalEvent.data) { 9200 // this has been deliberately done to get the actual data in case of max character. 9201 if (that.options.maxChars) { 9202 val = event.originalEvent.data; 9203 } else { 9204 val = val + event.originalEvent.data.substr(event.originalEvent.data.length - 1); 9205 } 9206 } 9207 var flag = that._maxCharsReached(val); 9208 if (flag) { 9209 // if max reached 9210 var newVal = val.substr(0, that.options.maxChars); 9211 //in case the value is not changed then we do not need to update value and close the android keyboard. 9212 if (val === newVal) { 9213 return false; 9214 } 9215 that.$userControl.val(newVal); 9216 } 9217 return flag; 9218 }, 9219 9220 _attachEventHandlers: function($control) { 9221 $.xfaWidget.defaultWidget.prototype._attachEventHandlers.apply(this, arguments); 9222 // IME specific handling, to handle japanese languages max limit 9223 $.xfaWidget.defaultWidget.prototype._attachCompositionEventHandlers.apply(this, arguments); 9224 }, 9225 9226 _handlePaste : function(event){ 9227 if (event) { 9228 var pastedChar = undefined; 9229 if (window.clipboardData && window.clipboardData.getData) { // IE 9230 pastedChar = window.clipboardData.getData('Text'); 9231 } else if (event.originalEvent.clipboardData && event.originalEvent.clipboardData.getData) { 9232 pastedChar = event.originalEvent.clipboardData.getData('text/plain'); 9233 } 9234 if(pastedChar) { 9235 this._handleKeyInput(event, pastedChar, 0); 9236 } 9237 } 9238 }, 9239 9240 _handleCut : function(event) { 9241 if (event) { 9242 this._handleKeyInput(event, "", 0); 9243 } 9244 }, 9245 9246 postProcessExit: function(evnt) { 9247 $.xfaWidget.defaultWidget.prototype.postProcessExit.apply(this,arguments); 9248 if (this.options.multiLine && this.options.hScrollDisabled) { 9249 return; 9250 } 9251 this._handleVAlignOnExit(); 9252 }, 9253 9254 preProcessEnter: function(evnt) { 9255 $.xfaWidget.defaultWidget.prototype.preProcessEnter.apply(this,arguments); 9256 if(this.options.multiLine && this.options.hScrollDisabled) 9257 return; 9258 this._handleVAlignOnEnter(); 9259 }, 9260 9261 /** 9262 * @brief: Select the given field on focus in Internet Explorer 9263 * 9264 */ 9265 _selectOnFocusInIE : function(){ 9266 // if the value is not same only then do selection in IE 9267 // For Issue: LC-9895, we check if value not same 9268 if($.browser.msie && !this._isValueSame()) { 9269 this.$userControl.select(); 9270 } 9271 else { 9272 //all other browsers behave like a good boy 9273 } 9274 }, 9275 9276 showValue : function() { 9277 $.xfaWidget.defaultWidget.prototype.showValue.apply(this,arguments); 9278 //IE doesn't show selected text if we focus and set its value all the time so force selection 9279 this._selectOnFocusInIE(); 9280 }, 9281 9282 getCommitValue: function() { 9283 var value = $.xfaWidget.defaultWidget.prototype.getCommitValue.apply(this, arguments); 9284 9285 if(this._maxCharsReached(value)) { 9286 value = value.slice(0,this.options.maxChars); 9287 } 9288 9289 this.$userControl.val(this.options.value); 9290 9291 //TODO: ask Sharad whether it is right 9292 if(this.options.multiLine && this.options.hScrollDisabled) { 9293 //var str= this._checkLines(value); 9294 //if(value != str) { 9295 return value; 9296 //} 9297 } 9298 return value; 9299 }, 9300 9301 /* 9302 ** returns the contentHeight which needs to be considered for padding for valign, 9303 ** if no contentHeight is present then fontSize is returned. 9304 */ 9305 _getContentHeight: function () {
9306 var contentHeight = Math.ceil(this.$userControl.get(0).scrollHeight); 9307 return contentHeight ? contentHeight : this.options.fontSize; 9308 } 9309 }); 9310})($, window._); 9311/************************************************************************* 9312 * 9313 * ADOBE CONFIDENTIAL 9314 * __________________ 9315 * 9316 * Copyright 2019 Adobe Systems Incorporated 9317 * All Rights Reserved. 9318 * 9319 * NOTICE: All information contained herein is, and remains 9320 * the property of Adobe Systems Incorporated and its suppliers, 9321 * if any. The intellectual and technical concepts contained 9322 * herein are proprietary to Adobe Systems Incorporated and its 9323 * suppliers and may be covered by U.S. and Foreign Patents, 9324 * patents in process, and are protected by trade secret or copyright law. 9325 * Dissemination of this information or reproduction of this material 9326 * is strictly forbidden unless prior written permission is obtained 9327 * from Adobe Systems Incorporated. 9328 **************************************************************************/ 9329 9330(function ($) { 9331 $.widget("xfaWidget.richTextField", $.xfaWidget.textField, { 9332 9333 _widgetName : "richTextField", 9334 9335 _richTextWidget : null, 9336 9337 _changeAccess : function (val) { 9338 switch (val) { 9339 case "open": 9340 if (this._richTextWidget) { 9341 this._richTextWidget.editor.enable(); 9342 this._richTextWidget.$toolbar.removeClass("hideToolbar"); 9343 } 9344 break; 9345 case "readOnly": 9346 if (this._richTextWidget) { 9347 this._richTextWidget.editor.disable(); 9348 this._richTextWidget.$toolbar.addClass("hideToolbar"); 9349 } 9350 break; 9351 } 9352 }, 9353 9354 getOptionsMap : function () { 9355 var parentOptionsMap = $.xfaWidget.textField.prototype.getOptionsMap.apply(this, arguments); 9356 return $.extend({}, parentOptionsMap, { 9357 "value" : function (val) { 9358 if (this._richTextWidget) { 9359 this._richTextWidget.setRichTextEditorContent(val); 9360 } 9361 }, 9362 "access" : function (val) { 9363 this._changeAccess(val); 9364 } 9365 }); 9366 }, 9367 9368 getEventMap : function () { 9369 // in case of IE browsers, focus event is delayed, hence adding activate method for content editable 9370 if (xfalib.ut.XfaUtil.prototype.isIE()) { 9371 var parentOptionsMap = $.xfaWidget.textField.prototype.getEventMap.apply(this, arguments); 9372 return $.extend({}, parentOptionsMap, { 9373 "activate.richTextField" : xfalib.ut.XfaUtil.prototype.XFA_ENTER_EVENT 9374 }); 9375 } else { 9376 return $.xfaWidget.textField.prototype.getEventMap.apply(this, arguments); 9377 } 9378 }, 9379 9380 render : function () { 9381 var $richTextWidget = this.element.find("div.richTextWidget").eq(0); 9382 if(!$richTextWidget.length){ 9383 var attachedTextareaClasses = this.element.children().attr('class'); 9384 var richTextWidgetElement = '<div class="richTextWidget ' + attachedTextareaClasses + '" id="richTextField_' + this.options.name + '_' + attachedTextareaClasses + '"></div>'; 9385 this.element.children().remove(); 9386 this.element.append(richTextWidgetElement); 9387 $richTextWidget = this.element.find("div.richTextWidget").eq(0); 9388 }else{ 9389 $richTextWidget.children().remove(); 9390 } 9391 $richTextWidget.append(this.options.value); 9392 return $.xfaWidget.defaultWidget.prototype.render.apply(this, arguments); 9393 }, 9394 9395 getCommitValue : function () { 9396 var value = ""; 9397 if (this._richTextWidget) { 9398 value = this._richTextWidget.getRichTextEditorContent(); 9399 } 9400 return value; 9401 }, 9402 9403 preProcessEnter : function (evnt) { 9404 $.xfaWidget.textField.prototype.preProcessEnter.apply(this, arguments); 9405 var $richTextDiv = this.$userControl.find("div.richTextWidget").eq(0); 9406 if(!$richTextDiv.length){ 9407 $richTextDiv = this.element.find("div.richTextWidget").eq(0); 9408 this.changeDefaultToolbarConfig();
9409 this.$userControl.parents('.richtextsupport').css('z-index', 'auto'); 9410 } 9411 if (window.Form === undefined || window.Form.rte === undefined) { 9412 /* Forms RTE is part of Forms Addon package only. Dont do anything if addon is not installed.*/ 9413 return; 9414 } else if (this._richTextWidget === null) { 9415 this._initializeRTEToolbar(); 9416 this._richTextWidget = new window.Form.rte.RichTextEditor({ 9417 selector : $richTextDiv.attr("id"), 9418 toolbar : window.Form.rte.RichTextEditor.MFToolbar, 9419 data : this.options.value, 9420 locale : $richTextDiv.data("locale") 9421 }); 9422 var that = this; 9423 this._richTextWidget.editor.on("blur:composer", function () { 9424 that.$userControl.trigger("blur"); 9425 }); 9426 // initialize the access 9427 if (this.options.access) { 9428 this._changeAccess(this.options.access); 9429 } 9430 } 9431 }, 9432 9433 changeDefaultToolbarConfig: function(){ 9434 if(window.Form && window.Form.rte){ 9435 var toolbarDefaultConfigData = window.Form.rte.DefaultConfig; 9436 toolbarDefaultConfigData.fontSize.defaultValue = this.options.fontSize; 9437 toolbarDefaultConfigData.fontFamily.defaultValue = this.options.fontFamily; 9438 9439 // Adding 'isFontInPx' flag and overriding two utility functions 9440 // 'getDefaultParaStyle' and 'getMissingParaStyle' are responsible for adding RTE font styling attributes to rich text elements 9441 toolbarDefaultConfigData.isFontInPx = true; 9442 this.changeDefaultParaStyleUtility(); 9443 this.changeMissingParaStyleUtility(); 9444 9445 // Adding dropdown values in default config if not available in options 9446 if(toolbarDefaultConfigData.fontSize.options.indexOf(this.options.fontSize) === -1){ 9447 toolbarDefaultConfigData.fontSize.options.push(this.options.fontSize); 9448 } 9449 if(toolbarDefaultConfigData.fontFamily.options.indexOf(this.options.fontFamily) === -1){ 9450 toolbarDefaultConfigData.fontFamily.options.push(this.options.fontFamily); 9451 } 9452 } 9453 }, 9454 9455 changeDefaultParaStyleUtility: function(){ 9456 Form.rte.util.HtmlUtils.getDefaultParaStyle = function (config) { 9457 var style = ""; 9458 if (config) { 9459 style += 'font-family:' + config.fontFamily.defaultValue + ';'; 9460 if(config.isFontInPx){ 9461 style += 'font-size:' + config.fontSize.defaultValue + 'px;'; 9462 style += 'letter-spacing:' + config.letterSpacing.defaultValue + 'px;'; 9463 }else{ 9464 style += 'font-size:' + config.fontSize.defaultValue + 'pt;'; 9465 style += 'letter-spacing:' + config.letterSpacing.defaultValue + 'pt;'; 9466 } 9467 style += 'color:#000000;'; 9468 style += 'text-align:left;'; 9469 } 9470 9471 return style; 9472 }; 9473 }, 9474 9475 changeMissingParaStyleUtility : function(){ 9476 Form.rte.util.HtmlUtils.getMissingParaStyle = function (style, config) { 9477 if (style && style.length > 0) { 9478 if (config) { 9479 if (!Form.rte.util.StringHelper.endsWith(style, ";")) { 9480 style += ";"; 9481 } 9482 if (style.indexOf("font-family") < 0) { 9483 style += 'font-family:' + config.fontFamily.defaultValue + ';'; 9484 } 9485 if (style.indexOf("font-size") < 0) { 9486 if(config.isFontInPx){ 9487 style += 'font-size:' + config.fontSize.defaultValue + 'px;'; 9488 }else{ 9489 style += 'font-size:' + config.fontSize.defaultValue + 'pt;'; 9490 } 9491 } 9492 if (style.indexOf("letter-spacing") < 0) { 9493 if(config.isFontInPx){ 9494 style += 'letter-spacing:' + config.letterSpacing.defaultValue + 'px;'; 9495 }else{ 9496 style += 'letter-spacing:' + config.letterSpacing.defaultValue + 'pt;'; 9497 } 9498 } 9499 if (style.indexOf("color") < 0) { 9500 style += 'color:#000000;'; 9501 } 9502 if (style.indexOf("text-align") < 0) { 9503 style += 'text-align:left;'; 9504 } 9505 } 9506 } else { 9507 style = Form.rte.util.HtmlUtils.getDefaultParaStyle(config); 9508 } 9509 return style; 9510 }; 9511 }, 9512 9513 _initializeRTEToolbar : function () { 9514 window.Form.rte.RichTextEditor.MFToolbar = window.Form.rte.RichTextEditor.MFToolbar || { 9515 defaultMode : 'basic', 9516 toolbars : { 9517 basic : { 9518 layout : [ 9519 { 9520 items : [Form.rte.Commands.HEADER] 9521 }, 9522 { 9523 items : [Form.rte.Commands.BOLD, Form.rte.Commands.ITALIC, Form.rte.Commands.UNDERLINE] 9524 }, 9525 { 9526 command : 'lists', 9527 icon : 'list', 9528 title : "List Type", 9529 type : 'popover', 9530 placement : 'bottom', 9531 items : [Form.rte.Commands.INSERT_UNORDERED_LIST, 9532 Form.rte.Commands.INSERT_ORDERED_LIST, 9533 Form.rte.Commands.INSERT_LOWERCASE_ALPHABET_LIST] 9534 }, 9535 { 9536 title : 'Expand', 9537 command : Form.rte.Commands.MODE, 9538 value : Form.rte.ToolbarMode.FULL, 9539 icon : 'resize-full' 9540 } 9541 ], 9542 floating : true 9543 }, 9544 full : { 9545 layout : [ 9546 { 9547 items : [Form.rte.Commands.BOLD, Form.rte.Commands.ITALIC, Form.rte.Commands.UNDERLINE] 9548 }, 9549 { 9550 items : [Form.rte.Commands.SUPERSCRIPT, Form.rte.Commands.SUBSCRIPT] 9551 }, 9552 { 9553 items : [ 9554 Form.rte.Commands.HEADER, Form.rte.Commands.FONT_FAMILY, Form.rte.Commands.LINE_HEIGHT, Form.rte.Commands.FORE_COLOR, Form.rte.Commands.HILITE_COLOR, Form.rte.Commands.LINK 9555 ] 9556 }, 9557 { 9558 items : [Form.rte.Commands.INSERT_UNORDERED_LIST, Form.rte.Commands.INSERT_ORDERED_LIST, Form.rte.Commands.INSERT_LOWERCASE_ALPHABET_LIST 9559 ] 9560 }, 9561 { 9562 title : 'Collapse', 9563 command : Form.rte.Commands.MODE, 9564 value : Form.rte.ToolbarMode.BASIC, 9565 icon : 'resize-small', 9566 selected : true 9567 } 9568 ] 9569 } 9570 } 9571 }; 9572 } 9573 }); 9574 9575})($); 9576(function($){ 9577 $.widget( "xfaWidget.imageField", $.xfaWidget.defaultWidget, { 9578 9579 _widgetName:"imageField", 9580 9581 options: { 9582 tabIndex: 0, 9583 "role": "img" 9584 }, 9585 9586 getEventMap: function () { 9587 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getEventMap.apply(this, arguments); 9588 return $.extend({}, parentOptionsMap, { 9589 "imagechange": xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT 9590 }) 9591 }, 9592 9593 getOptionsMap: function() { 9594 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this,arguments); 9595 return $.extend({},parentOptionsMap,{ 9596 "screenReaderText": function(val) { 9597 if(val) 9598 this.$userControl.attr("alt", val) 9599 }, 9600 "displayValue": function(val) { 9601 var widgetValue; 9602 if (this.options.value) { 9603 widgetValue = "data:;base64," + this.options.value; 9604 } else { 9605 widgetValue = ""; 9606 } 9607 this.$userControl.prop(this.options.commitProperty, widgetValue); 9608 this.$userControl.attr(this.options.commitProperty, widgetValue); 9609 }, 9610 "access" : function() {}, 9611 9612 // CQ-85514 : use max-ht & max-wd to honor image's intrinsic ht & wd attributes & prevent distortion 9613 "height" : function (val) { 9614 // in case aspect is actual then we need to crop the image, which will be not possible if max height and width are set 9615 if (val && this.options.aspect != "actual") { 9616 this.$css(this.$userControl[0], {"max-height": val}); 9617 } 9618 }, 9619 "width" : function (val) { 9620 if (val && this.options.aspect != "actual") { 9621 this.$css(this.$userControl[0], {"max-width": val}); 9622 } 9623 }, 9624 "aspect" : function (val) { 9625 // value of actual turns off scaling, causing the image to be drawn at its native size, 9626 // as per xfa spec Adobe implementations crop the image 9627 if(this.options.aspect == "actual") { 9628 var right = this.$userControl.attr("width"), 9629 bottom = this.$userControl.attr("height"); 9630 right = right.indexOf("px") >= 0 ? right : right + "px"; 9631 bottom = bottom.indexOf("px") >= 0 ? bottom : bottom + "px"; 9632 this._cropImage("0px", right, bottom, "0px"); 9633 this.$userControl.removeAttr("height width"); 9634 // value of none indicates no aspect ratio 9635 // as per xfa spec image is independently scaled in the horizontal and vertical directions to exactly f
9635ill the field, 9636 // which are already set to fill the field 9637 } else if (this.options.aspect != "none") { 9638 // A value of fit, which is the default, causes the scale to be such that the image fills as much of the field as possible 9639 // without overflowing it in either dimension. 9640 this.$userControl.attr({"height" : "auto", "width" : "auto"}); 9641 } 9642 } 9643 }); 9644 }, 9645 9646 // crop the image using top,right, bottom, left coordiantes of the image 9647 _cropImage : function (top, right, bottom, left) { 9648 var clipRect = "rect(" + top + "," + right + "," + bottom + "," + left + ")"; 9649 var clipPathPolygon = "polygon( 0px 0px, 0px " + bottom + "," + right + " " + bottom +"," + right + " 0px)"; 9650 // clip property is deprecated but still supported by all the major browsers 9651 // clip-path replaces the deprecated clip property but still is not fully supported by all major browser 9652 this.$userControl.css({"clip" : clipRect, "clip-path" : clipPathPolygon}); 9653 }, 9654 9655 render : function() { 9656 var self = this; 9657 if (typeof FileReader !== "undefined") { 9658 this.reader = new FileReader(); 9659 } else { 9660 xfalib.ut.XfaUtil.prototype.getLogger().error("Image Field is supported only for HTML5 supported browsers."); 9661 } 9662 if (this.element) { 9663 // change event triggered when new image is selected 9664 this.$widgetInput = this.element.find("input").on("change.imageField", function() { 9665 self._handleInputChange(); 9666 }).click(function(event) { 9667 // to stop bubbling of event from input to widget 9668 event.stopPropagation(); 9669 }); 9670 this.$widgetImg = this.element.on("click.imageField", function() { 9671 self._imageClick(); 9672 }).find("img"); 9673 } 9674 if (this.reader) { 9675 //load event is triggered each time the reading operation is successfully completed 9676 this.reader.addEventListener("load", function () { 9677 self.$widgetImg.attr("src",self.reader.result); 9678 self.$widgetImg.trigger("imagechange"); 9679 }, false); 9680 } 9681 return $.xfaWidget.defaultWidget.prototype.render.apply(this, arguments); 9682 }, 9683 9684 getCommitValue: function() { 9685 return this._extractData(this.$userControl.attr("src")); 9686 }, 9687 9688 // hidden input change handler, input change will be triggered on selecting a new image 9689 _handleInputChange : function() { 9690 this._displayImage(); 9691 }, 9692 9693 _imageClick : function(clickEvent) { 9694 //as the input button is hidden we trigger click explicitly on click of the widget 9695 this.$widgetInput.trigger("click"); 9696 }, 9697 9698 // removes "data\:.*\;base64," from the image base64 string 9699 _extractData : function(value) { 9700 return value.replace(/data\:.*\;base64,/, ""); 9701 }, 9702 9703 // previews image in the imagefield widget 9704 _displayImage : function() { 9705 var imageFile = this.$widgetInput.get(0).files ? this.$widgetInput.get(0).files[0] : null; 9706 if (imageFile && this._isFileOfImageType(imageFile.name)) { 9707 if (this.reader) { 9708 //readAsDataURL method is used to read the contents of the specified file, result attribute contains the data as a URL representing the file's data as a base64 encoded string 9709 this.reader.readAsDataURL(imageFile); 9710 } 9711 } 9712 }, 9713 9714 // Test for supported image file(jpg,jpeg,png,gif,tif,bmp) 9715 _isFileOfImageType : function(fileName) { 9716 if (fileName) { 9717 return (/\.(jpe?g|png|gif|tif|bmp)$/i.test(fileName)); 9718 } 9719 return false; 9720 } 9721}); 9722})($); 9723/** 9724 * Created with IntelliJ IDEA. 9725 * User: rpandey 9726 * Date: 12/24/12 9727 * Time: 8:06 PM 9728 * To change this template use File | Settings | File Templates. 9729 */ 9730 9731 9732(function($){ 9733 $.widget( "xfaWidget.signatureField", $.xfaWidget.defaultWidget, { 9734 9735 _widgetName:"signatureField", 9736 9737 getOptionsMap: function() { 9738 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this,arguments); 9739 return $.extend({},parentOptionsMap,{ 9740 "displayValue": function(val) {}, 9741 "access": function(val) {} 9742 }) 9743 }, 9744 9745 render : function() { 9746 var $control = $.xfaWidget.defaultWidget.prototype.render.apply(this, arguments); 9747 //pessimistic checks 9748 if($control) { 9749 $control.attr("readOnly","readonly").attr("disabled", true); 9750 } 9751 return $control; 9752 } 9753 }); 9754})($); 9755/* 9756 * ADOBE CONFIDENTIAL 9757 * ___________________ 9758 * 9759 * Copyright 2011-2012 Adobe Systems Incorporated 9760 * All Rights Reserved. 9761 *
9762 * NOTICE: All information contained herein is, and remains 9763 * the property of Adobe Systems Incorporated and its suppliers, 9764 * if any. The intellectual and technical concepts contained 9765 * herein are proprietary to Adobe Systems Incorporated and its 9766 * suppliers and may be covered by U.S. and Foreign Patents, 9767 * patents in process, and are protected by trade secret or copyright law. 9768 * Dissemination of this information or reproduction of this material 9769 * is strictly forbidden unless prior written permission is obtained 9770 * from Adobe Systems Incorporated. 9771 */ 9772 9773/** 9774 * widget definition for scribbleable field 9775 */ 9776(function($,xfalib){ 9777 9778 var TouchUtil=xfalib.ut.TouchUtil; 9779 var ScribbleUtil=(function(){ 9780 return { 9781 localeString:function(id){ 9782 return xfalib.ut.XfaUtil.prototype.encodeScriptableTags($.xfaWidget.abstractWidget.prototype.localeStrings()[id]) || id; 9783 } 9784 }; 9785 })(); 9786 var DELETE_KEY = 46; 9787 var ESC_KEY = 27; 9788 var ENTER_KEY = 13; 9789/** 9790 * Scribble class definition, used for drawing on canvas using mouse or touch 9791 */ 9792function Scribble( canvasID,image,_width,_height, callback) { 9793 this._callback = callback; 9794 this.canvasID = canvasID; 9795 this._lineWidth=5; 9796 this.canvas = $("#"+canvasID); 9797 this.context = this.canvas.get(0).getContext("2d"); 9798 this.context.clearRect(0,0,this.canvas.width,this.canvas.height); 9799 this._enabled=true; 9800 this.context.strokeStyle = "#000000"; 9801 this.canvasBorderWidth = parseInt(this.canvas.css('border-left-width'),10); // assuming top and left borders are same width 9802 this.context.lineWidth = this._lineWidth; 9803 this.lastMousePoint = {x:0, y:0}; 9804 9805 this.canvas[0].width = _width;// this.canvas.parent().innerWidth(); 9806 this.canvas[0].height = _height;//this.canvas.parent().innerHeight(); 9807 if(!image){ 9808 this.context.fillStyle = '#ffffff'; 9809 this.context.clearRect(0,0,_width,_height); 9810 } else {
9811 this.context.drawImage(image,0,0); 9812 } 9813 this.canvas.on( TouchUtil.POINTER_DOWN, this.onCanvasMouseDown() ); 9814} 9815Scribble.prototype.setLineWidth=function(w){ 9816 this._lineWidth=w; 9817}; 9818Scribble.prototype.onCanvasMouseDown = function () { 9819 var self = this; 9820 return function(event) { 9821 if(TouchUtil.getTouches(event).length < 2){ 9822 self.mouseMoveHandler = self.onCanvasMouseMove(); 9823 self.mouseUpHandler = self.onCanvasMouseUp(); 9824 //CQ-4261765 : Scribble sign scroll issue with ios 9825 //https://stackoverflow.com/questions/49500339/cant-prevent-touchmove-from-scrolling-window-on-ios 9826 //https://github.com/jquery/jquery/issues/2871 9827 document.addEventListener(TouchUtil.POINTER_MOVE, self.mouseMoveHandler,{ passive: false }); 9828 $(document).on(TouchUtil.POINTER_UP, self.mouseUpHandler ); 9829 self.updateMousePosition( event ); 9830 self.updateCanvas( event ); 9831 } 9832 } 9833}; 9834 9835Scribble.prototype.onCanvasMouseMove = function () { 9836 var self = this; 9837 return function(event) { 9838 if(TouchUtil.getTouches(event).length < 2){ 9839 self.updateCanvas( event ); 9840 event.preventDefault(); 9841 return false; 9842 } 9843 } 9844}; 9845 9846Scribble.prototype.onCanvasMouseUp = function (event) { 9847 var self = this; 9848 return function(event) { 9849 document.removeEventListener(TouchUtil.POINTER_MOVE, self.mouseMoveHandler,{ passive: false }); 9850 $(document).off(TouchUtil.POINTER_UP, self.mouseUpHandler ); 9851 self.mouseMoveHandler = null; 9852 self.mouseUpHandler = null; 9853 } 9854}; 9855 9856Scribble.prototype.updateMousePosition = function (event) { 9857 if(!this._enabled) return ; 9858 var target = TouchUtil.getTouchEvent(event); 9859 9860 var offset = this.canvas.offset(); 9861 /* In IE>=10 pageX values are incorrect when using zoom 9862 so calculate them using clientX and scrollLeft */ 9863 this.lastMousePoint.x = target.clientX + $(window).scrollLeft() - offset.left - this.canvasBorderWidth; 9864 this.lastMousePoint.y = target.clientY + $(window).scrollTop() - offset.top - this.canvasBorderWidth; 9865 9866}; 9867Scribble.prototype._isInsideCanvas = function(x,y){ 9868 return y>=0 && y<this.canvas[0].height && x>=0 && x < this.canvas[0].width; 9869}; 9870 Scribble.prototype.updateCanvas = function (event) { 9871 if(!this._enabled) { 9872 return; 9873 } 9874 var oldX,oldY,dX,dY,canDraw,scaleX,scaleY,cssWidth,cssHeight; 9875 cssWidth = parseInt(this.canvas[0].style.width,10); 9876 cssHeight = parseInt(this.canvas[0].style.height,10); 9877 scaleX = cssWidth?this.canvas[0].width/cssWidth:1; 9878 scaleY = cssHeight?this.canvas[0].height/cssHeight:1; 9879 9880 scaleX /= xfalib.ut.XfaUtil.prototype.formScaleFactor; 9881 scaleY /= xfalib.ut.XfaUtil.prototype.formScaleFactor; 9882 9883 oldX = this.lastMousePoint.x*scaleX; 9884 oldY = this.lastMousePoint.y*scaleY; 9885 9886 this.updateMousePosition( event ); 9887 9888 var newX = this.lastMousePoint.x*scaleX; 9889 var newY = this.lastMousePoint.y*scaleY; 9890 9891 dX = Math.abs(newX - oldX ); 9892 dY = Math.abs(newY - oldY ); 9893 9894 canDraw = ( dX > 0 || dY > 0 ) && this._isInsideCanvas(oldX,oldY) && this._isInsideCanvas(newX,newY);; 9895 9896 if(canDraw){ 9897 this.context.beginPath(); 9898 this.context.moveTo( oldX, oldY ); 9899 this.context.lineTo(newX, newY ); 9900 this.context.lineWidth=this._lineWidth; 9901 this.context.lineCap='round'; 9902 this.context.stroke(); 9903 9904 this._callback(); 9905 9906 } 9907}; 9908 9909Scribble.prototype.toString = function () { 9910 9911 var dataString = this.canvas.get(0).toDataURL("image/png"); 9912 //var index = dataString.indexOf( "," )+1; 9913 //dataString = dataString.substring( index ); 9914 9915 return dataString; 9916}; 9917Scribble.prototype.setEnabled=function(enable){ 9918 this._enabled=enable; 9919}; 9920Scribble.prototype.clear = function () { 9921 9922 var c = this.canvas[0]; 9923 this.context.clearRect( 0, 0, c.width, c.height ); 9924}; 9925 9926 9927// ImageEdit dialog box 9928var imageEditDialog=(function(_){ 9929 9930 // html used to construct dialog box 9931 var htmlStr=(function(){ 9932 var html=[ 9933 '<div id="iEBox_container" tabindex="0" role="dialog" aria-label="'+ScribbleUtil.localeString("pleaseSignText")+'">', 9934 '<div id="iEBox_panel">', 9935 '<div id = "iEBox_Cancel" class="iEBox_button" tabindex="0" role="button" aria-label="'+ScribbleUtil.localeString("cancel")+'" title="'+ScribbleUtil.localeString("cancel")+'" ></div>', 9936 '</div>', 9937 '<div id="iEBox_content">', 9938 '<div id="iEBox_canvases" align=center>', 9939 '<div style="display:inline-block; vertical-align:top;">', 9940 '<canvas id="iEBox_canvas" style="margin:0px;border-bottom:0px;" width="696" height="390" ></canvas>' , 9941 '<input type="text" id="keyboard_Sign_Box" name="signatureText" placeholder="'+ScribbleUtil.localeString("typeYourSignatureHere")+'">', 9942 '<fieldset id="iEBox_caption"><legend align="center">
9942'+ScribbleUtil.localeString("pleaseSignText")+'</legend></fieldset>', 9943 '</div>', 9944 '<canvas id="iEBox_geoCanvasRight" width="0" height="0" ></canvas>', 9945 '<div><canvas id="iEBox_geoCanvasBottom" width="0" height="0" ></canvas></div>', 9946 '</div>', 9947 '<div>', 9948 '<div id="iEBox_Brush" class="iEBox_button" tabindex="0" role="button" aria-label="'+ScribbleUtil.localeString("brushes")+'" title="'+ScribbleUtil.localeString("brushes")+'"></div>', 9949 '<div id="iEBox_Clear" class="iEBox_button" tabindex="0" role="button" aria-label="'+ScribbleUtil.localeString("clear")+'" title="'+ScribbleUtil.localeString("clear")+'" ></div>', 9950 '<div id="iEBox_Geo" class="iEBox_button" tabindex="0" role="button" aria-label="'+ScribbleUtil.localeString("geolocation")+'" title="'+ScribbleUtil.localeString("geolocation")+'" ></div>', 9951 '<div id="iEBox_Text" class="iEBox_button" tabindex="0" role="button" aria-label="'+ScribbleUtil.localeString("typeYourName")+'" title="'+ScribbleUtil.localeString("typeYourName")+'"></div>', 9952 '<div id="iEBox_title"></div>', 9953 '<div id="iEBox_Ok" class="iEBox_button" tabindex="0" role="button" aria-label="'+ScribbleUtil.localeString("ok")+'" title="'+ScribbleUtil.localeString("ok")+'" ></div>', 9954 '</div>' , 9955 '</div>' , 9956 '<div id="iEBox_moveframe" ></div>', 9957 '<div id="iEBox_brushList" ></div>', 9958 '</div>'].join(""); 9959 return function(){ 9960 return html; 9961 }; 9962 }); 9963 9964 /** 9965 * 9966 */ 9967 9968 var dialogObj = { 9969 verticalOffset: 0, // removing the magic value of -75 since it was not causing any impact 9970 horizontalOffset: 0, 9971 repositionOnResize: true, 9972 overlayOpacity: .75, 9973 overlayColor: '#CCCCCC', 9974 draggable: true, 9975 _brushes:[2,3,4,5,6,7,8,9,10], 9976 _buttonsEnabled:{}, 9977 _isOpen:false, 9978 show:function(title,callback){ 9979 this._show(callback); 9980 this._buttonsEnabled={Geo:true,Clear:true,Ok:true,Cancel:true,Brush:true,Text:true}; 9981 }, 9982 setEnabled:function(button,enable){ 9983 if(this._buttonsEnabled[button]!=enable){ 9984 this._buttonsEnabled[button]=enable; 9985 if(enable){ 9986 $('#iEBox_'+button).empty('<div style="background:white;width:100%;height:100%;opacity:0.75;"></div>'). 9987 removeClass("disable_button"); 9988 } else { 9989 $('#iEBox_'+button).append('<div style="background:white;width:100%;height:100%;opacity:0.75;"></div>'). 9990 addClass("disable_button"); 9991 } 9992 9993 } 9994 }, 9995 enableButtons:function(buttons){ 9996 for(var k in buttons){ 9997 this.setEnabled(k,buttons[k]); 9998 } 9999 }, 10000 toggleBrushList:function(event){ 10001 var that = this; 10002 if($('#iEBox_brushList').css('display')!='none'){ 10003 $('#iEBox_brushList').css({display:'none'}); 10004 return; 10005 } 10006 var tmpFn = document.onselectstart; 10007 document.onselectstart=function(){return false;}; 10008 $('#iEBox_brushList').css({display:'block',visibility:'hidden'}); 10009 $('#iEBox_brushList').offset($('#iEBox_Brush').offset()); 10010 $('#iEBox_brushList').offset({top:$('#iEBox_Brush').offset().top-$('#iEBox_brushList').height()}); 10011 $('#iEBox_brushList').css({display:'block',visibility:'visible'}); 10012 // $('#iEBox_brushList').focus(); 10013 $('#iEBox_brushList').one('mouseleave',function(event){ 10014 $('#iEBox_brushList').css({display:'none'}); 10015 document.onselectstart=tmpFn; 10016 }); 10017 }, 10018 _attachCallbacks: function(callback) { 10019 var that = this; 10020 var sigCanvas = $('#iEBox_canvas')[0]; 10021 var ctx=sigCanvas.getContext("2d"); 10022 var minSigCanvasFontSize=10; 10023 var maxSigCanvasFontSize=70;
10024 var sigCanvasFontSize=minSigCanvasFontSize; 10025 var initialSigCanvasFontSize=sigCanvasFontSize; 10026 var initialFontCalculatedFlag=false; 10027 var sigCanvasFontFamily="sans-serif, Georgia"; 10028 var sigCanvasFontStyle="italic"; 10029 _.each("Cancel-Clear-Geo-Ok-Brush-Text".split("-"),function(val,idx){ 10030 $("#iEBox_"+val).click( function(event) { 10031 if(that._buttonsEnabled[val]){ 10032 event.stopPropagation(); 10033 callback(val); 10034 } 10035 }); 10036 $("#iEBox_"+val).keydown( function(event) { 10037 if(that._buttonsEnabled[val] && (event.keyCode == ENTER_KEY || event.charCode == ENTER_KEY || event.which == ENTER_KEY) ){ 10038 event.stopPropagation(); 10039 callback(val); 10040 } 10041 }); 10042 }); 10043 _.each($("#iEBox_brushList").children(),function(itm,idx){ 10044 $(itm).on(TouchUtil.POINTER_UP,function(event){ 10045 callback("BrushSelect",that._brushes[idx]); 10046 $('#iEBox_brushList').css({display:'none'}); 10047 // $(itm).css({backgroundColor:'#FFFFFF'}); 10048 }); 10049 $(itm).on(TouchUtil.POINTER_DOWN,function(event){ 10050 // $(itm).css({backgroundColor:'#AAAAAA'}); 10051 event.preventDefault(); 10052 }); 10053 }); 10054 10055 $('#keyboard_Sign_Box').keydown(function (event){ 10056 var inputSign=$('#keyboard_Sign_Box')[0].value; 10057 10058 if(event.key==="Backspace") { 10059 ctx.font=sigCanvasFontStyle+sigCanvasFontSize+"px "+sigCanvasFontFamily; 10060 sigCanvasFontSize=dialogObj._increaseFontForSignature(ctx.measureText(inputSign).width,sigCanvas.width, 10061 sigCanvasFontSize,initialSigCanvasFontSize); 10062 ctx.font=sigCanvasFontStyle+" "+sigCanvasFontSize+"px "+sigCanvasFontFamily; 10063 ctx.clearRect(0, 0, sigCanvas.width, sigCanvas.height); 10064 ctx.fillText(inputSign, 3, sigCanvasFontSize, sigCanvas.width-5); 10065 } 10066 event.stopPropagation(); 10067 }); 10068 10069 $("#keyboard_Sign_Box").keyup(function (event){ 10070 var inputSign=$('#keyboard_Sign_Box')[0].value; 10071 if(inputSign.length==0) { 10072 dialogObj.enableButtons({Ok: false, Clear: false}); 10073 } 10074 if(inputSign.length>=1 && inputSign.trim().length!=0) { 10075 dialogObj.enableButtons({Ok: true, Clear: true}); 10076 } 10077 if(initialFontCalculatedFlag===false){ 10078 sigCanvasFontSize=sigCanvas.height-20; 10079 sigCanvasFontSize=sigCanvasFontSize<minSigCanvasFontSize?minSigCanvasFontSize:sigCanvasFontSize; 10080 sigCanvasFontSize=sigCanvasFontSize>maxSigCanvasFontSize?maxSigCanvasFontSize:sigCanvasFontSize; 10081 initialSigCanvasFontSize=sigCanvasFontSize; 10082 $('#keyboard_Sign_Box')[0].style.font=sigCanvasFontStyle+" 2rem "+sigCanvasFontFamily; 10083 initialFontCalculatedFlag=true; 10084 } 10085 ctx.font=sigCanvasFontStyle+sigCanvasFontSize+"px "+sigCanvasFontFamily; 10086 sigCanvasFontSize=dialogObj._decreaseFontForSignature(ctx,inputSign,sigCanvas.width, 10087 sigCanvasFontSize,sigCanvasFontFamily); 10088 ctx.font=sigCanvasFontStyle+" "+sigCanvasFontSize+"px "+sigCanvasFontFamily; 10089 ctx.clearRect(0, 0, sigCanvas.width, sigCanvas.height); 10090 ctx.fillText(inputSign,3,sigCanvasFontSize,sigCanvas.width-5); 10091 event.stopPropagation(); 10092 }); 10093 10094 // capture tab key and escape 10095 $('#iEBox_container').keydown(function(event){ 10096 var firstFocusableItem = document.querySelector("#iEBox_container"); 10097 var lastFocusableItem = document.querySelector("#iEBox_Ok"); 10098 var KEYCODE_TAB = 9; 10099 var isTabPressed = (event.key === 'Tab' || event.keyCode === KEYCODE_TAB); 10100 if((event.keyCode == ESC_KEY || event.charCode == ESC_KEY || event.which == ESC_KEY)) { 10101 event.stopPropagation(); 10102 event.preventDefault(); 10103 callback("Cancel"); 10104 } else if (isTabPressed) { 10105 // Trap focus inside the dialog box 10106 if (event.shiftKey && document.activeElement === firstFocusableItem) { 10107 // when shift + tab key is pressed 10108 lastFocusableItem.focus(); 10109 event.preventDefault(); 10110 } else if (document.activeElement === lastFocusableItem) { 10111 // when tab key is pressed 10112 firstFocusableItem.focus(); 10113 event.preventDefault(); 10114 } 10115 } 10116 10117 }); 10118 10119 if(this.draggable){ 10120 this._makeDraggable(TouchUtil.TOUCH_ENABLED); 10121 } 10122 }, 10123 10124 _decreaseFontForSignature:function(ctx,inputSign,sigCanvasWidth,fontSize,sigCanvasFontFamily){ 10125 while(ctx.measureText(inputSign).width>sigCanvasWidth-5 && fontSize>20){ 10126 fontSize=fontSize-10; 10127 ctx.font=fontSize+"px "+sigCanvasFontFamily; 10128 } 10129 return fontSize 10130 }, 10131 _increaseFontForSignature:function(textWidth,sigCanvasWidth,fontSize,initialSigCanvasFontSize){ 10132 if(sigCanvasWidth-textWidth>0){ 10133 fontSize=initialSigCanvasFontSize; 10134 } 10135 return fontSize; 10136 }, 10137 _makeDraggable:function(touchEnabled){ 10138 var _isMouseDown=false; 10139 var _that=this; 10140 var dX; 10141 var dY; 10142 var offsetPos; 10143 var _mouseMovFun; 10144 var _mouseUpFun; 10145 $('#iEBox_panel').on(TouchUtil.POINTER_DOWN,function( event ){ 10146 10147 if(TouchUtil.getTouches(event).length < 2){ 10148 if($(event.target).is('#iEBox_panel')){ 10149 $('body')[0].addEventListener(TouchUtil.POINTER_MO
10149VE,_mouseMovFun=function( event ){ 10150 if(TouchUtil.getTouches(event).length < 2 && _isMouseDown){ 10151 event.preventDefault(); 10152 var evt = TouchUtil.getTouchEvent(event); 10153 var delX = evt.pageX - dX; 10154 var delY = evt.pageY - dY; 10155 $('#iEBox_moveframe').offset({ 10156 top: offsetPos.top+delY, 10157 left: offsetPos.left+delX 10158 }); 10159 } 10160 }, { passive: false }); 10161 $('body').on(TouchUtil.POINTER_UP,_mouseUpFun=function(event){ 10162 if(_isMouseDown){ 10163 var offsetMove = $('#iEBox_moveframe').offset(); 10164 var topEdge = $(window).scrollTop(); 10165 var bottomEdge = topEdge + $(window).height(); 10166 if(offsetMove.top - topEdge < 1){ 10167 offsetMove.top = topEdge; 10168 } 10169 if(offsetMove.top - bottomEdge + $('#iEBox_panel').height() > 0 ){ 10170 offsetMove.top = bottomEdge - $('#iEBox_panel').height(); 10171 } 10172 $('#iEBox_container').offset(offsetMove ); 10173 $('#iEBox_moveframe').css({display:'none'}).offset(offsetMove); 10174 _isMouseDown=false; 10175 $('body')[0].removeEventListener(TouchUtil.POINTER_MOVE,_mouseMovFun,{ passive: false }); 10176 $('body').off(TouchUtil.POINTER_UP,_mouseUpFun); 10177 } 10178 }); 10179 10180 var evt = TouchUtil.getTouchEvent(event); 10181 _isMouseDown=true; dX = evt.pageX;dY=evt.pageY; 10182 offsetPos = $('#iEBox_container').offset(); 10183 $('#iEBox_moveframe').css({display:'block'}); 10184 $('#iEBox_moveframe').offset(offsetPos); 10185 $('#iEBox_moveframe').css('width',$('#iEBox_container').css('width')); 10186 $('#iEBox_moveframe').css('height',$('#iEBox_container').css('height')); 10187 } 10188 } 10189 }); 10190 10191 }, 10192 _createBrushes:function(){ 10193 var _that=this; 10194 _.each(this._brushes,function(val,idx){ 10195 var divel = document.createElement('DIV'); 10196 var cnv = document.createElement('CANVAS'); 10197 var ctx = cnv.getContext('2d'); 10198 cnv.style.border='1px solid #AAAAAA'; 10199 cnv.width=TouchUtil.TOUCH_ENABLED?200:100; 10200 cnv.height=TouchUtil.TOUCH_ENABLED?40:20;; 10201 ctx.lineWidth=val; 10202 ctx.beginPath(); 10203 ctx.moveTo(10,cnv.height/2); 10204 ctx.lineTo(cnv.width-10,cnv.height/2); 10205 ctx.stroke(); 10206 divel.appendChild(cnv); 10207 $('#iEBox_brushList').append(divel); 10208 }); 10209 }, 10210 getIsOpen:function(){ 10211 return dialogObj._isOpen; 10212 }, 10213 setIsOpen:function(open){ 10214 dialogObj._isOpen = open; 10215 }, 10216 _show: function(callback) { 10217 dialogObj.hide(); 10218 dialogObj._overlay('show'); 10219 10220 $("BODY").append(htmlStr()); 10221 dialogObj.setIsOpen(true); 10222 $('#iEBox_container').focus(); 10223 dialogObj._createBrushes(); 10224 10225 dialogObj._reposition(); 10226 10227 // calculate spacing around canvas area 10228 // this will be used to find canvas dimensions based on available screen area. 10229 var container_el = $('#iEBox_container'); 10230 var canvas_el = $('#iEBox_canvas'); 10231 var container_width = $('#iEBox_container').outerWidth(true);
10232 var container_height = $('#iEBox_container').outerHeight(true); 10233 var canvas_width = canvas_el[0].width; 10234 var canvas_height = canvas_el[0].height; 10235 dialogObj.canvas_spacing = { x:container_width - canvas_width, y:container_height-canvas_height}; 10236 10237 dialogObj._maintainPosition(true); 10238 10239 dialogObj._attachCallbacks(callback); 10240 }, 10241 10242 hide: function() { 10243 $("#iEBox_container").remove(); 10244 this._overlay('hide'); 10245 dialogObj.setIsOpen(false); 10246 this._maintainPosition(false); 10247 }, 10248 _overlayResize:function(event) { 10249 if($("#iEBox_overlay").height()!= $(document).height()){ 10250 $("#iEBox_overlay").height( $(document).height() ); 10251 } 10252 10253 }, 10254 _disableMove:function(event) { 10255 event.preventDefault(); 10256 }, 10257 _overlay: function(status) { 10258 switch( status ) { 10259 case 'show': 10260 this._overlay('hide'); 10261 $("BODY").append('<div id="iEBox_overlay"></div>'); 10262 $("#iEBox_overlay").css({ 10263 position: 'fixed', 10264 zIndex: 99997, 10265 top: '0px', 10266 left: '0px', 10267 width: '100%', 10268 height: $(document).height(), 10269 background: this.overlayColor, 10270 opacity: this.overlayOpacity 10271 }); 10272 if(xfalib.ut.XfaUtil.prototype.isSafari()) { 10273 $("#iEBox_overlay").on('touchmove', this._disableMove); 10274 } 10275 $(document).on('scroll',this._overlayResize); 10276 break; 10277 case 'hide': 10278 if(xfalib.ut.XfaUtil.prototype.isSafari()) { 10279 $("#iEBox_overlay").off('touchmove'); 10280 } 10281 $("#iEBox_overlay").remove(); 10282 $(document).off('scroll',this._overlayResize); 10283 break; 10284 } 10285 }, 10286 /** 10287 * resize dialog based on available screen area 10288 */ 10289 _resize:function(){ 10290 // available screen area 10291 var aWidth = $(window).width(); 10292 var aHeight = $(window).height(); 10293 10294 var sigCnv = $('#iEBox_canvas')[0]; 10295 var sigTextBox = $('#keyboard_Sign_Box')[0]; 10296 var bGeoCnv = $('#iEBox_geoCanvasBottom')[0]; 10297 var rGeoCnv = $('#iEBox_geoCanvasRight')[0]; 10298 10299 // calculate amount of width height we need to reduce 10300 10301 var totalCnvWidth = sigCnv.width + rGeoCnv.width; 10302 var totalCnvHeight = sigCnv.height + bGeoCnv.height; 10303 10304 10305 10306 10307 10308 var diffW = totalCnvWidth + dialogObj.canvas_spacing.x - aWidth; 10309 if(diffW < 0) { 10310 diffW = 0; 10311 } 10312 var diffH = totalCnvHeight + dialogObj.canvas_spacing.y - aHeight; 10313 if(diffH < 0){ 10314 diffH = 0; 10315 } 10316 10317 var newTotalCnvHeight, newTotalCnvWidth; 10318 if( diffW > 0 || diffH > 0 ){ // does any side need resize 10319 10320 if(diffH * totalCnvWidth > totalCnvHeight * diffW){ // need to reduce height 10321 newTotalCnvHeight = totalCnvHeight - diffH; 10322 newTotalCnvWidth = (newTotalCnvHeight * totalCnvWidth)/ totalCnvHeight; 10323 } else { 10324 newTotalCnvWidth = totalCnvWidth - diffW; 10325 newTotalCnvHeight = (newTotalCnvWidth * totalCnvHeight)/ totalCnvWidth; 10326 } 10327 10328 // distribute evenly the new dimensions 10329 10330 10331 var newSigCnvWidth = (newTotalCnvWidth*sigCnv.width)/totalCnvWidth; 10332 var newSigCnvHeight = (newTotalCnvHeight*sigCnv.height)/totalCnvHeight; 10333 10334 sigCnv.style.width = newSigCnvWidth + "px"; 10335 sigCnv.style.height = newSigCnvHeight + "px"; 10336 10337 sigTextBox.style.width = newSigCnvWidth + "px"; 10338 sigTextBox.style.height = newSigCnvHeight + "px"; 10339 10340 10341 bGeoCnv.style.width = newSigCnvWidth +"px"; 10342 bGeoCnv.style.height = (newTotalCnvHeight - newSigCnvHeight) +"px"; 10343 10344 rGeoCnv.style.width = (newTotalCnvWidth - newSigCnvWidth) +"px"; 10345 rGeoCnv.style.height = newSigCnvHeight + "px"; 10346 10347 10348 $('#iEBox_caption').width(Math.floor(newSigCnvWidth)); 10349 10350 } else { 10351 sigCnv.style.width = sigCnv.width + "px"; 10352 sigCnv.style.height = sigCnv.height + "px"; 10353 10354 sigTextBox.style.width = sigCnv.width + "px"; 10355 sigTextBox.style.height = sigCnv.height + "px"; 10356 10357 bGeoCnv.style.width = bGeoCnv.width + "px"; 10358 bGeoCnv.style.height = bGeoCnv.height + "px"; 10359 10360 rGeoCnv.style.width = rGeoCnv.width + "px"; 10361 rGeoCnv.style.height = rGeoCnv.height + "px"; 10362 10363 $('#iEBox_caption').width(sigCnv.width); 10364 10365 } 10366 }, 10367 _reposition: function() { 10368 var top = (($(window).height() * (1 / xfalib.ut.XfaUtil.prototype.formScaleFactor) / 2) - ($("#iEBox_container").outerHeight() / 2)) + dialogOb
10368j.verticalOffset; 10369 var left = (($(window).width() * (1 / xfalib.ut.XfaUtil.prototype.formScaleFactor) / 2) - ($("#iEBox_container").outerWidth() / 2)) + dialogObj.horizontalOffset; 10370 if( top < 0 ) top = 0; 10371 if( left < 0 ) left = 0; 10372 10373 $("#iEBox_container").css({ 10374 top: top + $(window).scrollTop() * (1 / xfalib.ut.XfaUtil.prototype.formScaleFactor) + 'px', 10375 left: left + $(window).scrollLeft() * (1 / xfalib.ut.XfaUtil.prototype.formScaleFactor) + 'px' 10376 }); 10377 $("#iEBox_container").focus(); // scroll up to the canvas 10378 $("#iEBox_overlay").height( $(document).height() ); 10379 }, 10380 _maintainDialog:function(){ 10381 dialogObj._resize(); 10382 dialogObj._reposition(); 10383 }, 10384 _maintainPosition: function(status) { 10385 if(dialogObj.repositionOnResize ) { 10386 switch(status) { 10387 case true: 10388 $(window).on('orientationchange', dialogObj._maintainDialog); // also reposition if device is tilted 10389 break; 10390 case false: 10391 $(window).off('orientationchange', dialogObj._maintainDialog); 10392 break; 10393 } 10394 } 10395 } 10396 10397 }; 10398 return dialogObj; 10399})(window._); 10400 10401/** 10402 * class definition for GeoLocationQueryRequest 10403 * encapsulated success and error handlers 10404 */ 10405function GeoLocQuery(){} 10406GeoLocQuery.prototype={ 10407 init:function(success,failure){ 10408 this._successHandler = success; 10409 this._errorHandler = failure; 10410 this._active=true; 10411 return this; 10412 }, 10413 _handleSuccess:function(data){ 10414 this._successHandler(data); 10415 }, 10416 _handleError:function(err){ 10417 this._errorHandler(err); 10418 }, 10419 query:function(){ 10420 _that=this; 10421 navigator.geolocation.getCurrentPosition(function(pos){ 10422 if(_that._active){ 10423 _that._handleSuccess(pos); 10424 } 10425 _that._active=false; 10426 },function(err){ 10427 if(_that._active){ 10428 _that._handleError(err); 10429 } 10430 _that._active=false; 10431 },{timeout:10000}); 10432 }, 10433 cancel:function(){ 10434 _that._active=false; 10435 } 10436 10437}; 10438// GeoLocQuery definition ends here 10439 10440/** 10441* 10442* Base64 encode / decode 10443* http://www.webtoolkit.info/ 10444* 10445**/ 10446 10447var Base64 = { 10448 10449 // private property 10450 _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", 10451 10452 // public method for encoding 10453 encode : function (input) { 10454 var output = ""; 10455 var chr1, chr2, chr3, enc1, enc2, enc3, enc4; 10456 var i = 0; 10457 10458 while (i < input.length) { 10459 10460 chr1 = input.charCodeAt(i++); 10461 chr2 = input.charCodeAt(i++); 10462 chr3 = input.charCodeAt(i++); 10463 10464 enc1 = chr1 >> 2; 10465 enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); 10466 enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); 10467 enc4 = chr3 & 63; 10468 10469 if (isNaN(chr2)) { 10470 enc3 = enc4 = 64; 10471 } else if (isNaN(chr3)) { 10472 enc4 = 64; 10473 } 10474 10475 output = output + 10476 this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) + 10477 this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4); 10478 10479 } 10480 10481 return output; 10482 }, 10483 10484 // public method for decoding 10485 decode : function (input) { 10486 var output = ""; 10487 var chr1, chr2, chr3; 10488 var enc1, enc2, enc3, enc4; 10489 var i = 0; 10490 10491 input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); 10492 10493 while (i < input.length) { 10494 10495 enc1 = this._keyStr.indexOf(input.charAt(i++)); 10496 enc2 = this._keyStr.indexOf(input.charAt(i++)); 10497 enc3 = this._keyStr.indexOf(input.charAt(i++)); 10498 enc4 = this._keyStr.indexOf(input.charAt(i++)); 10499 10500 chr1 = (enc1 << 2) | (enc2 >> 4); 10501 chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); 10502 chr3 = ((enc3 & 3) << 6) | enc4; 10503 10504 output = output + String.fromCharCode(chr1); 10505 10506 if (enc3 != 64) { 10507 output = output + String.fromCharCode(chr2); 10508 } 10509 if (enc4 != 64) { 10510 output = output + String.fromCharCode(chr3); 10511 } 10512 10513 } 10514 10515 return output; 10516 10517 } 10518 10519 10520 10521}; 10522 10523/** 10524 * Utility Singleton for handling PNG Data 10525 */ 10526var PNGUtil=(function(){ 10527 var slf={ 10528 _LC_Scribble_MetaDataKey:"LC_SCIBBLE_METADATA", 10529 _isPng:function(b64data){ 10530 return b64data && b64data.replace(/\s+/g, "").indexOf("iVBORw0KGgo") == 0; // LC-5711 : trim any leading WhiteSpace
10531 // TODO : base64 encoding may have white spaces even between the magic numbers !! Think of a better way to stop stripping white spaces repeatedly in PNGUtil, and cache the result 10532 }, 10533 _update_crc:function(crc,data){ 10534 var c = crc; 10535 var n; 10536 for(n=0;n<data.length;n++){ 10537 c = this._XOR(slf._crc_table[(this._XOR(c,data.charCodeAt(n))&0xff)>>>0],(c>>>8)); 10538 } 10539 return c; 10540 }, 10541 _XOR:function(a,b){ 10542 return (a^b)>>>0; 10543 }, 10544 _U32Int2Str:function(n){ 10545 return String.fromCharCode((n>>>24)&0xFF)+String.fromCharCode((n>>>16)&0xFF)+String.fromCharCode((n>>>8)&0xFF)+String.fromCharCode(n>>>0&0xFF); 10546 }, 10547 _init_crc_table:function(){ 10548 var c=0; 10549 var n,k; 10550 slf._crc_table=[]; 10551 for(n=0;n<256;n++){ 10552 c = n; 10553 for(k=0;k<8;k++){ 10554 if(((c&1)>>>0)>0){ 10555 c = slf._XOR(0xedb88320 , (c>>>1)); 10556 } else { 10557 c = c>>>1; 10558 } 10559 } 10560 slf._crc_table[n]=c; 10561 } 10562 }, 10563 _CRC:function(data){ 10564 if(!this._crc_table) this._init_crc_table(); 10565 return this._XOR(this._update_crc(0xffffffff,data) , 0xffffffff); 10566 }, 10567 _prepareTextChunk:function(content,pad){ 10568 // pad the data appropriately 10569 var len = content.length; 10570 var lenStr = slf._U32Int2Str(len); 10571 var chunkType="tEXt"; 10572 var checkSumStr = slf._U32Int2Str(slf._CRC(chunkType+content)); 10573 return lenStr+chunkType+content+checkSumStr; 10574 }, 10575 _start:function(str){ 10576 slf._startTime = new Date().getTime(); 10577 slf._startFun=str; 10578 }, 10579 _end:function(){ 10580 var str = "Time "+slf._startFun+": "+(new Date().getTime()-slf._startTime); 10581 // $('BODY').append("<p>"+str+"</p><br/>"); 10582 }, 10583 _readU32Int:function(ctx){ 10584 var val=0; 10585 var d=ctx.d; 10586 val=((d.charCodeAt(ctx.p++)<<24)|(d.charCodeAt(ctx.p++)<<16)|(d.charCodeAt(ctx.p++)<<8)|(d.charCodeAt(ctx.p++)))>>>0; 10587 return val; 10588 }, 10589 _readChunkType:function(ctx){ 10590 var d = ctx.d; 10591 var str = d[ctx.p++]+d[ctx.p++]+d[ctx.p++]+d[ctx.p++]; 10592 return str; 10593 }, 10594 _makeReadOnly:function(b64data){ 10595 slf._start("_makeReadOnly"); 10596 // assume a valid png image encoded in base64; 10597 var bindata = slf._atob(b64data.replace(/\s+/g, '')); // remove white spaces that might have been inserted 10598 var pngctx={p:0,d:bindata}; 10599 pngctx.p+=8;// skip pngheader 10600 // read IHDR 10601 var size = slf._readU32Int(pngctx); 10602 slf._readChunkType(pngctx); //IHDR 10603 pngctx.p+=size; //Data 10604 slf._readU32Int(pngctx);//CRC 10605 var metadataChunk = slf._prepareTextChunk(slf._LC_Scribble_MetaDataKey+String.fromCharCode(0)+"true"); 10606 var newdata = pngctx.d.substring(0,pngctx.p)+metadataChunk+pngctx.d.substring(pngctx.p); 10607 var ret= slf._btoa(newdata); 10608 slf._end(); 10609 return ret; 10610 }, 10611 _atob:function(inp){ 10612 if(window.atob){ return atob(inp); } 10613 return Base64.decode(inp); 10614 }, 10615 _btoa:function(inp){ 10616 if(window.btoa){ return btoa(inp); } 10617 return Base64.encode(inp); 10618 }, 10619 _isReadOnly:function(b64data){ 10620 slf._start("_isReadOnly"); 10621 if(slf._isPng(b64data)){ 10622 var testStr = slf._LC_Scribble_MetaDataKey+String.fromCharCode(0)+"true"; 10623 var bindata = slf._atob(b64data.replace(/\s+/g, ''));
10623 // strip white spaces 10624 var pngctx={p:0,d:bindata}; 10625 pngctx.p+=8;// skip header 10626 while(pngctx.p<pngctx.d.length){ 10627 var size = slf._readU32Int(pngctx); 10628 var type = slf._readChunkType(pngctx); 10629 if(type=="tEXt"){ 10630 if(pngctx.d.indexOf(testStr,pngctx.p)==pngctx.p){ 10631 slf._end(); 10632 return true; 10633 } 10634 10635 } 10636 pngctx.p+=size; 10637 slf._readU32Int(pngctx);// 10638 }// while end 10639 } 10640 slf._end(); 10641 return false; 10642 } 10643 }; 10644 return slf; 10645})(); 10646 10647/** 10648 * JQuery widget definition starts here 10649 */ 10650$.widget( "xfaWidget.ScribbleImageField", $.xfaWidget.imageField, { 10651 10652 _widgetName:"ScribbleImageField", 10653 _geoLocQuery:null, 10654 _emptyImageVal:null,// should be null, but for now 10655 _extraInfo:null, 10656 _defaultStatus:" ", 10657 _enforceGeoLoc:!!navigator.userAgent.match(/iPad/i), 10658 _sigCanvasWidth:696, 10659 _sigCanvasHeight:390, 10660 _geoCanvId:null, 10661 _geoLocAtBottom:false, 10662 _geoCanvasHeight:100, 10663 _geoCanvasWidth:696, 10664 10665 _is_readonly:false, 10666 10667 options: { 10668 tabIndex: 0, 10669 "role": "img" 10670 }, 10671 10672 getOptionsMap: function() { 10673 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this,arguments); 10674 return $.extend({},parentOptionsMap,{ 10675 "displayValue": function(val) { 10676 if(this.options.commitProperty) { 10677 if(!val){ 10678 this._displayValue(this._extractData(this._createEmptyImageData())); 10679 this.$userControl.addClass("emptyScribble"); 10680 this._is_readonly=false; 10681 } else { 10682 this.$userControl.removeClass("emptyScribble"); 10683 if(PNGUtil._isPng(val)){ 10684 var widgetValue = "data:image/png;base64,"+this.options.value; 10685 }else { 10686 var widgetValue = "data:;base64," + this.options.value; 10687 } 10688 this._setValue(widgetValue); 10689 } 10690 } 10691 } 10692 }) 10693 }, 10694 10695 getEventMap: function() { 10696 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getEventMap.apply(this,arguments); 10697 return $.extend({},parentOptionsMap,{ 10698 "scribblefocus":xfalib.ut.XfaUtil.prototype.XFA_ENTER_EVENT, 10699 "click":null, 10700 "scribbleclick":xfalib.ut.XfaUtil.prototype.XFA_CLICK_EVENT, 10701 "change":null, 10702 "scribblechange":xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT, 10703 "blur":null, 10704 "scribbleclose":xfalib.ut.XfaUtil.prototype.XFA_EXIT_EVENT 10705 }) 10706 }, 10707 10708 /** 10709 * This function achieves following 10710 * 1. Calculate dimensions of canvases to be used 10711 * 2. Findout if right or bottom canvas is to be used for geo location 10712 */ 10713 10714 aspectRatioToBeUsed :function(){ 10715 var aspectRatio ; 10716 if(this.options.aspectRatio && parseFloat(this.options.aspectRatio) > 0){ 10717 aspectRatio = 1/parseFloat(this.options.aspectRatio); //--in MF ratio is computed as height/width instead of width/height 10718 } else { 10719 var imgEl = this.element.children("img"), 10720 width = imgEl.attr('width'), 10721 height = imgEl.attr('height'), 10722 fieldWidth, 10723 fieldHeight; 10724 10725 if(width){ 10726 fieldWidth = parseInt(width,10); 10727 } else { 10728 fieldWidth = imgEl.width(); 10729 } 10730 if(height){ 10731 fieldHeight = parseInt(height,10); 10732 } else { 10733 fieldHeight = imgEl.height(); 10734 } 10735 aspectRatio = fieldHeight/fieldWidth; 10736 } 10737 return aspectRatio; 10738 }, 10739 10740 _setUpCanvas:function(){ 10741 var aspectRatio ; 10742 aspectRatio = this.aspectRatioToBeUsed(); 10743 10744 // max width, height of generated image 10745 var maxWidth = 640; 10746 var maxHeight = 480; 10747 10748 // width of field scaled to fit max image size 10749 var scaledWidth; 10750 var scaledHeight; 10751 10752 10753 // approx pixels required for rendering geo loc info in 12pt Arial font 10754 var approxGeoLocWidth=250; 10755 var approxGeoLocHeight=84; 10756 10757 scaledWidth = maxWidth; 10758 scaledHeight = maxWidth*aspectRatio; 10759 if(scaledHeight>maxHeight){ 10760 scaledHeight = maxHeight; 10761 scaledWidth = maxHeight/aspectRatio; 10762 } 10763 10764 // set canvas dimensions 10765 if(aspectRatio>=1){ 10766 this._geoCanvId='iEBox_geoCanvasBottom'; 10767 this._geoLocAtBottom=true; 10768 10769 10770 this._geoCanvasWidth = scaledWidth; 10771 // limit height to 30% of full height; 10772 this._geoCanvasHeight=Math.min(approxGeoLocHeight,scaledHeight/3);
10773 this._sigCanvasWidth = scaledWidth; 10774 this._sigCanvasHeight= scaledHeight-(this._enforceGeoLoc?this._geoCanvasHeight:0); 10775 } else { 10776 this._geoCanvId='iEBox_geoCanvasRight'; 10777 this._geoLocAtBottom=false; 10778 10779 10780 this._geoCanvasHeight = scaledHeight; 10781 // limit width to 30% of full width; 10782 this._geoCanvasWidth=Math.min(approxGeoLocWidth,scaledWidth/3); 10783 this._sigCanvasHeight= scaledHeight; 10784 this._sigCanvasWidth= scaledWidth-(this._enforceGeoLoc?this._geoCanvasWidth:0); 10785 } 10786 10787 }, 10788 10789 render : function() { 10790 var geoLocMandatoryOnIpad = this.options.geoLocMandatoryOnIpad; 10791 if(typeof(geoLocMandatoryOnIpad)!="undefined"){ 10792 this._enforceGeoLoc= this._enforceGeoLoc && (/^(true|1)$/i).test($.trim(geoLocMandatoryOnIpad)); 10793 } 10794 this._wgtId="wid"+~~(Math.random()*2000)+"_"+new Date().getTime(); 10795 10796 var $control = $.xfaWidget.defaultWidget.prototype.render.apply(this, arguments) 10797 10798 if(this.options.value || this.options.value != this._emptyImageVal){ 10799 this._is_readonly=!!PNGUtil._isReadOnly(this.options.value); 10800 } 10801 10802 if(this._is_readonly){ 10803 $control.after("<div id='"+this._wgtId+"' class='sc_popUpMenu'></div>"); 10804 } else { 10805 $control.after("<div id='"+this._wgtId+"' style='display:none;' class='sc_popUpMenu'></div>"); 10806 } 10807 10808 this._setUpCanvas(); 10809 return $control; 10810 }, 10811 10812 click: function() { 10813 this.focus(); 10814 var tmpEl = this.element.length?this.element[0]:this.element; 10815 if(this.options.access != "open") 10816 return; 10817 if (TouchUtil.POINTER_ENABLED || TouchUtil.TOUCH_ENABLED) { 10818 // simulate a click event 10819 tmpEl.dispatchEvent(TouchUtil.getPointerEvent(TouchUtil.POINTER_DOWN)); 10820 tmpEl.dispatchEvent(TouchUtil.getPointerEvent(TouchUtil.POINTER_UP)); 10821 } 10822 else { 10823 this.$userControl.triggerHandler("click"); 10824 } 10825 }, 10826 10827 _attachEventHandlers:function($control){ 10828 if(TouchUtil.POINTER_ENABLED || TouchUtil.TOUCH_ENABLED){ 10829 this._attachTouchEventHandlers($control); 10830 } else { 10831 this._attachMouseEventHandlers($control); 10832 } 10833 $control.keydown($.proxy(this._handleKeyDown,this)); 10834 }, 10835 _attachEventHandlerForCrossIcon:function($control){ 10836 var _that = this; 10837 $control.mouseenter(function(event){ 10838 if(_that.options.access != "open") 10839 return; 10840 event.stopPropagation(); 10841 if(_that._is_readonly){ 10842 $('#'+_that._wgtId).css({display:'block'}); 10843 var bodyMoveHandler; 10844 $('body').on('mousemove',bodyMoveHandler=function(event){ 10845 if(event.target!=$('#'+_that._wgtId)[0]&&event.target!=_that.$userControl[0]){ 10846 $('#'+_that._wgtId).css({display:'none'}); 10847 $('body').off('mousemove',bodyMoveHandler); 10848 } 10849 }); 10850 } 10851 }); 10852 10853 setTimeout(function(){ $("#"+_that._wgtId).click($.proxy(_that._onCrossClick,_that));},50); 10854 }, 10855 _attachTouchEventHandlers:function($control){ 10856 var _timer,_that=this; 10857 var tmpEl = this.element.length?this.element[0]:this.element; 10858 tmpEl.addEventListener(TouchUtil.POINTER_DOWN,function(event){ 10859 if(_that.options.access != "open") 10860 return; 10861 event.preventDefault(); 10862 _timer = setTimeout(function(){ 10863 _timer=0; 10864 _that._onCrossClick(event); 10865 },1000); 10866 }); 10867 tmpEl.addEventListener(TouchUtil.POINTER_UP,function(event){ 10868 if(_that.options.access != "open") 10869 return; 10870 event.preventDefault(); 10871 if(_timer){ 10872 clearTimeout(_timer); 10873 _that._onImageClick(event); 10874 } 10875 }); 10876 10877 if(TouchUtil.POINTER_ENABLED){ 10878 this._attachEventHandlerForCrossIcon($control); 10879 setTimeout(function(){ $("#"+_that._wgtId).on(TouchUtil.POINTER_UP,function(event){ 10880 event.stopPropagation(); 10881 });},50); 10882 } 10883 }, 10884 10885 _attachMouseEventHandlers:function($control){ 10886 var _timer=0,_that=this,_hoverTimer=0; 10887 $control.dblclick(function(event){ 10888 if(_that.options.access != "open") 10889 return; 10890 event.preventDefault();event.stopPropagation(); 10891 if(_timer.val){ 10892 clearTimeout(_timer);_timer =0; 10893 } 10894 _that._onCrossClick(event); 10895 }).click(function(event){ 10896 _that.$userControl.trigger("scribbleclick",event); 10897 if(_that.options.access != "open") 10898 return; 10899 event.preventDefault(); 10900 event.stopPropagation(); 10901 if(_timer){ 10902 clearTimeout(_timer);_timer=0; 10903 } else { 10904 _timer = setTimeout(function(){ 10905 _timer=0; 10906 _that._onImageClick(event); 10907 },500); 10908 } 10909 }); 10910 10911 this._attachEventHandlerForCrossIcon($control); 10912 10913 }, 10914 10915 _onCrossClick:function(event){ 10916 if(!this._is_readonly) return; 10917 this.$userControl.trigger("scribblefocus",event); 10918 this.$userControl.trigger("scribbleclick",event); 10919 event.stopPropagation(); 10920 $.alertBox.yesNo(null, 10921 this.localeStrings().clearSignatureConfirm, 10922 this.localeStrings().clearSignature, 10923 $.proxy(this._removeSigConfirmationHandler,this)); 10924 }, 10925 10926 _removeSigConfirmationHandler:function(isYes){ 10927 if(isYes){ 10928 this._saveValue(this._emptyImageVal); 10929 this._displayValue(this._extractData(this._createEmptyImageData())); 10930 this.$userControl.addClass("emptyScribble").trigger("scribbleclose",{}); 10931 this._is_readonly=false; 10932 } 10933 }, 10934 10935 _createEmptyImageData:function(){ 10936 if(!this._emptyImageData){ 10937 var emptyCanvasObj = document.createElement('canvas');
10938 emptyCanvasObj.style.width=this._sigCanvasWidth+'px'; 10939 emptyCanvasObj.style.height=this._sigCanvasHeight+'px'; 10940 emptyCanvasObj.width=this._sigCanvasWidth; 10941 emptyCanvasObj.height=this._sigCanvasHeight; 10942 var ctx = emptyCanvasObj.getContext('2d'); 10943 ctx.fillStyle='#ffffff'; 10944 ctx.clearRect(0,0,this._sigCanvasWidth,this._sigCanvasHeight); 10945 this._emptyImageData = emptyCanvasObj.toDataURL("image/png"); 10946 } 10947 return this._emptyImageData; 10948 }, 10949 10950 getCommitValue: function() { 10951 return this.options.value 10952 }, 10953 10954 _saveValue:function(val){ 10955 this.options.value=val; 10956 this.$userControl.trigger('scribblechange'); 10957 }, 10958 10959 _displayValue:function(val){ 10960 if(this.options.commitProperty) { 10961 //hardcode the widget VALUE by unknown image type 10962 if(val){ 10963 var widgetValue = "data:image/png;base64,"+val; 10964 this._setValue(widgetValue); 10965 } 10966 } 10967 else 10968 this.logger().debug("xfaView","[DefaultWidget._update], User Control or Commit Property is null" ); 10969 }, 10970 10971 _doOk:function(){ 10972 var mainCanvas = document.createElement('CANVAS'); 10973 var geoCnv = $('#'+this._geoCanvId)[0]; 10974 var sigCnv = $('#iEBox_canvas')[0]; 10975 var ctx = mainCanvas.getContext('2d'); 10976 10977 if(geoCnv.width>0&&geoCnv.height>0){ 10978 10979 if(this._geoLocAtBottom){ 10980 mainCanvas.width=sigCnv.width; 10981 mainCanvas.height =sigCnv.height+geoCnv.height; 10982 ctx.drawImage(sigCnv,0,0); 10983 ctx.drawImage(geoCnv,0,sigCnv.height); 10984 } else { 10985 mainCanvas.width=sigCnv.width+geoCnv.width; 10986 mainCanvas.height =sigCnv.height; 10987 ctx.drawImage(sigCnv,0,0); 10988 ctx.drawImage(geoCnv,sigCnv.width,0); 10989 } 10990 } else { 10991 mainCanvas.width=sigCnv.width; 10992 mainCanvas.height =sigCnv.height; 10993 ctx.drawImage(sigCnv,0,0); 10994 } 10995 imageEditDialog.hide(); 10996 var newdata = mainCanvas.toDataURL("image/png");//(this.myScribbleHandle||"").toString(); 10997 10998 var val,val1; 10999 if((val=/*=*/this._extractData(newdata))){ 11000 // val1 = PNGUtil._makeReadOnly(val); 11001 val = PNGUtil._makeReadOnly(val); 11002 this._saveValue(val); 11003 this._is_readonly=true; 11004 } 11005 this._geoLocQuery&&this._geoLocQuery.cancel();// cancel current geo loc request; 11006 this.$userControl.trigger("scribbleclose") 11007 }, 11008 _handleOk:function(){ 11009 if(this._enforceGeoLoc){ 11010 this._geoLocQuery = new GeoLocQuery().init($.proxy(function(data){ 11011 this._geoQuerySuccessHandler(data); 11012 this._doOk(); 11013 },this),$.proxy(this._geoQueryErrorHandler,this)); 11014 this._geoLocQuery.query(); 11015 this._showMessage(this.localeStrings().fetchGeoLocation); 11016 } else { 11017 this._doOk(); 11018 } 11019 }, 11020 11021 _handleCancel:function(){ 11022 imageEditDialog.hide(); 11023 this._geoLocQuery&&this._geoLocQuery.cancel();// cancel current geo loc request; 11024 this.$userControl.trigger("scribbleclose") 11025 }, 11026 11027 _handleClear:function(){ 11028 this.myScribbleHandle.setEnabled(true); 11029 this._is_readonly=false; 11030 this._makeReadOnly(this._is_readonly); 11031 $('#iEBox_canvas')[0].width=this._sigCanvasWidth; 11032 $('#iEBox_caption').width(this._sigCanvasWidth); 11033 $('#iEBox_canvas')[0].height=this._sigCanvasHeight; 11034 $('#keyboard_Sign_Box')[0].value=""; 11035 var geoCanv = $('#'+this._geoCanvId)[0]; 11036 imageEditDialog.enableButtons({Ok:false,Clear:false}); 11037 geoCanv.width=0; 11038 geoCanv.height=0; 11039 imageEditDialog._resize(); 11040 this._geoLocQuery&&this._geoLocQuery.cancel();// cancel current geo loc request; 11041 }, 11042 _makeReadOnly:function(readonly){ 11043 imageEditDialog.enableButtons({Ok:false,Clear:false,Geo:!readonly,Brush:!readonly,Text:!readonly}); 11044 if(readonly){ 11045 $('#iEBox_canvas').css({border:'1px solid gray'}); 11046 $('#iEBox_caption').css({display:'none'}); 11047 11048 } 11049 this._defaultStatus = " "; 11050 this._showMessage(this._defaultStatus); 11051 }, 11052 11053 _showMessage:function(msg){ 11054 var _that = this; 11055 if(this._msgTimeout) { clearTimeout(this._msgTimeout); this._msgTimeout=0; } 11056 $("#iEBox_title").replaceWith('<div id="iEBox_title">'+msg+'</div>'); 11057 this._msgTimeout = window.setTimeout(function(){ 11058 $("#iEBox_title").replaceWith('<div id="iEBox_title">'+_that._defaultStatus+'</div>'); 11059 },15000); 11060 }, 11061 11062 _geoQueryErrorHandler:function(err){ 11063 this._showMessage(this.localeStrings().errorFetchGeoLocation); 11064 }, 11065
11066 _getLogMessage:function(key){ 11067 return this.logMsgs()[key]||key; 11068 }, 11069 11070 _handleGeo:function(){ 11071 // initiate geolocation 11072 if(navigator.geolocation){ 11073 this._geoLocQuery = new GeoLocQuery().init($.proxy(this._geoQuerySuccessHandler,this),$.proxy(this._geoQueryErrorHandler,this)); 11074 this._geoLocQuery.query(); 11075 this._showMessage(this.localeStrings().fetchGeoLocation); 11076 } else { 11077 this.logger().debug("xfaView",this._getLogMessage("ALC-FRM-901-011")); 11078 } 11079 }, 11080 11081 // This Function is used to fetch the geolocation. 11082 calculateGeolocation: function(){ 11083 this._handleGeo(); 11084 }, 11085 11086 _handleText:function(){ 11087 var signBoxEl=document.getElementById("keyboard_Sign_Box"); 11088 var signCanvasEl=document.getElementById("iEBox_canvas"); 11089 if(signBoxEl.value.length==0){ 11090 this._handleClear(); 11091 } 11092 this._disableSignatureCanvas(); 11093 this._enableSignatureTextBox(); 11094 signBoxEl.focus(); 11095 }, 11096 11097 _disableSignatureTextBox:function(){ 11098 document.getElementById("keyboard_Sign_Box").style.display = "none"; 11099 }, 11100 11101 _enableSignatureTextBox:function(){ 11102 document.getElementById("keyboard_Sign_Box").style.display = "inline-block"; 11103 }, 11104 11105 _disableSignatureCanvas:function(){ 11106 document.getElementById("iEBox_canvas").style.display = "none"; 11107 }, 11108 11109 _enableSignatureCanvas:function(){ 11110 document.getElementById("iEBox_canvas").style.display = "inline-block"; 11111 }, 11112 11113 _handleBrushSelect:function(w){ 11114 if(this.myScribbleHandle&&!this._is_readonly) { 11115 this.myScribbleHandle.setLineWidth(w); 11116 } 11117 }, 11118 11119 _handleBrush:function(evt){ 11120 if($('#keyboard_Sign_Box')[0].value.length>0){ 11121 this._handleClear(); 11122 } 11123 this._disableSignatureTextBox(); 11124 this._enableSignatureCanvas(); 11125 imageEditDialog.toggleBrushList(evt); 11126 }, 11127 _handleKeyDown:function(event){ 11128 if(event.keyCode == ENTER_KEY || event.charCode == ENTER_KEY || event.which == ENTER_KEY) { // touch devices may return charCode 11129 event.preventDefault(); 11130 this._onImageClick(event); 11131 } else if(event.keyCode == DELETE_KEY || event.charCode == DELETE_KEY || event.which == DELETE_KEY) { 11132 this._onCrossClick(event); 11133 } 11134 }, 11135 _dialogCallback:function(button_val,arg1){ 11136 // add back on click handler 11137 // this.$userControl.click($.proxy(this._onImageClick, this)); 11138 11139 switch(button_val){ 11140 case "Ok": 11141 this._handleOk(); 11142 break; 11143 case "Cancel": 11144 this._handleCancel(); 11145 break; 11146 case "Clear": 11147 this._handleClear(); 11148 break; 11149 case "Geo": 11150 this.calculateGeolocation(); 11151 break; 11152 case "BrushSelect": 11153 this._handleBrushSelect(arg1); 11154 break; 11155 case "Brush": 11156 this._handleBrush(arg1); 11157 break; 11158 case "Text": 11159 this._handleText(); 11160 break; 11161 11162 } 11163 }, 11164 11165 _geoQuerySuccessHandler:function(data){ 11166 this._renderPosition(data); 11167 }, 11168 11169 _fitGeoLocText:function(latStr,longStr,timeStr,ctx,maxWidth,maxHeight){ 11170 var fontSize=12; 11171 ctx.font="bold "+fontSize+"pt Arial"; 11172 var width = Math.max(ctx.measureText(latStr).width,ctx.measureText(longStr).width,ctx.measureText(timeStr).width); 11173 var lineHeight = ctx.measureText("m").width*1.5; 11174 while((width>maxWidth||3*lineHeight>maxHeight)&&fontSize>1){ 11175 fontSize--; 11176 ctx.font="bold "+fontSize+"pt Arial"; 11177 width = Math.max(ctx.measureText(latStr).width,ctx.measureText(longStr).width,ctx.measureText(timeStr).width); 11178 lineHeight = ctx.measureText("m").width*1.5; 11179 } 11180 return {width:width,lineHeight:lineHeight,fontSize:fontSize}; 11181 }, 11182 11183 _renderPosition:function(position){ 11184 if(position&&position.coords){ 11185 this._showMessage(" "); 11186 var latStr = this.localeStrings().latitude+": " + position.coords.latitude; 11187 var longStr = this.localeStrings().longitude+": " + position.coords.longitude; 11188 var dateObj = new Date(); 11189 var tZone = (dateObj.getTimezoneOffset()/60*-1); 11190 11191 var timeStr = this.localeStrings().time+": "+(dateObj.getMonth()+1)+"/"+dateObj.getDate()+"/"+dateObj.getFullYear()+" "+dateObj.getHours()+":"+dateObj.getMinutes()+":"+dateObj.getSeconds()+((tZone>0)?" +":" ")+(tZone); 11192 var canvasObj = $('#'+this._geoCanvId)[0];
11193 var sigCanvas = $('#iEBox_canvas')[0]; 11194 var sigTextBox = $('#keyboard_Sign_Box')[0]; 11195 var dummyCanvas = document.createElement('canvas'); 11196 if(canvasObj){ 11197 var ctx = canvasObj.getContext('2d'); 11198 ctx.font="bold 12pt Arial"; 11199 11200 canvasObj.width=this._geoCanvasWidth; 11201 canvasObj.height=this._geoCanvasHeight; 11202 var layout = this._fitGeoLocText(latStr,longStr,timeStr,ctx,canvasObj.width,canvasObj.height); 11203 var aspectRatio ; 11204 aspectRatio = this.aspectRatioToBeUsed(); 11205 if(!this._enforceGeoLoc){ 11206 if(this._geoLocAtBottom){ 11207 dummyCanvas.height = this._sigCanvasHeight-canvasObj.height; 11208 dummyCanvas.width = dummyCanvas.height/aspectRatio; 11209 } else { 11210 dummyCanvas.width = this._sigCanvasWidth-canvasObj.width; 11211 dummyCanvas.height = dummyCanvas.width*aspectRatio; 11212 } 11213 // move drawn signature to a temporary canvas and scale it to new dimension 11214 dummyCanvas.getContext('2d').drawImage(sigCanvas,0,0,dummyCanvas.width,dummyCanvas.height); 11215 if(this._geoLocAtBottom){ 11216 sigCanvas.height = dummyCanvas.height; 11217 sigTextBox.height = dummyCanvas.height; 11218 sigCanvas.getContext('2d').drawImage(dummyCanvas,(sigCanvas.width-dummyCanvas.width)/2,0); 11219 } else { 11220 sigCanvas.width = dummyCanvas.width; 11221 sigTextBox.width = dummyCanvas.width; 11222 sigCanvas.getContext('2d').drawImage(dummyCanvas,0,(sigCanvas.height-dummyCanvas.height)/2); 11223 } 11224 $('#iEBox_caption').width(sigCanvas.width); 11225 imageEditDialog.enableButtons({Clear:true}); 11226 } 11227 11228 var fwidth = layout.width; 11229 var fheight = layout.lineHeight; 11230 var bottomMargin=2; 11231 ctx.fillStyle='#555555'; 11232 ctx.font="bold "+layout.fontSize+"pt Arial"; 11233 ctx.fillText(latStr,0,canvasObj.height-2*fheight-bottomMargin); 11234 ctx.fillText(longStr,0,canvasObj.height-fheight-bottomMargin); 11235 ctx.fillText(timeStr,0,canvasObj.height-bottomMargin); 11236 11237 imageEditDialog._resize(); 11238 } 11239 } 11240 }, 11241 _scribbleCallback:function(){ 11242 imageEditDialog.enableButtons({Clear:true,Ok:true}); // enable clear and ok buttons 11243 }, 11244 _onImageClick:function(){ 11245 if(!imageEditDialog.getIsOpen()){ 11246 var _that = this; 11247 imageEditDialog.show(" ",$.proxy(this._dialogCallback, this)); 11248 if(!this._enforceGeoLoc){ 11249 $('#iEBox_Geo').css({display:'inline-block'}); 11250 } 11251 var image = new Image(); 11252 image.onload=function(){ 11253 _that.myScribbleHandle = new Scribble("iEBox_canvas",image,image.width,image.height,$.proxy(_that._scribbleCallback,_that)); 11254 _that.myScribbleHandle.setEnabled(!_that._is_readonly); 11255 $('#iEBox_caption').width(image.width); 11256 $('#iEBox_container').css({display:'table'}); 11257 if($('#iEBox_container').length == 1){ 11258 $('#iEBox_container')[0].focus(); 11259 } 11260 imageEditDialog._resize(); 11261 imageEditDialog._reposition(); // recalculate position, so that the values are updated, esp. in iPad 11262 } 11263 if(!this.options.value||this.options.value==this._emptyImageVal){ 11264 this._is_readonly=false; 11265 this.$userControl.addClass("emptyScribble"); 11266 image.src = this._createEmptyImageData(); 11267 } else { 11268 this.$userControl.removeClass("emptyScribble"); 11269 if(PNGUtil._isPng(this.options.value)){ 11270 this._is_readonly = !!PNGUtil._isReadOnly(this.options.value); 11271 image.src = "data:image/png;base64,"+this.options.value;//this.createBl _that.$userControl.attr(_that.options.commitProperty); 11272 } else { 11273 image.src = "data:;base64," + this.options.value;//this.createBl _that.$userControl.attr(_that.options.commitProperty); 11274 } 11275 } 11276 this._makeReadOnly(this._is_readonly); 11277 } 11278 }, 11279 11280 _extractData:function(datauri){ 11281 var idx; 11282 if(datauri!=null&&datauri.length>0&&datauri.indexOf("data:")==0){ 11283 if((idx=datauri.indexOf(","))>0){ 11284 return datauri.substr(idx+1); 11285 } 11286 } 11287 }, 11288 11289 _setValue:function(val){ 11290 this.$userControl.prop(this.options.commitProperty, val); 11291 this.$userControl.attr(this.options.commitProperty, val); 11292 if(this._dummyImg){ 11293 this._dummyImg.setAttribute(this.options.commitProperty,val); 11294 } 11295 } 11296}); 11297 //hack for IOS5 touch bug 11298 $(function(){ 11299 $('body').on('touchstart', function(e) {}); 11300 }); 11301 11302})($,xfalib); 11303(function ($, window, _) { 11304 11305 var _defaults = { 11306 placeHolderText : "Enter comments here" 11307 }; 11308 11309 var AdobeFileAttachment = function (element, options) { 11310 this.options = options; 11311 this.$elementFileUploadBtn = []; 11312 this.$elementFileList = []; 11313 this.$element = $(element); 11314 if (this.$element.attr("multiple") && !xfalib.ut.Utilities._isDataContainerSupported()) { 11315 // remove multiple attribute if multi file selection in one go is not supported 11316 this.$element.removeAttr("multiple"); 11317 } 11318 this.$parent = this.$element.parent(); 11319 this.invalidFeature = { 11320 "SIZE":1, 11321 "NAME":2, 11322 "MIMETYPE":3 11323 }; 11324 Object.freeze(this.invalidFeature); 11325 // initialize the regex initially 11326 this.regexMimeTypeList = this.options.mimeType.map(function (value, i) { 11327 try { 11328 return new RegExp(value.trim()); 11329 } catch (e) { 11330 // failure during regex parsing, don't return anything specific to this value since the value contains 11331 // incorrect regex string 11332 if(window.console) { 11333 console.log(e); 11334 } 11335 } 11336 }); 11337 }; 11338 11339 var isBrowserIE9OrIE10 = ($.browser.msie && ($.browser.version === '9.0' || $.browser.version === '10.0')), 11340 fileLabelsCount = 0; 11341 11342 11343 AdobeFileAttachment.prototype = { 11344 _fileIframeName : "guide-fu-iframe", 11345 _addFile : "Add File", 11346 11347 clear: function () { 11348 this.$element.val(''); 11349 this.$elementFileList.empty(); 11350 }, 11351 11352 destroy: function () { 11353 this.$fileDomElements = $.map(this.$fileDomElements, function(item){ 11354 // since item can be null or object, doing this check 11355 if(_.isObject(item) && item.val().length === 0) { 11356 //TODO: remove item from dom, since there is a memory leak 11357 return item; 11358 } 11359 }); 11360 this.values = []; 11361 if(isBrowserIE9OrIE10){ 11362 if(_.last(this.$fileDomElements) == null){ 11363 this.cloneFileInputAndUpdateIdForIE9(); 11364 } else { 11365 this.updateLabelForAttr(_.last(this.$fileDomElements).attr("id")); 11366 } 11367 } 11368 this.$element.trigger("change.fileupload"); 11369 }, 11370 11371 _setUrl : function(url, index){ 11372 this.$elementFileList.find("span.guide-fu-fileName").eq(index).data("key", url); 11373 }, 11374 11375 _getUrl : function(index) { 11376 return this.$elementFileList.find("span.guide-fu-fileName").eq(index).data("key"); 11377 }, 11378 getSetFilePathAndReturnNamePathMap: function(valueList) { 11379 11380 var mapOfObjectsHavingTempPathAndFileNames = {}, 11381 $temp, 11382 tempPath; 11383 11384 $.each(this.$elementFileList.children(), function ( index, childLiElement) { 11385 $temp = $(childLiElement).find("span.guide-fu-fileName"); 11386 tempPath = $temp.data("key"); 11387 if(!tempPath && valueList && valueList[index]) { 11388 $temp.data("key", valueList[index]); 11389 } 11390 mapOfObjectsHavingTempPathAndFileNames[$temp.html()] = tempPath || $temp.data("key"); 11391 }); 11392 return mapOfObjectsHavingTempPathAndFileNames; 11393 }, 11394 11395 11396 value : function(value) { 11397 if(!_.isUndefined(value)) { 11398 var _self = this, 11399 comments = this.comment(), 11400 isChange = false, 11401 fileNames = _.isArray(this.options.fileNames) ? this.options.fileNames : null, 11402 oldUrls = {};
11403 // Cache the url before deletion 11404 this.$elementFileList.children().find("span.guide-fu-fileName").each(function(){ 11405 var url = $(this).data("key"); 11406 if(!_.isUndefined(url)){ 11407 var fileName = url.substring(url.lastIndexOf("/") + 1); 11408 oldUrls[fileName] = url; 11409 } 11410 }); 11411 this.$elementFileList.empty(); 11412 if(value != null) { 11413 var arr = value.split("\n"); 11414 // contruct initial file name and value map 11415 // this is done only once in entire live cycle, its done here, since we get value here 11416 if (fileNames && _.isEmpty(this._initialFileValueFileNameMap)) { 11417 for (var index = 0; index < fileNames.length; index++) { 11418 _self._initialFileValueFileNameMap[arr[index]] = fileNames[index] 11419 } 11420 } 11421 // Update the value array with the file 11422 this.values = _.map(arr, function(fileName, index){ 11423 // Check if file Name is a path, if yes get the last part after "/" 11424 var slash = fileName.lastIndexOf("/"), 11425 fileUrl = fileName, 11426 fileUploadUrl = null; 11427 if(slash !== -1) { 11428 // Store the cached url here 11429 fileUrl = fileUploadUrl = fileName; 11430 fileName = fileName.substring(slash + 1); 11431 // case: when you click on save second time 11432 if((_.isObject(_self.$fileDomElements[index]) && _self.$fileDomElements[index].val().length > 0) || _.isString(_self.$fileDomElements[index])){ 11433 isChange = true; 11434 _self.$fileDomElements[index] = null; 11435 } else if(_self.$fileDomElements[index] !== null) { // create a dummy file dom for the cached value 11436 isChange = true; 11437 _self.$fileDomElements.splice(index, 0, null); 11438 } 11439 } else if (oldUrls[fileName]) { 11440 fileUploadUrl = oldUrls[fileName]; 11441 } 11442 // if fileNames options is explicitly passed, use it 11443 if (fileNames && _self._initialFileValueFileNameMap[fileUrl]) { 11444 fileName = _self._initialFileValueFileNameMap[fileUrl]; 11445 } 11446 _self.showFileList(fileName, comments[index], fileUploadUrl); 11447 return fileUrl; 11448 }); 11449 if(isChange){ 11450 this.$element.trigger("change.fileupload"); 11451 } 11452 } else { 11453 if(_.isArray(this.values) && this.values.length !== 0){ 11454 this.destroy(); 11455 } 11456 } 11457 } 11458 else { 11459 return this.values; 11460 } 11461 }, 11462 11463 fileAttachment: function(){ 11464 return this.values; 11465 }, 11466 11467 comment : function(value){ 11468 var _self = this, 11469 $elem = null, 11470 comments; 11471 if (!_.isUndefined(value)) { 11472 if(value != null) { 11473 comments = value.split("\n"); 11474 $elem = this.$elementFileList.find('div.guide-fu-comment'); 11475 $elem.each(function(index){ 11476 $(this).text(comments[index]); 11477 }); 11478 } 11479 } 11480 else { 11481 $elem = this.$elementFileList.find('div.guide-fu-comment'); 11482 comments = []; 11483 $elem.each(function(){ 11484 comments.push($(this).text()); 11485 }); 11486 return comments; 11487 } 11488 }, 11489 11490 multiSelect : function(value){ 11491 if(value !== undefined) 11492 this.options.multiSelect = value; 11493 else 11494 return this.options.multiSelect; 11495 }, 11496 11497 fileSizeLimit : function(value){ 11498 if(value !== undefined) 11499 this.options.fileSizeLimit = value; 11500 else 11501 return this.options.fileSizeLimit; 11502 }, 11503 11504 mimeType : function(value){ 11505 if(value !== undefined) 11506 this.options.mimeType = value; 11507 else 11508 return this.options.mimeType; 11509 }, 11510 11511 access : function(value){ 11512 if(value == "readOnly") { 11513 this.$element.attr("disabled", "disabled"); 11514 //for readOnly hide the delete icon in file list
11515 $(this.$parent).addClass('guide-fu-disabled'); 11516 } 11517 else if(value == "open") { 11518 this.$element.removeAttr("disabled"); 11519 $(this.$parent).removeClass('guide-fu-disabled'); 11520 } 11521 }, 11522 11523 fileList : function(value) { 11524 var filtered, 11525 _self = this; 11526 if(value !== undefined){ 11527 this.$fileDomElements = []; 11528 _.each(value, function(item, index){ 11529 if((_.isObject(item) && (isBrowserIE9OrIE10 || item.val().length > 0)) || (_.isString(item))){ 11530 // check if index is within the length 11531 // this is written for delete case 11532 // if item is a string, then it should be set null 11533 if(_.isString(item)){ 11534 item = null; 11535 } 11536 _self.$fileDomElements[index] = item; 11537 } 11538 }); 11539 filtered = this.$fileDomElements; 11540 // In case of IE9, get the last element of fileDom and update the id for label 11541 if(isBrowserIE9OrIE10 && value !== null){ 11542 // Case: if it is single select, and then we do a restore and then after attaching another file we click save 11543 if(_.last(this.$fileDomElements) == null){ 11544 this.cloneFileInputAndUpdateIdForIE9(); 11545 } else { 11546 this.updateLabelForAttr(_.last(this.$fileDomElements).attr("id")); 11547 } 11548 } 11549 } 11550 else { 11551 // here filtered is a new array 11552 // A new array is returned over here so that the user of this API doesn't try to change the widget array directly 11553 filtered = $.map(this.$fileDomElements, function(item, index){ 11554 if(!item) { 11555 return _self._getUrl(index); 11556 } else if((item[0].files && item[0].files.length !== 0) 11557 || (_self.options.multiSelect || item[0].value.length > 0)) { 11558 return item; 11559 } 11560 }); 11561 } 11562 return filtered; 11563 }, 11564 11565 // file preview html 11566 fileItemPreview: function(){ 11567 return $("<span></span>").addClass("guide-fu-filePreview glyphicon glyphicon-ok"); 11568 }, 11569 11570 // force flag indicates that forcefully set the dom but don't update the options 11571 buttonText: function (value, force) { 11572 if (value !== undefined) { 11573 if(!force) 11574 this.options.buttonText = value; 11575 this.$elementFileUploadBtn.find('span.guide-fu-label').html(value); 11576 } else { 11577 return this.options.buttonText; 11578 } 11579 }, 11580 11581 // To change the icon of the button, the user should customize the class 11582 btnIcon: function () { 11583 return $("<span></span>").addClass("guide-fu-icon glyphicon glyphicon-folder-open"); 11584 }, 11585 11586 btnLabel: function(){ 11587 return $("<span></span>").addClass("guide-fu-label").html(this.options.buttonText); 11588 }, 11589 11590 fileItemList: function(){ 11591 return this.$parent.find(this.options.fileItemListClass); 11592 }, 11593 11594 getNewCommentElementSummary : function(text){ 11595 return $("<div title='Click to edit' tabindex='0'></p>").addClass("guide-fu-comment").text(text || _defaults.placeHolderText); 11596 }, 11597 11598 getNewCommentElement : function(text){ 11599 return $("<div contenteditable='true' tabindex='0'></div>").addClass("guide-fu-comment").text(text || ""); 11600 }, 11601 11602 fileItem: function(fileName, comment, fileUrl){ 11603 var $fileItem = $("<li></li>").addClass("guide-fu-fileItem"); 11604 var nameWithoutMarker = xfalib.ut.Utilities._getNameWithoutMarker(fileName); 11605 var $elem = $("<span tabindex='0'></span>").addClass("guide-fu-fileName").attr("aria-label", nameWithoutMarker).text(nameWithoutMarker).appendTo($fileItem).keypress(function(e) { 11606 if (e.keyCode === 13 || e.charCode === 32) { 11607 $(e.target).click(); 11608 } 11609 }).click($.proxy(this.handleFilePreview, this)); 11610 if(this.options.disablePreview) { 11611 $elem.addClass('non-preview-fileName'); 11612 } 11613 if(fileUrl != null){ 11614 $elem.attr("data-key", fileUrl); 11615 } 11616 $("<span tabindex='0'></span>").addClass("guide-fu-fileClose close").attr("role", "button").attr("aria-label", xfalib.locale.Strings.FileCloseAccessText
11616+ nameWithoutMarker).text("x").appendTo($fileItem).keypress(function(e) { 11617 if (e.keyCode === 13 || e.charCode === 32) { 11618 $(e.target).click(); 11619 } 11620 }) 11621 .click($.proxy(this.handleClick, this)); 11622 11623 this.fileItemPreview().appendTo($fileItem); 11624 11625 if(this.options.showComment){ 11626 this.getNewCommentElementSummary(comment).appendTo($fileItem).focus($.proxy(this.handleCommentClick, this)).click($.proxy(this.handleCommentClick, this)); 11627 } 11628 return $fileItem; 11629 }, 11630 11631 toggleFileUploadBtn: function(){ 11632 if(this.options.multiSelect) { 11633 // Change the look of file upload button 11634 if(this.$elementFileList.children().length > 0){ 11635 // Change the text 11636 this.buttonText(this._addFile, true); 11637 // Change the icon too 11638 this.$elementFileUploadBtn.find('span.guide-fu-icon').removeClass("glyphicon-folder-open").addClass("glyphicon-plus"); 11639 } else { 11640 this.buttonText(this.options.buttonText); 11641 this.$elementFileUploadBtn.find('span.guide-fu-icon').removeClass("glyphicon-plus").addClass("glyphicon-folder-open"); 11642 } 11643 } 11644 }, 11645 11646 showInvalidMessage: function(fileName, invalidFeature){ 11647 var that = this; 11648 var IS_IPAD = navigator.userAgent.match(/iPad/i) !== null, 11649 IS_IPHONE = (navigator.userAgent.match(/iPhone/i) !== null); 11650 if(IS_IPAD || IS_IPHONE){ 11651 setTimeout(function() { 11652 that.invalidMessage(that,fileName, invalidFeature); 11653 }, 0); 11654 } 11655 else { 11656 this.invalidMessage(this,fileName, invalidFeature); 11657 } 11658 }, 11659 11660 invalidMessage: function(refObj,fileName, invalidFeature){ 11661 if(invalidFeature === refObj.invalidFeature.SIZE) { 11662 alert(xfalib.ut.LocalizationUtil.prototype.getLocalizedMessage("", xfalib.locale.Strings["FileSizeGreater"], [fileName, refObj.options.fileSizeLimit])); 11663 } else if (invalidFeature === refObj.invalidFeature.NAME) { 11664 alert(xfalib.ut.LocalizationUtil.prototype.getLocalizedMessage("", xfalib.locale.Strings["FileNameInvalid"], [fileName])); 11665 } else if (invalidFeature === refObj.invalidFeature.MIMETYPE) { 11666 alert(xfalib.ut.LocalizationUtil.prototype.getLocalizedMessage("", xfalib.locale.Strings["FileMimeTypeInvalid"], [fileName])); 11667 } 11668 }, 11669 11670 /*** 11671 * Finds the value in the array, if the value is a url then it uses the filename in the url to search for the text 11672 * This is done since our model stores the URL too in case of draft restore or clicking on save in guide 11673 * @param text string representing the text of which the index is to be found 11674 * @param $elem reference to the jquery element. This is used if there are duplicate file names present in the file upload. 11675 * @returns {number} 11676 * @private 11677 */ 11678 _getIndexOfText : function(text, $elem){ 11679 var index = -1, 11680 self = this, 11681 isDuplicatePresent = false; 11682 _.find(this.values, function(value, iter){ 11683 // if value is a url, then compare with last 11684 var tempValue = value, 11685 // can't use getOrElse here since value can have "." in URL and getOrElse splits based on period to find key inside object 11686 fileName = (_.isObject(self._initialFileValueFileNameMap) && typeof self._initialFileValueFileNameMap[value] !== undefined) ? self._initialFileValueFileNameMap[value] : null; 11687 if(tempValue.match(/\//g) && tempValue.match(/\//g).length > 1){ 11688 tempValue = value.substring(value.lastIndexOf("/")+1); 11689 tempValue = xfalib.ut.Utilities._getNameWithoutMarker(tempValue); 11690 } 11691 // we pass file name explicityly as options, if passed use that as fallback to find the URL 11692 if(tempValue === text || fileName === text){ 11693 index = iter; 11694 isDuplicatePresent = self.values.indexOf(value, index + 1) !== -1; 11695 if($elem && isDuplicatePresent){ 11696 // now check if duplicate present and get its correct index 11697 // today all files are wrapped under .guide-fu-fileItem node 11698 index = $elem.closest(".guide-fu-fileItem").index(); 11699 } 11700 // check if there is a duplicate 11701 // this is to just break the loop 11702 return value; 11703 } 11704 }); 11705 return index; 11706 }, 11707 11708 11709 /* 11710 * Since input file element might contain multiple files. 11711 * This function takes absolute file index as parameter & returns position of the file w.r.t input file elt 11712 */ 11713 _getFileObjIdx : function (index) { 11714 if (index >= 0) { 11715 var currentIdx = 0; 11716 for (var fileInputEltIdx = 0; fileInputEltIdx < this.$fileDomElements.length; fileInputEltIdx++) { 11717 if (this.$fileDomElements[fileInputEltIdx]) { 11718 var files = this.$fileDomElements[fileInputEltIdx][0].files; 11719 if (files) { 11720 var filesLength = files.length; 11721 if ( index <= currentIdx + filesLength - 1 ) { 11722 return [fileInputEltIdx, index - currentIdx]; 11723 } 11724 currentIdx+=files.length; 11725 } 11726 } else { 11727 if (index == currentIdx) { 11728 return [fileInputEltIdx,0]; 11729 } 11730 currentIdx++; 11731 } 11732 } 11733 } 11734 return null; 11735 }, 11736 11737 /* 11738 * This function returns FileList object of the passed file array 11739 */ 11740 _getFileListItem : function (files) { 11741 try { 11742 var dataContainer = new DataTransfer() || (new ClipboardEvent("")).clipboardData; 11743 _.each(files, function (file) { 11744 dataContainer.items.add(file); 11745 }); 11746 return dataContainer.files; 11747 } catch(err) { 11748 console.error(err); 11749 throw err; 11750 } 11751 }, 11752 11753 _updateFilesInDom : function($fileDom, files) { 11754 // in safari, a change event is trigged if files property is changed dynamically 11755 // hence adding this check to clear existing state only for safari browsers 11756 this._isFileUpdate = true; 11757 $fileDom[0].files = this._getFileListItem(files); 11758 this._isFileUpdate = false;
11759 }, 11760 11761 /* 11762 * This function deletes files at specified indexes from input dom elt 11763 */ 11764 _deleteFilesFromInputDom : function ($fileDomElt, deletedIndexes) { 11765 var remainingFiles = []; 11766 _.each($fileDomElt[0].files, function(file,idx){ 11767 if(!deletedIndexes.includes(idx)){ 11768 remainingFiles.push(file); 11769 } 11770 }); 11771 try { 11772 // in safari, a change event is trigged if files property is changed dynamically 11773 // hence adding this check to clear existing state only for safari browsers 11774 this._updateFilesInDom($fileDomElt, remainingFiles); 11775 } catch(err){ 11776 console.error("Deleting files is not supported in your browser"); 11777 } 11778 }, 11779 11780 /** 11781 * This event listener gets called on click of close button in file upload 11782 * 11783 * @param event 11784 */ 11785 handleClick: function(event){ 11786 11787 var $elem = $(event.target), 11788 text = $elem.prev().text(), 11789 index = this._getIndexOfText(text, $elem), 11790 url = $elem.prev().data("key"), 11791 objectUrl = $elem.prev().data("objectUrl"); 11792 if (index != -1) { 11793 this.values.splice(index, 1); 11794 var fileObjIdx = this._getFileObjIdx(index); 11795 var $fileDomElt = this.$fileDomElements[fileObjIdx[0]]; 11796 if (!$fileDomElt || $fileDomElt[0].files.length === 1) { 11797 this.$fileDomElements.splice(fileObjIdx[0], 1); 11798 } else { 11799 this._deleteFilesFromInputDom($fileDomElt, [fileObjIdx[1]]); 11800 } 11801 if (isBrowserIE9OrIE10) { 11802 this.cloneFileInputAndUpdateIdForIE9(); 11803 } 11804 if (url != null) { 11805 // remove the data so that others don't use this url 11806 $elem.prev().removeData("key"); 11807 } 11808 if(objectUrl) { 11809 // revoke the object URL to avoid memory leaks in browser 11810 // since file is anyways getting deleted, remove the object URL's too 11811 window.URL.revokeObjectURL(objectUrl); 11812 } 11813 } 11814 // Remove the dom from view 11815 //All bound events and jQuery data associated with the element are also removed 11816 $elem.parent().remove(); 11817 // trigger the change event to update the value 11818 this.$element.trigger("change.fileupload"); 11819 // Set the focus on file upload button after click of close 11820 this.$elementFileUploadBtn.focus(); 11821 11822 }, 11823 11824 11825 displaySVG: function (objectUrl) { 11826 const url = objectUrl; 11827 const img = window.document.createElement('img'); 11828 img.src = url; 11829 const newTab = window.open('', '_blank', 'scrollbars=no,menubar=no,height=600,width=800,resizable=yes,toolbar=no,status=no'); 11830 newTab.document.body.appendChild(img); 11831 }, 11832 11833 11834 _previewFileUsingObjectUrl : function (file) { 11835 if (file) { 11836 if (window.navigator && window.navigator.msSaveOrOpenBlob) { // for IE 11837 window.navigator.msSaveOrOpenBlob(file, file.name); 11838 } else { 11839 var url = window.URL.createObjectURL(file); 11840 if (file.type === 'image/svg+xml') { 11841 this.displaySVG(url); 11842 } else { 11843 window.open(url, '', 'scrollbars=no,menubar=no,height=600,width=800,resizable=yes,toolbar=no,status=no'); 11844 } 11845 return url; 11846 } 11847 } 11848 }, 11849 11850 // this function maintains a map for 11851 handleFilePreview: function(event){ 11852 if(!this.options.disablePreview) { 11853 var $elem = $(event.target), 11854 text = $elem.text(), 11855 index = this._getIndexOfText(text, $elem), 11856 fileDom = null, 11857 fileName = null, 11858 fileUrl = null, 11859 timeStamp = new Date().getTime(); 11860 11861 // for draft usecase, if text contains "/" in it, it means the file is already uploaded 11862 // text should contain the path, assuming that the fileUrl is stored in data element 11863 11864 if (index != -1) { 11865 // Store the url of file as data 11866 if(!_.isUndefined($elem.data("key"))) 11867 fileUrl = $elem.data("key"); 11868 11869 if(fileUrl) { 11870 //prepend context path if not already appended 11871 if (!(fileUrl.lastIndexOf(this.options._getUrl, 0) === 0)) { 11872 fileUrl = this.options._getUrl + fileUrl; 11873 } 11874 this.previewFile.apply(this, [null, {"fileUrl" : fileUrl}]); 11875 } else { 11876 var previewFileObjIdx = this._getFileObjIdx(index); 11877 var previewFile = this.$fileDomElements[previewFileObjIdx[0]][0].files[previewFileObjIdx[1]]; 11878 var objectUrl = this._previewFileUsingObjectUrl(previewFile); 11879 if (objectUrl) { 11880 $elem.data("objectUrl", objectUrl); 11881 } 11882 } 11883 } 11884 } 11885 }, 11886 11887 previewFile: function(event){ 11888 var url = null; 11889 if(_.isUndefined(arguments[1])) 11890 url = this.$element[this.options.uploaderPluginName]("getFileUrl"); 11891 else 11892 url = arguments[1].fileUrl; 11893 var lastIndex = url.lastIndexOf('/'); 11894 //to make sure url has a slash '/' 11895 // added check for query param since sas url contains query params & does not have file name, encoding is not required in this case 11896 if(lastIndex >= 0 && url.indexOf('?') == -1) { 11897 //encode the filename after last slash to ensure the handling of special characters 11898 url = url.substr(0, lastIndex) +'/'+ encodeURIComponent(url.substr(lastIndex + 1)); 11899 } 11900 // this would work for dataURl or normal URL 11901 // todo: add support to preview base 64 encoded image, to preview base64 encoded binary, we would probably need 11902 // todo: the content type in the widget too 11903 window.open(url, '', 'scrollbars=no,menubar=no,height=600,width=800,resizable=yes,toolbar=no,status=no'); 11904 11905 }, 11906 11907 resetIfNotMultiSelect: function(){ 11908 if(!this.options.multiSelect){ 11909 // Reset the value and file array 11910 this.values = []; 11911 //this.comments = []; 11912 } 11913 }, 11914 11915 showFileList: function(fileName, comment, fileUrl){ 11916 if(!this.options.multiSelect || fileName == null || _.isUndefined(fileName)) { 11917 // if not multiselect, remove all the children of file list 11918 this.$elementFileList.empty(); 11919 } 11920 11921 // Add the file item 11922 // On click of close, remove the element and update the model 11923 // handle on click of preview button 11924 if(fileName != null) {
11925 this.$fileItem = this.$elementFileList.append(this.fileItem(fileName, comment, fileUrl)); 11926 } 11927 }, 11928 11929 /** 11930 * Handles the click on comment field 11931 * 11932 * TODO: Implement show/hide behaviour instead of replaceWith 11933 * This may be cause problem during bubble up of event 11934 * 11935 * @param event 11936 */ 11937 handleCommentClick : function(event){ 11938 var $commentElem = null, 11939 $elem = $(event.target); 11940 if ($elem.text() === _defaults.placeHolderText) { 11941 $commentElem = this.getNewCommentElement() 11942 } else { 11943 $commentElem = this.getNewCommentElement($(event.target).text()); 11944 } 11945 $elem.replaceWith($commentElem); 11946 // register the event again 11947 if(isBrowserIE9OrIE10){ 11948 $commentElem.focus().focusout($.proxy(this.handleCommentBlur, this)); 11949 } else { 11950 $commentElem.focus().blur($.proxy(this.handleCommentBlur, this)); 11951 } 11952 }, 11953 11954 handleCommentBlur : function(event){ 11955 var $commentSummaryElem = null, 11956 $elem = $(event.target); 11957 if ($elem.text() === _defaults.placeHolderText) { 11958 $commentSummaryElem = this.getNewCommentElementSummary(); 11959 } else { 11960 $commentSummaryElem = this.getNewCommentElementSummary($(event.target).text()); 11961 } 11962 $elem.replaceWith($commentSummaryElem); 11963 $commentSummaryElem.focus($.proxy(this.handleCommentClick,this)).click($.proxy(this.handleCommentClick,this)); 11964 // Add a div with the html 11965 this.$element.trigger("change.fileupload"); 11966 }, 11967 11968 // checks if file name is valid or not to prevent security threats 11969 isValid : function(fname) { 11970 var rg1=/^[^\\/:\*\;\$\%\?"<>\|]+$/; // forbidden characters \ / : * ? " < > | ; % $ 11971 var rg2=/^\./; // cannot start with dot (.) 11972 var rg3=/^(nul|prn|con|lpt[0-9]|com[0-9])(\.|$)/i; // forbidden file names 11973 return rg1.test(fname) && !rg2.test(fname) && !rg3.test(fname); 11974 }, 11975 11976 handleChange: function (evnt) { 11977 if (!this._isFileUpdate) { 11978 var currFileName = '', 11979 inValidSizefileNames = '', 11980 inValidNamefileNames = '', 11981 inValidMimeTypefileNames = '', 11982 $elem = $(evnt.target), 11983 files = $elem[0].files; 11984 // Initially set the invalid flag to false 11985 11986 // if not multiselect then remove the extra domELement clone 11987 if (!this.options.multiSelect && this.$fileDomElements.length > 1) { 11988 this.$fileDomElements.splice(0, 1) 11989 } 11990 11991 var isInvalidSize = false, 11992 isInvalidFileName = false, 11993 isInvalidMimeType = false;
11994 this.resetIfNotMultiSelect(); 11995 // Iterate through all the files 11996 if (isBrowserIE9OrIE10) { // IE9 doesn't support FileList, hence files variable is undefined 11997 currFileName = $elem.val().split("\\").pop(); 11998 //update the last element of array 11999 if (this.$fileDomElements.length > 0) { 12000 this.$fileDomElements[this.$fileDomElements.length - 1] = $elem; 12001 } 12002 this.cloneFileInputAndUpdateIdForIE9(); 12003 12004 // In case of IE9, only do this 12005 if (_.isUndefined(files)) { 12006 this.showFileList(currFileName); 12007 this.values.push(currFileName); 12008 // trigger the change event to update the value 12009 this.$element.trigger("change.fileupload"); 12010 } 12011 } 12012 if (!_.isUndefined(files)) { 12013 var invalidFilesIndexes = []; 12014 _.each(files, function (file, fileIndex) { 12015 var isCurrentInvalidFileSize = false, 12016 isCurrentInvalidFileName = false, 12017 isCurrentInvalidMimeType = false;
12018 currFileName = file.name.split("\\").pop(); 12019 // Now size is in MB 12020 var size = file.size / 1024 / 1024; 12021 // check if file size limit is within limits 12022 if ((size > parseFloat(this.options.fileSizeLimit))) { 12023 isInvalidSize = isCurrentInvalidFileSize = true; 12024 inValidSizefileNames = currFileName + "," + inValidSizefileNames; 12025 } else if (!this.isValid(currFileName)) { 12026 // check if file names are valid (ie) there are no control characters in file names 12027 isInvalidFileName = isCurrentInvalidFileName = true; 12028 inValidNamefileNames = currFileName + "," + inValidNamefileNames; 12029 } else if (file.type) { 12030 var isMatch = this.regexMimeTypeList.some(function (rx) { 12031 return rx.test(file.type); 12032 }); 12033 if (!isMatch) { 12034 isInvalidMimeType = isCurrentInvalidMimeType = true; 12035 inValidMimeTypefileNames = currFileName + "," + inValidMimeTypefileNames; 12036 } 12037 } 12038 12039 // if the file is not invalid, show it and push it to internal array 12040 if (!isCurrentInvalidFileSize && !isCurrentInvalidFileName && !isCurrentInvalidMimeType) { 12041 this.showFileList(currFileName); 12042 this.values.push(currFileName); 12043 } else { 12044 invalidFilesIndexes.push(fileIndex); 12045 } 12046 12047 12048 }, this); 12049 12050 if (invalidFilesIndexes.length > 0) { 12051 var currentFileDomIndex, 12052 $currentFileDomElement, 12053 filesCount; 12054 if (this.$fileDomElements.length > 0) { 12055 currentFileDomIndex = this.$fileDomElements.length - 1; 12056 $currentFileDomElement = this.$fileDomElements[currentFileDomIndex]; 12057 if ($currentFileDomElement && $currentFileDomElement.length > 0) { 12058 filesCount = $currentFileDomElement[0].files.length; 12059 //if all the files are invalid remove the input element as well otherwise only remove the invalid files. 12060 if (filesCount === invalidFilesIndexes.length) { 12061 this.$fileDomElements.splice(-1, 1); 12062 } else { 12063 this._deleteFilesFromInputDom($currentFileDomElement, invalidFilesIndexes); 12064 } 12065 } 12066 } 12067 12068 // in case of IE10, create one extra element 12069 if (isBrowserIE9OrIE10) { 12070 this.cloneFileInputAndUpdateIdForIE9(); 12071 } 12072 } 12073 12074 // trigger the change event to update the value 12075 this.$element.trigger("change.fileupload"); 12076 } 12077 12078 if (isInvalidSize) { 12079 this.showInvalidMessage(inValidSizefileNames.substring(0, inValidSizefileNames.lastIndexOf(',')), this.invalidFeature.SIZE); 12080 } else if (isInvalidFileName) { 12081 this.showInvalidMessage(inValidNamefileNames.substring(0, inValidNamefileNames.lastIndexOf(',')), this.invalidFeature.NAME); 12082 } else if (isInvalidMimeType) { 12083 this.showInvalidMessage(inValidMimeTypefileNames.substring(0, inValidMimeTypefileNames.lastIndexOf(',')), this.invalidFeature.MIMETYPE); 12084 } 12085 } 12086 }, 12087 12088 cloneFileInputAndUpdateIdForIE9 : function(){ 12089 var elem = _.last(this.$fileDomElements), 12090 elemExists = elem != null, 12091 elemHasValue = elemExists && elem.val().length > 0, 12092 elemId = null, 12093 selector = null; 12094 12095 // CQ-4237903 : create clone to handle the case when user clicks cancel in chrome and for multiselect 12096 // on clicking cancel in chrome file browser, chrome removes all the files from the input element 12097 // remove the extra clone in $fileDomElement on handleChange 12098 if(!elemExists || elemHasValue) { 12099 elem = this.$element.clone(); 12100 // copy the data attributes 12101 elem.data(this.$element.data()); 12102 if(isBrowserIE9OrIE10){ 12103 elemId = this.$element.attr("id") + (++fileLabelsCount); 12104 elem.attr("id", elemId); 12105 elem.css({ 12106 'position' : 'absolute', 12107 'top' : '-2000px', 12108 'left': '-2000px' 12109 }); 12110 elem.appendTo('body'); 12111 this.updateLabelForAttr(elemId); 12112 } 12113 elem.change($.proxy(this.handleChange, this)); 12114 this.$fileDomElements.push(elem); 12115 } 12116 // Case: if it is not multiselect and if the first file dom element is null 12117 // this case would hit when we restore a single select file attachment and attach a new file 12118 if(!this.options.multiSelect && this.$fileDomElements[0] === null){ 12119 //Splice null out of it, since we are attaching a new file 12120 this.$fileDomElements.splice(0, 1); 12121 } 12122 // if the browser is not IE9, then click it 12123 if(!isBrowserIE9OrIE10) { 12124 elem.click(); 12125 } 12126 return true; 12127 }, 12128 12129 /** 12130 * In case of IE9, get the last element of fileDom and update the id for label 12131 * 12132 * @param fileInputId 12133 */ 12134 updateLabelForAttr : function(fileInputId){ 12135 this.$label.attr("for" , fileInputId); 12136 }, 12137 12138 createLabelForFileInput : function (fileInputId){ 12139 if(isBrowserIE9OrIE10) { 12140 this.$label = $("<label></label>").addClass("guide-fu-attach-button button") 12141 .text(this.options.buttonText) 12142 .attr('for',fileInputId); 12143 this.$elementFileUploadBtn.replaceWith(this.$label); 12144 this.$label.parent().attr("tabindex", 0).attr("role", "button").attr("aria-label", this.options.screenReaderText || ""); 12145 } 12146 }, 12147 12148 12149 constructor: function () { 12150 // Initialize the self instance 12151 var _self = this, 12152 isFirst = true; 12153 //jquery instance of file upload button 12154 this.$elementFileUploadBtn = this.$parent.find(this.options.buttonClass); 12155 this.$elementFileUploadBtn.attr("aria-label", this.options.screenReaderText || ""); 12156 if(isBrowserIE9OrIE10){ 12157 this.elementId = this.$element.attr("id"); 12158 this.createLabelForFileInput(this.$element.attr("id")); 12159 } 12160 12161 // html for file list 12162 this.$elementFileList = $(this.fileItemList()); 12163 // Initialize the value and file(Refer FileList class mdn) 12164 this.values = []; 12165 this._initialFileValueFileNameMap = {}; 12166 // List of dom elements of input type file
12167 this.$fileDomElements = []; 12168 12169 var flag = false, 12170 $currElem = null; 12171 12172 $(document).mousedown(function(e) { 12173 $currElem = $(e.target); 12174 }); 12175 // Enter key should result in click of button 12176 this.$elementFileUploadBtn 12177 .focus(function(){ 12178 _self.$element.trigger("focus.fileupload"); 12179 }) 12180 .click($.proxy(this.cloneFileInputAndUpdateIdForIE9, this)) 12181 .blur(function(event){ 12182 // Check if the currElem does not belong to the fileItemList 12183 if(!flag && $currElem!= null && $currElem.closest(".guide-fu-fileItemList").length <=0){ 12184 _self.$element.trigger("focusout.fileupload"); 12185 } 12186 flag = false; 12187 }); 12188 //Initialize the filePreview Plugin 12189 this.$element[this.options.uploaderPluginName]({ 12190 iframeContainer: this.options.iframeContainer, 12191 _filePath: this.options._filePath, 12192 _uuidGenerator: this.options._uuidGenerator, 12193 _getUrl: this.options._getUrl 12194 12195 }); 12196 // Getting input file value 12197 // listening on fileuploaded event 12198 this.$element.change($.proxy(this.handleChange, this)) 12199 .on("adobeFileUploader.fileUploaded", $.proxy(this.previewFile, this)); 12200 } 12201 }; 12202 12203 $.fn.adobeFileAttachment = function (option, value) { 12204 var get = '', 12205 element = this.each(function () { 12206 // in case of input type file 12207 if ($(this).attr('type') === 'file') { 12208 var $this = $(this), 12209 data = $this.data('adobeFileAttachment'), 12210 options = $.extend({}, AdobeFileAttachment.prototype.defaults, typeof option === 'object' && option); 12211 12212 // Save the adobeFileAttachment data in jquery 12213 if (!data) { 12214 $this.data('adobeFileAttachment', (data = new AdobeFileAttachment(this, options))); 12215 data.constructor(); 12216 } 12217 12218 // code to get and set an option 12219 if (typeof option === 'string') { 12220 get = data[option](value); 12221 } 12222 } 12223 }); 12224 12225 if (typeof get !== 'undefined') { 12226 return get; 12227 } else { 12228 return element; 12229 } 12230 }; 12231 12232 // fileSizeLimit is in MB, default value is 2MB 12233 AdobeFileAttachment.prototype.defaults = { 12234 'buttonText': 'Attach', 12235 'multiSelect': false, 12236 'fileSizeLimit': 2, 12237 'uploaderPluginName': "adobeFileUploader", 12238 'mimeType' : ['audio/*', 'video/*', 'image/*', 'text/*', 'application/pdf'] 12239 }; 12240 12241})($, window, window._); 12242(function($, _) { 12243 var xfaUtil = xfalib.ut.XfaUtil.prototype; 12244 $.widget( "xfaWidget.fileUpload", $.xfaWidget.abstractWidget, { 12245 12246 _widgetName:"fileUpload", 12247 _superPrototype : $.xfaWidget.abstractWidget.prototype, 12248 getOptionsMap: function(){ 12249 var parentOptionsMap = this._superPrototype.getOptionsMap.apply(this,arguments), 12250 newMap = $.extend({},parentOptionsMap, $.extend({}, this.options, { 12251 "value" : function(value) { 12252 this.$userControl.adobeFileAttachment("value", value); 12253 }, 12254 "fileList": function(value){ 12255 this.$userControl.adobeFileAttachment("fileList", value); 12256 }, 12257 "comment" : function(value){ 12258 this.$userControl.adobeFileAttachment("comment", value); 12259 }, 12260 // "access" can be either open or readonly 12261 "access" : function(value){ 12262 this.$userControl.adobeFileAttachment("access", value); 12263 } 12264 12265 })); 12266 12267 return newMap; 12268 12269 }, 12270 // TODO: Will need to remove this functions 12271 // will be tracked by LC-391200 12272 12273 _initializeOptions: function () { 12274 _.each(this.optionsHandler, function (value, key) { 12275 // overriding the behaviour of _initializeOptions 12276 // only for _uuidGenerator 12277 // as we font want getUUID to be called at render time 12278 if (typeof value === "function" && key !== '_uuidGenerator' ) { 12279 value.apply(this, [this.options[key]]) 12280 } 12281 }, this) 12282 }, 12283 12284 _getFileList: function(){ 12285 return this.$userControl.adobeFileAttachment("fileList"); 12286 }, 12287 12288 _getComment: function(){ 12289 return this.$userControl.adobeFileAttachment("comment"); 12290 }, 12291 _getFileNamePathMap: function (pathList) { 12292 return this.$userControl.adobeFileAttachment("getSetFilePathAndReturnNamePathMap", pathList); 12293 }, 12294 getEventMap: function() { 12295 var parentEventMap = this._superPrototype.getEventMap.apply(this, arguments), 12296 newMap = $.extend({}, parentEventMap, 12297 { 12298 "change" : null, 12299 "focusout.fileupload" : xfaUtil.XFA_EXIT_EVENT, 12300 "focus.fileupload" : xfaUtil.XFA_ENTER_EVENT, 12301 "change.fileupload" : xfaUtil.XFA_CHANGE_EVENT 12302 }); 12303 return newMap; 12304 }, 12305 render: function() { 12306 var $el = this._superPrototype.render.apply(this,arguments); 12307 $el.adobeFileAttachment(this.getOptionsMap()); 12308 return $el; 12309 }, 12310 showDisplayValue: function() { 12311 //since value can't be set in file element input, leav
12311ing this fn empty 12312 }, 12313 showValue: function() { 12314 //since value can't be set in file element input, leaving this fn empty 12315 }, 12316 getCommitValue: function() { 12317 this.options.fileList = this._getFileList(); 12318 this.options.comment = this._getComment(); 12319 return this.$userControl.adobeFileAttachment("value"); 12320 } 12321 }); 12322})($, window._); 12323 12324/** 12325 * Adobe FilePreview Widget Plugin 12326 * 12327 * Options expected by file preview is the url 12328 * 12329 * Options Required Are: 12330 * 12331 * iframeName: Name of the Iframe 12332 * iframeContainer: Container of the iframe(eg Body) 12333 * fileUploadPath: Path where the file is to be uploaded 12334 * fileUploadServlet: Servlet where the file is to be uploaded 12335 * 12336 */ 12337(function ($, _) { 12338 12339 var AdobeFileUploader = function (element, options) { 12340 this.options = options; 12341 this.$element = $(element); 12342 }; 12343 12344 AdobeFileUploader.prototype = { 12345 12346 _fileIframeName: "guide-fu-iframe", 12347 12348 _filePath: "/tmp/fd/mf", 12349 12350 _iframeContainer: "body#formBody", 12351 12352 12353 fileIframe: function (name) { 12354 return $("<iframe></iframe>").attr({ 12355 style: "display:none", 12356 name: name 12357 }); 12358 }, 12359 12360 uploadFile: function (fileObject) { 12361 var multiple = false, 12362 fileName = null, 12363 actionUrl = null, 12364 fileUploadPath = fileObject.fileUploadPath, 12365 uuid; 12366 12367 if (!fileUploadPath) { 12368 uuid = fileObject._uuidGenerator(); 12369 } 12370 12371 // if uuid exists only then upload the file in the current instance 12372 if (_.isObject(fileObject) && (fileUploadPath || uuid)) { 12373 var fileDom = fileObject.fileDom, 12374 $form = $(this.options.iframeContainer).find(".filePreview"); 12375 fileName = fileObject.fileName; 12376 multiple = fileObject.multiple; 12377 if(!fileUploadPath) { 12378 fileUploadPath = this.options.fileUploadPath + "/" + uuid; 12379 } 12380 if (fileDom !== null) { 12381 //prepend contextpath 12382 actionUrl = fileObject._getUrl + fileUploadPath; 12383 if (!multiple) { 12384 if (!(fileUploadPath.lastIndexOf(fileObject._getUrl, 0) === 0)) { 12385 this.fileUrl = fileObject._getUrl + fileUploadPath + "/" + fileName; 12386 } else { 12387 this.fileUrl = fileUploadPath + "/" + fileName; 12388 } 12389 } else { 12390 this.fileUrl = actionUrl; 12391 } 12392 // done to solve issue LC-5835 12393 if($form.length === 0) { 12394 $form = $("<form method='post' enctype='multipart/form-data'></form>") 12395 .addClass("filePreview") 12396 // create id so that it does not intercept with other forms in the page 12397 .attr({ 12398 id : "form" + new Date().valueOf(), 12399 action : actionUrl, 12400 target : this.options.iframeName 12401 }) 12402 .appendTo(this.options.iframeContainer); 12403 } else { 12404 /// first empty all children, using detach so that data is not clear 12405 $form.children().detach(); 12406 // now update the new attributes 12407 $form.attr({ 12408 action : actionUrl, 12409 target : this.options.iframeName 12410 }); 12411 } 12412 // this is done so that the other events attached at some other level in DOM Tree don't interfere 12413 $form.one("submit", function(evnt){ 12414 evnt.stopPropagation(); 12415 }); 12416 12417 var data = new FormData(); 12418 12419 if (multiple) { 12420 _.each(fileDom, function (fileDomElement, index) { 12421 // OOTB, this code is still used in dashboard 12422 if(fileDomElement !== null && !_.isString(fileDomElement)) { 12423 $(fileDomElement[0]).attr('name', fileName[index]).appendTo($form); 12424 // fileDomElement might contain multiple files so all the files needs to be added to formdata. 12425 var currentFileNames = fileName[index].split("\n"); 12426 for(var fileIndex = 0; fileIndex < currentFileNames.length; fileIndex++) { 12427 data.append(currentFileNames[fileIndex], fileDomElement[0].files[fileIndex]); 12428 } 12429 } 12430 }, this); 12431 } else { 12432 fileDom.attr('name', fileName).appendTo($form); 12433 data.append(fileName, fileDom[0].files[0]); 12434 } 12435 12436 /* UseCase: Suppose the fileName is in other language, on click of fileName, it tries to upload the file 12437 so that it could be preview, this change would ensure that the file is properly previewed supp
12437orting 12438 the given UTF-8 charset */ 12439 $("<input type='hidden' name='_charset_' value='UTF-8'/>").appendTo($form); 12440 data.append("_charset_", "UTF-8"); 12441 if (!multiple) { 12442 this.fileMap[this.fileUrl] = this.$element; 12443 } 12444 var self = this; 12445 $.ajax({ 12446 url: $form.attr("action"), 12447 data: data, 12448 cache: false, 12449 contentType: false, 12450 processData: false, 12451 method: 'POST', 12452 type: 'POST', 12453 success: function(data){ 12454 if (!multiple) { 12455 self.handleSingleFileUpload(data); 12456 } else { 12457 self.handleMultipleFileUpload(data); 12458 } 12459 }, 12460 error: function() { 12461 this.$element.trigger("adobeFileUploader.fileUploadFailed"); 12462 } 12463 }); 12464 } 12465 } 12466 return this.fileUrl; 12467 }, 12468 12469 handleMultipleFileUpload: function (data) { 12470 this.$element.trigger("adobeFileUploader.multipleFileUploaded"); 12471 }, 12472 12473 getFileUrl: function () { 12474 return this.fileUrl; 12475 }, 12476 12477 getUrlContentsFromUploadData: function (data) { 12478 var temp; 12479 if(data != null) { 12480 temp = $(data).find("#ChangeLog").text().split("br", 2)[1]; 12481 } else { 12482 var selector = this.options.iframeContainer + " iframe[name='" + this.options.iframeName + "']"; 12483 temp = $(selector).contents().find("#ChangeLog").text().split("br", 2)[1]; 12484 } 12485 12486 temp = temp.substring(temp.indexOf("created") + 9, temp.indexOf(";<")); 12487 temp = temp.substring(0, temp.length - 2); 12488 var index = temp.indexOf("/jcr:content"); 12489 if (index !== -1) 12490 temp = temp.substring(0, index); 12491 return temp; 12492 }, 12493 12494 handleSingleFileUpload: function (data) { 12495 var url = this.getUrlContentsFromUploadData(data); 12496 12497 //prepend context path 12498 url = this.options._getUrl + url; 12499 if (url in this.fileMap) { 12500 this.fileMap[url].trigger("adobeFileUploader.fileUploaded"); 12501 } 12502 }, 12503 12504 initialize: function () { 12505 // Put iframe inside the iframe container 12506 // On the load of iframe, display the contents of file 12507 // since there is only one iframe for all the file attachments, there may be race condition 12508 if (this.$iframe == null || this.$iframe.length === 0) { 12509 this.$iframe = this.fileIframe(this.options.iframeName).appendTo(this.options.iframeContainer); 12510 // since there is only iframe for the preview of all file attachments 12511 // this map is added in the closure scope 12512 // map contains the url(key) vs fileDomElement(value) 12513 // it helps avoids the race condition 12514 this.fileMap = {}; 12515 } 12516 } 12517 }; 12518 12519 $.fn.adobeFileUploader = function (option, value) { 12520 var get = '', 12521 element = this.each(function () { 12522 // in case of input type file 12523 if ($(this).attr('type') === 'file') { 12524 var $this = $(this), 12525 data = $this.data('adobeFileUploader'), 12526 options = $.extend({}, AdobeFileUploader.prototype.defaults(option, value), typeof option === 'object' && option); 12527 12528 // Save the adobeFileAttachment data in jquery 12529 if (!data) { 12530 $this.data('adobeFileUploader', (data = new AdobeFileUploader(this, options))); 12531 data.initialize(); 12532 } else { 12533 // update elements if not equal, since sometimes one can clone too 12534 if(data.$element.get(0) !== this) { 12535 data.$element = $(this); 12536 } 12537 } 12538 12539 // code to get and set an option 12540 if (typeof option === 'string') { 12541 get = data[option](value); 12542 } 12543 } 12544 }); 12545 12546 if (typeof get !== 'undefined') { 12547 return get; 12548 } else { 12549 return element; 12550 } 12551 }; 12552 12553 12554 AdobeFileUploader.prototype.defaults = function (options,value) { 12555 var propertyObject = {}; 12556 if(typeof options == 'object') { 12557 propertyObject._fileIframeName = options._fileIframeName; 12558 propertyObject._filePath = options._filePath; 12559 propertyObject.actionUrl = options.actionUrl; 12560 propertyObject._getUrl = options._getUrl; 12561 } 12562 if(typeof value == 'object') { 12563 propertyObject._fileIframeName = value._fileIframeName; 12564 propertyObject._filePath = value._filePath; 12565 propertyObject.actionUrl = value.actionUrl; 12566 propertyObject._getUrl = options._getUrl; 12567 } 12568 return { 12569 'fileUploadPath': propertyObject._filePath || AdobeFileUploader.prototype._filePath, 12570 'iframeName': AdobeFileUploader.prototype._fileIframeName + new Date().valueOf(), 12571 'fileUploadServlet': propertyObject._filePath || AdobeFileUploader.prototype._filePath,
vendor: 74,301 bytes, lines 12572-15082
12572 'iframeContainer': propertyObject._iframeContainer || AdobeFileUploader.prototype._iframeContainer, 12573 '_getUrl': propertyObject._getUrl || "" 12574 }; 12575 }; 12576 12577})($, window._); 12578 12579/*! 12580 * Bootstrap v3.4.1 (https://getbootstrap.com/) 12581 * Copyright 2011-2019 Twitter, Inc. 12582 * Licensed under the MIT license 12583 */ 12584 12585if (typeof jQuery === 'undefined') { 12586 throw new Error('Bootstrap\'s JavaScript requires jQuery') 12587} 12588 12589+function ($) { 12590 'use strict'; 12591 var version = $.fn.jquery.split(' ')[0].split('.') 12592 if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) { 12593 throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4') 12594 } 12595}(jQuery); 12596 12597/* ======================================================================== 12598 * Bootstrap: transition.js v3.4.1 12599 * https://getbootstrap.com/docs/3.4/javascript/#transitions 12600 * ======================================================================== 12601 * Copyright 2011-2019 Twitter, Inc. 12602 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 12603 * ======================================================================== */ 12604 12605 12606+function ($) { 12607 'use strict'; 12608 12609 // CSS TRANSITION SUPPORT (Shoutout: https://modernizr.com/) 12610 // ============================================================ 12611 12612 function transitionEnd() { 12613 var el = document.createElement('bootstrap') 12614 12615 var transEndEventNames = { 12616 WebkitTransition : 'webkitTransitionEnd', 12617 MozTransition : 'transitionend', 12618 OTransition : 'oTransitionEnd otransitionend', 12619 transition : 'transitionend' 12620 } 12621 12622 for (var name in transEndEventNames) { 12623 if (el.style[name] !== undefined) { 12624 return { end: transEndEventNames[name] } 12625 } 12626 } 12627 12628 return false // explicit for ie8 ( ._.) 12629 } 12630 12631 // https://blog.alexmaccaw.com/css-transitions 12632 $.fn.emulateTransitionEnd = function (duration) { 12633 var called = false 12634 var $el = this 12635 $(this).one('bsTransitionEnd', function () { called = true }) 12636 var callback = function () { if (!called) $($el).trigger($.support.transition.end) } 12637 setTimeout(callback, duration) 12638 return this 12639 } 12640 12641 $(function () { 12642 $.support.transition = transitionEnd() 12643 12644 if (!$.support.transition) return 12645 12646 $.event.special.bsTransitionEnd = { 12647 bindType: $.support.transition.end, 12648 delegateType: $.support.transition.end, 12649 handle: function (e) { 12650 if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments) 12651 } 12652 } 12653 }) 12654 12655}(jQuery); 12656 12657/* ======================================================================== 12658 * Bootstrap: alert.js v3.4.1 12659 * https://getbootstrap.com/docs/3.4/javascript/#alerts 12660 * ======================================================================== 12661 * Copyright 2011-2019 Twitter, Inc. 12662 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 12663 * ======================================================================== */ 12664 12665 12666+function ($) { 12667 'use strict'; 12668 12669 // ALERT CLASS DEFINITION 12670 // ====================== 12671 12672 var dismiss = '[data-dismiss="alert"]' 12673 var Alert = function (el) { 12674 $(el).on('click', dismiss, this.close) 12675 } 12676 12677 Alert.VERSION = '3.4.1' 12678 12679 Alert.TRANSITION_DURATION = 150 12680 12681 Alert.prototype.close = function (e) { 12682 var $this = $(this) 12683 var selector = $this.attr('data-target') 12684 12685 if (!selector) { 12686 selector = $this.attr('href') 12687 selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 12688 } 12689 12690 selector = selector === '#' ? [] : selector 12691 var $parent = $(document).find(selector) 12692 12693 if (e) e.preventDefault() 12694 12695 if (!$parent.length) { 12696 $parent = $this.closest('.alert') 12697 } 12698 12699 $parent.trigger(e = $.Event('close.bs.alert')) 12700 12701 if (e.isDefaultPrevented()) return 12702 12703 $parent.removeClass('in') 12704 12705 function removeElement() { 12706 // detach from parent, fire event then clean up data 12707 $parent.detach().trigger('closed.bs.alert').remove() 12708 } 12709 12710 $.support.transition && $parent.hasClass('fade') ? 12711 $parent 12712 .one('bsTransitionEnd', removeElement) 12713 .emulateTransitionEnd(Alert.TRANSITION_DURATION) : 12714 removeElement() 12715 } 12716 12717 12718 // ALERT PLUGIN DEFINITION 12719 // ======================= 12720 12721 function Plugin(option) { 12722 return this.each(function () { 12723 var $this = $(this) 12724 var data = $this.data('bs.alert') 12725 12726 if (!data) $this.data('bs.alert', (data = new Alert(this))) 12727 if (typeof option == 'string') data[option].call($this) 12728 }) 12729 } 12730 12731 var old = $.fn.alert 12732 12733 $.fn.alert = Plugin 12734 $.fn.alert.Constructor = Alert 12735 12736 12737 // ALERT NO CONFLICT 12738 // ================= 12739 12740 $.fn.alert.noConflict = function () { 12741 $.fn.alert = old 12742 return this 12743 } 12744 12745 12746 // ALERT DATA-API 12747 // ============== 12748 12749 $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close) 12750 12751}(jQuery); 12752 12753/* ======================================================================== 12754 * Bootstrap: button.js v3.4.1 12755 * https://getbootstrap.com/docs/3.4/javascript/#buttons 12756 * ======================================================================== 12757 * Copyright 2011-2019 Twitter, Inc. 12758 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 12759 * ======================================================================== */ 12760 12761 12762+function ($) { 12763 'use strict'; 12764 12765 // BUTTON PUBLIC CLASS DEFINITION 12766 // ============================== 12767 12768 var Button = function (element, options) { 12769 this.$element = $(element) 12770 this.options = $.extend({}, Button.DEFAULTS, options) 12771 this.isLoading = false 12772 } 12773 12774 Button.VERSION = '3.4.1' 12775 12776 Button.DEFAULTS = { 12777 loadingText: 'loading...' 12778 } 12779 12780 Button.prototype.setState = function (state) { 12781 var d = 'disabled' 12782 var $el = this.$element 12783 var val = $el.is('input') ? 'val' : 'html' 12784 var data = $el.data() 12785 12786 state += 'Text' 12787 12788 if (data.resetText == null) $el.data('resetText', $el[val]()) 12789 12790 // push to event loop to allow forms to submit 12791 setTimeout($.proxy(function () { 12792 $el[val](data[state] == null ? this.options[state] : data[state]) 12793 12794 if (state == 'loadingText') { 12795 this.isLoading = true 12796 $el.addClass(d).attr(d, d).prop(d, true) 12797 } else if (this.isLoading) { 12798 this.isLoading = false 12799 $el.removeClass(d).removeAttr(d).prop(d, false) 12800 } 12801 }, this), 0) 12802 } 12803 12804 Button.prototype.toggle = function () { 12805 var changed = true 12806 var $parent = this.$element.closest('[data-toggle="buttons"]') 12807 12808 if ($parent.length) { 12809 var $input = this.$element.find('input') 12810 if ($input.prop('type') == 'radio') { 12811 if ($input.prop('checked')) changed = false 12812 $parent.find('.active').removeClass('active') 12813 this.$element.addClass('active') 12814 } else if ($input.prop('type') == 'checkbox') { 12815 if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false 12816 this.$element.toggleClass('active') 12817 } 12818 $input.prop('checked', this.$element.hasClass('active')) 12819 if (changed) $input.trigger('change') 12820 } else { 12821 this.$element.attr('aria-pressed', !this.$element.hasClass('active')) 12822 this.$element.toggleClass('active') 12823 } 12824 } 12825 12826 12827 // BUTTON PLUGIN DEFINITION 12828 // ======================== 12829 12830 function Plugin(option) { 12831 return this.each(function () { 12832 var $this = $(this) 12833 var data = $this.data('bs.button') 12834 var options = typeof option == 'object' && option 12835 12836 if (!data) $this.data('bs.button', (data = new Button(this, options))) 12837 12838 if (option == 'toggle') data.toggle() 12839 else if (option) data.setState(option) 12840 }) 12841 } 12842 12843 var old = $.fn.button 12844 12845 $.fn.button = Plugin 12846 $.fn.button.Constructor = Button 12847 12848 12849 // BUTTON NO CONFLICT 12850 // ================== 12851 12852 $.fn.button.noConflict = function () { 12853 $.fn.button = old 12854 return this 12855 } 12856 12857 12858 // BUTTON DATA-API 12859 // =============== 12860 12861 $(document) 12862 .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) { 12863 var $btn = $(e.target).closest('.btn') 12864 Plugin.call($btn, 'toggle') 12865 if (!($(e.target).is('input[type="radio"], input[type="checkbox"]'))) { 12866 // Prevent double click on radios, and the double selections (so cancellation) on checkboxes 12867 e.preventDefault() 12868 // The target component still receive the focus 12869 if ($btn.is('input,button')) $btn.trigger('focus') 12870 else $btn.find('input:visible,button:visible').first().trigger('focus') 12871 } 12872 }) 12873 .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) { 12874 $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type)) 12875 }) 12876 12877}(jQuery); 12878 12879/* ======================================================================== 12880 * Bootstrap: carousel.js v3.4.1 12881 * https://getbootstrap.com/docs/3.4/javascript/#carousel 12882 * ======================================================================== 12883 * Copyright 2011-2019 Twitter, Inc. 12884 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 12885 * ======================================================================== */ 12886 12887 12888+function ($) { 12889 'use strict'; 12890 12891 // CAROUSEL CLASS DEFINITION 12892 // ========================= 12893 12894 var Carousel = function (element, options) { 12895 this.$element = $(element) 12896 this.$indicators = this.$element.find('.carousel-indicators') 12897 this.options = options 12898 this.paused = null 12899 this.sliding = null 12900 this.interval = null 12901 this.$active = null 12902 this.$items = null 12903 12904 this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this)) 12905 12906 this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element 12907 .on('mouseenter.bs.carousel', $.proxy(this.pause, this)) 12908 .on('mouseleave.bs.carousel', $.proxy(this.cycle, this)) 12909 } 12910 12911 Carousel.VERSION = '3.4.1' 12912 12913 Carousel.TRANSITION_DURATION = 600 12914 12915 Carousel.DEFAULTS = { 12916 interval: 5000, 12917 pause: 'hover', 12918 wrap: true, 12919 keyboard: true 12920 } 12921 12922 Carousel.prototype.keydown = function (e) { 12923 if (/input|textarea/i.test(e.target.tagName)) return 12924 switch (e.which) { 12925 case 37: this.prev(); break 12926 case 39: this.next(); break 12927 default: return 12928 } 12929 12930 e.preventDefault() 12931 } 12932 12933 Carousel.prototype.cycle = function (e) { 12934 e || (this.paused = false) 12935 12936 this.interval && clearInterval(this.interval) 12937 12938 this.options.interval 12939 && !this.paused 12940 && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) 12941 12942 return this 12943 } 12944 12945 Carousel.prototype.getItemIndex = function (item) { 12946 this.$items = item.parent().children('.item') 12947 return this.$items.index(item || this.$active) 12948 } 12949 12950 Carousel.prototype.getItemForDirection = function (direction, active) { 12951 var activeIndex = this.getItemIndex(active) 12952 var willWrap = (direction == 'prev' && activeIndex === 0) 12953 || (direction == 'next' && activeIndex == (this.$items.length - 1)) 12954 if (willWrap && !this.options.wrap) return active 12955 var delta = direction == 'prev' ? -1 : 1 12956 var itemIndex = (activeIndex + delta) % this.$items.length 12957 return this.$items.eq(itemIndex) 12958 } 12959 12960 Carousel.prototype.to = function (pos) { 12961 var that = this 12962 var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active')) 12963 12964 if (pos > (this.$items.length - 1) || pos < 0) return 12965 12966 if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid" 12967 if (activeIndex == pos) return this.pause().cycle() 12968 12969 return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos)) 12970 } 12971 12972 Carousel.prototype.pause = function (e) { 12973 e || (this.paused = true) 12974 12975 if (this.$element.find('.next, .prev').length && $.support.transition) { 12976 this.$element.trigger($.support.transition.end) 12977 this.cycle(true) 12978 } 12979 12980 this.interval = clearInterval(this.interval) 12981 12982 return this 12983 } 12984 12985 Carousel.prototype.next = function () { 12986 if (this.sliding) return 12987 return this.slide('next') 12988 } 12989 12990 Carousel.prototype.prev = function () { 12991 if (this.sliding) return 12992 return this.slide('prev') 12993 } 12994 12995 Carousel.prototype.slide = function (type, next) { 12996 var $active = this.$element.find('.item.active') 12997 var $next = next || this.getItemForDirection(type, $active) 12998 var isCycling = this.interval 12999 var direction = type == 'next' ? 'left' : 'right' 13000 var that = this 13001 13002 if ($next.hasClass('active')) return (this.sliding = false) 13003 13004 var relatedTarget = $next[0] 13005 var slideEvent = $.Event('slide.bs.carousel', { 13006 relatedTarget: relatedTarget, 13007 direction: direction 13008 }) 13009 this.$element.trigger(slideEvent) 13010 if (slideEvent.isDefaultPrevented()) return 13011 13012 this.sliding = true 13013 13014 isCycling && this.pause() 13015 13016 if (this.$indicators.length) { 13017 this.$indicators.find('.active').removeClass('active') 13018 var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)]) 13019 $nextIndicator && $nextIndicator.addClass('active') 13020 } 13021 13022 var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid" 13023 if ($.support.transition && this.$element.hasClass('slide')) { 13024 $next.addClass(type) 13025 if (typeof $next === 'object' && $next.length) { 13026 $next[0].offsetWidth // force reflow 13027 } 13028 $active.addClass(direction) 13029 $next.addClass(direction) 13030 $active 13031 .one('bsTransitionEnd', function () { 13032 $next.removeClass([type, direction].join(' ')).addClass('active') 13033 $active.removeClass(['active', direction].join(' ')) 13034 that.sliding = false 13035 setTimeout(function () { 13036 that.$element.trigger(slidEvent) 13037 }, 0) 13038 }) 13039 .emulateTransitionEnd(Carousel.TRANSITION_DURATION) 13040 } else { 13041 $active.removeClass('active') 13042 $next.addClass('active') 13043 this.sliding = false 13044 this.$element.trigger(slidEvent) 13045 } 13046 13047 isCycling && this.cycle() 13048 13049 return this 13050 } 13051 13052 13053 // CAROUSEL PLUGIN DEFINITION 13054 // ========================== 13055 13056 function Plugin(option) { 13057 return this.each(function () { 13058 var $this = $(this) 13059 var data = $this.data('bs.carousel') 13060 var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option) 13061 var action = typeof option == 'string' ? option : options.slide 13062 13063 if (!data) $this.data('bs.carousel', (data = new Carousel(this, options))) 13064 if (typeof option == 'number') data.to(option) 13065 else if (action) data[action]() 13066 else if (options.interval) data.pause().cycle() 13067 }) 13068 } 13069 13070 var old = $.fn.carousel 13071 13072 $.fn.carousel = Plugin 13073 $.fn.carousel.Constructor = Carousel 13074 13075 13076 // CAROUSEL NO CONFLICT 13077 // ==================== 13078 13079 $.fn.carousel.noConflict = function () { 13080 $.fn.carousel = old 13081 return this 13082 } 13083 13084 13085 // CAROUSEL DATA-API 13086 // ================= 13087 13088 var clickHandler = function (e) { 13089 var $this = $(this) 13090 var href = $this.attr('href') 13091 if (href) { 13092 href = href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7 13093 } 13094 13095 var target = $this.attr('data-target') || href 13096 var $target = $(document).find(target) 13097 13098 if (!$target.hasClass('carousel')) return 13099 13100 var options = $.extend({}, $target.data(), $this.data()) 13101 var slideIndex = $this.attr('data-slide-to') 13102 if (slideIndex) options.interval = false 13103 13104 Plugin.call($target, options) 13105 13106 if (slideIndex) { 13107 $target.data('bs.carousel').to(slideIndex) 13108 } 13109 13110 e.preventDefault() 13111 } 13112 13113 $(document) 13114 .on('click.bs.carousel.data-api', '[data-slide]', clickHandler) 13115 .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler) 13116 13117 $(window).on('load', function () { 13118 $('[data-ride="carousel"]').each(function () { 13119 var $carousel = $(this) 13120 Plugin.call($carousel, $carousel.data()) 13121 }) 13122 }) 13123 13124}(jQuery); 13125 13126/* ======================================================================== 13127 * Bootstrap: collapse.js v3.4.1 13128 * https://getbootstrap.com/docs/3.4/javascript/#collapse 13129 * ======================================================================== 13130 * Copyright 2011-2019 Twitter, Inc. 13131 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 13132 * ======================================================================== */ 13133 13134/* jshint latedef: false */ 13135 13136+function ($) { 13137 'use strict'; 13138 13139 // COLLAPSE PUBLIC CLASS DEFINITION 13140 // ================================ 13141 13142 var Collapse = function (element, options) { 13143 this.$element = $(element) 13144 this.options = $.extend({}, Collapse.DEFAULTS, options) 13145 this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' + 13146 '[data-toggle="collapse"][data-target="#' + element.id + '"]') 13147 this.transitioning = null 13148 13149 if (this.options.parent) { 13150 this.$parent = this.getParent() 13151 } else { 13152 this.addAriaAndCollapsedClass(this.$element, this.$trigger) 13153 } 13154 13155 if (this.options.toggle) this.toggle() 13156 } 13157 13158 Collapse.VERSION = '3.4.1' 13159 13160 Collapse.TRANSITION_DURATION = 350 13161 13162 Collapse.DEFAULTS = { 13163 toggle: true 13164 } 13165 13166 Collapse.prototype.dimension = function () { 13167 var hasWidth = this.$element.hasClass('width') 13168 return hasWidth ? 'width' : 'height' 13169 } 13170 13171 Collapse.prototype.show = function () { 13172 if (this.transitioning || this.$element.hasClass('in')) return 13173 13174 var activesData 13175 var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing') 13176 13177 if (actives && actives.length) { 13178 activesData = actives.data('bs.collapse') 13179 if (activesData && activesData.transitioning) return 13180 } 13181 13182 var startEvent = $.Event('show.bs.collapse') 13183 this.$element.trigger(startEvent) 13184 if (startEvent.isDefaultPrevented()) return 13185 13186 if (actives && actives.length) { 13187 Plugin.call(actives, 'hide') 13188 activesData || actives.data('bs.collapse', null) 13189 } 13190 13191 var dimension = this.dimension() 13192 13193 this.$element 13194 .removeClass('collapse') 13195 .addClass('collapsing')[dimension](0) 13196 .attr('aria-expanded', true) 13197 13198 this.$trigger 13199 .removeClass('collapsed') 13200 .attr('aria-expanded', true) 13201 13202 this.transitioning = 1 13203 13204 var complete = function () { 13205 this.$element 13206 .removeClass('collapsing') 13207 .addClass('collapse in')[dimension]('') 13208 this.transitioning = 0 13209 this.$element 13210 .trigger('shown.bs.collapse') 13211 } 13212 13213 if (!$.support.transition) return complete.call(this) 13214 13215 var scrollSize = $.camelCase(['scroll', dimension].join('-')) 13216 13217 this.$element 13218 .one('bsTransitionEnd', $.proxy(complete, this)) 13219 .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize]) 13220 } 13221 13222 Collapse.prototype.hide = function () { 13223 if (this.transitioning || !this.$element.hasClass('in')) return 13224 13225 var startEvent = $.Event('hide.bs.collapse') 13226 this.$element.trigger(startEvent) 13227 if (startEvent.isDefaultPrevented()) return 13228 13229 var dimension = this.dimension() 13230 13231 this.$element[dimension](this.$element[dimension]())[0].offsetHeight 13232 13233 this.$element 13234 .addClass('collapsing') 13235 .removeClass('collapse in') 13236 .attr('aria-expanded', false) 13237 13238 this.$trigger 13239 .addClass('collapsed') 13240 .attr('aria-expanded', false) 13241 13242 this.transitioning = 1 13243 13244 var complete = function () { 13245 this.transitioning = 0 13246 this.$element 13247 .removeClass('collapsing') 13248 .addClass('collapse') 13249 .trigger('hidden.bs.collapse') 13250 } 13251 13252 if (!$.support.transition) return complete.call(this) 13253 13254 this.$element 13255 [dimension](0) 13256 .one('bsTransitionEnd', $.proxy(complete, this)) 13257 .emulateTransitionEnd(Collapse.TRANSITION_DURATION) 13258 } 13259 13260 Collapse.prototype.toggle = function () { 13261 this[this.$element.hasClass('in') ? 'hide' : 'show']() 13262 } 13263 13264 Collapse.prototype.getParent = function () { 13265 return $(document).find(this.options.parent) 13266 .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]') 13267 .each($.proxy(function (i, element) { 13268 var $element = $(element) 13269 this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element) 13270 }, this)) 13271 .end() 13272 } 13273 13274 Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) { 13275 var isOpen = $element.hasClass('in') 13276 13277 $element.attr('aria-expanded', isOpen) 13278 $trigger 13279 .toggleClass('collapsed', !isOpen) 13280 .attr('aria-expanded', isOpen) 13281 } 13282 13283 function getTargetFromTrigger($trigger) { 13284 var href 13285 var target = $trigger.attr('data-target') 13286 || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7 13287 13288 return $(document).find(target) 13289 } 13290 13291 13292 // COLLAPSE PLUGIN DEFINITION 13293 // ========================== 13294 13295 function Plugin(option) { 13296 return this.each(function () { 13297 var $this = $(this) 13298 var data = $this.data('bs.collapse') 13299 var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) 13300 13301 if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false 13302 if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) 13303 if (typeof option == 'string') data[option]() 13304 }) 13305 } 13306 13307 var old = $.fn.collapse 13308 13309 $.fn.collapse = Plugin 13310 $.fn.collapse.Constructor = Collapse 13311 13312 13313 // COLLAPSE NO CONFLICT 13314 // ==================== 13315 13316 $.fn.collapse.noConflict = function () { 13317 $.fn.collapse = old 13318 return this 13319 } 13320 13321 13322 // COLLAPSE DATA-API 13323 // ================= 13324 13325 $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { 13326 var $this = $(this) 13327 13328 if (!$this.attr('data-target')) e.preventDefault() 13329 13330 var $target = getTargetFromTrigger($this) 13331 var data = $target.data('bs.collapse') 13332 var option = data ? 'toggle' : $this.data() 13333 13334 Plugin.call($target, option) 13335 }) 13336 13337}(jQuery); 13338 13339/* ======================================================================== 13340 * Bootstrap: dropdown.js v3.4.1 13341 * https://getbootstrap.com/docs/3.4/javascript/#dropdowns 13342 * ======================================================================== 13343 * Copyright 2011-2019 Twitter, Inc. 13344 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 13345 * ======================================================================== */ 13346 13347 13348+function ($) { 13349 'use strict'; 13350 13351 // DROPDOWN CLASS DEFINITION 13352 // ========================= 13353 13354 var backdrop = '.dropdown-backdrop' 13355 var toggle = '[data-toggle="dropdown"]' 13356 var Dropdown = function (element) { 13357 $(element).on('click.bs.dropdown', this.toggle) 13358 } 13359 13360 Dropdown.VERSION = '3.4.1' 13361 13362 function getParent($this) { 13363 var selector = $this.attr('data-target') 13364 13365 if (!selector) { 13366 selector = $this.attr('href') 13367 selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 13368 } 13369 13370 var $parent = selector !== '#' ? $(document).find(selector) : null 13371 13372 return $parent && $parent.length ? $parent : $this.parent() 13373 } 13374 13375 function clearMenus(e) { 13376 if (e && e.which === 3) return 13377 $(backdrop).remove() 13378 $(toggle).each(function () { 13379 var $this = $(this) 13380 var $parent = getParent($this) 13381 var relatedTarget = { relatedTarget: this } 13382 13383 if (!$parent.hasClass('open')) return 13384 13385 if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return 13386 13387 $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget)) 13388 13389 if (e.isDefaultPrevented()) return 13390 13391 $this.attr('aria-expanded', 'false') 13392 $parent.removeClass('open').trigger($.Event('hidden.bs.dropdown', relatedTarget)) 13393 }) 13394 } 13395 13396 Dropdown.prototype.toggle = function (e) { 13397 var $this = $(this) 13398 13399 if ($this.is('.disabled, :disabled')) return 13400 13401 var $parent = getParent($this) 13402 var isActive = $parent.hasClass('open') 13403 13404 clearMenus() 13405 13406 if (!isActive) { 13407 if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { 13408 // if mobile we use a backdrop because click events don't delegate 13409 $(document.createElement('div')) 13410 .addClass('dropdown-backdrop') 13411 .insertAfter($(this)) 13412 .on('click', clearMenus) 13413 } 13414 13415 var relatedTarget = { relatedTarget: this } 13416 $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget)) 13417 13418 if (e.isDefaultPrevented()) return 13419 13420 $this 13421 .trigger('focus') 13422 .attr('aria-expanded', 'true') 13423 13424 $parent 13425 .toggleClass('open') 13426 .trigger($.Event('shown.bs.dropdown', relatedTarget)) 13427 } 13428 13429 return false 13430 } 13431 13432 Dropdown.prototype.keydown = function (e) { 13433 if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return 13434 13435 var $this = $(this) 13436 13437 e.preventDefault() 13438 e.stopPropagation() 13439 13440 if ($this.is('.disabled, :disabled')) return 13441 13442 var $parent = getParent($this) 13443 var isActive = $parent.hasClass('open') 13444 13445 if (!isActive && e.which != 27 || isActive && e.which == 27) { 13446 if (e.which == 27) $parent.find(toggle).trigger('focus') 13447 return $this.trigger('click') 13448 } 13449 13450 var desc = ' li:not(.disabled):visible a' 13451 var $items = $parent.find('.dropdown-menu' + desc) 13452 13453 if (!$items.length) return 13454 13455 var index = $items.index(e.target) 13456 13457 if (e.which == 38 && index > 0) index-- // up 13458 if (e.which == 40 && index < $items.length - 1) index++ // down 13459 if (!~index) index = 0 13460 13461 $items.eq(index).trigger('focus') 13462 } 13463 13464 13465 // DROPDOWN PLUGIN DEFINITION 13466 // ========================== 13467 13468 function Plugin(option) { 13469 return this.each(function () { 13470 var $this = $(this) 13471 var data = $this.data('bs.dropdown') 13472 13473 if (!data) $this.data('bs.dropdown', (data = new Dropdown(this))) 13474 if (typeof option == 'string') data[option].call($this) 13475 }) 13476 } 13477 13478 var old = $.fn.dropdown 13479 13480 $.fn.dropdown = Plugin 13481 $.fn.dropdown.Constructor = Dropdown 13482 13483 13484 // DROPDOWN NO CONFLICT 13485 // ==================== 13486 13487 $.fn.dropdown.noConflict = function () { 13488 $.fn.dropdown = old 13489 return this 13490 } 13491 13492 13493 // APPLY TO STANDARD DROPDOWN ELEMENTS 13494 // =================================== 13495 13496 $(document) 13497 .on('click.bs.dropdown.data-api', clearMenus) 13498 .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) 13499 .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle) 13500 .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown) 13501 .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown) 13502 13503}(jQuery); 13504 13505/* ======================================================================== 13506 * Bootstrap: modal.js v3.4.1 13507 * https://getbootstrap.com/docs/3.4/javascript/#modals 13508 * ======================================================================== 13509 * Copyright 2011-2019 Twitter, Inc. 13510 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 13511 * ======================================================================== */ 13512 13513 13514+function ($) { 13515 'use strict'; 13516 13517 // MODAL CLASS DEFINITION 13518 // ====================== 13519 13520 var Modal = function (element, options) { 13521 this.options = options 13522 this.$body = $(document.body) 13523 this.$element = $(element) 13524 this.$dialog = this.$element.find('.modal-dialog') 13525 this.$backdrop = null 13526 this.isShown = null 13527 this.originalBodyPad = null 13528 this.scrollbarWidth = 0 13529 this.ignoreBackdropClick = false 13530 this.fixedContent = '.navbar-fixed-top, .navbar-fixed-bottom' 13531 13532 if (this.options.remote) { 13533 this.$element 13534 .find('.modal-content') 13535 .load(this.options.remote, $.proxy(function () { 13536 this.$element.trigger('loaded.bs.modal') 13537 }, this)) 13538 } 13539 } 13540 13541 Modal.VERSION = '3.4.1' 13542 13543 Modal.TRANSITION_DURATION = 300 13544 Modal.BACKDROP_TRANSITION_DURATION = 150 13545 13546 Modal.DEFAULTS = { 13547 backdrop: true, 13548 keyboard: true, 13549 show: true 13550 } 13551 13552 Modal.prototype.toggle = function (_relatedTarget) { 13553 return this.isShown ? this.hide() : this.show(_relatedTarget) 13554 } 13555 13556 Modal.prototype.show = function (_relatedTarget) { 13557 var that = this 13558 var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget }) 13559 13560 this.$element.trigger(e) 13561 13562 if (this.isShown || e.isDefaultPrevented()) return 13563 13564 this.isShown = true 13565 13566 this.checkScrollbar() 13567 this.setScrollbar() 13568 this.$body.addClass('modal-open') 13569 13570 this.escape() 13571 this.resize() 13572 13573 this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this)) 13574 13575 this.$dialog.on('mousedown.dismiss.bs.modal', function () { 13576 that.$element.one('mouseup.dismiss.bs.modal', function (e) { 13577 if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true 13578 }) 13579 }) 13580 13581 this.backdrop(function () { 13582 var transition = $.support.transition && that.$element.hasClass('fade') 13583 13584 if (!that.$element.parent().length) { 13585 that.$element.appendTo(that.$body) // don't move modals dom position 13586 } 13587 13588 that.$element 13589 .show() 13590 .scrollTop(0) 13591 13592 that.adjustDialog() 13593 13594 if (transition) { 13595 that.$element[0].offsetWidth // force reflow 13596 } 13597 13598 that.$element.addClass('in') 13599 13600 that.enforceFocus() 13601 13602 var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget }) 13603 13604 transition ? 13605 that.$dialog // wait for modal to slide in 13606 .one('bsTransitionEnd', function () { 13607 that.$element.trigger('focus').trigger(e) 13608 }) 13609 .emulateTransitionEnd(Modal.TRANSITION_DURATION) : 13610 that.$element.trigger('focus').trigger(e) 13611 }) 13612 } 13613 13614 Modal.prototype.hide = function (e) { 13615 if (e) e.preventDefault() 13616 13617 e = $.Event('hide.bs.modal') 13618 13619 this.$element.trigger(e) 13620 13621 if (!this.isShown || e.isDefaultPrevented()) return 13622 13623 this.isShown = false 13624 13625 this.escape() 13626 this.resize() 13627 13628 $(document).off('focusin.bs.modal') 13629 13630 this.$element 13631 .removeClass('in') 13632 .off('click.dismiss.bs.modal') 13633 .off('mouseup.dismiss.bs.modal') 13634 13635 this.$dialog.off('mousedown.dismiss.bs.modal') 13636 13637 $.support.transition && this.$element.hasClass('fade') ? 13638 this.$element 13639 .one('bsTransitionEnd', $.proxy(this.hideModal, this)) 13640 .emulateTransitionEnd(Modal.TRANSITION_DURATION) : 13641 this.hideModal() 13642 } 13643 13644 Modal.prototype.enforceFocus = function () { 13645 $(document) 13646 .off('focusin.bs.modal') // guard against infinite focus loop 13647 .on('focusin.bs.modal', $.proxy(function (e) { 13648 if (document !== e.target && 13649 this.$element[0] !== e.target && 13650 !this.$element.has(e.target).length) { 13651 this.$element.trigger('focus') 13652 } 13653 }, this)) 13654 } 13655 13656 Modal.prototype.escape = function () { 13657 if (this.isShown && this.options.keyboard) { 13658 this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) { 13659 e.which == 27 && this.hide() 13660 }, this)) 13661 } else if (!this.isShown) { 13662 this.$element.off('keydown.dismiss.bs.modal') 13663 } 13664 } 13665 13666 Modal.prototype.resize = function () { 13667 if (this.isShown) { 13668 $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this)) 13669 } else { 13670 $(window).off('resize.bs.modal') 13671 } 13672 } 13673 13674 Modal.prototype.hideModal = function () { 13675 var that = this 13676 this.$element.hide() 13677 this.backdrop(function () { 13678 that.$body.removeClass('modal-open') 13679 that.resetAdjustments() 13680 that.resetScrollbar() 13681 that.$element.trigger('hidden.bs.modal') 13682 }) 13683 } 13684 13685 Modal.prototype.removeBackdrop = function () { 13686 this.$backdrop && this.$backdrop.remove() 13687 this.$backdrop = null 13688 } 13689 13690 Modal.prototype.backdrop = function (callback) { 13691 var that = this 13692 var animate = this.$element.hasClass('fade') ? 'fade' : '' 13693 13694 if (this.isShown && this.options.backdrop) { 13695 var doAnimate = $.support.transition && animate 13696 13697 this.$backdrop = $(document.createElement('div')) 13698 .addClass('modal-backdrop ' + animate) 13699 .appendTo(this.$body) 13700 13701 this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) { 13702 if (this.ignoreBackdropClick) { 13703 this.ignoreBackdropClick = false 13704 return 13705 } 13706 if (e.target !== e.currentTarget) return 13707 this.options.backdrop == 'static' 13708 ? this.$element[0].focus() 13709 : this.hide() 13710 }, this)) 13711 13712 if (doAnimate) this.$backdrop[0].offsetWidth // force reflow 13713 13714 this.$backdrop.addClass('in') 13715 13716 if (!callback) return 13717 13718 doAnimate ? 13719 this.$backdrop 13720 .one('bsTransitionEnd', callback) 13721 .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : 13722 callback() 13723 13724 } else if (!this.isShown && this.$backdrop) { 13725 this.$backdrop.removeClass('in') 13726 13727 var callbackRemove = function () { 13728 that.removeBackdrop() 13729 callback && callback() 13730 } 13731 $.support.transition && this.$element.hasClass('fade') ? 13732 this.$backdrop 13733 .one('bsTransitionEnd', callbackRemove) 13734 .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : 13735 callbackRemove() 13736 13737 } else if (callback) { 13738 callback() 13739 } 13740 } 13741 13742 // these following methods are used to handle overflowing modals 13743 13744 Modal.prototype.handleUpdate = function () { 13745 this.adjustDialog() 13746 } 13747 13748 Modal.prototype.adjustDialog = function () { 13749 var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight 13750 13751 this.$element.css({ 13752 paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '', 13753 paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : '' 13754 }) 13755 } 13756 13757 Modal.prototype.resetAdjustments = function () { 13758 this.$element.css({ 13759 paddingLeft: '', 13760 paddingRight: '' 13761 }) 13762 } 13763 13764 Modal.prototype.checkScrollbar = function () { 13765 var fullWindowWidth = window.innerWidth 13766 if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8 13767 var documentElementRect = document.documentElement.getBoundingClientRect() 13768 fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left) 13769 } 13770 this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth 13771 this.scrollbarWidth = this.measureScrollbar() 13772 } 13773 13774 Modal.prototype.setScrollbar = function () { 13775 var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10) 13776 this.originalBodyPad = document.body.style.paddingRight || '' 13777 var scrollbarWidth = this.scrollbarWidth 13778 if (this.bodyIsOverflowing) { 13779 this.$body.css('padding-right', bodyPad + scrollbarWidth) 13780 $(this.fixedContent).each(function (index, element) { 13781 var actualPadding = element.style.paddingRight 13782 var calculatedPadding = $(element).css('padding-right') 13783 $(element) 13784 .data('padding-right', actualPadding) 13785 .css('padding-right', parseFloat(calculatedPadding) + scrollbarWidth + 'px') 13786 }) 13787 } 13788 } 13789 13790 Modal.prototype.resetScrollbar = function () { 13791 this.$body.css('padding-right', this.originalBodyPad) 13792 $(this.fixedContent).each(function (index, element) { 13793 var padding = $(element).data('padding-right') 13794 $(element).removeData('padding-right') 13795 element.style.paddingRight = padding ? padding : '' 13796 }) 13797 } 13798 13799 Modal.prototype.measureScrollbar = function () { // thx walsh 13800 var scrollDiv = document.createElement('div') 13801 scrollDiv.className = 'modal-scrollbar-measure' 13802 this.$body.append(scrollDiv) 13803 var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth 13804 this.$body[0].removeChild(scrollDiv) 13805 return scrollbarWidth 13806 } 13807 13808 13809 // MODAL PLUGIN DEFINITION 13810 // ======================= 13811 13812 function Plugin(option, _relatedTarget) { 13813 return this.each(function () { 13814 var $this = $(this) 13815 var data = $this.data('bs.modal') 13816 var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option) 13817 13818 if (!data) $this.data('bs.modal', (data = new Modal(this, options))) 13819 if (typeof option == 'string') data[option](_relatedTarget) 13820 else if (options.show) data.show(_relatedTarget) 13821 }) 13822 } 13823 13824 var old = $.fn.modal 13825 13826 $.fn.modal = Plugin 13827 $.fn.modal.Constructor = Modal 13828 13829 13830 // MODAL NO CONFLICT 13831 // ================= 13832 13833 $.fn.modal.noConflict = function () { 13834 $.fn.modal = old 13835 return this 13836 } 13837 13838 13839 // MODAL DATA-API 13840 // ============== 13841 13842 $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) { 13843 var $this = $(this) 13844 var href = $this.attr('href') 13845 var target = $this.attr('data-target') || 13846 (href && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7 13847 13848 var $target = $(document).find(target) 13849 var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data()) 13850 13851 if ($this.is('a')) e.preventDefault() 13852 13853 $target.one('show.bs.modal', function (showEvent) { 13854 if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown 13855 $target.one('hidden.bs.modal', function () { 13856 $this.is(':visible') && $this.trigger('focus') 13857 }) 13858 }) 13859 Plugin.call($target, option, this) 13860 }) 13861 13862}(jQuery); 13863 13864/* ======================================================================== 13865 * Bootstrap: tooltip.js v3.4.1 13866 * https://getbootstrap.com/docs/3.4/javascript/#tooltip 13867 * Inspired by the original jQuery.tipsy by Jason Frame 13868 * ======================================================================== 13869 * Copyright 2011-2019 Twitter, Inc. 13870 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 13871 * ======================================================================== */ 13872 13873+function ($) { 13874 'use strict'; 13875 13876 var DISALLOWED_ATTRIBUTES = ['sanitize', 'whiteList', 'sanitizeFn'] 13877 13878 var uriAttrs = [ 13879 'background', 13880 'cite', 13881 'href', 13882 'itemtype', 13883 'longdesc', 13884 'poster', 13885 'src', 13886 'xlink:href' 13887 ] 13888 13889 var ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i 13890 13891 var DefaultWhitelist = { 13892 // Global attributes allowed on any supplied element below. 13893 '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN], 13894 a: ['target', 'href', 'title', 'rel'], 13895 area: [], 13896 b: [], 13897 br: [], 13898 col: [], 13899 code: [], 13900 div: [], 13901 em: [], 13902 hr: [], 13903 h1: [], 13904 h2: [], 13905 h3: [], 13906 h4: [], 13907 h5: [], 13908 h6: [], 13909 i: [], 13910 img: ['src', 'alt', 'title', 'width', 'height'], 13911 li: [], 13912 ol: [], 13913 p: [], 13914 pre: [], 13915 s: [], 13916 small: [], 13917 span: [], 13918 sub: [], 13919 sup: [], 13920 strong: [], 13921 u: [], 13922 ul: [] 13923 } 13924 13925 /** 13926 * A pattern that recognizes a commonly useful subset of URLs that are safe. 13927 * 13928 * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts 13929 */ 13930 var SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi 13931 13932 /** 13933 * A pattern that matches safe data URLs. Only matches image, video and audio types. 13934 * 13935 * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts 13936 */ 13937 var DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+/]+=*$/i 13938 13939 function allowedAttribute(attr, allowedAttributeList) { 13940 var attrName = attr.nodeName.toLowerCase() 13941 13942 if ($.inArray(attrName, allowedAttributeList) !== -1) { 13943 if ($.inArray(attrName, uriAttrs) !== -1) { 13944 return Boolean(attr.nodeValue.match(SAFE_URL_PATTERN) || attr.nodeValue.match(DATA_URL_PATTERN)) 13945 } 13946 13947 return true 13948 } 13949 13950 var regExp = $(allowedAttributeList).filter(function (index, value) { 13951 return value instanceof RegExp 13952 }) 13953 13954 // Check if a regular expression validates the attribute. 13955 for (var i = 0, l = regExp.length; i < l; i++) { 13956 if (attrName.match(regExp[i])) { 13957 return true 13958 } 13959 } 13960 13961 return false 13962 } 13963 13964 function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) { 13965 if (unsafeHtml.length === 0) { 13966 return unsafeHtml 13967 } 13968 13969 if (sanitizeFn && typeof sanitizeFn === 'function') { 13970 return sanitizeFn(unsafeHtml) 13971 } 13972 13973 // IE 8 and below don't support createHTMLDocument 13974 if (!document.implementation || !document.implementation.createHTMLDocument) { 13975 return unsafeHtml 13976 } 13977 13978 var createdDocument = document.implementation.createHTMLDocument('sanitization') 13979 createdDocument.body.innerHTML = unsafeHtml 13980 13981 var whitelistKeys = $.map(whiteList, function (el, i) { return i }) 13982 var elements = $(createdDocument.body).find('*') 13983 13984 for (var i = 0, len = elements.length; i < len; i++) { 13985 var el = elements[i] 13986 var elName = el.nodeName.toLowerCase() 13987 13988 if ($.inArray(elName, whitelistKeys) === -1) { 13989 el.parentNode.removeChild(el) 13990 13991 continue 13992 } 13993 13994 var attributeList = $.map(el.attributes, function (el) { return el }) 13995 var whitelistedAttributes = [].concat(whiteList['*'] || [], whiteList[elName] || []) 13996 13997 for (var j = 0, len2 = attributeList.length; j < len2; j++) { 13998 if (!allowedAttribute(attributeList[j], whitelistedAttributes)) { 13999 el.removeAttribute(attributeList[j].nodeName) 14000 } 14001 } 14002 } 14003 14004 return createdDocument.body.innerHTML 14005 } 14006 14007 // TOOLTIP PUBLIC CLASS DEFINITION 14008 // =============================== 14009 14010 var Tooltip = function (element, options) { 14011 this.type = null 14012 this.options = null 14013 this.enabled = null 14014 this.timeout = null 14015 this.hoverState = null 14016 this.$element = null 14017 this.inState = null 14018 14019 this.init('tooltip', element, options) 14020 } 14021 14022 Tooltip.VERSION = '3.4.1' 14023 14024 Tooltip.TRANSITION_DURATION = 150 14025 14026 Tooltip.DEFAULTS = { 14027 animation: true, 14028 placement: 'top', 14029 selector: false, 14030 template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>', 14031 trigger: 'hover focus', 14032 title: '', 14033 delay: 0, 14034 html: false, 14035 container: false, 14036 viewport: { 14037 selector: 'body', 14038 padding: 0 14039 }, 14040 sanitize : true, 14041 sanitizeFn : null, 14042 whiteList : DefaultWhitelist 14043 } 14044 14045 Tooltip.prototype.init = function (type, element, options) { 14046 this.enabled = true 14047 this.type = type 14048 this.$element = $(element) 14049 this.options = this.getOptions(options) 14050 this.$viewport = this.options.viewport && $(document).find($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport)) 14051 this.inState = { click: false, hover: false, focus: false } 14052 14053 if (this.$element[0] instanceof document.constructor && !this.options.selector) { 14054 throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!') 14055 } 14056 14057 var triggers = this.options.trigger.split(' ') 14058 14059 for (var i = triggers.length; i--;) { 14060 var trigger = triggers[i] 14061 14062 if (trigger == 'click') { 14063 this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) 14064 } else if (trigger != 'manual') { 14065 var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin' 14066 var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout' 14067 14068 this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) 14069 this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) 14070 } 14071 } 14072 14073 this.options.selector ? 14074 (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : 14075 this.fixTitle() 14076 } 14077 14078 Tooltip.prototype.getDefaults = function () { 14079 return Tooltip.DEFAULTS 14080 } 14081 14082 Tooltip.prototype.getOptions = function (options) { 14083 var dataAttributes = this.$element.data() 14084 14085 for (var dataAttr in dataAttributes) { 14086 if (dataAttributes.hasOwnProperty(dataAttr) && $.inArray(dataAttr, DISALLOWED_ATTRIBUTES) !== -1) { 14087 delete dataAttributes[dataAttr] 14088 } 14089 } 14090 14091 options = $.extend({}, this.getDefaults(), dataAttributes, options) 14092 14093 if (options.delay && typeof options.delay == 'number') { 14094 options.delay = { 14095 show: options.delay, 14096 hide: options.delay 14097 } 14098 } 14099 14100 if (options.sanitize) { 14101 options.template = sanitizeHtml(options.template, options.whiteList, options.sanitizeFn) 14102 } 14103 14104 return options 14105 } 14106 14107 Tooltip.prototype.getDelegateOptions = function () { 14108 var options = {} 14109 var defaults = this.getDefaults() 14110 14111 this._options && $.each(this._options, function (key, value) { 14112 if (defaults[key] != value) options[key] = value 14113 }) 14114 14115 return options 14116 } 14117 14118 Tooltip.prototype.enter = function (obj) { 14119 var self = obj instanceof this.constructor ? 14120 obj : $(obj.currentTarget).data('bs.' + this.type) 14121 14122 if (!self) { 14123 self = new this.constructor(obj.currentTarget, this.getDelegateOptions()) 14124 $(obj.currentTarget).data('bs.' + this.type, self) 14125 } 14126 14127 if (obj instanceof $.Event) { 14128 self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true 14129 } 14130 14131 if (self.tip().hasClass('in') || self.hoverState == 'in') { 14132 self.hoverState = 'in' 14133 return 14134 } 14135 14136 clearTimeout(self.timeout) 14137 14138 self.hoverState = 'in' 14139 14140 if (!self.options.delay || !self.options.delay.show) return self.show() 14141 14142 self.timeout = setTimeout(function () { 14143 if (self.hoverState == 'in') self.show() 14144 }, self.options.delay.show) 14145 } 14146 14147 Tooltip.prototype.isInStateTrue = function () { 14148 for (var key in this.inState) { 14149 if (this.inState[key]) return true 14150 } 14151 14152 return false 14153 } 14154 14155 Tooltip.prototype.leave = function (obj) { 14156 var self = obj instanceof this.constructor ? 14157 obj : $(obj.currentTarget).data('bs.' + this.type) 14158 14159 if (!self) { 14160 self = new this.constructor(obj.currentTarget, this.getDelegateOptions()) 14161 $(obj.currentTarget).data('bs.' + this.type, self) 14162 } 14163 14164 if (obj instanceof $.Event) { 14165 self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false 14166 } 14167 14168 if (self.isInStateTrue()) return 14169 14170 clearTimeout(self.timeout) 14171 14172 self.hoverState = 'out' 14173 14174 if (!self.options.delay || !self.options.delay.hide) return self.hide() 14175 14176 self.timeout = setTimeout(function () { 14177 if (self.hoverState == 'out') self.hide() 14178 }, self.options.delay.hide) 14179 } 14180 14181 Tooltip.prototype.show = function () { 14182 var e = $.Event('show.bs.' + this.type) 14183 14184 if (this.hasContent() && this.enabled) { 14185 this.$element.trigger(e) 14186 14187 var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0]) 14188 if (e.isDefaultPrevented() || !inDom) return 14189 var that = this 14190 14191 var $tip = this.tip() 14192 14193 var tipId = this.getUID(this.type) 14194 14195 this.setContent() 14196 $tip.attr('id', tipId) 14197 this.$element.attr('aria-describedby', tipId) 14198 14199 if (this.options.animation) $tip.addClass('fade') 14200 14201 var placement = typeof this.options.placement == 'function' ? 14202 this.options.placement.call(this, $tip[0], this.$element[0]) : 14203 this.options.placement 14204 14205 var autoToken = /\s?auto?\s?/i 14206 var autoPlace = autoToken.test(placement) 14207 if (autoPlace) placement = placement.replace(autoToken, '') || 'top' 14208 14209 $tip 14210 .detach() 14211 .css({ top: 0, left: 0, display: 'block' }) 14212 .addClass(placement) 14213 .data('bs.' + this.type, this) 14214 14215 this.options.container ? $tip.appendTo($(document).find(this.options.container)) : $tip.insertAfter(this.$element) 14216 this.$element.trigger('inserted.bs.' + this.type) 14217 14218 var pos = this.getPosition() 14219 var actualWidth = $tip[0].offsetWidth 14220 var actualHeight = $tip[0].offsetHeight 14221 14222 if (autoPlace) { 14223 var orgPlacement = placement 14224 var viewportDim = this.getPosition(this.$viewport) 14225 14226 placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' : 14227 placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' : 14228 placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' : 14229 placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' : 14230 placement 14231 14232 $tip 14233 .removeClass(orgPlacement) 14234 .addClass(placement) 14235 } 14236 14237 var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight) 14238 14239 this.applyPlacement(calculatedOffset, placement) 14240 14241 var complete = function () { 14242 var prevHoverState = that.hoverState 14243 that.$element.trigger('shown.bs.' + that.type) 14244 that.hoverState = null 14245 14246 if (prevHoverState == 'out') that.leave(that) 14247 } 14248 14249 $.support.transition && this.$tip.hasClass('fade') ? 14250 $tip 14251 .one('bsTransitionEnd', complete) 14252 .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : 14253 complete() 14254 } 14255 } 14256 14257 Tooltip.prototype.applyPlacement = function (offset, placement) { 14258 var $tip = this.tip() 14259 var width = $tip[0].offsetWidth 14260 var height = $tip[0].offsetHeight 14261 14262 // manually read margins because getBoundingClientRect includes difference 14263 var marginTop = parseInt($tip.css('margin-top'), 10) 14264 var marginLeft = parseInt($tip.css('margin-left'), 10) 14265 14266 // we must check for NaN for ie 8/9 14267 if (isNaN(marginTop)) marginTop = 0 14268 if (isNaN(marginLeft)) marginLeft = 0 14269 14270 offset.top += marginTop 14271 offset.left += marginLeft 14272 14273 // $.fn.offset doesn't round pixel values 14274 // so we use setOffset directly with our own function B-0 14275 $.offset.setOffset($tip[0], $.extend({ 14276 using: function (props) { 14277 $tip.css({ 14278 top: Math.round(props.top), 14279 left: Math.round(props.left) 14280 }) 14281 } 14282 }, offset), 0) 14283 14284 $tip.addClass('in') 14285 14286 // check to see if placing tip in new offset caused the tip to resize itself 14287 var actualWidth = $tip[0].offsetWidth 14288 var actualHeight = $tip[0].offsetHeight 14289 14290 if (placement == 'top' && actualHeight != height) { 14291 offset.top = offset.top + height - actualHeight 14292 } 14293 14294 var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight) 14295 14296 if (delta.left) offset.left += delta.left 14297 else offset.top += delta.top 14298 14299 var isVertical = /top|bottom/.test(placement) 14300 var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight 14301 var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight' 14302 14303 $tip.offset(offset) 14304 this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical) 14305 } 14306 14307 Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) { 14308 this.arrow() 14309 .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%') 14310 .css(isVertical ? 'top' : 'left', '') 14311 } 14312 14313 Tooltip.prototype.setContent = function () { 14314 var $tip = this.tip() 14315 var title = this.getTitle() 14316 14317 if (this.options.html) { 14318 if (this.options.sanitize) { 14319 title = sanitizeHtml(title, this.options.whiteList, this.options.sanitizeFn) 14320 } 14321 14322 $tip.find('.tooltip-inner').html(title) 14323 } else { 14324 $tip.find('.tooltip-inner').text(title) 14325 } 14326 14327 $tip.removeClass('fade in top bottom left right') 14328 } 14329 14330 Tooltip.prototype.hide = function (callback) { 14331 var that = this 14332 var $tip = $(this.$tip) 14333 var e = $.Event('hide.bs.' + this.type) 14334 14335 function complete() { 14336 if (that.hoverState != 'in') $tip.detach() 14337 if (that.$element) { // TODO: Check whether guarding this code with this `if` is really necessary. 14338 that.$element 14339 .removeAttr('aria-describedby') 14340 .trigger('hidden.bs.' + that.type) 14341 } 14342 callback && callback() 14343 } 14344 14345 this.$element.trigger(e) 14346 14347 if (e.isDefaultPrevented()) return 14348 14349 $tip.removeClass('in') 14350 14351 $.support.transition && $tip.hasClass('fade') ? 14352 $tip 14353 .one('bsTransitionEnd', complete) 14354 .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : 14355 complete() 14356 14357 this.hoverState = null 14358 14359 return this 14360 } 14361 14362 Tooltip.prototype.fixTitle = function () { 14363 var $e = this.$element 14364 if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') { 14365 $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') 14366 } 14367 } 14368 14369 Tooltip.prototype.hasContent = function () { 14370 return this.getTitle() 14371 } 14372 14373 Tooltip.prototype.getPosition = function ($element) { 14374 $element = $element || this.$element 14375 14376 var el = $element[0] 14377 var isBody = el.tagName == 'BODY' 14378 14379 var elRect = el.getBoundingClientRect() 14380 if (elRect.width == null) { 14381 // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093 14382 elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top }) 14383 } 14384 var isSvg = window.SVGElement && el instanceof window.SVGElement 14385 // Avoid using $.offset() on SVGs since it gives incorrect results in jQuery 3. 14386 // See https://github.com/twbs/bootstrap/issues/20280 14387 var elOffset = isBody ? { top: 0, left: 0 } : (isSvg ? null : $element.offset()) 14388 var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() } 14389 var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null 14390 14391 return $.extend({}, elRect, scroll, outerDims, elOffset) 14392 } 14393 14394 Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) { 14395 return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } : 14396 placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } : 14397 placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } : 14398 /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width } 14399 14400 } 14401 14402 Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) { 14403 var delta = { top: 0, left: 0 } 14404 if (!this.$viewport) return delta 14405 14406 var viewportPadding = this.options.viewport && this.options.viewport.padding || 0 14407 var viewportDimensions = this.getPosition(this.$viewport) 14408 14409 if (/right|left/.test(placement)) { 14410 var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll 14411 var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight 14412 if (topEdgeOffset < viewportDimensions.top) { // top overflow 14413 delta.top = viewportDimensions.top - topEdgeOffset 14414 } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow 14415 delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset 14416 } 14417 } else { 14418 var leftEdgeOffset = pos.left - viewportPadding 14419 var rightEdgeOffset = pos.left + viewportPadding + actualWidth 14420 if (leftEdgeOffset < viewportDimensions.left) { // left overflow 14421 delta.left = viewportDimensions.left - leftEdgeOffset 14422 } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow 14423 delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset 14424 } 14425 } 14426 14427 return delta 14428 } 14429 14430 Tooltip.prototype.getTitle = function () { 14431 var title 14432 var $e = this.$element 14433 var o = this.options 14434 14435 title = $e.attr('data-original-title') 14436 || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) 14437 14438 return title 14439 } 14440 14441 Tooltip.prototype.getUID = function (prefix) { 14442 do prefix += ~~(Math.random() * 1000000) 14443 while (document.getElementById(prefix)) 14444 return prefix 14445 } 14446 14447 Tooltip.prototype.tip = function () { 14448 if (!this.$tip) { 14449 this.$tip = $(this.options.template) 14450 if (this.$tip.length != 1) { 14451 throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!') 14452 } 14453 } 14454 return this.$tip 14455 } 14456 14457 Tooltip.prototype.arrow = function () { 14458 return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')) 14459 } 14460 14461 Tooltip.prototype.enable = function () { 14462 this.enabled = true 14463 } 14464 14465 Tooltip.prototype.disable = function () { 14466 this.enabled = false 14467 } 14468 14469 Tooltip.prototype.toggleEnabled = function () { 14470 this.enabled = !this.enabled 14471 } 14472 14473 Tooltip.prototype.toggle = function (e) { 14474 var self = this 14475 if (e) { 14476 self = $(e.currentTarget).data('bs.' + this.type) 14477 if (!self) { 14478 self = new this.constructor(e.currentTarget, this.getDelegateOptions()) 14479 $(e.currentTarget).data('bs.' + this.type, self) 14480 } 14481 } 14482 14483 if (e) { 14484 self.inState.click = !self.inState.click 14485 if (self.isInStateTrue()) self.enter(self) 14486 else self.leave(self) 14487 } else { 14488 self.tip().hasClass('in') ? self.leave(self) : self.enter(self) 14489 } 14490 } 14491 14492 Tooltip.prototype.destroy = function () { 14493 var that = this 14494 clearTimeout(this.timeout) 14495 this.hide(function () { 14496 that.$element.off('.' + that.type).removeData('bs.' + that.type) 14497 if (that.$tip) { 14498 that.$tip.detach() 14499 } 14500 that.$tip = null 14501 that.$arrow = null 14502 that.$viewport = null 14503 that.$element = null 14504 }) 14505 } 14506 14507 Tooltip.prototype.sanitizeHtml = function (unsafeHtml) { 14508 return sanitizeHtml(unsafeHtml, this.options.whiteList, this.options.sanitizeFn) 14509 } 14510 14511 // TOOLTIP PLUGIN DEFINITION 14512 // ========================= 14513 14514 function Plugin(option) { 14515 return this.each(function () { 14516 var $this = $(this) 14517 var data = $this.data('bs.tooltip') 14518 var options = typeof option == 'object' && option 14519 14520 if (!data && /destroy|hide/.test(option)) return 14521 if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) 14522 if (typeof option == 'string') data[option]() 14523 }) 14524 } 14525 14526 var old = $.fn.tooltip 14527 14528 $.fn.tooltip = Plugin 14529 $.fn.tooltip.Constructor = Tooltip 14530 14531 14532 // TOOLTIP NO CONFLICT 14533 // =================== 14534 14535 $.fn.tooltip.noConflict = function () { 14536 $.fn.tooltip = old 14537 return this 14538 } 14539 14540}(jQuery); 14541 14542/* ======================================================================== 14543 * Bootstrap: popover.js v3.4.1 14544 * https://getbootstrap.com/docs/3.4/javascript/#popovers 14545 * ======================================================================== 14546 * Copyright 2011-2019 Twitter, Inc. 14547 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 14548 * ======================================================================== */ 14549 14550 14551+function ($) { 14552 'use strict'; 14553 14554 // POPOVER PUBLIC CLASS DEFINITION 14555 // =============================== 14556 14557 var Popover = function (element, options) { 14558 this.init('popover', element, options) 14559 } 14560 14561 if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js') 14562 14563 Popover.VERSION = '3.4.1' 14564 14565 Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, { 14566 placement: 'right', 14567 trigger: 'click', 14568 content: '', 14569 template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>' 14570 }) 14571 14572 14573 // NOTE: POPOVER EXTENDS tooltip.js 14574 // ================================ 14575 14576 Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype) 14577 14578 Popover.prototype.constructor = Popover 14579 14580 Popover.prototype.getDefaults = function () { 14581 return Popover.DEFAULTS 14582 } 14583 14584 Popover.prototype.setContent = function () { 14585 var $tip = this.tip() 14586 var title = this.getTitle() 14587 var content = this.getContent() 14588 14589 if (this.options.html) { 14590 var typeContent = typeof content 14591 14592 if (this.options.sanitize) { 14593 title = this.sanitizeHtml(title) 14594 14595 if (typeContent === 'string') { 14596 content = this.sanitizeHtml(content) 14597 } 14598 } 14599 14600 $tip.find('.popover-title').html(title) 14601 $tip.find('.popover-content').children().detach().end()[ 14602 typeContent === 'string' ? 'html' : 'append' 14603 ](content) 14604 } else { 14605 $tip.find('.popover-title').text(title) 14606 $tip.find('.popover-content').children().detach().end().text(content) 14607 } 14608 14609 $tip.removeClass('fade top bottom left right in') 14610 14611 // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do 14612 // this manually by checking the contents. 14613 if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide() 14614 } 14615 14616 Popover.prototype.hasContent = function () { 14617 return this.getTitle() || this.getContent() 14618 } 14619 14620 Popover.prototype.getContent = function () { 14621 var $e = this.$element 14622 var o = this.options 14623 14624 return $e.attr('data-content') 14625 || (typeof o.content == 'function' ? 14626 o.content.call($e[0]) : 14627 o.content) 14628 } 14629 14630 Popover.prototype.arrow = function () { 14631 return (this.$arrow = this.$arrow || this.tip().find('.arrow')) 14632 } 14633 14634 14635 // POPOVER PLUGIN DEFINITION 14636 // ========================= 14637 14638 function Plugin(option) { 14639 return this.each(function () { 14640 var $this = $(this) 14641 var data = $this.data('bs.popover') 14642 var options = typeof option == 'object' && option 14643 14644 if (!data && /destroy|hide/.test(option)) return 14645 if (!data) $this.data('bs.popover', (data = new Popover(this, options))) 14646 if (typeof option == 'string') data[option]() 14647 }) 14648 } 14649 14650 var old = $.fn.popover 14651 14652 $.fn.popover = Plugin 14653 $.fn.popover.Constructor = Popover 14654 14655 14656 // POPOVER NO CONFLICT 14657 // =================== 14658 14659 $.fn.popover.noConflict = function () { 14660 $.fn.popover = old 14661 return this 14662 } 14663 14664}(jQuery); 14665 14666/* ======================================================================== 14667 * Bootstrap: scrollspy.js v3.4.1 14668 * https://getbootstrap.com/docs/3.4/javascript/#scrollspy 14669 * ======================================================================== 14670 * Copyright 2011-2019 Twitter, Inc. 14671 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 14672 * ======================================================================== */ 14673 14674 14675+function ($) { 14676 'use strict'; 14677 14678 // SCROLLSPY CLASS DEFINITION 14679 // ========================== 14680 14681 function ScrollSpy(element, options) { 14682 this.$body = $(document.body) 14683 this.$scrollElement = $(element).is(document.body) ? $(window) : $(element) 14684 this.options = $.extend({}, ScrollSpy.DEFAULTS, options) 14685 this.selector = (this.options.target || '') + ' .nav li > a' 14686 this.offsets = [] 14687 this.targets = [] 14688 this.activeTarget = null 14689 this.scrollHeight = 0 14690 14691 this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this)) 14692 this.refresh() 14693 this.process() 14694 } 14695 14696 ScrollSpy.VERSION = '3.4.1' 14697 14698 ScrollSpy.DEFAULTS = { 14699 offset: 10 14700 } 14701 14702 ScrollSpy.prototype.getScrollHeight = function () { 14703 return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight) 14704 } 14705 14706 ScrollSpy.prototype.refresh = function () { 14707 var that = this 14708 var offsetMethod = 'offset' 14709 var offsetBase = 0 14710 14711 this.offsets = [] 14712 this.targets = [] 14713 this.scrollHeight = this.getScrollHeight() 14714 14715 if (!$.isWindow(this.$scrollElement[0])) { 14716 offsetMethod = 'position' 14717 offsetBase = this.$scrollElement.scrollTop() 14718 } 14719 14720 this.$body 14721 .find(this.selector) 14722 .map(function () { 14723 var $el = $(this) 14724 var href = $el.data('target') || $el.attr('href') 14725 var $href = /^#./.test(href) && $(href) 14726 14727 return ($href 14728 && $href.length 14729 && $href.is(':visible') 14730 && [[$href[offsetMethod]().top + offsetBase, href]]) || null 14731 }) 14732 .sort(function (a, b) { return a[0] - b[0] }) 14733 .each(function () { 14734 that.offsets.push(this[0]) 14735 that.targets.push(this[1]) 14736 }) 14737 } 14738 14739 ScrollSpy.prototype.process = function () { 14740 var scrollTop = this.$scrollElement.scrollTop() + this.options.offset 14741 var scrollHeight = this.getScrollHeight() 14742 var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height() 14743 var offsets = this.offsets 14744 var targets = this.targets 14745 var activeTarget = this.activeTarget 14746 var i 14747 14748 if (this.scrollHeight != scrollHeight) { 14749 this.refresh() 14750 } 14751 14752 if (scrollTop >= maxScroll) { 14753 return activeTarget != (i = targets[targets.length - 1]) && this.activate(i) 14754 } 14755 14756 if (activeTarget && scrollTop < offsets[0]) { 14757 this.activeTarget = null 14758 return this.clear() 14759 } 14760 14761 for (i = offsets.length; i--;) { 14762 activeTarget != targets[i] 14763 && scrollTop >= offsets[i] 14764 && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1]) 14765 && this.activate(targets[i]) 14766 } 14767 } 14768 14769 ScrollSpy.prototype.activate = function (target) { 14770 this.activeTarget = target 14771 14772 this.clear() 14773 14774 var selector = this.selector + 14775 '[data-target="' + target + '"],' + 14776 this.selector + '[href="' + target + '"]' 14777 14778 var active = $(selector) 14779 .parents('li') 14780 .addClass('active') 14781 14782 if (active.parent('.dropdown-menu').length) { 14783 active = active 14784 .closest('li.dropdown') 14785 .addClass('active') 14786 } 14787 14788 active.trigger('activate.bs.scrollspy') 14789 } 14790 14791 ScrollSpy.prototype.clear = function () { 14792 $(this.selector) 14793 .parentsUntil(this.options.target, '.active') 14794 .removeClass('active') 14795 } 14796 14797 14798 // SCROLLSPY PLUGIN DEFINITION 14799 // =========================== 14800 14801 function Plugin(option) { 14802 return this.each(function () { 14803 var $this = $(this) 14804 var data = $this.data('bs.scrollspy') 14805 var options = typeof option == 'object' && option 14806 14807 if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options))) 14808 if (typeof option == 'string') data[option]() 14809 }) 14810 } 14811 14812 var old = $.fn.scrollspy 14813 14814 $.fn.scrollspy = Plugin 14815 $.fn.scrollspy.Constructor = ScrollSpy 14816 14817 14818 // SCROLLSPY NO CONFLICT 14819 // ===================== 14820 14821 $.fn.scrollspy.noConflict = function () { 14822 $.fn.scrollspy = old 14823 return this 14824 } 14825 14826 14827 // SCROLLSPY DATA-API 14828 // ================== 14829 14830 $(window).on('load.bs.scrollspy.data-api', function () { 14831 $('[data-spy="scroll"]').each(function () { 14832 var $spy = $(this) 14833 Plugin.call($spy, $spy.data()) 14834 }) 14835 }) 14836 14837}(jQuery); 14838 14839/* ======================================================================== 14840 * Bootstrap: tab.js v3.4.1 14841 * https://getbootstrap.com/docs/3.4/javascript/#tabs 14842 * ======================================================================== 14843 * Copyright 2011-2019 Twitter, Inc. 14844 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 14845 * ======================================================================== */ 14846 14847 14848+function ($) { 14849 'use strict'; 14850 14851 // TAB CLASS DEFINITION 14852 // ==================== 14853 14854 var Tab = function (element) { 14855 // jscs:disable requireDollarBeforejQueryAssignment 14856 this.element = $(element) 14857 // jscs:enable requireDollarBeforejQueryAssignment 14858 } 14859 14860 Tab.VERSION = '3.4.1' 14861 14862 Tab.TRANSITION_DURATION = 150 14863 14864 Tab.prototype.show = function () { 14865 var $this = this.element 14866 var $ul = $this.closest('ul:not(.dropdown-menu)') 14867 var selector = $this.data('target') 14868 14869 if (!selector) { 14870 selector = $this.attr('href') 14871 selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 14872 } 14873 14874 if ($this.parent('li').hasClass('active')) return 14875 14876 var $previous = $ul.find('.active:last a') 14877 var hideEvent = $.Event('hide.bs.tab', { 14878 relatedTarget: $this[0] 14879 }) 14880 var showEvent = $.Event('show.bs.tab', { 14881 relatedTarget: $previous[0] 14882 }) 14883 14884 $previous.trigger(hideEvent) 14885 $this.trigger(showEvent) 14886 14887 if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return 14888 14889 var $target = $(document).find(selector) 14890 14891 this.activate($this.closest('li'), $ul) 14892 this.activate($target, $target.parent(), function () { 14893 $previous.trigger({ 14894 type: 'hidden.bs.tab', 14895 relatedTarget: $this[0] 14896 }) 14897 $this.trigger({ 14898 type: 'shown.bs.tab', 14899 relatedTarget: $previous[0] 14900 }) 14901 }) 14902 } 14903 14904 Tab.prototype.activate = function (element, container, callback) { 14905 var $active = container.find('> .active') 14906 var transition = callback 14907 && $.support.transition 14908 && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length) 14909 14910 function next() { 14911 $active 14912 .removeClass('active') 14913 .find('> .dropdown-menu > .active') 14914 .removeClass('active') 14915 .end() 14916 .find('[data-toggle="tab"]') 14917 .attr('aria-expanded', false) 14918 14919 element 14920 .addClass('active') 14921 .find('[data-toggle="tab"]') 14922 .attr('aria-expanded', true) 14923 14924 if (transition) { 14925 element[0].offsetWidth // reflow for transition 14926 element.addClass('in') 14927 } else { 14928 element.removeClass('fade') 14929 } 14930 14931 if (element.parent('.dropdown-menu').length) { 14932 element 14933 .closest('li.dropdown') 14934 .addClass('active') 14935 .end() 14936 .find('[data-toggle="tab"]') 14937 .attr('aria-expanded', true) 14938 } 14939 14940 callback && callback() 14941 } 14942 14943 $active.length && transition ? 14944 $active 14945 .one('bsTransitionEnd', next) 14946 .emulateTransitionEnd(Tab.TRANSITION_DURATION) : 14947 next() 14948 14949 $active.removeClass('in') 14950 } 14951 14952 14953 // TAB PLUGIN DEFINITION 14954 // ===================== 14955 14956 function Plugin(option) { 14957 return this.each(function () { 14958 var $this = $(this) 14959 var data = $this.data('bs.tab') 14960 14961 if (!data) $this.data('bs.tab', (data = new Tab(this))) 14962 if (typeof option == 'string') data[option]() 14963 }) 14964 } 14965 14966 var old = $.fn.tab 14967 14968 $.fn.tab = Plugin 14969 $.fn.tab.Constructor = Tab 14970 14971 14972 // TAB NO CONFLICT 14973 // =============== 14974 14975 $.fn.tab.noConflict = function () { 14976 $.fn.tab = old 14977 return this 14978 } 14979 14980 14981 // TAB DATA-API 14982 // ============ 14983 14984 var clickHandler = function (e) { 14985 e.preventDefault() 14986 Plugin.call($(this), 'show') 14987 } 14988 14989 $(document) 14990 .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler) 14991 .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler) 14992 14993}(jQuery); 14994 14995/* ======================================================================== 14996 * Bootstrap: affix.js v3.4.1 14997 * https://getbootstrap.com/docs/3.4/javascript/#affix 14998 * ======================================================================== 14999 * Copyright 2011-2019 Twitter, Inc. 15000 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 15001 * ======================================================================== */ 15002 15003 15004+function ($) { 15005 'use strict'; 15006 15007 // AFFIX CLASS DEFINITION 15008 // ====================== 15009 15010 var Affix = function (element, options) { 15011 this.options = $.extend({}, Affix.DEFAULTS, options) 15012 15013 var target = this.options.target === Affix.DEFAULTS.target ? $(this.options.target) : $(document).find(this.options.target) 15014 15015 this.$target = target 15016 .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this)) 15017 .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this)) 15018 15019 this.$element = $(element) 15020 this.affixed = null 15021 this.unpin = null 15022 this.pinnedOffset = null 15023 15024 this.checkPosition() 15025 } 15026 15027 Affix.VERSION = '3.4.1' 15028 15029 Affix.RESET = 'affix affix-top affix-bottom' 15030 15031 Affix.DEFAULTS = { 15032 offset: 0, 15033 target: window 15034 } 15035 15036 Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) { 15037 var scrollTop = this.$target.scrollTop() 15038 var position = this.$element.offset() 15039 var targetHeight = this.$target.height() 15040 15041 if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false 15042 15043 if (this.affixed == 'bottom') { 15044 if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom' 15045 return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom' 15046 } 15047 15048 var initializing = this.affixed == null 15049 var colliderTop = initializing ? scrollTop : position.top 15050 var colliderHeight = initializing ? targetHeight : height 15051 15052 if (offsetTop != null && scrollTop <= offsetTop) return 'top' 15053 if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom' 15054 15055 return false 15056 } 15057 15058 Affix.prototype.getPinnedOffset = function () { 15059 if (this.pinnedOffset) return this.pinnedOffset 15060 this.$element.removeClass(Affix.RESET).addClass('affix') 15061 var scrollTop = this.$target.scrollTop() 15062 var position = this.$element.offset() 15063 return (this.pinnedOffset = position.top - scrollTop) 15064 } 15065 15066 Affix.prototype.checkPositionWithEventLoop = function () { 15067 setTimeout($.proxy(this.checkPosition, this), 1) 15068 } 15069 15070 Affix.prototype.checkPosition = function () { 15071 if (!this.$element.is(':visible')) return 15072 15073 var height = this.$element.height() 15074 var offset = this.options.offset 15075 var offsetTop = offset.top 15076 var offsetBottom = offset.bottom 15077 var scrollHeight = Math.max($(document).height(), $(document.body).height()) 15078 15079 if (typeof offset != 'object') offsetBottom = offsetTop = offset 15080 if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element) 15081 if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element) 15082
15083 var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom) 15084 15085 if (this.affixed != affix) { 15086 if (this.unpin != null) this.$element.css('top', '') 15087 15088 var affixType = 'affix' + (affix ? '-' + affix : '') 15089 var e = $.Event(affixType + '.bs.affix') 15090 15091 this.$element.trigger(e) 15092 15093 if (e.isDefaultPrevented()) return 15094 15095 this.affixed = affix 15096 this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null 15097 15098 this.$element 15099 .removeClass(Affix.RESET) 15100 .addClass(affixType) 15101 .trigger(affixType.replace('affix', 'affixed') + '.bs.affix') 15102 } 15103 15104 if (affix == 'bottom') { 15105 this.$element.offset({ 15106 top: scrollHeight - height - offsetBottom 15107 }) 15108 } 15109 } 15110 15111 15112 // AFFIX PLUGIN DEFINITION 15113 // ======================= 15114 15115 function Plugin(option) { 15116 return this.each(function () { 15117 var $this = $(this) 15118 var data = $this.data('bs.affix') 15119 var options = typeof option == 'object' && option 15120 15121 if (!data) $this.data('bs.affix', (data = new Affix(this, options))) 15122 if (typeof option == 'string') data[option]() 15123 }) 15124 } 15125 15126 var old = $.fn.affix 15127 15128 $.fn.affix = Plugin 15129 $.fn.affix.Constructor = Affix 15130 15131 15132 // AFFIX NO CONFLICT 15133 // ================= 15134 15135 $.fn.affix.noConflict = function () { 15136 $.fn.affix = old 15137 return this 15138 } 15139 15140 15141 // AFFIX DATA-API 15142 // ============== 15143 15144 $(window).on('load', function () { 15145 $('[data-spy="affix"]').each(function () { 15146 var $spy = $(this) 15147 var data = $spy.data() 15148 15149 data.offset = data.offset || {} 15150 15151 if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom 15152 if (data.offsetTop != null) data.offset.top = data.offsetTop 15153 15154 Plugin.call($spy, data) 15155 }) 15156 }) 15157 15158}(jQuery); 15159 15160/* 15161 * jQuery Templating Plugin 15162 * Copyright 2010, John Resig 15163 * Dual licensed under the MIT or GPL Version 2 licenses. 15164 */ 15165(function( jQuery, undefined ){ 15166 var oldManip = jQuery.fn.domManip, tmplItmAtt = "_tmplitem", htmlExpr = /^[^<]*(<[\w\W]+>)[^>]*$|\{\{\! /, 15167 newTmplItems = {}, wrappedItems = {}, appendToTmplItems, topTmplItem = { key: 0, data: {} }, itemKey = 0, cloneIndex = 0, stack = []; 15168 15169 function newTmplItem( options, parentItem, fn, data ) { 15170 // Returns a template item data structure for a new rendered instance of a template (a 'template item'). 15171 // The content field is a hierarchical array of strings and nested items (to be 15172 // removed and replaced by nodes field of dom elements, once inserted in DOM). 15173 var newItem = { 15174 data: data || (parentItem ? parentItem.data : {}), 15175 _wrap: parentItem ? parentItem._wrap : null, 15176 tmpl: null, 15177 parent: parentItem || null, 15178 nodes: [], 15179 calls: tiCalls, 15180 nest: tiNest, 15181 wrap: tiWrap, 15182 html: tiHtml, 15183 update: tiUpdate 15184 }; 15185 if ( options ) { 15186 jQuery.extend( newItem, options, { nodes: [], parent: parentItem } ); 15187 } 15188 if ( fn ) { 15189 // Build the hierarchical content to be used during insertion into DOM 15190 newItem.tmpl = fn; 15191 newItem._ctnt = newItem._ctnt || newItem.tmpl( jQuery, newItem ); 15192 newItem.key = ++itemKey; 15193 // Keep track of new template item, until it is stored as jQuery Data on DOM element 15194 (stack.length ? wrappedItems : newTmplItems)[itemKey] = newItem; 15195 } 15196 return newItem; 15197 } 15198 15199 // Override appendTo etc., in order to provide support for targeting multiple elements. (This code would disappear if integrated in jquery core). 15200 jQuery.each({ 15201 appendTo: "append", 15202 prependTo: "prepend", 15203 insertBefore: "before", 15204 insertAfter: "after", 15205 replaceAll: "replaceWith" 15206 }, function( name, original ) { 15207 jQuery.fn[ name ] = function( selector ) { 15208 var ret = [], insert = jQuery( selector ), elems, i, l, tmplItems, 15209 parent = this.length === 1 && this[0].parentNode; 15210 15211 appendToTmplItems = newTmplItems || {}; 15212 if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) { 15213 insert[ original ]( this[0] ); 15214 ret = this; 15215 } else { 15216 for ( i = 0, l = insert.length; i < l; i++ ) { 15217 cloneIndex = i; 15218 elems = (i > 0 ? this.clone(true) : this).get(); 15219 jQuery.fn[ original ].apply( jQuery(insert[i]), elems ); 15220 ret = ret.concat( elems ); 15221 } 15222 cloneIndex = 0; 15223 ret = this.pushStack( ret, name, insert.selector ); 15224 } 15225 tmplItems = appendToTmplItems; 15226 appendToTmplItems = null; 15227 jQuery.tmpl.complete( tmplItems ); 15228 return ret; 15229 }; 15230 }); 15231 15232 jQuery.fn.extend({ 15233 // Use first wrapped element as template markup. 15234 // Return wrapped set of template items, obtained by rendering template against data. 15235 tmpl: function( data, options, parentItem ) { 15236 return jQuery.tmpl( this[0], data, options, parentItem ); 15237 }, 15238 15239 // Find which rendered template item the first wrapped DOM element belongs to 15240 tmplItem: function() { 15241 return jQuery.tmplItem( this[0] ); 15242 }, 15243 15244 // Consider the first wrapped element as a template declaration, and get the compiled template or store it as a named template. 15245 template: function( name ) { 15246 return jQuery.template( name, this[0] ); 15247 }, 15248 15249 domManip: function( args, table, callback, options ) { 15250 // This appears to be a bug in the appendTo, etc. implementation 15251 // it should be doing .call() instead of .apply(). See #6227 15252 if ( args[0] && args[0].nodeType ) { 15253 var dmArgs = jQuery.makeArray( arguments ), argsLength = args.length, i = 0, tmplItem; 15254 while ( i < argsLength && !(tmplItem = jQuery.data( args[i++], "tmplItem" ))) {} 15255 if ( argsLength > 1 ) { 15256 dmArgs[0] = [jQuery.makeArray( args )]; 15257 } 15258 if ( tmplItem && cloneIndex ) { 15259 dmArgs[2] = function( fragClone ) { 15260 // Handler called by oldManip when rendered template has been inserted into DOM. 15261 jQuery.tmpl.afterManip( this, fragClone, callback ); 15262 }; 15263 } 15264 oldManip.apply( this, dmArgs ); 15265 } else { 15266 oldManip.apply( this, arguments ); 15267 } 15268 cloneIndex = 0; 15269 if ( !appendToTmplItems ) { 15270 jQuery.tmpl.complete( newTmplItems ); 15271 } 15272 return this; 15273 } 15274 }); 15275 15276 jQuery.extend({ 15277 // Return wrapped set of template items, obtained by rendering template against data. 15278 tmpl: function( tmpl, data, options, parentItem ) { 15279 var ret, topLevel = !parentItem; 15280 if ( topLevel ) { 15281 // This is a top-level tmpl call (not from a nested template using {{tmpl}}) 15282 parentItem = topTmplItem; 15283 tmpl = jQuery.template[tmpl] || jQuery.template( null, tmpl ); 15284 wrappedItems = {}; // Any wrapped items will be rebuilt, since this is top level 15285 } else if ( !tmpl ) { 15286 // The template item is already associated with DOM - this is a refresh. 15287 // Re-evaluate rendered template for the parentItem 15288 tmpl = parentItem.tmpl; 15289 newTmplItems[parentItem.key] = parentItem; 15290 parentItem.nodes = []; 15291 if ( parentItem.wrapped ) { 15292 updateWrapped( parentItem, parentItem.wrapped ); 15293 } 15294 // Rebuild, without creating a new template item 15295 return jQuery( build( parentItem, null, parentItem.tmpl( jQuery, parentItem ) )); 15296 } 15297 if ( !tmpl ) { 15298 return []; // Could throw... 15299 } 15300 if ( typeof data === "function" ) { 15301 data = data.call( parentItem || {} ); 15302 } 15303 if ( options && options.wrapped ) { 15304 updateWrapped( options, options.wrapped ); 15305 } 15306 ret = jQuery.isArray( data ) ? 15307 jQuery.map( data, function( dataItem ) { 15308 return dataItem ? newTmplItem( options, parentItem, tmpl, dataItem ) : null; 15309 }) : 15310 [ newTmplItem( options, parentItem, tmpl, data ) ]; 15311 return topLevel ? jQuery( build( parentItem, null, ret ) ) : ret; 15312 }, 15313 15314 // Return rendered template item for an element. 15315 tmplItem: function( elem ) { 15316 var tmplItem; 15317 if ( elem instanceof jQuery ) { 15318 elem = elem[0]; 15319 } 15320 while ( elem && elem.nodeType === 1 && !(tmplItem = jQuery.data( elem, "tmplItem" )) && (elem = elem.parentNode) ) {} 15321 return tmplItem || topTmplItem; 15322 }, 15323 15324 // Set: 15325 // Use $.template( name, tmpl ) to cache a named template, 15326 // where tmpl is a template string, a script element or a jQuery instance wrapping a script element, etc. 15327 // Use $( "selector" ).template( name ) to provide access by name to a script block template declaration. 15328 15329 // Get: 15330 // Use $.template( name ) to access a cached template. 15331 // Also $( selectorToScriptBlock ).template(), or $.template( null, templateString ) 15332 // will return the compiled template, without adding a name reference. 15333 // If templateString includes at least one HTML tag, $.template( templateString )
15333is equivalent 15334 // to $.template( null, templateString ) 15335 template: function( name, tmpl ) { 15336 if (tmpl) { 15337 // Compile template and associate with name 15338 if ( typeof tmpl === "string" ) { 15339 // This is an HTML string being passed directly in. 15340 tmpl = buildTmplFn( tmpl ) 15341 } else if ( tmpl instanceof jQuery ) { 15342 tmpl = tmpl[0] || {}; 15343 } 15344 if ( tmpl.nodeType ) { 15345 // If this is a template block, use cached copy, or generate tmpl function and cache. 15346 tmpl = jQuery.data( tmpl, "tmpl" ) || jQuery.data( tmpl, "tmpl", buildTmplFn( tmpl.innerHTML )); 15347 } 15348 return typeof name === "string" ? (jQuery.template[name] = tmpl) : tmpl; 15349 } 15350 // Return named compiled template 15351 return name ? (typeof name !== "string" ? jQuery.template( null, name ): 15352 (jQuery.template[name] || 15353 // If not in map, treat as a selector. (If integrated with core, use quickExpr.exec) 15354 jQuery.template( null, htmlExpr.test( name ) ? name : jQuery( name )))) : null; 15355 }, 15356 15357 encode: function( text ) { 15358 // Do HTML encoding replacing < > & and ' and " by corresponding entities. 15359 return ("" + text).split("<").join("<").split(">").join(">").split('"').join(""").split("'").join("'"); 15360 } 15361 }); 15362 15363 jQuery.extend( jQuery.tmpl, { 15364 tag: { 15365 "tmpl": { 15366 _default: { $2: "null" }, 15367 open: "if($notnull_1){_=_.concat($item.nest($1,$2));}" 15368 // tmpl target parameter can be of type function, so use $1, not $1a (so not auto detection of functions) 15369 // This means that {{tmpl foo}} treats foo as a template (which IS a function). 15370 // Explicit parens can be used if foo is a function that returns a template: {{tmpl foo()}}. 15371 }, 15372 "wrap": { 15373 _default: { $2: "null" }, 15374 open: "$item.calls(_,$1,$2);_=[];", 15375 close: "call=$item.calls();_=call._.concat($item.wrap(call,_));" 15376 }, 15377 "each": { 15378 _default: { $2: "$index, $value" }, 15379 open: "if($notnull_1){$.each($1a,function($2){with(this){", 15380 close: "}});}" 15381 }, 15382 "if": { 15383 open: "if(($notnull_1) && $1a){", 15384 close: "}" 15385 }, 15386 "else": { 15387 _default: { $1: "true" }, 15388 open: "}else if(($notnull_1) && $1a){" 15389 }, 15390 "html": { 15391 // Unecoded expression evaluation. 15392 open: "if($notnull_1){_.push($1a);}" 15393 }, 15394 "=": { 15395 // Encoded expression evaluation. Abbreviated form is ${}. 15396 _default: { $1: "$data" }, 15397 open: "if($notnull_1){_.push($.encode($1a));}" 15398 }, 15399 "!": { 15400 // Comment tag. Skipped by parser 15401 open: "" 15402 } 15403 }, 15404 15405 // This stub can be overridden, e.g. in jquery.tmplPlus for providing rendered events 15406 complete: function( items ) { 15407 newTmplItems = {}; 15408 }, 15409 15410 // Call this from code which overrides domManip, or equivalent 15411 // Manage cloning/storing template items etc. 15412 afterManip: function afterManip( elem, fragClone, callback ) { 15413 // Provides cloned fragment ready for fixup prior to and after insertion into DOM 15414 var content = fragClone.nodeType === 11 ? 15415 jQuery.makeArray(fragClone.childNodes) : 15416 fragClone.nodeType === 1 ? [fragClone] : []; 15417 15418 // Return fragment to original caller (e.g. append) for DOM insertion 15419 callback.call( elem, fragClone ); 15420 15421 // Fragment has been inserted:- Add inserted nodes to tmplItem data structure. Replace inserted element annotations by jQuery.data. 15422 storeTmplItems( content ); 15423 cloneIndex++; 15424 } 15425 }); 15426 15427 //========================== Private helper functions, used by code above ========================== 15428 15429 function build( tmplItem, nested, content ) { 15430 // Convert hierarchical content into flat string array 15431 // and finally return array of fragments ready for DOM insertion 15432 var frag, ret = content ? jQuery.map( content, function( item ) { 15433 return (typeof item === "string") ? 15434 // Insert template item annotations, to be converted to jQuery.data( "tmplItem" ) when elems are inserted into DOM. 15435 (tmplItem.key ? item.replace( /(<\w+)(?=[\s>])(?![^>]*_tmplitem)([^>]*)/g, "$1 " + tmplItmAtt + "=\"" + tmplItem.key + "\" $2" ) : item) : 15436 // This is a child template item. Build nested template. 15437 build( item, tmplItem, item._ctnt ); 15438 }) : 15439 // If content is not defined, insert tmplItem directly. Not a template item. May be a string, or a string array, e.g. from {{html $item.html()}}. 15440 tmplItem; 15441 if ( nested ) { 15442 return ret; 15443 } 15444 15445 // top-level template 15446 ret = ret.join(""); 15447
15448 // Support templates which have initial or final text nodes, or consist only of text 15449 // Also support HTML entities within the HTML markup. 15450 ret.replace( /^\s*([^<\s][^<]*)?(<[\w\W]+>)([^>]*[^>\s])?\s*$/, function( all, before, middle, after) { 15451 frag = jQuery( middle ).get(); 15452 15453 storeTmplItems( frag ); 15454 if ( before ) { 15455 frag = unencode( before ).concat(frag); 15456 } 15457 if ( after ) { 15458 frag = frag.concat(unencode( after )); 15459 } 15460 }); 15461 return frag ? frag : unencode( ret ); 15462 } 15463 15464 function unencode( text ) { 15465 // Use createElement, since createTextNode will not render HTML entities correctly 15466 var el = document.createElement( "div" ); 15467 el.innerHTML = text; 15468 return jQuery.makeArray(el.childNodes); 15469 } 15470 15471 // Generate a reusable function that will serve to render a template against data 15472 function buildTmplFn( markup ) { 15473 return new Function("jQuery","$item", 15474 "var $=jQuery,call,_=[],$data=$item.data;" + 15475 15476 // Introduce the data as local variables using with(){} 15477 "with($data){_.push('" + 15478 15479 // Convert the template into pure JavaScript 15480 jQuery.trim(markup) 15481 .replace( /([\\'])/g, "\\$1" ) 15482 .replace( /[\r\t\n]/g, " " ) 15483 .replace( /\$\{([^\}]*)\}/g, "{{= $1}}" ) 15484 .replace( /\{\{(\/?)(\w+|.)(?:\(((?:[^\}]|\}(?!\}))*?)?\))?(?:\s+(.*?)?)?(\(((?:[^\}]|\}(?!\}))*?)\))?\s*\}\}/g, 15485 function( all, slash, type, fnargs, target, parens, args ) { 15486 var tag = jQuery.tmpl.tag[ type ], def, expr, exprAutoFnDetect; 15487 if ( !tag ) { 15488 throw "Template command not found: " + type; 15489 } 15490 def = tag._default || []; 15491 if ( parens && !/\w$/.test(target)) { 15492 target += parens; 15493 parens = ""; 15494 } 15495 if ( target ) { 15496 target = unescape( target ); 15497 args = args ? ("," + unescape( args ) + ")") : (parens ? ")" : ""); 15498 // Support for target being things like a.toLowerCase(); 15499 // In that case don't call with template item as 'this' pointer. Just evaluate... 15500 expr = parens ? (target.indexOf(".") > -1 ? target + parens : ("(" + target + ").call($item" + args)) : target; 15501 exprAutoFnDetect = parens ? expr : "(typeof(" + target + ")==='function'?(" + target + ").call($item):(" + target + "))"; 15502 } else { 15503 exprAutoFnDetect = expr = def.$1 || "null"; 15504 } 15505 fnargs = unescape( fnargs ); 15506 return "');" + 15507 tag[ slash ? "close" : "open" ] 15508 .split( "$notnull_1" ).join( target ? "typeof(" + target + ")!=='undefined' && (" + target + ")!=null" : "true" ) 15509 .split( "$1a" ).join( exprAutoFnDetect ) 15510 .split( "$1" ).join( expr ) 15511 .split( "$2" ).join( fnargs ? 15512 fnargs.replace( /\s*([^\(]+)\s*(\((.*?)\))?/g, function( all, name, parens, params ) { 15513 params = params ? ("," + params + ")") : (parens ? ")" : ""); 15514 return params ? ("(" + name + ").call($item" + params) : all; 15515 }) 15516 : (def.$2||"") 15517 ) + 15518 "_.push('"; 15519 }) + 15520 "');}return _;" 15521 ); 15522 } 15523 function updateWrapped( options, wrapped ) { 15524 // Build the wrapped content. 15525 options._wrap = build( options, true, 15526 // Suport imperative scenario in which options.wrapped can be set to a selector or an HTML string. 15527 jQuery.isArray( wrapped ) ? wrapped : [htmlExpr.test( wrapped ) ? wrapped : jQuery( wrapped ).html()] 15528 ).join(""); 15529 } 15530 15531 function unescape( args ) { 15532 return args ? args.replace( /\\'/g, "'").replace(/\\\\/g, "\\" ) : null; 15533 } 15534 function outerHtml( elem ) { 15535 var div = document.createElement("div"); 15536 div.appendChild( elem.cloneNode(true) ); 15537 return div.innerHTML; 15538 } 15539 15540 // Store template items in jQuery.data(), ensuring a unique tmplItem data data structure for each rendered template instance. 15541 function storeTmplItems( content ) { 15542 var keySuffix = "_" + cloneIndex, elem, elems, newClonedItems = {}, i, l, m; 15543 for ( i = 0, l = content.length; i < l; i++ ) { 15544 if ( (elem = content[i]).nodeType !== 1 ) { 15545 continue; 15546 } 15547 elems = elem.getElementsByTagName("*"); 15548 for ( m = elems.length - 1; m >= 0; m-- ) { 15549 processItemKey( elems[m] ); 15550 } 15551 processItemKey( elem ); 15552 } 15553 function processItemKey( el ) { 15554 var pntKey, pntNode = el, pntItem, tmplItem, key; 15555 // Ensure that each rendered template inserted into the DOM has its own template item, 15556 if ( (key = el.getAttribute( tmplItmAtt ))) { 15557 while ( pntNode.parentNode && (pntNode = pntNode.parentNode).nodeType === 1 && !(pntKey = pntNode.getAttribute( tmplItmAtt ))) { } 15558 if ( pntKey !== key ) { 15559 // The next ancestor with a _tmplitem expando is on a different key than this one. 15560 // So this is a top-level element within this template item 15561 // Set pntNode to the key of the parentNode, or to 0 if pntNode.parentNode is null, or pntNode is a fragment. 15562 pntNode = pntNode.parentNode ? (pntNode.nodeType === 11 ? 0 : (pntNode.getAttribute( tmplItmAtt ) || 0)) : 0; 15563 if ( !(tmplItem = newTmplItems[key]) ) { 15564 // The item is for wrapped content, and was copied from the temporary parent wrappedItem. 15565 tmplItem = wrappedItems[key]; 15566 tmplItem = newTmplItem( tmplItem, newTmplItems[pntNode]||wrappedItems[pntNode], null, true ); 15567 tmplItem.key = ++itemKey; 15568 newTmplItems[itemKey] = tmplItem; 15569 } 15570 if ( cloneIndex ) { 15571 cloneTmplItem( key ); 15572 } 15573 } 15574 el.removeAttribute( tmplItmAtt ); 15575 } else if ( cloneIndex && (tmplItem = jQuery.data( el, "tmplItem" )) ) { 15576 // This was a rendered element, cloned during append or appendTo etc. 15577 // TmplItem stored in jQuery data has already been cloned in cloneCopyEvent. We must replace it with a fresh cloned tmplItem. 15578 cloneTmplItem( tmplItem.key ); 15579 newTmplItems[tmplItem.key] = tmplItem; 15580 pntNode = jQuery.data( el.parentNode, "tmplItem" ); 15581 pntNode = pntNode ? pntNode.key : 0; 15582 } 15583 if ( tmplItem ) { 15584 pntItem = tmplItem; 15585 // Find the template item of the parent element. 15586 // (Using !=, not !==, since pntItem.key is number, and pntNode may be a string) 15587 while ( pntItem && pntItem.key != pntNode ) { 15588 // Add this element as a top-level node for this rendered template item, as well as for any 15589 // ancestor items between this item and the item of its parent element 15590 pntItem.nodes.push( el ); 15591 pntItem = pntItem.parent; 15592 } 15593 // Delete content built during rendering - reduce API surface area and memory use, and avoid exposing of stale data after rendering... 15594 delete tmplItem._ctnt; 15595 delete tmplItem._wrap; 15596 // Store template item as jQuery data on the element 15597 jQuery.data( el, "tmplItem", tmplItem ); 15598 } 15599 function cloneTmplItem( key ) { 15600 key = key + keySuffix; 15601 tmplItem = newClonedItems[key] = 15602 (newClonedItems[key] || newTmplItem( tmplItem, newTmplItems[tmplItem.parent.key + keySuffix] || tmplItem.parent, null, true )); 15603 } 15604 } 15605 } 15606 15607 //---- Helper functions for template item ---- 15608 15609 function tiCalls( content, tmpl, data, options ) { 15610 if ( !content ) { 15611 return stack.pop(); 15612 } 15613 stack.push({ _: content, tmpl: tmpl, item:this, data: data, options: options }); 15614 } 15615 15616 function tiNest( tmpl, data, options ) { 15617 // nested template, using {{tmpl}} tag 15618 return jQuery.tmpl( jQuery.template( tmpl ), data, options, this ); 15619 } 15620 15621 function tiWrap( call, wrapped ) { 15622 // nested template, using {{wrap}} tag 15623 var options = call.options || {}; 15624 options.wrapped = wrapped; 15625 // Apply the template, which may incorporate wrapped content, 15626 return jQuery.tmpl( jQuery.template( call.tmpl ), call.data, options, call.item ); 15627 } 15628 15629 function tiHtml( filter, textOnly ) { 15630 var wrapped = this._wrap; 15631 return jQuery.map( 15632 jQuery( jQuery.isArray( wrapped ) ? wrapped.join("") : wrapped ).filter( filter || "*" ), 15633 function(e) { 15634 return textOnly ? 15635 e.innerText || e.textContent : 15636 e.outerHTML || outerHtml(e); 15637 }); 15638 } 15639 15640 function tiUpdate() { 15641 var coll = this.nodes; 15642 jQuery.tmpl( null, null, null, this).insertBefore( coll[0] ); 15643 jQuery( coll ).remove(); 15644 } 15645})( jQuery ); 15646/*! 15647 * jQuery Mobile 1.4.1 15648 * Git HEAD hash: 18c1e32bfc4e0e92756dedc105d799131607f5bb <> Date: Wed Feb 12 2014 22:15:20 UTC 15649 * http://jquerymobile.com 15650 * 15651 * Copyright 2010, 2014 jQuery Foundation, Inc. and other contributors 15652 * Released under the MIT license. 15653 * http://jquery.org/license 15654 * 15655 */ 15656/*! 15657 * code snippet for just swipe-right and swipe-left 15658 */ 15659(function( $, window, undefined ) { 15660 var $document = $(document), 15661 TouchUtil = xfalib.ut.TouchUtil, 15662 touchStartEvent = TouchUtil.POINTER_DOWN, 15663 touchStopEvent = TouchUtil.POINTER_UP,
15664 touchMoveEvent = TouchUtil.POINTER_MOVE; 15665 15666 function triggerCustomEvent( obj, eventType, event, bubble ) { 15667 var originalType = event.type; 15668 event.type = eventType; 15669 if ( bubble ) { 15670 $.event.trigger( event, undefined, obj ); 15671 } else { 15672 $.event.dispatch.call( obj, event ); 15673 } 15674 event.type = originalType; 15675 } 15676 15677 $.event.special.swipe = { 15678 15679 // More than this horizontal displacement, and we will suppress scrolling. 15680 scrollSupressionThreshold: 30, 15681 15682 // More time than this, and it isn't a swipe. 15683 durationThreshold: 1000, 15684 15685 // Swipe horizontal displacement must be more than this. 15686 horizontalDistanceThreshold: 30, 15687 15688 // Swipe vertical displacement must be less than this. 15689 verticalDistanceThreshold: 30, 15690 15691 getLocation: function ( event ) { 15692 var winPageX = window.pageXOffset, 15693 winPageY = window.pageYOffset, 15694 x = event.clientX || event.originalEvent.clientX, 15695 y = event.clientY || event.originalEvent.clientY; 15696 15697 if ( event.pageY === 0 && Math.floor( y ) > Math.floor( event.pageY ) || 15698 event.pageX === 0 && Math.floor( x ) > Math.floor( event.pageX ) ) { 15699 15700 // iOS4 clientX/clientY have the value that should have been 15701 // in pageX/pageY. While pageX/page/ have the value 0 15702 x = x - winPageX; 15703 y = y - winPageY; 15704 } else if ( y < ( event.pageY - winPageY) || x < ( event.pageX - winPageX ) ) { 15705 15706 // Some Android browsers have totally bogus values for clientX/Y 15707 // when scrolling/zooming a page. Detectable since clientX/clientY 15708 // should never be smaller than pageX/pageY minus page scroll 15709 x = event.pageX - winPageX; 15710 y = event.pageY - winPageY; 15711 } 15712 15713 return { 15714 x: x, 15715 y: y 15716 }; 15717 }, 15718 15719 start: function( event ) { 15720 var data = event.originalEvent.touches ? 15721 event.originalEvent.touches[ 0 ] : event, 15722 location = $.event.special.swipe.getLocation( data ); 15723 return { 15724 time: ( new Date() ).getTime(), 15725 coords: [ location.x, location.y ], 15726 origin: $( event.target ) 15727 }; 15728 }, 15729 15730 stop: function( event ) { 15731 var data = event.originalEvent.touches ? 15732 event.originalEvent.touches[ 0 ] : event, 15733 location = $.event.special.swipe.getLocation( data ); 15734 return { 15735 time: ( new Date() ).getTime(), 15736 coords: [ location.x, location.y ] 15737 }; 15738 }, 15739 15740 handleSwipe: function( start, stop, thisObject, origTarget ) { 15741 if ( stop.time - start.time < $.event.special.swipe.durationThreshold && 15742 Math.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.horizontalDistanceThreshold && 15743 Math.abs( start.coords[ 1 ] - stop.coords[ 1 ] ) < $.event.special.swipe.verticalDistanceThreshold ) { 15744 var direction = start.coords[0] > stop.coords[ 0 ] ? "swipeleft" : "swiperight"; 15745 15746 triggerCustomEvent( thisObject, direction,$.Event( direction, { target: origTarget, swipestart: start, swipestop: stop } ), true ); 15747 return true; 15748 } 15749 return false; 15750 15751 }, 15752 15753 // This serves as a flag to ensure that at most one swipe event event is 15754 // in work at any given time 15755 eventInProgress: false, 15756 15757 setup: function() { 15758 var events, 15759 thisObject = this, 15760 $this = $( thisObject ), 15761 context = {}; 15762 15763 // Retrieve the events data for this element and add the swipe context 15764 events = $.data( this, "mobile-events" ); 15765 if ( !events ) { 15766 events = { length: 0 }; 15767 $.data( this, "mobile-events", events ); 15768 } 15769 events.length++; 15770 events.swipe = context; 15771 15772 context.start = function( event ) { 15773 // If its not a touch event on IE, ignore 15774 if (event.originalEvent.pointerType !== undefined && !(event.originalEvent.pointerType === 2 || event.originalEvent.pointerType === "touch")) { 15775 return; 15776 } 15777 15778 // Bail if we're already working on a swipe event 15779 if ( $.event.special.swipe.eventInProgress ) { 15780 return; 15781 } 15782 $.event.special.swipe.eventInProgress = true; 15783 15784 var stop, 15785 start = $.event.special.swipe.start( event ), 15786 origTarget = event.target, 15787 emitted = false;
15788 15789 context.move = function( event ) { 15790 if ( !start ) { 15791 return; 15792 } 15793 15794 stop = $.event.special.swipe.stop( event ); 15795 if ( !emitted ) { 15796 emitted = $.event.special.swipe.handleSwipe( start, stop, thisObject, origTarget ); 15797 if ( emitted ) { 15798 15799 // Reset the context to make way for the next swipe event 15800 $.event.special.swipe.eventInProgress = false; 15801 } 15802 } 15803 // prevent scrolling 15804 if ( Math.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.scrollSupressionThreshold ) { 15805 event.preventDefault(); 15806 } 15807 }; 15808 15809 context.stop = function() { 15810 emitted = true; 15811 15812 // Reset the context to make way for the next swipe event 15813 $.event.special.swipe.eventInProgress = false; 15814 $document.off( touchMoveEvent, context.move ); 15815 context.move = null; 15816 }; 15817 15818 $document.on( touchMoveEvent, context.move ) 15819 .one( touchStopEvent, context.stop ); 15820 }; 15821 $this.on( touchStartEvent, context.start ); 15822 }, 15823 15824 teardown: function() { 15825 var events, context; 15826 15827 events = $.data( this, "mobile-events" ); 15828 if ( events ) { 15829 context = events.swipe; 15830 delete events.swipe; 15831 events.length--; 15832 if ( events.length === 0 ) { 15833 $.removeData( this, "mobile-events" ); 15834 } 15835 } 15836 15837 if ( context ) { 15838 if ( context.start ) { 15839 $( this ).off( touchStartEvent, context.start ); 15840 } 15841 if ( context.move ) { 15842 $document.off( touchMoveEvent, context.move ); 15843 } 15844 if ( context.stop ) { 15845 $document.off( touchStopEvent, context.stop ); 15846 } 15847 } 15848 } 15849 }; 15850 $.each({ 15851 swipeleft: "swipe", 15852 swiperight: "swipe" 15853 }, function( event, sourceEvent ) { 15854 // Ignoring mouse events, for all browsers except IE 10>, which has pointer events. 15855 if (TouchUtil.POINTER_DOWN !== "mousedown") { 15856 $.event.special[ event ] = { 15857 setup: function() { 15858 $( this ).on( sourceEvent, $.noop ); 15859 }, 15860 teardown: function() { 15861 $( this ).off( sourceEvent ); 15862 } 15863 }; 15864 } 15865 }); 15866 15867})( jQuery, this ); 15868 15869/************************************************************************* 15870 * 15871 * ADOBE CONFIDENTIAL 15872 * __________________ 15873 * 15874 * Copyright 2017 Adobe Systems Incorporated 15875 * All Rights Reserved. 15876 *
15877 * NOTICE: All information contained herein is, and remains 15878 * the property of Adobe Systems Incorporated and its suppliers, 15879 * if any. The intellectual and technical concepts contained 15880 * herein are proprietary to Adobe Systems Incorporated and its 15881 * suppliers and may be covered by U.S. and Foreign Patents, 15882 * patents in process, and are protected by trade secret or copyright law. 15883 * Dissemination of this information or reproduction of this material 15884 * is strictly forbidden unless prior written permission is obtained 15885 * from Adobe Systems Incorporated. 15886 **************************************************************************/ 15887 15888(function (window, $) { 15889 15890 var DefaultPanelProvider = { 15891 15892 /** 15893 * Makes an ajax call and returns an object containing the template json of the template ids 15894 * @returns {Object} 15895 * @param options {Object} This object contains the path, the list of templateIds, and success handler 15896 */ 15897 getMultipleTemplateJson : function (options) { 15898 var externalizedPath = options.path, 15899 listOfTemplateIds = options.listOfTemplateIds; 15900 if (listOfTemplateIds.length > 0) { 15901 $.ajax({ 15902 url : externalizedPath, 15903 type : "GET", 15904 data : { 15905 listOfTemplateIds : JSON.stringify(listOfTemplateIds), 15906 fetchMultipleJson : true 15907 }, 15908 async : false, 15909 success : function (response) { 15910 options.success.call(this, JSON.parse(response.multipleJson)); 15911 }, 15912 error : function (error) { 15913 window.guideBridge._guide().logger().log(error); 15914 } 15915 }); 15916 } 15917 }, 15918 15919 /** 15920 * Makes an ajax call and gets json and html of the lazy loaded panel 15921 * @param options {Object}
15921 This object contains the templateId, fetchJson parameter and fetchHtml parameter. 15922 * These can be set to true or false depending on whether the respective content 15923 * needs to be fetched or not. Options object also contains the success, error, and complete handler as well. 15924 * @returns {JSONObject} The JSON object has two entries, json and html. 15925 */ 15926 getHtmlJson : function (options) { 15927 var ajaxOptions = { 15928 url : options.path, 15929 type : "GET", 15930 async : options.async !== undefined ? options.async : false, 15931 success : options.success, 15932 error : options.error, 15933 complete : options.complete 15934 }; 15935 15936 // Only add data parameters if they are present in options 15937 if (options.templateId || options.fetchJSON || options.fetchHTML) { 15938 ajaxOptions.data = {}; 15939 if (options.templateId) { 15940 ajaxOptions.data.templateId = options.templateId; 15941 } 15942 if (options.fetchJSON) { 15943 ajaxOptions.data.fetchJSON = options.fetchJSON; 15944 } 15945 if (options.fetchHTML) { 15946 ajaxOptions.data.fetchHTML = options.fetchHTML; 15947 } 15948 } 15949 15950 $.ajax(ajaxOptions); 15951 } 15952 }; 15953 15954 window.addEventListener("bridgeInitializeStart", function (evnt) { 15955 var bridge = evnt.detail.guideBridge; 15956 if (bridge) { 15957 bridge.registerPanelProvider(DefaultPanelProvider); 15958 } 15959 }); 15960 15961}(window, $)); 15962 15963// jscs:disable requireDotNotation 15964/************************************************************************* 15965 * 15966 * ADOBE CONFIDENTIAL 15967 * __________________ 15968 * 15969 * Copyright 2014 Adobe Systems Incorporated 15970 * All Rights Reserved. 15971 *
15972 * NOTICE: All information contained herein is, and remains 15973 * the property of Adobe Systems Incorporated and its suppliers, 15974 * if any. The intellectual and technical concepts contained 15975 * herein are proprietary to Adobe Systems Incorporated and its 15976 * suppliers and may be covered by U.S. and Foreign Patents, 15977 * patents in process, and are protected by trade secret or copyright law. 15978 * Dissemination of this information or reproduction of this material 15979 * is strictly forbidden unless prior written permission is obtained 15980 * from Adobe Systems Incorporated. 15981 **************************************************************************/ 15982 15983(function ($, _) { 15984 Function.prototype.bind = Function.prototype.bind || function (ctx) { 15985 var that = this; 15986 return function () { 15987 that.call(ctx, arguments); 15988 }; 15989 }; 15990 15991 var nValidationContext = 0, 15992 /** 15993 * flag to check if adaptive forms is online or not 15994 * @type {boolean} 15995 */ 15996 checkAFOffline = false, 15997 _focusedSubmitButtonModel = null, 15998 sValidationContext = ""; 15999 16000 /** 16001 * Class representing the result of {@link GuideBridge} API. This class provides API to access the result of the 16002 * GuideBridge API and retrieve any error messages the API has thrown. 16003 * @class GuideResultObject 16004 * @docStatus review 2016-05-03 16005 * @since 6.0 16006 */ 16007 var GuideResultObject = function () { 16008 var _message = []; 16009 var _errorCode = []; 16010 var _somExpression = []; 16011 /** 16012 * The value of this property is true if the API succeeded, otherwise false. The 16013 * {@link GuideResultObject#getNextMessage|getNextMessage} API can be used to retrieve the error messages in 16014 * case the value of this property is false. 16015 * @summary whether the API succeeded or failed. 16016 * 16017 * @type {boolean} 16018 * @member errors 16019 * @memberof GuideResultObject 16020 * @instance 16021 * @readonly 16022 * @since 6.0 16023 */ 16024 this.errors = false; 16025 /** 16026 * The type of the data is specific to the API and documentation of that API provides more details about the 16027 * data 16028 * @summary data returned by GuideBridge API 16029 * 16030 * @member {*} data 16031 * @memberof GuideResultObject 16032 * @instance 16033 * @readonly 16034 * @since 6.0 16035 */ 16036 this.data; 16037 16038 /** 16039 * API to add a message in the GuideResultObject 16040 * @private 16041 * @memberof GuideResultObject 16042 * @instance 16043 * @since 6.0 16044 */ 16045 this.addMessage = function (code, msg, som) { 16046 this.errors = true; 16047 _message.push(msg); 16048 _somExpression.push(som); 16049 _errorCode.push(code); 16050 }; 16051 16052 /** 16053 * Error Message returned by GuideBridge API 16054 * @typedef {object} GuideResultObject~ErrorMessage 16055 * @property {number} code Error Code 16056 * @property {?string} somExpression Som Expression of the GuideNode the error is related to. It can be null if 16057 * error is not related to a GuideNode. For example, server failure when submitting the form. 16058 * @property {string} message User friendly message for the error. 16059 * @see GuideNode#somExpression 16060 */ 16061 /** 16062 * When a GuideBridge API fails, it throws an error message. This is indicated by the 16063 * {@link GuideResultObject#errors|errors} property. To get the errors, one has to call this API. The API can throw 16064 * multiple errors and the user has to call this API until it returns null indicating no more errors. 16065 * @summary Returns the error message thrown by the GuideBridge API. 16066 * @function getNextMessage 16067 * @memberof GuideResultObject 16068 * @instance 16069 * @return {GuideResultObject~ErrorMessage} object containing the error message 16070 * @since 6.0 16071 */ 16072 this.getNextMessage = function () { 16073 if (_errorCode.length == 0) { 16074 return null; 16075 } 16076 return { 16077 code : _errorCode.pop(), 16078 somExpression : _somExpression.pop(), 16079 message : _message.pop() 16080 }; 16081 }; 16082 }; 16083 16084 var GUIDE_BRIDGE_VERSION = "1.0"; 16085 /* 16086 * Callback to accept result of asynchronous GuideBridge APIs. 16087 * @callback GuideBridge~AsyncAPIResultCallback 16088 * @param {GuideResultObject}
16088 guideResultObject object containing the result of the API 16089 */ 16090 /* 16091 * Signature of the input to be passed to GuideBridge asynchronous APIs 16092 * @typedef {object} GuideBridge~AsyncAPIInput 16093 * @property {GuideBridge~AsyncAPIResultCallback} [success] callback which receives the result of the API in case of 16094 * success. The argument this callback will recieve will have its {@link GuideResultObject#errors|errors} property 16095 * as false. 16096 * @property {GuideBridge~AsyncAPIResultCallback} [error] callback which receives the result of the API in case of 16097 * failure. The argument this callback will recieve will have its {@link GuideResultObject#errors|errors} property 16098 * as true. 16099 * @param {object} [context] _this_ object inside the _success_ and _error_ callback will point to this 16100 * object 16101 */ 16102 /** 16103 * GuideBridge provides an interface using which, wrapper html (page hosting/embedding adaptive forms) or external 16104 * window scripts like Parent window javascript (in case form is embedded in an iframe), can communicate with 16105 * current Adaptive Form and manipulate or query it's current state. 16106 * 16107 * Some of the use cases for using this API 16108 * * Submit Adaptive Form from a custom button present outside the Form. 16109 * * Get current Adaptive Form state and save it in local storage for restoring it later on. 16110 * * Plugging in custom widgets. 16111 * * Manipulate the Adaptive Form component properties, like value, visibility from outside the Form 16112 * * Listen to bridge events and send data to Analytics server for reporting 16113 * 16114 * ### Accessing the Instance of GuideBridge 16115 * To access the GuideBridge APIs, one needs to get hold of an instance of GuideBridge. The object is 16116 * available on the window after the GuideBridge script is loaded. One can directly access it by using 16117 * `window.guideBridge`. But 16118 * that requires the user script is written after the GuideBridge script is loaded. In certain cases, a user might 16119 * not be 16120 * aware of when their script gets loaded, in those cases the recommended approach is to listen to the 16121 * {@link GuideBridge.event:bridgeInitializeStart|bridgeInitializeStart} event which provides an instance of 16122 * GuideBridge object. 16123 *``` 16124 * window.addEventListener("bridgeInitializeStart", function(evnt) { 16125 * // get hold of the guideBridge object 16126 * var gb = evnt.detail.guideBridge; 16127 * }) 16128 * ``` 16129 * 16130 * **Or**, if you are sure that your script will execute after GuideBridge Script is loaded, then you can directly 16131 * use `window.guideBridge`. In cases like your script is present at the bottom of the page or you are executing on 16132 * jquery dom ready event. 16133 * ``` 16134 * $(function () { 16135 * // one can directly access guideBridge object here. 16136 * window.guideBridge.connect(function () { 16137 * //call guideBridge APIs 16138 * }) 16139 * }) 16140 * ``` 16141 * 16142 * <a name="wait-form-ready"></a> 16143 * ### Wait for Form to get ready 16144 * After getting the GuideBridge object one needs to wait for the Form to get initialized. This can be done by 16145 * providing a callback to the {@link GuideBridge#connect|connect} API 16146 * ``` 16147 * guideBridge.connect(function (){ 16148 * //this callback will be called after adaptive form is initialized 16149 * // do your custom processing 16150 * }) 16151 * ``` 16152 * 16153 * _**Note:** There is no link between Dom ready events and the connect API. If one wants to access the HTML DOM 16154 * from inside the connect callback, the recommended approach is to listen on the jQuery 16155 * [ready](https://api.jquery.com/ready/) event or the native 16156 * [DOMContentLoaded](https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded) event. Similarly if one 16157 * wants to access GuideBridge APIs one needs to wait for the connect callback to get fired._ 16158 * 16159 * <a name="guidebridge-api-usage"></a> 16160 * ### Using the GuideBridge API 16161 * APIs are provided for external applications to connect with Adaptive Form and FormDom. The APIs can be
16162 * loosely divided into two categories, **synchronous** and **asynchronous**. 16163 * 16164 * The synchronous getter API returns a {@link GuideResultObject} which represents the result of the API whereas 16165 * each setter API throws an exception in case of error(s) and it is the responsibility of the API to catch those 16166 * exceptions. The {@link GuideResultObject} either contains error or the return value of the API and provides easy 16167 * mechanism to access each of them. 16168 * 16169 * ``` 16170 * var result = guideBridge.hideGlobalToolbar() 16171 * if (result.errors) { 16172 * console.error("Unable to hide toolbar"); 16173 * var msg = guideResultObject.getNextMessage(); 16174 * while (msg != null) { 16175 * console.error(msg.message); 16176 * msg = guideResultObject.getNextMessage(); 16177 * } 16178 * } else { 16179 * console.log("toolbar hidden successfully"); 16180 * } 16181 * ``` 16182 * 16183 * Each asynchronous API provides callback mechanism to return the result of the API. Each API takes a Javascript 16184 * Object having success and error handlers. The success and error handlers receive {@link GuideResultObject} as input. 16185 * In the success callback, the arguments {@link GuideResultObject#data|data} property is set to the return value 16186 * of the API, while in the error callback the {@link GuideResultObject#errors|errors} property is set to _true_. 16187 * Some APIs might need extra input and that will be defined by the API 16188 * ``` 16189 * guideBridge.getData({ 16190 * success : function (guideResultObject) { 16191 * console.log("data received" + guideResultObject.data); 16192 * } 16193 * error : function (guideResultObject) { 16194 * console.error("API Failed"); 16195 * var msg = guideResultObject.getNextMessage(); 16196 * while (msg != null) { 16197 * console.error(msg.message); 16198 * msg = guideResultObject.getNextMessage(); 16199 * } 16200 * } 16201 * }); 16202 * ``` 16203 * _**Note:** Some APIs do not follow the above norm and it is mentioned in the documentation of that API_ 16204 * 16205 * <a name="guidebridge-events"></a> 16206 * ### GuideBridge Events 16207 * 16208 * GuideBridge API triggers a set of events to notify the current action a user has taken. Developers can listen on 16209 * that event using the {@link GuideBridge#on|on} API and perform some tasks. For example a developer can listen on 16210 * {@link GuideBridge.event:elementFocusChanged|elementFocusChanged} and capture for how long a user spends time 16211 * on that field. All the events triggered by GuideBridge are mentioned below. 16212 * 16213 * GuideBridge provides an event object which contains extra information about the event. For 16214 * example _elementFocusChanged_ event provides information about the previous field that was in focus and the 16215 * current field that came to focus. 16216 * 16217 * The {@link GuideBridge#on|on} API takes a {@link GuideBridge~GuideBridgeEventCallback|GuideBridgeEventCallback} 16218 * as input. The callback is passed two arguments, event and payload where the extra information is passed in the 16219 * payload argument. The documentation of each event lists the values of different properties of the payload 16220 * object. 16221 * 16222 * ``` 16223 * guideBridge.on(eventName, function (event, payload) { 16224 * // access payload properties 16225 * ... 16226 * }) 16227 * ``` 16228 * 16229 * @class GuideBridge 16230 * @docStatus review 2016-05-03 16231 * @since 6.0 16232 */ 16233 var GuideBridge = function () { 16234 this._$target = null; 16235 this._guide = null; 16236 this._guideView = null; 16237 this._version = GUIDE_BRIDGE_VERSION; 16238 this._guideInitHandler = {}; 16239 // _guideModelInitHandler is for internal use only 16240 this._guideModelInitHandler = {}; 16241 $(window).on("guideModelInitialized", this._guideModelInitialized.bind(this)); 16242 $(window).on("guideInitialized", this._guideInitialized.bind(this)); 16243 $(window).on("guideInitializationError", this._guideError); 16244 this.userConfig = {}; 16245 this.panelProvider = null; 16246 // set the host name whether it is client or server, by default it is client 16247 this.hostName = "client"; 16248 }; 16249 16250 var _formInstanceUUID;
16251 var GUIDE_TEMP_STORAGE_PATH = "/tmp/fd/af", 16252 FM_DAM_ROOT = "/content/dam/formsanddocuments/", 16253 FM_AF_ROOT = "/content/forms/af/", 16254 _isAutoSaveEnabled = false, 16255 LOCAL_METADATA_SELECTOR = "local"; 16256 16257 var defaultErrorHandler = function (obj) { 16258 if (typeof(console) == "undefined") { 16259 return; 16260 } 16261 var d = obj.getNextMessage(); 16262 while (d) { 16263 this._guide.logger().log(d.message); 16264 d = obj.getNextMessage(); 16265 } 16266 }; 16267 16268 /** 16269 * 16270 * Default function to check Validations errors after getting the data from the 16271 * server with getDataXML call. 16272 * @private 16273 */ 16274 var defaultValidationChecker = function (validations, obj) { 16275 if (validations && validations.length > 0) { 16276 for (var i = 0; i < validations.length; i++) { 16277 obj.addMessage(0, validations[i], ""); 16278 } 16279 return false; 16280 } 16281 return true; 16282 }; 16283 16284 function getOrElse() { 16285 return xfalib.ut.XfaUtil.prototype.getOrElse.apply(null, arguments); 16286 } 16287 16288 $.extend(GuideBridge.prototype, { 16289 16290 /** 16291 * Dispatched when the instance of GuideBridge is available. The GuideBridge object 16292 * will be passed to the listener and further communication can be done using that object. 16293 * 16294 * _**Note :** bridgeInitializeStart event is dispatched at window_ 16295 * 16296 * @summary Notifies when the instance of GuideBridge is available. 16297 * 16298 * @event bridgeInitializeStart 16299 * @property {Object} detail an object containing guideBridge 16300 * @property {GuideBridge} detail.guideBridge GuideBridge Instance 16301 * @memberof GuideBridge 16302 * @since 6.0 16303 * @example 16304 * window.addEventListener("bridgeInitializeStart", function(evnt) { 16305 * // get hold of the guideBridge object 16306 * var gb = evnt.detail.guideBridge; 16307 * //wait for the completion of adaptive forms 16308 * gb.connect(function (){ 16309 * //this function will be called after adaptive form is initialized 16310 * }) 16311 * }) 16312 */ 16313 GUIDE_BRIDGE_INITIALIZE_START : "bridgeInitializeStart", 16314 16315 /** 16316 * @summary Dispatched when the initialization of Adaptive Form is complete. 16317 * 16318 * @name bridgeInitializeComplete 16319 * @event 16320 * @property {object} payload payload passed to the event listener 16321 * @property {object} payload.target instance of GuideBridge object 16322 * @memberof GuideBridge 16323 * @deprecated since 6.3 this event is deprecated. Please use {@link GuideBridge#connect|connect} API 16324 * @since 6.0 16325 * @example 16326 * guideBridge.on("bridgeInitializeComplete" , function(event, payload) { 16327 * var gb = payload.target; 16328 * assert(gb === guideBridge) 16329 * } 16330 */ 16331 GUIDE_BRIDGE_INITIALIZE_COMPLETE : "bridgeInitializeComplete", 16332 16333 /** 16334 * @summary Dispatched when visibility of any Adaptive Form component(Panel or Field) changes. 16335 * @name elementVisibleChanged 16336 * @event 16337 * @property {object} payload payload containing more information about the event 16338 * @property {Scriptable} payload.target Adaptive Form component whose {@link Scriptable#visible|visible} property has 16339 * changed. 16340 * @property {boolean} payload.oldText old value of the visible property 16341 * @property {boolean} payload.newText new value of the visible property 16342 * @memberof GuideBridge 16343 * @since 6.0 16344 * @example 16345 * guideBridge.on("elementVisibleChanged" , function(event, payload) { 16346 * var component = payload.target; // scripting model of the component whose visibility has changed 16347 * var newValue = payload.newText; 16348 * if (newValue) { 16349 * console.log(component.name + " is visible now"; 16350 * } else { 16351 * console.log(component.name + " is hidden now"; 16352 * } 16353 * } 16354 * 16355 */ 16356 GUIDE_ELEMENT_VISIBLE_CHANGED : "elementVisibleChanged", 16357 16358 /** 16359 * @summary Dispatched when any Adaptive Form component is enabled/disabled, i.e. 16360 * {@link Scriptable#enabled|enabled} property of a component changes. 16361 * @name elementEnableChanged 16362 * @event 16363 * @property {object} payload payload containing more information about the event 16364 * @property {Scriptable} payload.target component whose {@link Scriptable#enabled|enabled} property has changed 16365 * @property {boolean} payload.oldText old value of the enabled property 16366 * @property {boolean} payload.newText new value of the enabled property 16367 * @memberof GuideBridge 16368 * @since 6.0 16369 * @example 16370 * guideBridge.on("elementEnableChanged" , function(event, payload) { 16371 * var component = payload.target; // scripting model of the component whose enabled property has changed 16372 * var newValue = payload.newText; 16373 * if (newValue) { 16374 * console.log(component.name + " is enabled now"; 16375 * } else { 16376 * console.log(component.name + " is disabled now"; 16377 * } 16378 * } 16379 */ 16380 GUIDE_ELEMENT_ENABLE_CHANGED : "elementEnableChanged", 16381 16382 /** 16383 * @summary Dispatched when value of any Field changes. 16384 * @name elementValueChanged 16385 * @event 16386 * @property {object} payload payload containing more information about the event 16387 * @property {Field} payload.target Field whose {@link Field#value|value} has changed 16388 * @property {string|number} payload.oldText old value of the Field 16389 * @property {string|number} payload.newText new value of the Field 16390 * @memberof GuideBridge 16391 * @since 6.0 16392 * @example 16393 * guideBridge.on("elementValueChanged" , function(event, payload) { 16394 * var component = payload.target; // Field whose value has changed 16395 * console.log("Value of component " + component.name + " was " + payload.oldText); 16396 * console.log("Value of component " + component.name + " is " + payload.newText); 16397 * } 16398 */ 16399 GUIDE_ELEMENT_VALUE_CHANGED : "elementValueChanged", 16400 16401 /** 16402 * In layouts like Wizard or Tabbed layout, when a user navigates from one tab to another, this event is 16403 * triggered 16404 * @summary Event to notify that the user has navigated from one Panel to another. 16405 * 16406 * @name elementNavigationChanged 16407 * @event 16408 * @property {object} payload payload containing more information about the event 16409 * @property {Panel} payload.target Panel to which the user moved to 16410 * @property {string} payload.prevText SomExpression of the panel from which user moved 16411 * @property {string} payload.newText SomExpression of the panel to which user moved 16412 * @memberof GuideBridge 16413 * @see GuideNode#somExpression 16414 * @since 6.0 16415 * @example 16416 * guideBridge.on("elementNavigationChanged" , function(event, payload) { 16417 * var component = payload.target;
16418 * console.log("old panel's SOM Expression: " + payload.oldText); 16419 * console.log("new panel's SOM Expression: " + payload.newText); 16420 * } 16421 */ 16422 GUIDE_ELEMENT_NAVIGATION_CHANGED : "elementNavigationChanged", 16423 16424 /** 16425 * @summary Dispatched whenever a Field/Panel gets Focus 16426 * @name elementFocusChanged 16427 * @event 16428 * @property {object} payload payload containing more information about the event 16429 * @property {Panel|Field} payload.target new focused component 16430 * @property {string} oldText SOM Expression of component that was previously in focus or null 16431 * @property {string} newText SOM Expression of the component that is currently in focus or null 16432 * @memberof GuideBridge 16433 * @see GuideNode#somExpression 16434 * @see {@link GuideBridge#setFocus|setFocus API} 16435 * @since 6.0 16436 * @example 16437 * guideBridge.on("elementFocusChanged" , function(event, payload) { 16438 * var component = payload.target; 16439 * console.log("old elements's SOM Expression: " + payload.oldText); 16440 * console.log("new elements's SOM Expression: " + payload.newText); 16441 * } 16442 */ 16443 GUIDE_ELEMENT_FOCUS_CHANGED : "elementFocusChanged", 16444 16445 /** 16446 * @summary Dispatched when a user looks at the help description of any Adaptive Form component(Panel or field) 16447 * @name elementHelpShown 16448 * @event 16449 * @property {object} payload payload containing more information about the event 16450 * @property {Panel|Field} payload.target component whose help is being shown 16451 * @property {string} payload._property what kind of help is being shown. The value can be 16452 * * shortDescription (if Short Description becomes visible) 16453 * * longDescription (if Long Description becomes visible) 16454 * @property {string} payload.prevText empty string 16455 * @property {object} payload.newText object containing the help content 16456 * @property {string} payload.newText.help help content of the component 16457 * @memberof GuideBridge 16458 * @since 6.0 16459 * @see {@link https://helpx.adobe.com/aem-forms/6-1/authoring-in-field-help.html|Help Description in Adaptive Form} 16460 * @example 16461 * guideBridge.on("elementHelpShown" , function(event, payload) { 16462 * var component = payload.target; 16463 * console.log("component whose help is shown " + payload.target.name); 16464 * console.log("Help shown: " + payload._property); 16465 * console.log("Help Content: " + payload.newText.help); 16466 * } 16467 */ 16468 GUIDE_ELEMENT_HELP_SHOWN : "elementHelpShown", 16469 16470 /** 16471 * @summary Dispatched when validity of a Field changes. 16472 * @name elementValidationStatusChanged 16473 * @event 16474 * @property {object} payload payload containing more information about the event 16475 * @property {Field} payload.target Field which either became valid/invalid 16476 * @property {boolean} payload.prevText old validation status 16477 * @property {boolean} payload.newText new validation status 16478 * @memberof GuideBridge 16479 * @see Field#validate 16480 * @see Field#validationState 16481 * @since 6.0 16482 * @example 16483 * guideBridge.on("elementValidationStatusChanged" , function(event, payload) { 16484 * var component = payload.target; 16485 * if (payload.prevText) { 16486 * console.log("component became invalid" ); 16487 * } else { 16488 * console.log("component became valid" ); 16489 * } 16490 * } 16491 */ 16492 GUIDE_ELEMENT_VALIDATION_STATUS_CHANGED : "elementValidationStatusChanged", 16493 16494 /** 16495 * Developers must not modify the Form Fields inside the listener. This is mostly use to update the UI outside 16496 * the Form or capture some data for analytics. If you want to modify form field value on the click of a button 16497 * please use the [Click Expression](https://helpx.adobe.com/aem-forms/6-1/adaptive-form-expressions.html#main-pars_header_6) 16498 * provided in the Forms Authoring. 16499 * 16500 * @summary Dispatched when a Button component is clicked. 16501 * 16502 * @name elementButtonClicked 16503 * @event 16504 * @property {object} payload payload containing more information about the event 16505 * @property {Button} payload.target Button which was clicked 16506 * @memberof GuideBridge 16507 * @since 6.0 16508 * @see {@link https://helpx.adobe.com/aem-forms/6-1/adaptive-form-expressions.html#main-pars_header_6|Click Expression in Buttons} 16509 * @example 16510 * guideBridge.on("elementButtonClicked" , function(event, payload) { 16511 * var component = payload.target; // Button which wass clicked 16512 * console.log("Button which was clicked " + component.name); 16513 * } 16514 */ 16515 GUIDE_ELEMENT_BUTTON_CLICKED : "elementButtonClicked", 16516 16517 /** 16518 * Whenever the full form validations are run via the {@link GuideBridge#validate|val
16518idate} API, this event is triggered. 16519 * @summary Dispatched when the validation of all the Adaptive Form fields are completed. 16520 * 16521 * @name validationComplete 16522 * @event 16523 * @property {object} payload payload containing more information about the event 16524 * @property {GuideContainerNode} payload.target root Node of the Adaptive Form 16525 * @property {boolean} payload.prevText result of running the validation. true if validations are successful, 16526 * false otherwise 16527 * @property {Field~ValidationError[]} payload.newText List of objects containing error messages. 16528 * @memberof GuideBridge 16529 * @since 6.0 16530 * @example 16531 * guideBridge.on("validationComplete" , function(event, payload) { 16532 * if (payload.prevText) { 16533 * console.log("validation success"); 16534 * } else { 16535 * console.log("validation failure"); 16536 * if (payload.newText.length) { 16537 * payload.newText.forEach(function (error) { 16538 * console.log("validation failed for " + error.som + " with message " + error.errorText); 16539 * }) 16540 * } 16541 * } 16542 * } 16543 */ 16544 GUIDE_VALIDATION_COMPLETE : "validationComplete", 16545 16546 /** 16547 * Adaptive Form can be configured to be saved automatically at regular intervals. This can be controlled 16548 * dynamically based on the values filled in the Form. Authors can write custom scripts which can enable/disable 16549 * auto save functionality dynamically 16550 * @summary Dispatched when auto save gets enabled in the Form 16551 * @name guideAutoSaveStart 16552 * @event 16553 * @property {object} payload payload containing more information about the event 16554 * @property {GuideContainerNode} payload.target root Node of the Adaptive Form 16555 * @memberof GuideBridge 16556 * @since 6.1 16557 * @see {@link https://helpx.adobe.com/aem-forms/6-1/auto-save-an-adaptive-form.html|Auto Save an Adaptive Form} 16558 * @example 16559 * guideBridge.on("guideAutoSaveStart" , function(event, payload) { 16560 * console.log("Forms is now being saved as draft automatically"); 16561 * } 16562 */ 16563 GUIDE_AUTO_SAVE_START : "guideAutoSaveStart", 16564 16565 /** 16566 * @summary Dispatched when save of adaptive form data has started 16567 * @name saveStarted 16568 * @event 16569 * @memberof GuideBridge 16570 * @since 6.1 16571 * @example 16572 * guideBridge.on("saveStarted" , function(event) { 16573 * console.log("Save of Adaptive Form data is about to start"); 16574 * } 16575 */ 16576 GUIDE_SAVE_START : "saveStarted", 16577 16578 /** 16579 * @summary Dispatched when save of adaptive form data is completed 16580 * @name saveCompleted 16581 * @event 16582 * @memberof GuideBridge 16583 * @since 6.1 16584 * @example 16585 * guideBridge.on("saveCompleted" , function(event) { 16586 * console.log("Save of Adaptive Form data is completed"); 16587 * } 16588 */ 16589 GUIDE_SAVE_COMPLETED : "saveCompleted", 16590 16591 /** 16592 * Users can add some pre submit code in the listener to this event. 16593 * @summary Dispatched when the user clicks on the submit button 16594 * @name submitStart 16595 * @event 16596 * @memberof GuideBridge 16597 * @since 6.0 16598 * @example 16599 * guideBridge.on("submitStart" , function(event) { 16600 * // do some pre submit processing 16601 * } 16602 */ 16603 GUIDE_SUBMIT_START : "submitStart", 16604 GUIDE_PATH : "guidePath", 16605 GUIDE_NAME : "guideName", 16606 GUIDE_DESC : "guideDesc", 16607 GUIDE_TYPE : "guideType", 16608 16609 /** 16610 * @summary Dispatched when an Adaptive Form fragment is lazily loaded successfully 16611 * @name elementLazyLoaded 16612 * @property {object} payload payload containing more information about the event 16613 * @property {Panel} payload.target Adaptive Form Fragment which is lazily loaded 16614 * @event 16615 * @memberof GuideBridge 16616 * @since 6.1 FP1 16617 * @see {@link https://helpx.adobe.com/aem-forms/6-1/lazy-loading-adaptive-forms.html|Lazy Loading Adaptive Form} 16618 * @example 16619 * guideBridge.on("elementLazyLoaded" , function(event, payload) { 16620 * var component = payload.target; 16621 * console.log("Panel " + component.name + " loaded"); 16622 * } 16623 */ 16624 GUIDE_ELEMENT_LAZY_LOADED : "elementLazyLoaded", 16625 16626 /** 16627 * All GuideBridge APIs (except {@link GuideBridge#connect|connect}) require Adaptive Form to be initialized. 16628 * Checking the return value of this API is not necessary if guideBridge API is called only after the 16629 * <a href="#wait-form-ready">Form is initialized</a> 16630 * @summary Whether the Adaptive Form has been initialized or not 16631 * 16632 * @method 16633 * @memberof GuideBridge 16634 * @returns {boolean} true if the Adaptive Form is ready for interaction, false otherwise 16635 * @since 6.0 16636 * @instance 16637 */ 16638 isConnected : function () { 16639 if (this._guide) { 16640 return true; 16641 } 16642 return false;
16643 }, 16644 16645 /** 16646 * Specify a callback function which is called/notified when Adaptive Form gets initialized. After Adaptive 16647 * Form is initialized GuideBridge is ready for interaction and one can call any API. 16648 * 16649 * The callback can also be registered after the Form gets initialized. In that case, the callback will be 16650 * called immediately. 16651 * 16652 * @summary Register a callback to be executed when the Adaptive Form gets initialized 16653 * @param handler {function} function that would be called when guideBridge is ready for interaction. The 16654 * signature of the callback should be 16655 * ``` 16656 * function() { 16657 * // app specific code here 16658 * } 16659 * ``` 16660 * @param {object} [context] _this_ object in the callback function will point to context 16661 * @since 6.0 16662 * @instance 16663 * @method 16664 * @memberof GuideBridge 16665 * @example 16666 * guideBridge.connect(function() { 16667 * console.log("Hurrah! Guide Bridge Activated"); 16668 * }) 16669 */ 16670 connect : function (handler, context) { 16671 context = context || guideBridge; 16672 if (this.isConnected()) { 16673 // handle exceptions gracefully since it executes in our thread 16674 try { 16675 handler.call(context); 16676 } catch (exception) { 16677 // guide model should be initialized in bridge in connect, still adding a null check 16678 if (this._guide) { 16679 this._guide.logger().log(exception); 16680 } 16681 } 16682 } else { 16683 this._guideInitHandler.handler = this._guideInitHandler.handler || []; 16684 this._guideInitHandler.handler.push(handler); 16685 this._guideInitHandler.context = this._guideInitHandler.context || []; 16686 this._guideInitHandler.context.push(context); 16687 } 16688 }, 16689 16690 _viewConnect : function (handler, context) { 16691 // ideally connect should do this but not changing the original function 16692 if (this._guideView && this._guide) { 16693 try { 16694 handler.call(context); 16695 } catch (exception) { 16696 // guide model should be initialized in bridge in connect, still adding a null check 16697 if (this._guide) { 16698 this._guide.logger().log(exception); 16699 } 16700 } 16701 } else { 16702 this._guideInitHandler.handler = this._guideInitHandler.handler || []; 16703 this._guideInitHandler.handler.push(handler); 16704 this._guideInitHandler.context = this._guideInitHandler.context || []; 16705 this._guideInitHandler.context.push(context); 16706 } 16707 }, 16708 16709 /** 16710 * @private 16711 * @since 6.5 16712 */ 16713 _modelConnect : function (handler, context) { 16714 context = context || guideBridge; 16715 if (this.isConnected()) { 16716 // handle exceptions gracefully since it executes in our thread 16717 try { 16718 handler.call(context); 16719 } catch (exception) { 16720 // guide model should be initialized in bridge in connect, still adding a null check 16721 if (this._guide) { 16722 this._guide.logger().log(exception); 16723 } 16724 } 16725 } else { 16726 this._guideModelInitHandler.handler = this._guideModelInitHandler.handler || []; 16727 this._guideModelInitHandler.handler.push(handler); 16728 this._guideModelInitHandler.context = this._guideModelInitHandler.context || []; 16729 this._guideModelInitHandler.context.push(context); 16730 } 16731 }, 16732 16733 _guideModelInitialized : function (e) { 16734 this._guide = e.guide; 16735 if (this._guideModelInitHandler.handler) { 16736 for (var i = 0; i < this._guideModelInitHandler.handler.length; i++) { 16737 try { 16738 this._guideModelInitHandler.handler[i].call(this._guideModelInitHandler.context[i]); 16739 } catch (exception) { 16740 // guide model should be initialized in bridge in connect, still adding a null check 16741 if (this._guide) { 16742 this._guide.logger().log(exception); 16743 } 16744 } 16745 } 16746 } 16747 }, 16748 16749 /* 16750 * 16751 * Handler for guideInitialized event which is fired by Adaptive Form library after Adaptive Form Dom is initialized 16752 * 16753 * @private 16754 */ 16755 _guideInitialized : function (e) { 16756 if (this._guideInitHandler.handler) { 16757 for (var i = 0; i < this._guideInitHandler.handler.length; i++) { 16758 try { 16759 this._guideInitHandler.handler[i].call(this._guideInitHandler.context[i]); 16760 } catch (exception) { 16761 // guide model should be initialized in bridge in connect, still adding a null check 16762 if (this._guide) { 16763 this._guide.logger().log(exception); 16764 } 16765 } 16766 } 16767 } 16768 window.guideBridge.trigger("bridgeInitializeComplete", 16769 guidelib.event.GuideModelEvent.createEvent( 16770 "bridgeInitializeComplete", 16771 guideBridge 16772 ) 16773 ); 16774 }, 16775 _setGuideView : function (guideView) { 16776 this._guideView = guideView; 16777 }, 16778 _guideError : function (e) { 16779 this._guide.logger().debug("AF", e); 16780 }, 16781 _checkGuide : function (obj) { 16782 if (!this._guide) { 16783 obj.addMessage(1, "Guide Dom not Initialized", ""); 16784 return false;
16785 } 16786 return true; 16787 }, 16788 /** 16789 * @summary returns the version of GuideBridge library 16790 * @returns {string} the version of the GuideBridge library 16791 * @method getBridgeVersion 16792 * @memberof GuideBridge 16793 * @instance 16794 * @since 6.0 16795 */ 16796 getBridgeVersion : function () { 16797 return this._version; 16798 }, 16799 16800 /** 16801 * Callback to execute when bridgeInitializeStart is triggered. 16802 * @callback GuideBridge~postExternalCallback 16803 * @param {string} name constant string `bridgeInitializeStart` 16804 * @param {object} data object containing the GuideBridge instance 16805 * @param {GuideBridge} data.guideBridge instance of GuideBridge 16806 * @since 6.0 16807 * @deprecated since 6.3 this callback is deprecated. One must do the handling in 16808 * {@link GuideBridge.events:bridgeInitializeStart} event 16809 * @memberof GuideBridge 16810 * @see GuideBridge#registerConfig 16811 * @see GuideBridge~postExternalMessageConfig 16812 */ 16813 /** 16814 * @typedef {object} GuideBridge~postExternalMessageConfig 16815 * @property {GuideBridge~postExternalCallback} postExternalHandler callback to be executed when GuideBridge 16816 * instance is available 16817 * @since 6.0 16818 * @deprecated since 6.3 this configuration is deprecated. One must do the handling in 16819 * {@link GuideBridge.events:bridgeInitializeStart} event 16820 * @memberof GuideBridge 16821 * @see GuideBridge#registerConfig 16822 */ 16823 /** 16824 * @typedef {object} GuideBridge~submitConfig 16825 * @property {HTMLFormElement} form During submission Adaptive Form creates a new HTMLFormElement and puts all the 16826 * value in that Form. One can provide an existing HTMLFormElement that will be reused for submitting the Form. The 16827 * action and method property of the Form element will be ignored. 16828 * @property {boolean} useAjax submit the form via a XMLHttpRequest rather than using a HTMLFormElement 16829 * instance is available 16830 * @property {function} submitSuccessHandler success Handler to be called post submission. This option is ignored 16831 * if _useAjax_ is set to false 16832 * @since 6.0 16833 * @memberof GuideBridge 16834 * @see GuideBridge#registerConfig 16835 */ 16836 /** 16837 * @typedef {object} GuideBridge~renderConfig 16838 * @property {boolean} enableFocusOnFirstField option to enable focus on first field. Default value is true. 16839 * @since 6.5 16840 * @memberof GuideBridge 16841 * @see GuideBridge#registerConfig 16842 */ 16843 /** 16844 * Adaptive Form uses some default named configurations to provide its default behaviour. This configurations 16845 * can be modified by providing a new configuration. 16846 * 16847 * The API accepts the name of the configuration and updated configuration. Based on value of the new 16848 * configuration the behaviour of the Form gets changed. 16849 * Currently supported configurations are: 16850 * #### postExternalMessageConfig 16851 * 16852 * <div class="deprecated"><span class="deprecated-heading">Deprecated :</span><span> since 6.2 this 16853 * configuration is deprecated. Use the {@link GuideBridge.events:bridgeInitializeStart} event to do the same 16854 * handling</span> 16855 * </div> 16856 * In case Adaptive Form is embedded inside an iframe, this configuration allows developers to provide 16857 * GuideBridge Instance to parent or child windows.
16858 * 16859 * By default, GuideBridge instance is only available to the current window and to the parent window if it 16860 * doesn't violate the cross-origin policy. Now there may be a case when this doesn't solves the problem, then 16861 * one can take advantage of this configuration to extend this functionality. 16862 * 16863 * For the signature of the configuration see 16864 * {@link GuideBridge~postExternalMessageConfig|postExternalMessageConfig} 16865 * ##### Example 16866 * To provide the GuideBridge instance to a child window 16867 * ``` 16868 * window.on("bridgeInitializeStart", function (evnt) { 16869 * var gb = evnt.detail.guideBridge; 16870 * gb.registerConfig("postExternalMessageConfig", { 16871 * "postExternalHandler" : function(data) { 16872 * // assume we have a child window with an id 'childWindowId' 16873 * var childWindow = document.getElementById("#childWindowId").contentWindow; 16874 * var tmpEvent = document.createEvent("CustomEvent"); 16875 * tmpEvent.initCustomEvent(data.name, true, true, data.data); 16876 * childWindow.dispatchEvent(tmpEvent); 16877 * } 16878 * }); 16879 * }); 16880 * ``` 16881 * #### widgetConfig 16882 * The configuration is used to modify the appearance of a specific Field. Adaptive Form allows developers to 16883 * [create custom widgets](http://helpx.adobe.com/aem-forms/6-1/custom-appearance-widget-adaptive-form.html) and 16884 * use them in their Forms. 16885 * 16886 * The signature of the config is 16887 * ``` 16888 * { "<component-identifier> : "<widget-name>"} 16889 * ``` 16890 * where `<component-identifier>` can be either the name or classname of Adaptive Form Field, 16891 * while widget name is the name of the jQuery Widget. 16892 * 16893 * #### submitConfig 16894 * To modify the default submit behaviour one can provide this configuration. The signature of the config is 16895 * defined {@link GuideBridge~submitConfig|below} 16896 * ``` 16897 * guideBridge.registerConfig("submitConfig", {"useAjax" : true}); 16898 * ``` 16899 * 16900 * #### renderConfig 16901 * To modify the default render behaviour one can provide this configuration. The signature of the config is 16902 * defined {@link GuideBridge~renderConfig|below} 16903 * ``` 16904 * guideBridge.registerConfig("renderConfig", {"enableFocusOnFirstField" : false}); 16905 * ``` 16906 * @summary Registers user/portal specific configurations to GuideBridge 16907 * @returns {GuideResultObject} {@link GuideResultObject} with {@link GuideResultObject#data|data} having the 16908 * old configuration against the same _key_ 16909 * 16910 * @param key {string} configuration name. one of the following 16911 * * postExternalMessageConfig 16912 * * widgetConfig 16913 * * submitConfig 16914 * * renderConfig 16915 * @param {widgetConfig|GuideBridge~submitConfig|GuideBridge~renderConfig|GuideBridge~postExternalMessageConfig} [config] configuration object for the configuration 16916 * @method 16917 * @memberof GuideBridge 16918 * @since 6.0 16919 * @instance 16920 */ 16921 registerConfig : function (key, config) { 16922 var obj = new GuideResultObject(); 16923 obj.data = this.userConfig[key]; 16924 this.userConfig[key] = config; 16925 obj.completed = true; 16926 return obj; 16927 }, 16928 16929 /** 16930 * Their exists a customPropertyMap which can be set from the server. For prefilling files 16931 * fileAttachmentMap key should be present in the map. 16932 * @name customContextProperty 16933 * @param value {object} object to be replaced with the current customPropertyMap. 16934 * @memberof GuideBridge 16935 * @method 16936 * since 6.0 16937 */ 16938 16939 /** 16940 * Their exists a customPropertyMap which can be set from the server. For prefilling files 16941 * fileAttachmentMap key should be present in the map. 16942 * @name customContextProperty 16943 * @param property {string} object to be replaced with the current customPropertyMap. 16944 * @method 16945 * @memberof GuideBridge 16946 * since 6.0 16947 */ 16948 16949 /** 16950 * Their exists a customPropertyMap which can be set from the server. For prefilling files 16951 * fileAttachmentMap key should be present in the map. 16952 * @param property {string} property to update in the custom property map 16953 * @param value {*} value of the property 16954 * @return {*} old value of the property 16955 * since 6.0 16956 */ 16957 customContextProperty : function (property, value) { 16958 var customPropertyMap = getOrElse(guidelib, "__runtime__.guideContext.customPropertyMap", {}); 16959 // use both the customContextProperty map since customers also access that 16960 var newCustomPropertyMap = _.extend({}, customPropertyMap, getOrElse(this._guide, "runtime.guideContext.customPropertyMap", {})); 16961 if (_.isUndefined(value)) { 16962 if (_.isObject(property)) { 16963 guideBridge._modelConnect((function (newCustomPropertyMap, property) { 16964 return function () { 16965 var localMap = _.extend({}, guideBridge._guide.runtime.guideContext.customPropertyMap, newCustomPropertyMap); 16966 _.extend(localMap, property); 16967 guideBridge._guide.runtime.guideContext.customPropertyMap = localMap; 16968 }; 16969 })(newCustomPropertyMap, property)); 16970 } else { 16971 return newCustomPropertyMap[property]; 16972 } 16973 } else { 16974 var oldValue = newCustomPropertyMap[property]; 16975 guideBridge._modelConnect((function (property, value, newCustomPropertyMap) { 16976 return function () { 16977 var localMap = _.extend({}, guideBridge._guide.runtime.guideContext.customPropertyMap, newCustomPropertyMap); 16978 localMap[property] = value; 16979 guideBridge._guide.runtime.guideContext.customPropertyMap = localMap; 16980 }; 16981 })(property, value, newCustomPropertyMap)); 16982 return oldValue; 16983 } 16984 }, 16985 16986 getNavigablePanel : function (somExpression) { 16987 return this._guideView.getSomOnNavigableAncestor(somExpression); 16988 }, 16989 16990 /** 16991 * Sets the value of a property for a set of {@link GuideNode} to a different value. Property must be a valid 16992 * writable property for that Node 16993 * 16994 * Each entry in _somList_ should have a corresponding entry in the _valueList_. Mismatch in the length of these
16995 * two arguments will make the function do nothing 16996 * @summary Modify a property for a set of Nodes 16997 * @method setProperty 16998 * @param {string[]} somList an array having someExpression for the nodes. Invalid SomExpressions and 16999 * the corresponding value in the _valueList_ are ignored. 17000 * @param {string} propertyName name of the property which has to be modified 17001 * @param {Array.<*>} valueList an array containing value of the _propertyName_ for each element in _somList_ 17002 * 17003 * @memberof GuideBridge 17004 * @instance 17005 * @since 6.0 17006 * @see GuideNode#somExpression 17007 * @example <caption>Modifying the value of a set of fields</caption> 17008 * guideBridge.setProperty(["SOM_OF_FIELD_1", "SOM_OF_FIELD_2"...... "SOM_OF_FIELD_N"] 17009 * "value" 17010 * [VALUE_1, VALUE_2 .... VALUE_N]); 17011 * @example <caption>Hiding a single field</caption> 17012 * guideBridge.setProperty(["SOM_OF_FIELD_1"] 17013 * "visibility" 17014 * [false]); 17015 */ 17016 setProperty : function (somList, propertyName, valueList) { 17017 if (!propertyName) { 17018 return; 17019 } 17020 if (!_.isArray(somList) || !_.isArray(valueList)) { 17021 return; 17022 } 17023 if (somList.length !== valueList.length) { 17024 return; 17025 } 17026 var gb = this; 17027 _.each(somList, function (som, index) { 17028 var node = gb.resolveNode(som); 17029 if (node) { 17030 node[propertyName] = valueList[index]; 17031 } else { 17032 gb._guide.logger().log("som not valid:" + som); 17033 } 17034 }); 17035 if (!this._guide._currentContext) { 17036 this._guide.runPendingExpressions(); 17037 } 17038 }, 17039 17040 /** 17041 * Used to retrieve the Form data as XML. The API gets the data xml synchronously/asynchronously based on the 17042 * _async_ option and invokes the success/error handlers passed in the arguments upon completion. 17043 * 17044 * In the success callback the {@link GuideResultObject#data|data} parameter contains the xml string. 17045 * 17046 * The success and error handlers receive {@link GuideResultObject} as input. 17047 * @summary Return Form data as XML. 17048 * 17049 * @param {object} options input to the getDataXML API 17050 * @param {function} [options.success] callback which receives the result of the API 17051 * in case of success. 17052 * @param {function} [options.error] callback which receives the result of the API in 17053 * case of failure. 17054 * {@link GuideResultObject#errors|errors} property as true. 17055 * @param {object} [options.context] _this_ object inside the _success_ and _error_ callback will point to this 17056 * object 17057 * @param {boolean} [options.async=true] whether to make the server call asynchronously or not. If false, the 17058 * browser will wait for the server to return the XML and then execute the success or error callbacks object 17059 * @see <a href="#guidebridge-api-usage" >GuideBridge API Usage</a> 17060 * @method 17061 * @memberof GuideBridge 17062 * @since 6.0 17063 * @instance 17064 * @example 17065 * guideBridge.getDataXML({ 17066 * success : function (guideResultObject) { 17067 * console.log("xml data received" + guideResultObject.data); 17068 * } 17069 * error : function (guideResultObject) { 17070 * console.error("API Failed"); 17071 * var msg = guideResultObject.getNextMessage(); 17072 * while (msg != null) { 17073 * console.error(msg.message); 17074 * msg = guideResultObject.getNextMessage(); 17075 * } 17076 * } 17077 * }); 17078 * 17079 * @deprecated since 6.3 this API is deprecated. Use getData API instead. 17080 * @param options 17081 */ 17082 getDataXML : function (options) { 17083 guideBridge.getData(options); 17084 }, 17085 17086 /** 17087 * Used to retrieve the Form data as XML or JSON depending on the Schema Type. Only for JSON Schema based Forms 17088 * and Form Data Model based forms, the data will be in JSON format while for others, the data will be in XML format. 17089 * The API gets the data synchronously/asynchronously based on the 17090 * _async_ option and invokes the success/error handlers passed in the arguments upon completion. 17091 * 17092 * In the success callback the {@link GuideResultObject#data|data} parameter contains the data string. 17093 * 17094 * The success and error handlers receive {@link GuideResultObject} as input. 17095 * @summary Return Form data as XML or JSON depending on the Schema Type. 17096 * 17097 * @param {object} options input to the getData API 17098 * @param {function} [options.success] callback which receives the result of the API 17099 * in case of success. 17100 * @param {function} [options.error] callback which receives the result of the API in 17101 * case of failure. 17102 * {@link GuideResultObject#errors|errors} property as true. 17103 * @param {object} [options.context] _this_ object inside the _success_ and _error_ callback will point to this 17104 * object 17105 * @param {boolean} [options.async=true] whether to make the server call asynchronously or not. If false, the 17106 * browser will wait for the server to return the data (XML or JSON) and then execute the success or error callbacks object 17107 * @see <a href="#guidebridge-api-usage" >GuideBridge API Usage</a> 17108 * @method 17109 * @memberof GuideBridge 17110 * @since 6.3 17111 * @instance 17112 * @example 17113 * guideBridge.getData({ 17114 * success : function (guideResultObject) { 17115 * console.log("data received" + guideResultObject.data); 17116 * } 17117 * error : function (guideResultObject) { 17118 * console.error("API Failed"); 17119 * var msg = guideResultObject.getNextMessage(); 17120 * while (msg != null) { 17121 * console.error(msg.message); 17122 * msg = guideResultObject.getNextMessage(); 17123 * } 17124 * } 17125 * }); 17126 * @deprecated use {@link GuideBridge#getFormDataString} instead 17127 */ 17128 getData : function (options) { 17129 options = options || {}; 17130 17131 /* Earlier this API would support boundData for getting data tro be merged in PDF. Now that flag has been renamed to dorData 17132 * Earlier, boundData flag now maps to boundData for backward compatibility. 17133 * */ 17134 options.dorData = options.dorData || options.boundData; 17135 17136 var resultObject = new GuideResultObject(); 17137 if (!options.guideState && !this._checkGuide(resultObject)) { 17138 options.error.call(options.context, resultObject); 17139 return; 17140 } 17141 17142 this._submitInternal({ 17143 success : function (data) { 17144 var resultJson = data || {}; 17145 resultObject.completed = true; 17146 if (options.dorData) { 17147 resultObject.data = resultJson["dorDataXml"]; 17148 } else { 17149 resultObject.data = resultJson["data"]; 17150 } 17151 if (_.isFunction(options.success)) { 17152 options.success.call(options.context, resultObject); 17153 } 17154 }, 17155 error : function (xhr, txtStatus, errorThrown) { 17156 var msg = "Error in getData API"; 17157 resultObject.completed = false;
17158 resultObject.addMessage(2, msg, ""); 17159 if (_.isFunction(options.error)) { 17160 options.error.call(options.context, resultObject); 17161 } 17162 }, 17163 guideState : options.guideState, 17164 async : options.async, 17165 fileUploadPath : options.fileUploadPath, 17166 excludeFormState : options.excludeFormState || false, 17167 dorData : options.dorData || false 17168 }); 17169 }, 17170 17171 /** 17172 * returns form data object {@link FormData} 17173 * @returns {*} 17174 * @private 17175 */ 17176 _getFormDataObj : function () { 17177 guideBridge._updateAFSubmissionInfo(); 17178 guideBridge._guide.internal.liveDataUtils.updateLiveData(null, true); // fetching client side data 17179 guideBridge._guide.internal.liveDataUtils.insertSubmissionInfo(guideBridge._guide.runtime.guideContext.afSubmissionInfo); 17180 var data = guideBridge._guide.internal.liveDataUtils.getLiveDataStr(); 17181 var contentType = "application/xml"; 17182 if (guideBridge._guide.internal.liveDataUtils instanceof guidelib.model.LiveJsonUtils) { 17183 contentType = "application/json"; 17184 } 17185 return new guidelib.model.FormData({ 17186 "data" : data, 17187 "contentType" : contentType, 17188 "attachments" : guideBridge.getFileAttachmentWrapper() 17189 }); 17190 }, 17191 17192 /** 17193 * invoked inside server-side-validation to return excludeFromDor data. 17194 * @param {Object} guide input to _getExcludeFromDorData API 17195 * @returns {Array} containing excludeFromDoR info 17196 * */ 17197 _getExcludeFromDorData : function (guide) { 17198 var newGuide = guide ? guide : guideBridge._guide; 17199 var excludeFromDorData = null; 17200 window.guideBridge._updateAFSubmissionInfo(newGuide); 17201 var afSubmissionInfo = newGuide.runtime.guideContext.afSubmissionInfo; 17202 if(afSubmissionInfo.excludeFromDoR) { 17203 excludeFromDorData = afSubmissionInfo.excludeFromDoR; 17204 } 17205 return excludeFromDorData; 17206 }, 17207 17208 /** 17209 * returns FormData object {@link FormData} containing form data xml or json and attachments 17210 * @param {object} options input to the getFormDataObject API 17211 * @param {function} [options.success] callback which receives the result of the API 17212 * in case of success. 17213 * @method 17214 * @memberof GuideBridge 17215 * @since Forms As A Cloud Service 17216 * @instance 17217 */ 17218 getFormDataObject : function (options) { 17219 var formDataObj = guideBridge._getFormDataObj(); 17220 var resultObject = new GuideResultObject(); 17221 resultObject.data = formDataObj; 17222 // using typeof for built in types 17223 if (options && typeof options.success === 'function') { 17224 options.success(resultObject); 17225 } 17226 }, 17227 17228 /** 17229 * returns string representation of form data xml or json 17230 * @param {object} options input to the getData API 17231 * @param {function} [options.success] callback which receives the result of the API 17232 * in case of success. 17233 * @method 17234 * @memberof GuideBridge 17235 * @since 6.5 17236 * @instance 17237 */ 17238 getFormDataString : function (options) { 17239 var formDataObj = guideBridge._getFormDataObj(); 17240 var resultObject = new GuideResultObject(); 17241 resultObject.data = formDataObj.data; 17242 if (options && typeof options.success === 'function') { 17243 options.success(resultObject); 17244 } 17245 }, 17246 17247 17248 /** 17249 * Imports form data from a given string, which can be either JSON or XML format. 17250 * This is useful for initializing a form with pre-filled data received as a string. 17251 * 17252 * @param {Object} options - The options for importing data. 17253 * @param {string} options.data - The string representation of form data (XML or JSON). 17254 * @method 17255 * @memberof GuideBridge 17256 * @since Forms As A Cloud Service 17257 * @instance 17258 * @example 17259 * guideBridge.importData({ data: jsonString }); // For JSON data 17260 * guideBridge.importData({ data: xmlString }); // For XML data 17261 */ 17262 importData : function (options) { 17263 // todo: add support for attachments and custom context later 17264 var prefillData = { 17265 data: options.data, 17266 isMergedJson: false 17267 // customContext: {} 17268 // fileAttachmentMap: {} 17269 // fileAttachmentWrappers: 17270 // attachments: '[]' 17271 }; 17272 guidelib.model.mergeData(prefillData, guideBridge._guide, guideBridge._guide.runtime.guideContext); 17273 }, 17274 17275 /** 17276 * @summary Hides all the submit buttons present in the Adaptive Form 17277 * 17278 * @returns {GuideResultObject} the data property of GuideResultObject would be undefined. The API will fail if
17279 * the Form is not initialized which would be indicated by the {@link GuideResultObject#errors|errors} property. 17280 * @memberof GuideBridge 17281 * @instance 17282 * @since 6.0 17283 */ 17284 hideSubmitButtons : function () { 17285 return this._hideElements("guideButton", "submit"); 17286 }, 17287 17288 /** 17289 * @returns {string} Current Locale of the Form 17290 * @method 17291 * @memberof GuideBridge 17292 * @since Forms As A Cloud Service 17293 * @instance 17294 */ 17295 getFormLocale : function() { 17296 return this._readRuntimeLocale(); 17297 }, 17298 17299 /** 17300 * @returns {string} ID of the Form 17301 * @method 17302 * @memberof GuideBridge 17303 * @since Forms As A Cloud Service 17304 * @instance 17305 */ 17306 getFormId : function() { 17307 var guidePath = guideBridge._guide.jsonModel["jcr:path"]; 17308 return btoa(guidePath); 17309 }, 17310 17311 /** 17312 * Gets the Document of Record. If options is not passed or if success function is not defined, 17313 * then the default behaviour is to download the Document of Record PDF in user's system. 17314 * @param {object} options options to control the behaviour after Document of Record (DOR) is retrieved 17315 * @param {function} [options.success] callback which receives the result of the API 17316 * {@link GuideResultObject#errors|errors} property as false. 17317 * @param {function} [options.error] callback for error handling 17318 * {@link GuideResultObject#errors|errors} property as true. 17319 * @method 17320 * @memberof GuideBridge 17321 * @since Forms As A Cloud Service 17322 * @instance 17323 * @example <caption>Getting the Document of Record</caption> 17324 * guideBridge.getDocumentOfRecord({ 17325 * success: function (guideResultObject) {}, 17326 * error: function (guideResultObject) {} 17327 * }) 17328 */ 17329 getDocumentOfRecord : function(options) { 17330 var self = this; 17331 var formName = self._getFormName(self.getGuidePath()); 17332 if (!options) { 17333 options = {}; 17334 } 17335 if (!_.isFunction(options.success)) { 17336 options.success = function (guideResultObject) { 17337 if (guideResultObject.completed && guideResultObject.data) { 17338 var blob = new Blob([guideResultObject.data], {type: 'application/pdf'}); 17339 var downloadUrl = URL.createObjectURL(blob); 17340 var a = document.createElement("a"); 17341 a.setAttribute('href', downloadUrl); 17342 a.setAttribute('download', formName); 17343 a.setAttribute('style', 'display:none'); 17344 document.body.appendChild(a); 17345 a.click(); 17346 } 17347 } 17348 } 17349 if (!_.isFunction(options.error)) { 17350 options.error = function(guideResultObject) { 17351 console.error(guideResultObject.data); 17352 } 17353 } 17354 function _getDocumentOfRecord(formData) { 17355 var formId = self.getFormId(); 17356 var locale = self.getFormLocale(); 17357 var dorGenerationURL = self._getUrl("/adobe/forms/af/dor/" + formId + "?locale=" + locale); 17358 $.ajax({ 17359 url : dorGenerationURL, 17360 type : "POST", 17361 processData : false, 17362 cache : false, 17363 contentType : false, 17364 data : formData, 17365 xhrFields:{ 17366 responseType: 'blob' 17367 }, 17368 success : function(blob) { 17369 var guideResultObject = new GuideResultObject(); 17370 guideResultObject.data = blob; 17371 guideResultObject.completed = true; 17372 options.success(guideResultObject); 17373 }, 17374 error : function (exception) { 17375 var guideResultObject = new GuideResultObject(); 17376 guideResultObject.data = exception; 17377 guideResultObject.completed = false;
17378 options.error(guideResultObject); 17379 } 17380 }); 17381 }; 17382 17383 self.getFormDataString({ 17384 success: function(result) { 17385 var attachedFilesList = self._getFileAttachmentsList(); 17386 var fileNameDomMap = self._juiceOutNameAndFileDomMap(attachedFilesList); 17387 var dataForm = new FormData(); 17388 var fileAttachmentPromise = self._appendFileAttachmentsToFormData(dataForm, fileNameDomMap, attachedFilesList); 17389 fileAttachmentPromise.then(function (dataForm) { 17390 dataForm.append('data', result.data); 17391 _getDocumentOfRecord(dataForm); 17392 }).catch(function (e) { 17393 console.error(e); 17394 }); 17395 } 17396 }) 17397 }, 17398 17399 /** 17400 * This API is designed to evaluate the expression entered by the author. 17401 * This API is given only to enable Auto Save meta information use case. 17402 * @returns value obtained after executing the expression. 17403 * @method 17404 * @private 17405 * @memberof GuideBridge 17406 * @deprecated since 6.3 this API is deprecated 17407 */ 17408 _evaluateExpression : function (expression) { 17409 if (this._guide) { 17410 var compiledExpression = this._guide._compileExpression(expression, null); 17411 return compiledExpression.apply(this._guide); 17412 } 17413 }, 17414 17415 /** 17416 * Adaptive Form can be configured to save draft automatically. This property indicates whether Adaptive Form is 17417 * configured to save draft automatically or not. 17418 * 17419 * Enabling auto save doesn't mean that AF will create the draft when the Form is loaded. Based on the result of 17420 * **Auto save start expression** the draft will be created. Once the expression returns true, drafts will be 17421 * saved at regular interval or at specific events as configured. 17422 * 17423 * @summary Whether autoSave is enabled for this Adaptive Form or not 17424 * @returns {boolean} true if auto save is enabled otherwise false. 17425 * @method 17426 * @memberof GuideBridge 17427 * @instance 17428 * @since 6.1 FP1 17429 * @see {@link https://helpx.adobe.com/aem-forms/6-1/auto-save-an-adaptive-form.html|Saving an adaptive Form} 17430 */ 17431 getAutoSaveEnabledStatus : function () { 17432 var _isAutoSaveEnable = false; 17433 // check if form is loaded or not, if loaded then check for auto save 17434 if (this.isConnected()) { 17435 _isAutoSaveEnable = this._guide.enableAutoSave; 17436 } 17437 return _isAutoSaveEnable; 17438 }, 17439 17440 /** 17441 * This API indicates that auto save is enabled and draft is being saved at the configured location. 17442 * @summary Whether Adaptive Form data is being saved as draft or not. 17443 * @returns {Boolean} whether autoSave has started. 17444 * @method 17445 * @memberof GuideBridge 17446 * @instance 17447 * @since 6.1 FP1 17448 * @see {@link https://helpx.adobe.com/aem-forms/6-1/auto-save-an-adaptive-form.html|Saving an adaptive Form} 17449 **/ 17450 hasAutoSaveStarted : function () { 17451 return this._guide && this._guide.enableAutoSave && this._guide.autoSaveStart; 17452 }, 17453 17454 /** 17455 * @summary the autoSaveinfo that is stored at the guideContainer. 17456 * @returns {object}
17456 object contains the additional meta information stored along with form data 17457 * @method 17458 * @memberof GuideBridge 17459 * @instance 17460 * @since 6.1 FP1 17461 * @deprecated since 6.3 17462 */ 17463 getAutoSaveInfo : function () { 17464 return this._guide.autoSaveInfo; 17465 }, 17466 17467 /** 17468 * The API is used to provide extra information to be saved in Final data XML. It can also be used to retrieve 17469 * that information. 17470 * 17471 * If _value_ is null then the value of the _property_ is returned 17472 * @summary store or retrieve submission related information 17473 * @param {string} property name of the property against which to save the value or retrieve the value of 17474 * property 17475 * @param {string} [value] value to save. 17476 * @returns {*} old value of the property 17477 * @method 17478 * @since 6.1 FP1 17479 * @memberof GuideBridge 17480 * @instance 17481 * @deprecated since 6.3 17482 */ 17483 afSubmissionInfo : function (property, value) { 17484 var afSubmissionInfo = guideBridge._guide.runtime.guideContext.afSubmissionInfo || {}; 17485 if (_.isUndefined(value)) { 17486 return afSubmissionInfo[property]; 17487 } else { 17488 var oldValue = afSubmissionInfo[property]; 17489 afSubmissionInfo[property] = value; 17490 guideBridge._guide.runtime.guideContext.afSubmissionInfo = afSubmissionInfo; 17491 return oldValue; 17492 } 17493 }, 17494 17495 /** 17496 * @summary this API returns the globalMetaInfo stored in global context (in globalMetaInfo tab). 17497 * @returns {object} 17498 * @method 17499 * @memberof GuideBridge 17500 * @instance 17501 * @deprecated since 6.3 17502 */ 17503 getGlobalMetaInfo : function () { 17504 return this._guide.globalMetaInfo; 17505 }, 17506 17507 /** 17508 * @summary this API returns the metadata configured for submission. Value depends on the selection of metadata 17509 * type, local or global. 17510 * @returns {Object} 17511 * @method 17512 * @since 6.1 FP1 17513 * @memberof GuideBridge 17514 * @instance 17515 * @deprecated since 6.3 17516 */ 17517 getSubmissionMetadataInfo : function () { 17518 if (this._guide.submissionMetaInfo && this._guide.submissionMetaInfo.metadataselector === LOCAL_METADATA_SELECTOR) { 17519 // In order to maintain backward compatibility, this piece of code will always be here. 17520 // For the cases where metadata selection is being configured for submit actions 17521 return getOrElse(this._guide, "submissionMetaInfo.metadata", null); 17522 } else { 17523 //From 6.2 onwards, we are asking author to provide metadata only at one place, which is global to whole form 17524 // In case, metadataselector's value is "global" or not configured at all, this block will get executed 17525 return getOrElse(this._guide, "globalMetaInfo.metadata", null); 17526 } 17527 }, 17528 17529 /** 17530 * The API enables auto save in Adaptive Form 17531 * @summary enable auto save in Adaptive Form. 17532 * @param value {boolean} true to enable auto save otherwise false. 17533 * @method 17534 * @memberof GuideBridge 17535 * @instance 17536 * @since 6.1 FP1 17537 * @see {@link GuideBridge#getAutoSaveEnabledStatus|getAutoSaveEnabledStatus} 17538 * @see {@link https://helpx.adobe.com/aem-forms/6-1/auto-save-an-adaptive-form.html|Auto Save an Adaptive Form} 17539 */ 17540 setEnabledAutoSave : function (value) { 17541 this._guide.enableAutoSave = value; 17542 }, 17543 17544 /** 17545 * @summary Hides all the file attachment listing buttons present in the Adaptive Form 17546 * 17547 * @returns {GuideResultObject} the data property of GuideResultObject would be undefined. The API will fail if 17548 * the Form is not initialized which would be indicated by the {@link GuideResultObject#errors} property. 17549 * @memberof GuideBridge 17550 * @instance 17551 * @since 6.0 17552 */ 17553 hideFileAttachmentListingButtons : function () { 17554 return this._hideElements("guideListFileAttachmentButton"); 17555 }, 17556 17557 /** 17558 * @todo: Function can change as per usecase, it can behave as a wrapper 17559 * where it can use the configuration provided through registerConfig and invoke any callback if required 17560 * 17561 * @returns {boolean} boolean indicating whether Adaptive Form is offline 17562 * @private 17563 */ 17564 isOffline : function () { 17565 return checkAFOffline; 17566 }, 17567 17568 /** 17569 * function to set the status of Adaptive Form (online or offline) 17570 * @type {boolean} 17571 * @private 17572 */ 17573 setIsOffline : function (value) { 17574 checkAFOffline = value; 17575 }, 17576 17577 /** 17578 * @summary Hide all the File Attachment component present in the Adaptive Form 17579 * 17580 * @returns {GuideResultObject} the data property of GuideResultObject would be undefined. The API will fail if
17581 * the Form is not initialized which would be indicated by the {@link GuideResultObject#errors} property. 17582 * @memberof GuideBridge 17583 * @instance 17584 * @since 6.0 17585 */ 17586 hideFileAttachments : function () { 17587 return this._hideElements("guideFileUpload"); 17588 }, 17589 17590 /** 17591 * @summary Hides the global toolbar of the Adaptive Form. 17592 * @returns {GuideResultObject} the data property of GuideResultObject would be undefined. The API will fail if 17593 * the Form is not initialized which would be indicated by the {@link GuideResultObject#errors} property. 17594 * @memberof GuideBridge 17595 * @instance 17596 * @since 6.0 17597 */ 17598 hideGlobalToolbar : function () { 17599 var resultObject = new GuideResultObject(), 17600 $toolbar; 17601 17602 // If guide dom not initialized, return 17603 if (!this._checkGuide(resultObject)) { 17604 return resultObject; 17605 } 17606 17607 if (guideBridge._guide.toolbar) { 17608 $toolbar = this._getGuideDomElement(guideBridge._guide.toolbar.somExpression); 17609 if ($toolbar && $toolbar.length > 0) { 17610 $toolbar.hide(); 17611 } 17612 } 17613 17614 resultObject.completed = true; 17615 return resultObject; 17616 }, 17617 17618 /* 17619 * 17620 * This API is designed to return all the toolbar buttons present in the Adaptive Form(except submit, save, reset and file attachment listing) 17621 * 17622 * @returns {GuideResultObject} data contains an array of all the tool bar buttons available(except submit, save, reset and file attachment listing) 17623 * Each element of data property is an object holding model and html property. 17624 * The html string does not contain any script tags, this is to avoid crosss site scripting attacks 17625 */ 17626 /* 17627 getToolbarButtons : function(){ 17628 var resultObject = new GuideResultObject(), 17629 resultData = [], 17630 $elem = null; 17631 // If guide dom not initialized, return 17632 if (!this._checkGuide(resultObject)) { 17633 return resultObject; 17634 } 17635 resultObject.completed = true; 17636 this.visit(function(node){ 17637 // Check if this node is a guide button and if it resides inside a guideToolBar 17638 if(node.className === "guideButton" && node.parent.className === "guideToolbar"){ 17639 if(node.type !== "submit" && node.type !== "save" && node.type !== "fileattachmentlisting" && node.type !== "next" && node.type !=="prev") { 17640 $elem = this._getGuideDomElement(node.somExpression); 17641 // Remove the script tag from the $html, we don't support execution of Adaptive Form Scripts in parent or other domain 17642 // This is to avoid cross site scripting attacks 17643 $elem.find("script").remove(); 17644 resultData.push({ 17645 "model" : node, 17646 "html" : $elem.html() 17647 }); 17648 } 17649 } 17650 }); 17651 resultObject.data = resultData; 17652 return resultObject; 17653 }, */ 17654 17655 /** 17656 * @summary Hides all the save buttons present in the Adaptive Form 17657 * 17658 * @returns {GuideResultObject} the data property of GuideResultObject would be undefined. The API will fail if 17659 * the Form is not initialized which would be indicated by the {@link GuideResultObject#errors} property. 17660 * @memberof GuideBridge 17661 * @instance 17662 * @since 6.0 17663 */ 17664 hideSaveButtons : function () { 17665 return this._hideElements("guideButton", "save"); 17666 }, 17667 17668 /** 17669 * @summary Hides all the reset buttons present in the Adaptive Form 17670 * 17671 * @returns {GuideResultObject} the data property of GuideResultObject would be undefined. The API will fail if 17672 * the Form is not initialized which would be indicated by the {@link GuideResultObject#errors} property. 17673 * @memberof GuideBridge 17674 * @instance 17675 * @since 6.3 17676 */ 17677 hideResetButtons : function () { 17678 return this._hideElements("guideButton", "reset"); 17679 }, 17680 17681 /** 17682 * The API can be used to retrieve the value of a specific property for a list of AF components. If the property 17683 * doesn't exists for a component then the corresponding value in the resulting array will be null. 17684 * 17685 * The {@link GuideResultObject#data|data} element of the return object will be an array containing the values 17686 * of the _property_ for each component in the list of components 17687 * 17688 * The API fails if the Form is not initiailzed 17689 * 17690 * **_Note:_** If a somExpression provided doesn't points to a valid {@link GuideNode} null is returned for 17691 * that element and an error message is added in the returned object 17692 * @summary returns the value of a specific property for a set of Adaptive Form Components 17693 * 17694 * @param {object}
17694 options input object containing the propertyName and the list of components 17695 * @param {string} options.propertyName name of the property whose value has to be returned 17696 * @param {string[]} options.somExpression list of somExpression of the components for which the value is to be 17697 * returned. 17698 * 17699 * @returns {GuideResultObject} The {@link GuideResultObject#data|data} member of the object contains the property 17700 * values 17701 * @method 17702 * @memberof GuideBridge 17703 * @since 6.0 17704 * @instance 17705 * @deprecated since 6.3 17706 * @see GuideNode#somExpression 17707 * @example 17708 * var result = guideBridge.getElementProperty({ 17709 * propertyName: "value", 17710 * somExpression: ["somExpression1", "somExpression2"] 17711 * }); 17712 * if (result.errors) { 17713 * console.log("some som expressions were invalid"); 17714 * var err = result.getNextMessage(); 17715 * while(err != null) { 17716 * //err.somExpression will point to the invalid somExpression in the Field. 17717 * console.log(err.message); 17718 * } 17719 * } 17720 * for(var i = 0; i< result.data.length; i++) { 17721 * console.log(result.data[i]); 17722 * } 17723 */ 17724 getElementProperty : function (options) { 17725 var somExpressions = options.somExpressions; 17726 var propertyName = options.propertyName; 17727 var resultObject = new GuideResultObject(); 17728 if (!this._checkGuide(resultObject)) { 17729 return resultObject; 17730 } 17731 resultObject.data = []; 17732 for (var i = 0; i < somExpressions.length; i++) { 17733 var element = this.resolveNode(somExpressions[i]); 17734 if (element == null) { 17735 resultObject.addMessage(0, "No element " + somExpressions[i] + " exists", somExpressions[i]); 17736 resultObject.data.push(null); 17737 } else { 17738 resultObject.completed = true; 17739 resultObject.data.push(element[propertyName]); 17740 } 17741 } 17742 return resultObject; 17743 }, 17744 17745 _getGuideDomElement : function (somExpression, option) { 17746 if (this._guideView) { 17747 return this._guideView._getGuideDomElement(somExpression, option); 17748 } else { 17749 return null; 17750 } 17751 }, 17752 17753 /** 17754 * File Attachment object 17755 * @typedef {object} GuideBridge~FileAttachementObject 17756 * @property {string} name name of the uploaded File 17757 * @property {string} path path of the uploaded File 17758 * @memberof GuideBridge 17759 * @since 6.0 17760 */ 17761 /** 17762 * Success callback that is called from {@link GuideBridge#getFileAttachmentsInfo} with the list of File 17763 * Attachments 17764 * @callback GuideBridge~FileAttachmentInfoHandler 17765 * @param {GuideBridge~FileAttachementObject[]} fileAttachementList list of file attachement objects uploaded 17766 * in the Form 17767 */ 17768 /** 17769 * The API provides a list containing File Names and File URLS for the Files Attached by the user using the 17770 * File Attachment component. The API is a asynchronous API and takes success handler which is called with 17771 * the list of File Names and URLs. 17772 * 17773 * @param {object} options Object containing the callback which will be invoked with the result of this API 17774 * @param {function} options.success success callback which will be invoked. The signature of the callback should 17775 * match the signature of {@link GuideBridge~FileAttachmentInfoHandler|FileAttachmentInfoHandler} 17776 * @param {object} [options.context] _this_ parameter in the success handler will point to this object 17777 * 17778 * @example <caption>Example usage of the getFileAttachmentsInfo API</caption> 17779 * guideBridge.getFileAttachmentsInfo({ 17780 * success:function(list) { 17781 * for(var i = 0; i< list.length; i++) { 17782 * console.log(list[i].name + " "+ list[i].path); 17783 * } 17784 * } 17785 * }); 17786 * @method 17787 * @memberof GuideBridge 17788 * @since 6.0 17789 * @deprecated since Forms As a Cloud Service 17790 * @instance 17791 */ 17792 getFileAttachmentsInfo : function (options) { 17793 console.error("getFileAttachmentsInfo API is not supported on Forms As a Cloud Service"); 17794 options.success.call(options.context, []); 17795 }, 17796 17797 /** 17798 * Syntax - argObject : {"options" : options to be passed to the callback, 17799 * "fileAttachmentsList" : fileAttachmentsList, 17800 * "fileUploadPath" :fileUploadPath 17801 * "callback" :callback, "errorCallback" :errorCallback} 17802 * @param {object}
17802 argObject Input object containing the callbacks that will be invoked 17803 * to provide the result of the API 17804 * @private 17805 * @memberof GuideBridge 17806 * @since 6.0 17807 */ 17808 _getGuideAttachments : function (argObject) { 17809 var fileDoms = [], 17810 fileNames = [], 17811 fileUrl = null, 17812 didSubmit = false, 17813 contextRoot = this._getContextRoot(), 17814 options = argObject.options, 17815 fileAttachmentsList = argObject.fileAttachmentsList, 17816 fileUploadPath = argObject.fileUploadPath, 17817 callback = argObject.callback, 17818 errorCallback = argObject.errorCallback, 17819 fileNameDomMap; 17820 17821 // In the case of draft, url comes with context root. Need to remove it so that correct 17822 // value gets stored in model 17823 if (contextRoot) { 17824 if (fileUploadPath.indexOf(contextRoot) === 0) { 17825 fileUploadPath = fileUploadPath.substring(contextRoot.length); 17826 } 17827 } 17828 // File attachment list is an array containing the list of file attachments 17829 // We need to fetch the fileNameDomMap even when there's no fileAttachmentsList as there can be 17830 // lazy loaded file attachment models as well. 17831 fileNameDomMap = this._juiceOutNameAndFileDomMap(fileAttachmentsList); 17832 fileDoms = fileNameDomMap.fileDom; 17833 fileNames = fileNameDomMap.fileName; 17834 if (fileDoms.length > 0) { 17835 // since there can be a dom element which is null, in case of draft reload, get the first 17836 // non null file dom 17837 var firstNonNullFileDom = _.indexOf(fileDoms, _.find(fileDoms, function (item) { 17838 return item !== null && !_.isString(item); 17839 })); 17840 // fileUploadPath doesn't contain the context path and hence we need to to pass the baseURL 17841 // FileUploader takes a _getUrl option which is baseUrl/contextPath 17842 if (firstNonNullFileDom !== -1 && fileUploadPath) { 17843 var uploaderPluginName = guideBridge.userConfig.uploaderPluginName || "adobeFileUploader"; 17844 fileUrl = fileDoms[firstNonNullFileDom][uploaderPluginName]("uploadFile", { 17845 'fileName' : fileNames, 17846 'fileDom' : fileDoms, 17847 'fileUploadPath' : fileUploadPath, 17848 'multiple' : true, 17849 _getUrl : guideBridge._getUrl("") 17850 }); 17851 17852 // The file url returned by file upload widget can contain context root. 17853 // Remove it so that correct value gets stored in model. 17854 if (contextRoot) { 17855 if (fileUrl.indexOf(contextRoot) === 0) { 17856 fileUrl = fileUrl.substring(contextRoot.length); 17857 } 17858 } 17859 17860 fileDoms[firstNonNullFileDom].one("adobeFileUploader.multipleFileUploaded", 17861 $.proxy(callback, { 17862 "attachments" : fileNames, 17863 "fileUrl" : fileUrl, 17864 "fileAttachmentsList" : fileAttachmentsList, 17865 "options" : options 17866 }) 17867 ); 17868 if (errorCallback) { 17869 fileDoms[firstNonNullFileDom].one("adobeFileUploader.fileUploadFailed", 17870 $.proxy(errorCallback, { 17871 "attachments" : fileNames, 17872 "fileUrl" : fileUrl, 17873 "fileAttachmentsList" : fileAttachmentsList, 17874 "options" : options 17875 }) 17876 ); 17877 } 17878 didSubmit = true; 17879 } 17880 // if fileUrl is not yet set, default it to fileUploadPath 17881 if (fileUrl === null && fileUploadPath) { 17882 fileUrl = fileUploadPath; 17883 } 17884 } 17885 if (!didSubmit) { 17886 // if there are no files attached, still call the callback to submit the json contents 17887 // if there is only one file attachment component with no files, in this case else is
17887important 17888 callback.apply({ 17889 "attachments" : fileNames, 17890 "fileUrl" : fileUrl, 17891 "fileAttachmentsList" : fileAttachmentsList, 17892 "options" : options 17893 }); 17894 } 17895 }, 17896 /** 17897 * Iterates over all the components in the Adaptive Form and invokes its {@link GuideNode#visit|visit} method 17898 * passing the _callback_ to the API. 17899 * 17900 * @summary Traverse all the components in the Adaptive Form and invoke callback function for each of the 17901 * component 17902 * @param {function} callback Function to be called for every Adaptive Form Component present 17903 * in the Form. The signature of the callback matches the signature of 17904 * {@link GuideNode~VisitorCallback|VisitorCallback} 17905 * @param {object} [context=window] _this_ object in the callback will point to this object 17906 * 17907 * @example <caption>Creating a list of all components having name <i>testName</i></caption> 17908 * var myList = [] 17909 * guideBridge.visit(function(cmp) { 17910 * if(cmp.name === "testName") { 17911 * myList.push[cmp]; 17912 * } 17913 * }}; 17914 * @method 17915 * @memberof GuideBridge 17916 * @since 6.0 17917 * @instance 17918 */ 17919 visit : function (callback, context) { 17920 this._guide.visit(callback, context || window); 17921 }, 17922 17923 /** 17924 * 17925 * Hides the elements of the specified class name. 17926 * In case of guideButton, it checks for type too, if no type is specified in "guideButton", then that button 17927 * cannot be made hidden 17928 * 17929 * @param className String representing the classname of the node 17930 * @param type [optional] type will be used only if the classname is "guideButton" 17931 * @private 17932 */ 17933 _hideElements : function (className, type) { 17934 var resultObject = new GuideResultObject(); 17935 // If guide dom not initialized, return 17936 if (!this._checkGuide(resultObject)) { 17937 return resultObject; 17938 } 17939 resultObject.completed = true; 17940 this.visit(function (node) { 17941 // if the class name is guide button only the use the type 17942 if (node.className === "guideButton") { 17943 if (node.type === type) { 17944 node.visible = false; 17945 } 17946 } else { 17947 // else just compare the classname and hide it 17948 if (node.className === className) { 17949 node.visible = false; 17950 } 17951 } 17952 }); 17953 return resultObject; 17954 }, 17955 17956 /** 17957 * In Adaptive Form there is a summary component to show the summary of submission. This API hides the parent 17958 * panel of the summary component. If the component is not present inside the Form, this operation doesn't do 17959 * anything 17960 * @summary Hides the panel that contains the summary component. 17961 * 17962 * @returns {GuideResultObject} the data property of GuideResultObject would be undefined. The API will fail if 17963 * the Form is not initialized which would be indicated by the {@link GuideResultObject#errors} property. 17964 * @memberof GuideBridge 17965 * @instance 17966 * @since 6.0 17967 */ 17968 hideSummaryPanel : function () { 17969 var resultObject = new GuideResultObject(); 17970 // If guide dom not initialized, return 17971 if (!this._checkGuide(resultObject)) { 17972 return resultObject; 17973 } 17974 resultObject.completed = true; 17975 this.visit(function (node) { 17976 if (node.className === "guideNode" && node.jsonModel['sling:resourceType'] === "fd/afaddon/components/summary") { 17977 node.panel.visible = false; 17978 } 17979 }); 17980 return resultObject; 17981 }, 17982 17983 _getFileAttachmentsList : function () { 17984 var fileAttachmentsList = []; 17985 this.visit(function (node) { 17986 if (node.className === "guideFileUpload") { 17987 fileAttachmentsList.push(node); 17988 } 17989 }); 17990 return fileAttachmentsList; 17991 }, 17992 17993 /** 17994 * @summary the captchaData which will be submitted to server for validation purposes. 17995 * @param captchaModel 17996 * @returns {object}
17996 object contains the captchaData which includes captcha service provider name, its SOM exp and 17997 * data coming from OOTB/third-party captcha widget. 17998 * @method 17999 * @memberof GuideBridge 18000 * @instance 18001 * @since 6.3 18002 */ 18003 _getCaptchaData : function (captchaModel) { 18004 if (captchaModel) { 18005 return { 18006 serviceType : captchaModel.captchaService, 18007 somExpression : captchaModel.somExpression, 18008 validationMessage : captchaModel.validateExpMessage, 18009 mandatoryMessage : captchaModel.mandatoryMessage, 18010 data : captchaModel.value 18011 }; 18012 } 18013 return {}; 18014 }, 18015 18016 /** 18017 * This function returns the additional action Field information that is required during submit. 18018 * 18019 * @returns {object} object having the action Field information. 18020 * @memberof GuideBridge 18021 */ 18022 _getAdditionalSubmitInfo : function () { 18023 var additionalSubmitInfo = {}, 18024 actionFieldDiv = $("#actionField"); 18025 var thankYouPage = this._getThankYouPageFromConfig(); 18026 if (typeof thankYouPage === "string") { 18027 document.getElementById(":redirect").value = thankYouPage; 18028 } 18029 var actionFields = actionFieldDiv.find('input') 18030 .each(function () { 18031 additionalSubmitInfo[$(this).attr("name")] = $(this).val(); 18032 if ($(this).attr("name") == "_guideValueMap" && $(this).val() == "yes") { 18033 var guideKeyValue = {}; 18034 window.guideBridge._guide._collectValues(guideKeyValue); 18035 additionalSubmitInfo['_guideValuesMap'] = JSON.stringify(guideKeyValue); 18036 } 18037 }); 18038 return additionalSubmitInfo; 18039 }, 18040 18041 /** 18042 * Gets the guideDom based on whether reducedJSON option is true or not. 18043 * If reducedJSON is true, only the white-listed properties are included. 18044 * 18045 * @returns {object} guideDom 18046 * @memberof GuideBridge 18047 */ 18048 18049 _getGuideDom : function (options) { 18050 var guideDom; 18051 if (options.reducedJSON) { 18052 guideDom = guideBridge._guide._getReducedJSON(); 18053 } else { 18054 guideDom = guideBridge._guide.jsonModel; 18055 } 18056 return guideDom; 18057 }, 18058 18059 /** 18060 * Creates the guideState and the liveXml. 18061 * 18062 * @param options {object} options should contain a GuideResultObject [{obj:"<GuideResultObject type>"}] 18063 * @memberof GuideBridge 18064 * Steps performed by the function - 18065 * 1) creates the xfaState 18066 * 2) creates the guideState that consists of guideDom, guideContext and additionalSubmitInfo 18067 * 3) creates guideLiveData 18068 * 4) adds xfaState and guideLiveData to the guideState 18069 * 18070 * @private 18071 */ 18072 _createGuideStateAndLiveXml : function (options) { 18073 var obj = new GuideResultObject(); 18074 // add the guideResultObject to options so that it can be passed to the success handler 18075 options.obj = obj; 18076 18077 if (!this._checkGuide(obj)) { 18078 return; 18079 } 18080 18081 var saveXfaXml = function (xfaResultObj) { 18082 if (!xfaResultObj.errors && xfaResultObj.completed) { 18083 xfaState.currentContext = {'data' : xfaResultObj.data}; 18084 } 18085 }; 18086 18087 obj.data = {}; 18088 var xfaState = null; 18089 if (this._isXfaGuide() && this._isValidXFAGuide()) { 18090 var xfaResultObject = null; 18091 if (options.reducedJSON) { 18092 //If reduceJson is asked, then xfaState should also be reduced by passing the diff and bSubmit flag to true 18093 xfaResultObject = window.formBridge.getFormState(true, true); 18094 } else { 18095 xfaResultObject = window.formBridge.getFormState(); 18096 } 18097 if (xfaResultObject.errors) { 18098 guideBridge._guide.logger().log("Error in getting Xfa State:" + JSON.stringify(xfaResultObject.getNextMessage())); 18099 alert(guidelib.util.GuideUtil.getLocalizedMessage("AF", guidelib.i18n.LogMessages["AEM-AF-901-001"])); 18100 } 18101 xfaState = xfaResultObject.data; 18102 } 18103 18104 var guideDom = guideBridge._getGuideDom(options); 18105 18106 //adding additionalSubmitInfo in the guideState. 18107 //additionalSubmitInfo contains the information about action fields. 18108 var additionalSubmitInfo = guideBridge._getAdditionalSubmitInfo(); 18109 //set the updated file attachment map in the customPropertyMap 18110 guideBridge.customContextProperty("fileAttachmentMap", JSON.stringify(this.getFileAttachmentMap())); 18111 var guideState = { 18112 guideDom : guideDom, 18113 //save renderContext in guide state to enable deferred submit even if guide is not open 18114 guideContext : guideBridge._guide.runtime.guideContext, 18115 additionalSubmitInfo : additionalSubmitInfo 18116 }; 18117 18118 if (guideBridge._guide.allLazyChildren.length > 0) { 18119 guideBridge._guide.internal.liveDataUtils.updateLiveData(); 18120 var listOfDirtyPanels = guideBridge._guide.internal.GuideDirtyMarkerAndVisitor.flatten
18120DirtyPanelMapToCSV(); 18121 if (listOfDirtyPanels.length > 0) { 18122 this.afSubmissionInfo("afDraft", listOfDirtyPanels); 18123 } 18124 // save live xml & xfa state as xml for restoration of lazy model on 'restore' 18125 guideState.guideLiveData = guideBridge._guide.internal.liveDataUtils.getLiveDataStr(); 18126 if (this._isXfaGuide() && this._isValidXFAGuide()) { 18127 formBridge.getDataXML({"success" : saveXfaXml}); // currently xfa restore relies on formBridge.getDataXML being sync 18128 } 18129 } 18130 obj.data.guideState = guideState; 18131 if (xfaState) { 18132 obj.data.guideState.xfaState = xfaState; 18133 } 18134 18135 }, 18136 18137 _updateAFSubmissionInfo : function (guide) { 18138 if (guideBridge.isGuideLoaded(true) && !guide) { 18139 var previousFocusSom = this._guideView._previousFocusItemSom; 18140 var previousItemModel = guideBridge.resolveNode(this._guideView._previousFocusItemSom); 18141 if (getOrElse(previousItemModel, "parent.className", undefined) === "guideToolbar") { 18142 previousFocusSom = previousItemModel.parent.parent.somExpression; 18143 } 18144 this.afSubmissionInfo("lastFocusItem", this._guideView.getSomOnNavigableAncestor(previousFocusSom)); 18145 } 18146 var newGuide = guide ? guide : guideBridge._guide; 18147 this.afSubmissionInfo("excludeFromDoR", newGuide._getExcludeFromDorMap()); 18148 // send state override on in cases when we have dor 18149 var stateOverrides = {}; 18150 if (newGuide.dorType && "none" !== newGuide.dorType) { 18151 stateOverrides = newGuide._getStateOverrideMap(); 18152 } 18153 this.afSubmissionInfo("stateOverrides", stateOverrides); 18154 // Add signers to af submission info 18155 this.afSubmissionInfo("signers", newGuide._getSigners()); 18156 18157 }, 18158 18159 /** 18160 * Adaptive Form stores its state in the form of JSON. The Files attached in the component are uploaded 18161 * onto the server and their paths are returned in the JSON state except in certain conditions mentioned below. 18162 * The API is an asynchronous call which calls the success and error handlers with the data. 18163 * 18164 * In the below mentioned scenarios the file will not be uploaded 18165 * * User doesn't have **write permissions** on the _fileUploadPath_ provided 18166 * * The _fileUploadPath_ property doesn't point to a node of type _**sling:Folder**_ 18167 * 18168 * @summary Retrieve the current state of Adaptive Form as json string 18169 * @param {object} options Input object containing the callbacks that will be invoked 18170 * to provide the result of the API 18171 * @param {function} [options.success] callback which receives the result of the API 18172 * in case of success. 18173 * {@link GuideResultObject#errors|errors} property as false. 18174 * @param {function} [options.error] callback which receives the result of the API in 18175 * case of failure. 18176 * {@link GuideResultObject#errors|errors} property as true. 18177 * @param {object} [options.context] _this_ object inside the _success_ and _error_ callback will point to this 18178 * object 18179 * @param {string} [options.fileUploadPath] controls whether the files in the File Attachment component have to be 18180 * uploaded or not. If _fileUploadPath_ is non null, only then file gets uploaded and the model's value is 18181 * updated with the file url 18182 * 18183 * @method 18184 * @memberof GuideBridge 18185 * @since 6.0 18186 * @instance 18187 */ 18188 getGuideState : function (options) { 18189 18190 // walk through the model to get the list of file attachment components 18191 var fileAttachmentsList = this._getFileAttachmentsList(); 18192 guideBridge._updateAFSubmissionInfo(); 18193 18194 if (guideBridge.isGuideLoaded(true)) { 18195 this.customContextProperty("lastFocusItem", this._guideView.getSomOnNavigableAncestor(this._guideView._previousFocusItemSom)); 18196 } 18197 18198 // Walk through the list of file Attachment components 18199 // and update the value of every item 18200 // Get the list of file Attachments 18201 if (options.fileUploadPath) { 18202 var optionArgument = {"options" : options, 18203 "fileAttachmentsList" : fileAttachmentsList, 18204 "fileUploadPath" : options.fileUploadPath, 18205 "callback" : window.guideBridge._collectFileUrls, 18206 "errorCallback" : window.guideBridge._fileUploadFailed}; 18207 18208 this._getGuideAttachments(optionArgument); 18209 } else { 18210 this._createGuideStateAndLiveXml(options); 18211 if (options.success) { 18212 options.success.call(options.context, options.obj); 18213 } 18214 } 18215 18216 }, 18217 18218 /** 18219 * Validates the Adaptive Form or it's specific panel and return the validation status. The API also moves 18220 * focus to first invalid element 18221 * @summary validate the entire Form or a component in Adaptive Form 18222 * @param {Field~ValidationError[]} errorList Input must be an empty array. The array will be filled with list 18223 * of Adaptive Form Components that failed validation. 18224 * @param {string}
18224 [somExpression] SOM Expression of the Guide Node for which validation should be triggered. 18225 * If not provided, it would validate the entire Adaptive Form 18226 * @param {boolean} [setFocus=true] If true, set focus to the first invalid element. 18227 * @returns {boolean} true if the component/form was valid, false otherwise 18228 * @method 18229 * @memberof GuideBridge 18230 * @since 6.0 18231 * @instance 18232 * @see Field#validate 18233 * @see Panel#validate 18234 */ 18235 validate : function (errorList, somExpression, setFocus, guide) { 18236 // guide parameter is not to be documented and it is meant for internal use only 18237 var guideNode = null, 18238 isFocusEnabled = _.isUndefined(setFocus) ? true : setFocus, 18239 ec = guidelib.util.ErrorConstants, 18240 validationContext, 18241 afContainer = guide ? guide : this._guide; // done, to keep this thread safe 18242 // get Json of all the dirty , non visited (templateJson missing from cache) 18243 if (afContainer.allLazyChildren.length > 0) { 18244 afContainer.guideLazyUtil.putDirtyToTemplateCacheIfMissing(afContainer); 18245 } 18246 if (somExpression) { 18247 guideNode = this.resolveNode(somExpression); 18248 // how to know if the panel is navigable from the model. We do not bring the nonNavigable property ? 18249 if (guideNode instanceof guidelib.model.GuidePanel) { 18250 validationContext = ec.CONTEXT_NAVIGATION; 18251 } 18252 } else { 18253 guideNode = afContainer; 18254 validationContext = ec.CONTEXT_SUBMISSION; 18255 } 18256 this.setValidationContext(validationContext); 18257 var status = false; 18258 if (!errorList) { 18259 errorList = []; 18260 } 18261 status = guideNode.validate(errorList); 18262 18263 try { 18264 // there can be errors in the user script, hence handling the exception gracefully, and resetting the global error state properly 18265 this._guide._triggerOnBridge("validationComplete", this._guide, status, "", errorList); 18266 if (!status && isFocusEnabled) { 18267 var errorSom = errorList[0]["som"]; 18268 18269 guideBridge._guide.on(guidelib.event.GuideModelEvent.LAZY_LOADED, function () { 18270 var errorField = guideBridge.resolveNode(errorSom); 18271 if (errorField) { 18272 errorField.validate(); 18273 } 18274 }, {}); 18275 18276 this.setFocus(errorSom); 18277 18278 guideBridge._guide.off(guidelib.event.GuideModelEvent.LAZY_LOADED); 18279 } 18280 18281 } catch (exception) { 18282 this._guide.logger().log(exception); 18283 } finally { 18284 // since the errors have been published reset the state back to normal 18285 //guidelib.runtime.errorManager.setGlobalError(false); 18286 this.unsetValidationContext(validationContext); 18287 return status; 18288 } 18289 18290 }, 18291 18292 // todo: submit behaviour should make sure that if the value of file upload 18293 /** 18294 * Adaptive Form can be restore in three ways 18295 * * by passing the JSON data obtained from {@link GuideBridge#getGuideState}. This can be done by setting 18296 * _**data**_ property . 18297 * * by passing a URL pointing to a resource that returns JSON/XML data that should be used. This can be done by setting 18298 * _**dataRef**_ property. The data can be obtained by calling the 18299 * {@link GuideBridge#getData|getData} API. 18300 * * by passing a URL pointing to a resource that returns JSON data obtained from {@link GuideBridge#getGuideState}. 18301 * This can be done by setting _**guideStatePathRef**_ property . 18302 * 18303 * When restoring from dataRef, only values and other properties, that are dependant on value, are restored. For 18304 * example, If a Field was hidden based on the click of a Button then 18305 * when restoring from data XML/JSON the Field will not remain hidden. 18306 * 18307 * **NOTE:** The _data_, _dataRef_ and _guideStatePathRef_ must not be null simultaneously and only one property 18308 * must be specified. Specifying more than one can lead to undesired results. 18309 * @summary restore/prepopulate the state of Adaptive Form from an earlier saved state 18310 * @param {object}
18310 options object containing the callbacks to be invoked on 18311 * success/failure and data from where to restore the object. 18312 * @param {function} [options.success] callback which receives the result of the API 18313 * in case of success 18314 * {@link GuideResultObject#errors|errors} property as false. 18315 * @param {function} [options.error] callback which receives the result of the API in 18316 * case of failure. 18317 * {@link GuideResultObject#errors|errors} property as true. 18318 * @param {object} [options.context] _this_ object inside the _success_ and _error_ callback will point to this 18319 * object. 18320 * @param {object} [options.data] It must be the value of the {@link GuideResultObject#data|data} property passed to 18321 * the _success_ handler of {@link GuideBridge#getGuideState|getGuideState} API. 18322 * @param {string} [options.dataRef] URL pointing to the data XML/JSON. 18323 * @param {string} [options.guideStatePathRef] URL pointing to the JSON state of Adaptive Form. 18324 * 18325 * @method 18326 * @memberof GuideBridge 18327 * @since 6.0 18328 * @instance 18329 * @example <caption>Restoring from JSON data</caption> 18330 * var jsonData; 18331 * guideBridge.getGuideState({ 18332 * success : function (guideResultObj) { 18333 * jsonData = guideResultObj.data; 18334 * }, 18335 * error : function (guideResultObj) { 18336 * // log error 18337 * } 18338 * }); 18339 * 18340 * // after some time or on click of a button or reloading the page 18341 * guideBridge.restoreGuideState({ 18342 * guideState : jsonData.guideState, 18343 * error : function (guideResultObject) { 18344 * // log the errors 18345 * } 18346 * }) 18347 * 18348 * @example <caption>Restoring from data XML/JSON</caption> 18349 * guideBridge.getData({ 18350 * success : function (guideResultObj) { 18351 * var data = guideResultObj.data; 18352 * //post the data to a server that saves it at say http://abc.com/my/data.xml 18353 * //or http://abc.com/my/data.json 18354 * }, 18355 * error : function (guideResultObj) { 18356 * // log the errors 18357 * } 18358 * }); 18359 * 18360 * // after some time or on click of a button or reloading the page 18361 * guideBridge.restoreGuideState({ 18362 * dataRef : "http://abc.com/my/data.xml", 18363 * error : function (guideResultObject) { 18364 * // log the errors 18365 * } 18366 * }) 18367 * 18368 * @example <caption>Restoring from URL to a JSON</caption> 18369 * guideBridge.getGuideState({ 18370 * success : function (guideResultObj) { 18371 * var json = guideResultObj.data; 18372 * //post the JSON to a server that saves it at say http://abc.com/my/data.json 18373 * }, 18374 * error : function (guideResultObj) { 18375 * // log the errors 18376 * } 18377 * }); 18378 * 18379 * // after some time or on click of a button or reloading the page 18380 * guideBridge.restoreGuideState({ 18381 * guideStatePathRef : "http://abc.com/my/data.json", 18382 * error : function (guideResultObject) { 18383 * // log the errors 18384 * } 18385 * }) 18386 **/ 18387 restoreGuideState : function (options) { 18388 var parameters, 18389 path; 18390 if (options && options.dataRef) { 18391 parameters = {"dataRef" : options.dataRef}; 18392 } else if (options && options.guideStatePathRef) { 18393 parameters = {"guideStatePathRef" : options.guideStatePathRef}; 18394 } 18395 // if parameters have DataRef or guideStatePathRef, a recursive call is made to restoreGuideState. 18396 if (parameters) { 18397 path = window.guideBridge.getGuidePath(); 18398 path = path + ".guidejson"; 18399 $.ajax({ 18400 url : path, 18401 type : "GET", 18402 async : false, 18403 cache : false, 18404 data : parameters, 18405 success : function (response) { 18406 //case where section information exist in guideState 18407 if (response.guideState && response.guideState.guideContext 18408 && response.guideState.guideContext.customPropertyMap 18409 && response.guideState.guideContext.customPropertyMap.sections 18410 && response.guideState.guideContext.customPropertyMap.sections.length > 0) { 18411 // todo: add safe check for string vs array 18412 window.guideBridge.customContextProperty.sections = response.guideState.guideContext.customPropertyMap.sections; 18413 } 18414 //passing the options again, but with DataRef or guideStatePathRef removed from it. 18415 window.guideBridge.restoreGuideState(_.extend( 18416 {}, 18417 options, 18418 { 18419 guideState : response.guideState, 18420 dataRef : undefined, 18421 guideStatePathRef : undefined 18422 } 18423 )); 18424 }, 18425 error : function (response) { 18426 window.guideBridge._guide.logger().log("Error: " + response); 18427 } 18428 }); 18429 return; 18430 } 18431 18432 /* 18433 * We have to merge the runtime guideContext with the guideContext passed in the guideState 18434 * so that no custom properties that were set in the guideState.guideContext are ignored. 18435 */ 18436 guidelib.__runtime__.guideContext = guidelib.__runtime__.guideContext || {}; 18437 if (guideBridge.isGuideLoaded()) { 18438 guideBridge._guide.runtime.guideContext = guideBridge._guide.runtime.guideContext || {}; 18439 } 18440 var gc = getOrElse(options, "guideState.guideContext", undefined); 18441 if (!_.isUndefined(options.guideState.guideContext)) { 18442 /* Runtime custom property map is set by external application and hence, shallow copy will set the value 18443 * as set externally. If no value was set, the guideState custom property map keys stay. 18444 */ 18445 _.extend(gc.customPropertyMap, guidelib.__runtime__.guideContext.customPropertyMap); 18446 if (guideBridge.isGuideLoaded()) { 18447 _.extend(gc.customPropertyMap, guideBridge._guide.runtime.guideContext.customPropertyMap); 18448 } 18449 } 18450 // not setting at guidelib runtime, but honoring if anyone has set customPropertyMap 18451 // through guidelib.runtime.guideContext directly 18452 if (guideBridge.isGuideLoaded()) { 18453 _.extend(guideBridge._guide.runtime.guideContext, gc); 18454 } 18455 18456 if (!this._guide) { 18457 this.storage = {}; 18458 this.storage.guideState = options.guideState; 18459 //NOCHECKMARX - This is error callback to be provided by the user of this API. 18460 this.storage.error = options.error; 18461 this.storage.success = options.success; 18462 this.storage.context = options.context; 18463 } else { 18464 this._playGuideJson(options); 18465 // Trigger the event 18466 // If guide has restore state, call sync guide node to html 18467 // Case 1: If this is called before view gets initialized, there would be no listener present, hence nothing would happen 18468 // Case 2: If it is called after view gets initialized(using restore guide state in mobile workspace), then the model would sync to view 18469 // using this event 18470 // If view is initialized, which means a listener would to MODEL_REFRESH would be set, hence just trigger the event for execution 18471 if (this._guideView) { 18472 this._guide._triggerEvent(guidelib.event.GuideModelEvent.MODEL_REFRESH, "jsonModel", null, null); 18473 } 18474 } 18475 18476 }, 18477 18478 /** 18479 * Adaptive Form can set data in three ways: 18480 * * by passing the JSON data obtained from {@link GuideBridge#getGuideState}. This can be done by setting 18481 * _**data**_ property . 18482 * * by passing a URL pointing to a resource that returns data JSON/XML that should be used. This can be done by setting 18483 * _**dataRef**_ property. The data can be obtained by calling the 18484 * {@link GuideBridge#getData|getData} API. 18485 * * by passing a URL pointing to a resource that returns JSON data obtained from {@link GuideBridge#getGuideState}. 18486 * This can be done by setting _**guideStatePathRef**_ property . 18487 * 18488 * When setting data from dataRef, only values and other properties, that are dependant on value, are set. For 18489 * example, If a Field was hidden based on the click of a Button in the data passed then 18490 * when setting data from XML/JSON the Field will not remain hidden. 18491 * 18492 * **NOTE:** The _data_, _dataRef_ and _guideStatePathRef_ must not be null simultaneously and only one property 18493 * must be specified. Specifying more than one can lead to undesired results. 18494 * @summary Populate the Adaptive Form from the data. 18495 * @param {object}
18495 options object containing the callbacks to be invoked on 18496 * success/failure and data from where to restore the object. 18497 * @param {function} [options.success] callback which receives the result of the API 18498 * in case of success 18499 * {@link GuideResultObject#errors|errors} property as false. 18500 * @param {function} [options.error] callback which receives the result of the API in 18501 * case of failure. 18502 * {@link GuideResultObject#errors|errors} property as true. 18503 * @param {object} [options.context] _this_ object inside the _success_ and _error_ callback will point to this 18504 * object. 18505 * @param {object} [options.data] It must be the value of the {@link GuideResultObject#data|data} property passed to 18506 * the _success_ handler of {@link GuideBridge#getGuideState|getGuideState} API. 18507 * @param {string} [options.dataRef] URL pointing to the data JSON/XML. 18508 * @param {string} [options.guideStatePathRef] URL pointing to the JSON state of Adaptive Form. 18509 * 18510 * @method 18511 * @memberof GuideBridge 18512 * @since 6.3 18513 * @instance 18514 * @example <caption>Setting data from JSON data</caption> 18515 * var jsonData; 18516 * guideBridge.getGuideState({ 18517 * success : function (guideResultObj) { 18518 * jsonData = guideResultObj.data; 18519 * }, 18520 * error : function (guideResultObj) { 18521 * // log the errors 18522 * } 18523 * }); 18524 * 18525 * guideBridge.setData({ 18526 * guideState : jsonData, 18527 * error : function (guideResultObject) { 18528 * // log the errors 18529 * } 18530 * }) 18531 * 18532 * @example <caption>Setting data from XML/JSON</caption> 18533 * guideBridge.getData({ 18534 * success : function (guideResultObj) { 18535 * var data = guideResultObj.data; 18536 * //post the XML/JSON to a server that saves it at say http://abc.com/my/data.xml 18537 * //or http://abc.com/my/data.json 18538 * }, 18539 * error : function (guideResultObj) { 18540 * // log the errors 18541 * } 18542 * }); 18543 * 18544 * guideBridge.setData({ 18545 * dataRef : "http://abc.com/my/data.xml", 18546 * error : function (guideResultObject) { 18547 * // log the errors 18548 * } 18549 * }) 18550 * 18551 * @example <caption>Setting data from URL to a JSON</caption> 18552 * guideBridge.getGuideState({ 18553 * success : function (guideResultObj) { 18554 * var json = guideResultObj.data; 18555 * //post the JSON to a server that saves it at say http://abc.com/my/data.json 18556 * }, 18557 * error : function (guideResultObj) { 18558 * // log the errors 18559 * } 18560 * }); 18561 * 18562 * guideBridge.setData({ 18563 * guideStatePathRef : "http://abc.com/my/data.json", 18564 * error : function (guideResultObject) { 18565 * // log the errors 18566 * } 18567 * }) 18568 **/ 18569 setData : function (options) { 18570 guideBridge.restoreGuideState(options); 18571 }, 18572 18573 /* 18574 * @private 18575 */ 18576 _getStorage : function () { 18577 var storage = null; 18578 if (this.storage) { 18579 // Get the storage 18580 storage = this.storage; 18581 this.storage = null; 18582 } 18583 return storage; 18584 }, 18585 18586 getGuideContext : function () { 18587 var obj = new GuideResultObject(); 18588 obj.data = jQuery.extend(true, {}, (this._guide ? this._guide.runtime.guideContext : null)); 18589 return obj; 18590 }, 18591 18592 _getContextRoot : function () { 18593 return this.userConfig["contextPath"]; 18594 }, 18595 18596 _getEnableFocusOnFirstField : function () { 18597 var renderConfig = this.userConfig.renderConfig || {}, 18598 enableFocusOnFirstField = renderConfig.enableFocusOnFirstField === undefined ? true : renderConfig.enableFocusOnFirstField, 18599 // convert "true"/"false" strings to boolean too 18600 enableFocusOnFirstFieldAsBoolean = enableFocusOnFirstField === 'true' || (enableFocusOnFirstField === 'false' ? false : enableFocusOnFirstField); 18601 // default value is true 18602 return enableFocusOnFirstFieldAsBoolean; 18603 }, 18604 18605 _updateAjaxUrl : function (baseUrl) { 18606 if (this.hostName === "server") { 18607 $.ajaxPrefilter(function (options, originalOptions, jqXHR) { 18608 // 'Rebase' the URL if required. 18609 var thisUrl = options.url; 18610 if ((thisUrl.lastIndexOf('http://', 0) !== 0) && (thisUrl.lastIndexOf('https://', 0) !== 0)) { 18611 // thisUrl is relative. 18612 // thisUrl may or may not begin with slash
18613 // encoding taken care by the ajax call 18614 if (thisUrl.indexOf("/") === 0) { 18615 // if begins with slash 18616 thisUrl = baseUrl + thisUrl; 18617 } else { 18618 thisUrl = baseUrl + "/" + thisUrl; 18619 } 18620 options.url = thisUrl; 18621 } 18622 }); 18623 18624 // Native XHR Wrapper 18625 var originalOpen = XMLHttpRequest.prototype.open; 18626 XMLHttpRequest.prototype.open = function(method, url) { 18627 if ((url.lastIndexOf('http://', 0) !== 0) && (url.lastIndexOf('https://', 0) !== 0)) { 18628 // url is relative 18629 if (url.indexOf("/") === 0) { 18630 url = baseUrl + url; 18631 } else { 18632 url = baseUrl + "/" + url; 18633 } 18634 } 18635 originalOpen.apply(this, arguments); 18636 }; 18637 } 18638 }, 18639 18640 _getUrl : function (url) { 18641 var baseUrl = this.userConfig["baseUrl"], 18642 contextPath = this.userConfig["contextPath"]; 18643 if (baseUrl) { 18644 return baseUrl + url; 18645 } else if (contextPath && contextPath !== "/" && url.indexOf(contextPath) !== 0 && (url.length === 0 || url.indexOf("/") === 0)) { 18646 //if url does not have contextPath and starts with /, pre-pend contextPath 18647 // Also url.length check because I need to pass "" to getUrl and get context path 18648 return contextPath + url; 18649 } 18650 return url; 18651 }, 18652 18653 _getGuidePathUrl : function (urlSuffix, guidePath) { 18654 // guidePath here refers to the path got from json state of guide 18655 // we use this path, if there is no guidePath set in guidelib.runtime.guideContext, cases where guide is not initialized but 18656 // guideBridge is present 18657 var path = guidePath || this.getGuidePath(), 18658 url = path + (urlSuffix || ""); 18659 return this._getUrl(url); 18660 }, 18661 18662 /** 18663 * @summary Returns the path which refers to the location of 18664 * the content resource of adaptive form container 18665 * @returns {String} Path to the content resource of the adaptive form container 18666 * @method 18667 * @memberof GuideBridge 18668 * @since 6.5 18669 * @instance 18670 */ 18671 getGuidePath : function () { 18672 var guideContext = this.getGuideContext().data; 18673 if (guideContext && guideContext.hasOwnProperty("guidePath")) { 18674 return guideContext["guidePath"]; 18675 } 18676 return null; 18677 }, 18678 18679 /** 18680 * @summary Given a somExpression, return the {@link GuideNode} having the same somExpression. 18681 * @param {string} somExpression somExpression of the Adaptive Form component 18682 * @returns {GuideNode} GuideNode matching the som expression or null if not found 18683 * @method 18684 * @memberof GuideBridge 18685 * @since 6.0 18686 * @instance 18687 * @see GuideNode#somExpression 18688 */ 18689 resolveNode : function (somExpression) { 18690 return this._guide.resolveNode(somExpression); 18691 }, 18692 /* 18693 * Internal API. Should be used carefully. 18694 */ 18695 _resolveId : function (id) { 18696 var node = this._guide._modelTemplateCacheStore.getModel(id); 18697 return node; 18698 }, 18699 18700 /** 18701 * Helper method for accesibility announcements 18702 * Is part of the fix for FORMS-7071 (CQ-4276669) 18703 */ 18704 _ariaLiveAnnouncement : function (text) { 18705 var ariaLiveElement = $("#ariaLiveElement"); 18706 setTimeout(function() { 18707 $(ariaLiveElement).text(text); 18708 return (setTimeout(function() { 18709 $(ariaLiveElement).text(""); 18710 }, 2000)) 18711 }, 500); 18712 }, 18713 18714 /** 18715 * Invokes {@link Field#resetData}
18715 API for all the Fields inside the Form to reset their values to default 18716 * @summary Reset the values of all the Fields to their default values. 18717 * 18718 * @method 18719 * @memberof GuideBridge 18720 * @instance 18721 * @since 6.0 18722 */ 18723 reset : function () { 18724 if (window.xfalib && window.xfalib.runtime && window.xfalib.runtime.xfa) { 18725 var xfa = window.xfalib.runtime.xfa; 18726 xfa.host.resetData(); 18727 } 18728 this._guide.resetData(); 18729 18730 if (this._guide.internal.liveDataUtils.isLiveDataInitialized()) { 18731 this._guide.internal.liveDataUtils.updateLiveData(); 18732 } 18733 18734 var guideDirtyMarkerAndVisitor = this._guide.internal.GuideDirtyMarkerAndVisitor; 18735 guideDirtyMarkerAndVisitor.visitMap = guidelib.model.util.CommonUtils.createMap(this._guide.allLazyChildren, 0); 18736 18737 this._ariaLiveAnnouncement(guidelib.i18n.strings["formHasBeenReset"]); 18738 }, 18739 18740 _getPreviousFocus : function () { 18741 return this._guideView._previousFocusItemSom; 18742 }, 18743 18744 /** 18745 * Returns the somExpression of the current {@link Panel} or current {@link Field} in Focus. The API can also 18746 * be used to get the somExpression of the Navigable Panel that contains the current Element in Focus. 18747 * 18748 * @summary return the somExpression of the {@link Panel} or {@link Field} that is currently in focus 18749 * @param {object} options configuration to be passed to the API to get the desired result 18750 * @param {?string} [options.focusOption] Currently the following value of this option are supported 18751 * * `navigablePanel`: if one wants to get the somExpression of the Navigable Panel 18752 * @returns {string} somExpression of Adaptive Form component representing the field or panel. 18753 * @method 18754 * @memberof GuideBridge 18755 * @instance 18756 * @since 6.0 18757 * @see {GuideNode#somExpression} 18758 * @example 18759 * guideBridge.getFocus({"focusOption": "navigablePanel"}) 18760 */ 18761 getFocus : function (options) { 18762 var focusOption; 18763 if (_.isUndefined(options)) { 18764 return this._guideView.currentFocusItemSom; 18765 } 18766 if ((focusOption = getOrElse(options, "focusOption", null)) === "navigablePanel") { 18767 return this._guideView._lastFocussedPanelForNonActionFields; 18768 } 18769 this._guide.logger().log("Invalid Focus option.", focusOption); 18770 }, 18771 18772 /** 18773 * The API is equivalent to calling 18774 * `guideBridge.setFocus(options.somExpression, options.focusOption, options.runCompletionScript)` 18775 * @summary An alternate signature to the {@link GuideBridge#setFocus|setFocus} API 18776 * @method setFocus 18777 * @memberof GuideBridge 18778 * @instance 18779 * @since 6.1 FP1 18780 * @param {object} options options passed to the API 18781 * @param {string} options.somExpression somExpression to set the focus to 18782 * @param {string} options.focusOption item inside the Panel to focus to 18783 * @param {string} options.runCompletionScript whether to run the completion script or not. 18784 * @return {boolean} true if the focus was set successfully otherwise false. 18785 */ 18786 18787 /** 18788 * In Adaptive Form one can focus a Field/Panel. Setting focus on a Panel means setting focus to its first 18789 * child. This can be controlled using the _focusOption_ provided in this API. 18790 * 18791 * The API provides two mechanism to focus a Field/Panel. 18792 * * **Direct** : By providing the somExpression of the Field/Panel. If the somExpression of Panel is provided, 18793 * then based on the focusOption one of its child (or their child) is set to Focus 18794 * * **Indirect** : By providing an item's relative position inside a Panel, first or last item inside of a 18795 * Panel, sibling of current focussed Item of a Panel, etc. If the item is a Panel then the First Item of 18796 * that Panel (if that is again a Panel, this process continues until a Field is found) is activated. 18797 * 18798 * The first way is trivial, by providing the _somExpression_ of a {@link Field} to the API, the focus will be 18799 * set to the Field. 18800 * 18801 * If that Field is inside a Panel that is not currently open because of tabbed/wizard navigation, then that tab 18802 * would be opened and focus would be set to the Field/Panel. 18803 * 18804 * The API can also execute the 18805 * [completion expression](https://helpx.adobe.com/aem-forms/6-1/adaptive-form-expressions.html#main-pars_header_8) 18806 * of the current Panel and only if the expression returns true set focus to the required element. 18807 * 18808 * **Note:** 18809 * * If _focusOption_ is either of nextItemDeep or prevItemDeep then _somExpression_ parameter must not be 18810 * passed. Otherwise the API will throw an exception 18811 * * If _somExpression_ points to a {@link Field} and _focusOption_ is not _nextItemDeep_ or _prevItemDeep_ then 18812 * _focusOption_ is ignored. 18813 * 18814 * @summary Sets focus to a {@link Field} or {@link Panel} 18815 * @param {?string} somExpression SOM Expression of the Adaptive Form Field or Panel which has to be activated. 18816 * @param {string} [focusOption=firstItem] The option provides the mechanism to focus onto an sibling of the 18817 * current active item. 18818 * * **_firstItem_** - Focuses to the first focusable item of the Panel whose _SOM Expression_ is provided 18819 * * **_lastItem_** - Focuses to the last focusable item of the Panel whose _SOM Expression_ is provided 18820 * 18821 * If either the _firstItem_ or _lastItem_ is a Panel, then the _firstItem_ of that Panel (until a Field is 18822 * found) is set to Focus. 18823 * 18824 * * **_nextItem_** - Next sibling component of the current active Item of the Panel whose _somExpression_ is 18825 * provided. It is equivalent to the result of `panel.navigationContext.nextItem` API. 18826 * * **prevItem** - Previous sibling component of the current active Item of the Panel show _somExpression_ is 18827 * provided. It is equivalent to the result of `panel.navigationContext.prevItem` API. 18828 * 18829 * * **_nextItemDeep_** - Focus is set to the next Navigable Panel of root Panel in DFS Order 18830 * * **_prevItemDeep_** - Focus is set to the next Navigable Panel of root Panel in DFS Order 18831 * @param {boolean} [runCompletionScript=false] indicating whether to execute the completion expression or not. 18832 * @returns {boolean} true if the focus was set to requested field successfully otherwise false 18833 * @method 18834 * @memberof GuideBridge 18835 * @since 6.0 18836 * @instance 18837 * @example 18838 * setFocus(somExpression); // Focus is set to the specified somExpression. 18839 * setFocus(this.panel.somExpression,'nextItem',true); // Focus is set to next item in the Panel. 18840 * setFocus(null,'nextItemDeep',true); // Focus is set to next navigable Panel in rootPanel 18841 */ 18842 setFocus : function (somExpression, focusOption, runCompletionScript) { 18843 var options, 18844 focusDone, 18845 originalSkipFieldFocus; 18846 if (_.isObject(somExpression)) { 18847 options = somExpression; 18848 } else { 18849 options = { 18850 somExpression : somExpression, 18851 focusOption : focusOption, 18852 runCompletionScript : runCompletionScript 18853 }; 18854 } 18855 try { 18856 originalSkipFieldFocus = this._guideView.skipFieldFocus; 18857 /** 18858 * Setting of this._guideView.skipFieldFocus was added for issue LC-3911361 18859 * Here we set a skipFieldFocus property for gudeContainerView, which prevents 18860 * actual 'input' / widget focus. This was done to prevent opening of keyboard or dropdown spinner 18861 * or date picker.. in case of swipe and use of deep navigators in mobile view of Adaptive Form. 18862 * 18863 * when user validates Adaptive Form, skipFieldFocus is set to options.skipFieldFocus based on somExpression 18864 * which has default value of'undefined' else the skipFieldFocus set to the negated value of global variable 18865 * enableFocusOnFirstField to enable/disable focus on first field of Adaptive Form. 18866 */ 18867 var fallbackSkipFieldFocus = !this._guide.enableFocusOnFirstField; 18868 if (!fallbackSkipFieldFocus) { 18869 fallbackSkipFieldFocus = !guideBridge._getEnableFocusOnFirstField(); 18870 } 18871 this._guideView.skipFieldFocus = options.somExpression ? options.skipFieldFocus : fallbackSkipFieldFocus; 18872 focusDone = this._guideView.setFocus(options); 18873 } finally { 18874 this._guideView.skipFieldFocus = originalSkipFieldFocus; //moving back to original state 18875 } 18876 //TODO: need a more common place to do that. 18877 if (!this._guide._currentContext) { 18878 this._guide.runPendingExpressions(); 18879 } 18880 return focusDone; 18881 }, 18882 18883 /** 18884 * Loads the lazy fragment specified by somExpression 18885 * @param {string} somExpression somexpression of the lazy loaded fragment 18886 * @param {object} options options to control the behaviour of loadLazyFragment API. 18887 * @param {object} [options.async] options to control if the fragment is to be loaded lazily 18888 * @param {function} [options.error] callback which receives the result of the API in 18889 * case of failure. 18890 * @method 18891 * @memberof GuideBridge 18892 * @since 6.4 18893 * @instance 18894 * @example <caption>Loading a lazy loaded fragment with somexpression x[0].y[0].z[0]. If both y and z form objects are lazy loaded, this API 18895 * would load both</caption> 18896 * guideBridge.loadLazyFragment("x[0].y[0].z[0]"); 18897 * 18898 */ 18899 loadLazyFragment : function (somExpression, options) { 18900 options = options || {}; 18901 if (!_.isUndefined(somExpression)) { 18902 var relativeSom = guidelib.util.GuideUtil.relativeSom(this._guide.rootPanel.somExpression, somExpression); 18903 if (relativeSom) { 18904 var somTokens = relativeSom.split("."); 18905 var currItem = this._guide.rootPanel; 18906 _.each(somTokens, function (qName, index) { 18907 if (currItem != null) { 18908 var arr = currItem._findChildren(qName, false); 18909 if (arr.length > 0) { 18910 var node = arr[0]; 18911 if (node && node._lazyReference && !node._itemsLoaded) { 18912 this._guide.internal.liveDataUtils.updateLiveData(); 18913 if (options.async) { 18914 var successFunc = (function () { 18915 return function (complete) { 18916 if (options.success) { // Check if success callback exists 18917 options.success.call(this, {lazyLoadingComplete: complete}); 18918 } 18919 } 18920 }(index === somTokens.length - 1)) 18921 } 18922 node._loadLazyFragment(options); 18923 } 18924 currItem = options.async === true ? null : node; 18925 } else { 18926 currItem = null; 18927 } 18928 } 18929 }, this); 18930 } 18931 } 18932 }, 18933 18934 /* 18935 * Get the download link of signed document set by signing service. 18936 * @return: url from where the signed document can be accessed, empty in case its not set by signing service. 18937 */ 18938 getSignedDocDownloadLink : function () { 18939 var url = ""; 18940 if (!_.isUndefined(FD) 18941 && !_.isUndefined(FD.AFaddon) 18942 && !_.isUndefined(FD.AFaddon.Signing) 18943 && !_.isUndefined(FD.AFaddon.Signing.signedDocDownloadLink)) { 18944 url = FD.AFaddon.Signing.signedDocDownloadLink; 18945 } 18946 return url; 18947 }, 18948 18949 /* 18950 If true is passed to the function then it checks for model and view both, 18951 if false or no parameter is passed, then it checks the model only. 18952 */ 18953 isGuideLoaded : function (complete) { 18954 if (complete) { 18955 return !_.isEmpty(window.guideBridge._guide && window.guideBridge._guideView); 18956 } 18957 return !_.isEmpty(window.guideBridge._guide); 18958 }, 18959 18960 _doInternalSubmit : function (options) { 18961 if (options.excludeFormState) { 18962 var submissionInfo = options.guideState.data.guideState.guideContext.afSubmissionInfo; 18963 if (submissionInfo && submissionInfo.hasOwnProperty('lastFocusItem')) { 18964 submissionInfo.lastFocusItem = undefined; 18965 } 18966 } 18967 // Make a clone of options so that original options are not modified. 18968 // Remove additionalSubmitInfo from the guideState so that no extra information 18969 // is sent to the server. 18970 var clonedGuideState = JSON.parse(JSON.stringify(options.guideState)); 18971 if (!_.isEmpty(clonedGuideState.data.guideState.additionalSubmitInfo)) { 18972 clonedGuideState.data.guideState.additionalSubmitInfo = {}; 18973 } 18974 var guideState = clonedGuideState, 18975 strContent = this.getMultipartData({ 18976 guideState : JSON.stringify(guideState.data), 18977 dorData : options.dorData || false, 18978 _charset_ : "UTF-8" 18979 }), 18980 // check if guide state is present, if yes get guide path from guide state 18981 // Specifically written for mobile workspace to getDataXML from current json state 18982 guidePath = ((guideState && guideState.data) ? guideState.data.guideState.guideContext.guidePath : null); 18983 18984 $.ajax({ 18985 url : this._getGuidePathUrl(".af.internalsubmit.jsp", guidePath), 18986 type : "POST", 18987 async : options.async || false, 18988 contentType : "multipart/form-data; charset=UTF-8; boundary=" + strContent[0], 18989 data : strContent[1], 18990 success : options.success, 18991 error : options.error 18992 }); 18993 }, 18994 18995 _submitInternal : function (options) { 18996 var self = this; 18997 options = options || {}; 18998 if (!options.guideState) { 18999 this.getGuideState({ 19000 "diff" : "diff", 19001 "fileUploadPath" : options.fileUploadPath, 19002 "success" : function (guideState) { 19003 self._doInternalSubmit({ 19004 guideState : guideState, 19005 success : options.success, 19006 error : options.error, 19007 async : options.async, 19008 excludeFormState : options.excludeFormState, 19009 dorData : options.dorData 19010 }); 19011 }, 19012 "error" : options.error, 19013 reducedJSON : true 19014 }); 19015 } else { 19016 this._doInternalSubmit({ 19017 guideState : options.guideState, 19018 success : options.success, 19019 error : options.error, 19020 async : options.async, 19021 excludeFormState : options.excludeFormState, 19022 dorData : options.dorData 19023 }); 19024
19024 } 19025 }, 19026 19027 getMultipartData : function (data) { 19028 //Start multipart formatting 19029 var initBoundary = this.randomString(); 19030 var strBoundary = "--" + initBoundary; 19031 var strMultipartBody = ""; 19032 var strCRLF = "\r\n"; 19033 19034 //Create multipart for each element of the form 19035 for (var key in data) { 19036 if (data.hasOwnProperty(key)) { 19037 var value = _.isObject(data[key]) ? JSON.stringify(data[key]) : data[key]; 19038 strMultipartBody += 19039 strBoundary + 19040 strCRLF + 19041 "Content-Disposition: form-data; name=\"" + key + "\"" + 19042 strCRLF + 19043 strCRLF + 19044 value + 19045 strCRLF; 19046 } 19047 } 19048 //End the body by delimiting it 19049 strMultipartBody += strBoundary + "--" + strCRLF; 19050 //Return boundary without -- and the multipart content 19051 return [initBoundary, strMultipartBody]; 19052 }, 19053 19054 randomString : function () { 19055 var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz"; 19056 var string_length = 8; 19057 var randomstring = ''; 19058 for (var i = 0; i < string_length; i++) { 19059 var rnum = Math.floor(Math.random() * chars.length); 19060 randomstring += chars.substring(rnum, rnum + 1); 19061 } 19062 return randomstring; 19063 }, 19064 19065 /* 19066 * Get the file Attachment map that contains a mapping of som expression vs path when files have been uploaded 19067 * and som expression vs name when the files have not yet been uploaded . 19068 * @return: map of som expression and paths. 19069 * @private 19070 */ 19071 getFileAttachmentMap : function () { 19072 var fileAttachmentMap = {}, 19073 fileAttachmentsList = window.guideBridge._getFileAttachmentsList(); 19074 for (var i = 0; i < fileAttachmentsList.length; i++) { 19075 var node = fileAttachmentsList[i]; 19076 if (!_.isEmpty(node.fileAttachment.value)) { 19077 fileAttachmentMap[node.somExpression] = node.fileAttachment.value; 19078 } 19079 } 19080 19081 var lazyAttachmentMap = this._guide.internal.liveDataUtils._getLazyAttachmentMap(); 19082 _.each(lazyAttachmentMap, function (mapObject, key) { 19083 fileAttachmentMap[key] = mapObject.value; 19084 }); 19085 return fileAttachmentMap; 19086 }, 19087 19088 /* 19089 * sets the value of the file attachment component based on the map that is passed. 19090 * @private 19091 */ 19092 putFileAttachmentMap : function (fileAttachmentMap) { 19093 _.each(fileAttachmentMap, function (value, som) { 19094 var node = guideBridge.resolveNode(som); 19095 node.fileAttachment.value = value; 19096 }); 19097 }, 19098 19099 _appendFileAttachmentsToFormData : function (dataForm, fileNameDomMap, fileAttachmentsList) { 19100 var fileNamesIndex, 19101 fileDoms = fileNameDomMap.fileDom, 19102 fileNames = fileNameDomMap.fileName, 19103 faPromise = {}, 19104 rejectedFileNames = [], 19105 isIOS = guidelib.util.GuideUtil._isIOS(), 19106 createUnorderedList = function (list, bulletChar) { 19107 var result = ""; 19108 for (var i = 0; i < list.length; ++i) { 19109 result += bulletChar + " " + list[i] + "\n"; 19110 } 19111 return "\n" + result; 19112 }, 19113 throwException = function (fileNames) { 19114 if (fileNames && fileNames.length > 0) { 19115 throw guidelib.util.GuideUtil.getLocalizedMessage("AF", guidelib.i18n.LogMessages["AEM-AF-901-024"], [createUnorderedList(fileNames, "•")]); 19116 } 19117 }; 19118 for (fileNamesIndex = 0; fileNamesIndex < fileNames.length; fileNamesIndex++) { 19119 // multiple files inside one filedom element & draft save case is handled. 19120 var currentFileNames = fileNames[fileNamesIndex].split("\n"); 19121 for (var fileIndex = 0; fileIndex < currentFileNames.length; fileIndex++) { 19122 if (currentFileNames[fileIndex] && _.isString(fileDoms[fileNamesIndex])) { 19123 //handle draft save scenario when fileDoms[fileNamesIndex] is string(URL) & currentFileNames[fileIndex] is a url 19124 dataForm.append("_guideFileAttachment." + guideBridge._getRelativeFilePath(currentFileNames[fileIndex]), fileDoms[fileNamesIndex]); 19125 } 19126 } 19127 } 19128 dataForm.append("_guideAttachments", fileNames.toString()); 19129 if (isIOS) { 19130 var allFAPromises = []; 19131 _.each(fileAttachmentsList, function (fileAttachmentModel, index) { 19132 var fileAttachmentWrapperPromises = fileAttachmentModel._fileAttachmentWrapperIOS; 19133 if (fileAttachmentWrapperPromises) { 19134 allFAPromises.push.apply(allFAPromises, fileAttachmentWrapperPromises); 19135 } 19136 });
19137 faPromise = Promise.allSettled(allFAPromises).then(function (results) { 19138 for (var pIndex = 0; pIndex < results.length; pIndex++) { 19139 // if status rejected, fail submission 19140 if (results[pIndex].status === "rejected") { 19141 rejectedFileNames.push(results[pIndex].reason); 19142 } else { 19143 var resultValue = results[pIndex].value; 19144 var completeNameOfFile = resultValue.formElementName + "/" + resultValue.name; 19145 dataForm.append(completeNameOfFile, resultValue.dataURLtoBlob(), resultValue.name); 19146 } 19147 } 19148 // to fail this promise, throw an exception here 19149 throwException(rejectedFileNames); 19150 return dataForm; 19151 }); 19152 } else { 19153 var allFileAccessPromise = []; 19154 for (fileNamesIndex = 0; fileNamesIndex < fileNames.length; fileNamesIndex++) { 19155 // multiple files inside one filedom element & draft save case is handled. 19156 var currentFileNames = fileNames[fileNamesIndex].split("\n"); 19157 for (var fileIndex = 0; fileIndex < currentFileNames.length; fileIndex++) { 19158 // in case of IOS, file binary is from file object, we use the in-memory data 19159 if (fileDoms[fileNamesIndex] && !_.isString(fileDoms[fileNamesIndex]) && fileDoms[fileNamesIndex].length > 0) { 19160 // promise is not supported in IE11 19161 // for IE11, we don't read file bytes 19162 if (window.Promise) { 19163 var fileAccessPromise = guidelib.util.GuideUtil._checkIfFileIsAccessible(currentFileNames[fileIndex], fileDoms[fileNamesIndex][0].files[fileIndex]); 19164 allFileAccessPromise.push(fileAccessPromise); 19165 } else { 19166 // append each file of input file element to formdata 19167 dataForm.append(currentFileNames[fileIndex], fileDoms[fileNamesIndex][0].files[fileIndex]); 19168 } 19169 19170 } 19171 } 19172 } 19173 // promise is not supported in IE11 19174 if (window.Promise) { 19175 faPromise = Promise.allSettled(allFileAccessPromise).then(function (results) { 19176 for (var pIndex = 0; pIndex < results.length; pIndex++) { 19177 // if status rejected, fail submission 19178 if (results[pIndex].status === "rejected") { 19179 rejectedFileNames.push(results[pIndex].reason); 19180 } else { 19181 var resultValue = results[pIndex].value; 19182 dataForm.append(resultValue.fileName, resultValue.file); 19183 } 19184 } 19185 throwException(rejectedFileNames); 19186 return dataForm; 19187 }); 19188 } else { 19189 faPromise = $.Deferred().resolve(dataForm); 19190 } 19191 } 19192 return faPromise; 19193 }, 19194 19195 doAjaxSubmitWithFileAttachment : function (actionUrl, submitData, options, fileAttachmentsList) { 19196 var _options = options || {}, 19197 self = this, 19198 dataForm = new FormData(), 19199 fileNameDomMap = this._juiceOutNameAndFileDomMap(fileAttachmentsList), 19200 faPromise = this._appendFileAttachmentsToFormData(dataForm, fileNameDomMap, fileAttachmentsList); 19201 19202 var _submitForm = function () { 19203 $.ajax({ 19204 url : actionUrl, 19205 type : "POST", 19206 processData : false, 19207 cache : false, 19208 contentType : false, 19209 dataType : 'json', 19210 data : dataForm, 19211 success : function (data) { 19212 self.doAjaxSubmitSuccess(data, _options); 19213 }, 19214 error : function (data) { 19215 self.doAjaxSubmitError(data, _options); 19216 } 19217 }); 19218 };
19219 faPromise.then(function (dataForm) { 19220 $.each(submitData, function (key, val) { 19221 if (typeof val == "object") { 19222 val = JSON.stringify(val); 19223 } 19224 dataForm.append(key, val); 19225 }); 19226 _submitForm(); 19227 }) 19228 .catch(function (e) { 19229 // handle errors here 19230 console.error(e); 19231 if (typeof e === "string") { 19232 guideBridge._handleSubmitError("", e); 19233 } else { 19234 guideBridge._handleSubmitError({ 19235 "status" : 400 19236 }); 19237 } 19238 19239 }); 19240 }, 19241 19242 doAjaxSubmit : function (actionUrl, submitData, options) { 19243 var _options = options || {}, 19244 self = this, 19245 asyncSubmit = _options.async !== false, 19246 strContent = this.getMultipartData(submitData); 19247 $.ajax({ 19248 url : actionUrl, 19249 type : "POST", 19250 traditional : true, 19251 async : asyncSubmit, 19252 contentType : "multipart/form-data; charset=UTF-8; boundary=" + strContent[0], 19253 data : strContent[1], 19254 success : function (data) { 19255 self.doAjaxSubmitSuccess(data, _options); 19256 }, 19257 error : function (data) { 19258 self.doAjaxSubmitError(data, _options); 19259 } 19260 }); 19261 }, 19262 19263 KEY_AF_SUCCESS_PAYLOAD : "afSuccessPayload", 19264 KEY_AF_SUCCESS_DOCUMENT_OF_RECORD : "afSuccessDocumentOfRecord", 19265 19266 doAjaxSubmitSuccess : function (data, options) { 19267 var guideResultObject = new GuideResultObject(); 19268 guideResultObject.data = data; 19269 guideResultObject.completed = true; 19270 // remove the submitting message too after success of ajax submit 19271 guideBridge._showGuideLoading(false); 19272 if (_.isFunction(options.success)) { 19273 options.success.call(options.context, guideResultObject); 19274 } else { 19275 if (data.hasOwnProperty("signingURL")) { 19276 // Adobe sign : FormFiller enabled case. 19277 window.location.href = data.signingURL; 19278 } else { 19279 var payload = {}; 19280 if (data.hasOwnProperty(guideBridge.KEY_AF_SUCCESS_PAYLOAD)) { 19281 try { 19282 payload = JSON.parse(data[guideBridge.KEY_AF_SUCCESS_PAYLOAD]); 19283 payload.data = this._guide.internal.afdata; 19284 if(data.hasOwnProperty(guideBridge.KEY_AF_SUCCESS_DOCUMENT_OF_RECORD)) { 19285 payload.dorUri = data[guideBridge.KEY_AF_SUCCESS_DOCUMENT_OF_RECORD]; 19286 } 19287 var schemaType = this._guide.runtime.guideContext.schemaType; 19288 if (!schemaType) { 19289 //TODO define a constant for schema Type. 19290 schemaType = "xmlschema"; 19291 } 19292 payload.contentType = schemaType; 19293 } catch (e) { 19294 guideBridge._guide.logger().log("Error while parsing AF Success Payload: " + e); 19295 } 19296 } 19297 guideBridge._guide.executeExpression("submitSuccess", payload); // Executing Rule Editor code for submit success. 19298 if (data.agreementId && guideBridge._guide._isFirstSignerFormFiller()) { 19299 guidelib.util.GuideUtil.redirectWithDelay(data.afSuccessRedirectUrl, 3000); 19300 } 19301 } 19302 } 19303 }, 19304 19305 doAjaxSubmitError : function (data, options) { 19306 var guideResultObject = new GuideResultObject(); 19307 guideResultObject.data = data; 19308 guideResultObject.completed = false;
19309 guideResultObject.addMessage(2, "Error in Async Submit", ""); 19310 guideBridge._showGuideLoading(false); 19311 if (_.isFunction(options.error)) { 19312 options.error.call(options.context, guideResultObject); 19313 } else { 19314 var errorPayload = {}; 19315 try { 19316 errorPayload = JSON.parse(data.responseText); 19317 } catch (e) { 19318 guideBridge._guide.logger().log("Error while parsing errorPayload." + e); 19319 } 19320 guideBridge._guide.executeExpression("submitError", errorPayload); //Executing Rule Editor code for submitError 19321 } 19322 }, 19323 19324 handleUpload : function () { 19325 self = this.self; 19326 this.submitData['_guideAttachments'] = this.attachments.toString(); 19327 _.each(this.attachments, function (att) { 19328 this.submitData["_guideFileAttachment." + att] = this.submitData['fileUrl'] + "/" + att; 19329 }, this); 19330 delete this.submitData['fileUrl']; 19331 self.doAjaxSubmit(this.actionUrl, this.submitData, this.options); 19332 }, 19333 19334 _handleSubmitError : function (data, message) { 19335 // case: show message if it exists, for example, there could be client side errors during submit 19336 if (message) { 19337 alert(message); 19338 } else { 19339 // based on http status show error, these errors are based on server side http response codes 19340 var status = Number(data.status); 19341 switch (status) { 19342 case 502: 19343 alert(guidelib.util.GuideUtil.getLocalizedMessage("AF", guidelib.i18n.LogMessages["AEM-AF-901-003"])); 19344 break; 19345 case 400: 19346 alert(guidelib.util.GuideUtil.getLocalizedMessage("AF", guidelib.i18n.LogMessages["AEM-AF-901-022"])); 19347 break; 19348 default: 19349 alert(guidelib.util.GuideUtil.getLocalizedMessage("AF", guidelib.i18n.LogMessages["AEM-AF-901-004"])); 19350 break; 19351 } 19352 } 19353 guideBridge._showGuideLoading(false); 19354 }, 19355 19356 updateSubmitData : function (fileAttachmentsList, submitData, fileList) { 19357 var fileCount = 0, 19358 attachments = [], 19359 name; 19360 if (fileList.length === 0 && fileAttachmentsList.length > 0) { 19361 _.each(fileAttachmentsList, function (fileUploadComponentId, index) { 19362 var currentCount = 0; 19363 var componentInModel = window.guideBridge._resolveId(fileUploadComponentId); 19364 var fileNameList = componentInModel["fileAttachment"].value; 19365 if (fileNameList) { 19366 var fileNames = fileNameList.split("\n"); 19367 _.each(fileNames, function (fileUrl, index) { 19368 name = componentInModel.name + "/" + fileUrl.substring(fileUrl.lastIndexOf("/") + 1); 19369 if (name) { 19370 attachments[fileCount++] = name; 19371 submitData["_guideFileAttachment." + name] = fileUrl; 19372 } 19373 }, this); 19374 } 19375 }, this); 19376 submitData['_guideAttachments'] = attachments; 19377 } else if (fileList.length > 0) { 19378 _.each(fileList, function (file, index) { 19379 name = guideBridge._getRelativeFilePath(file); 19380 attachments[fileCount++] = name; 19381 submitData["_guideFileAttachment." + name] = file; 19382 }, this); 19383 submitData['_guideAttachments'] = attachments; 19384 } 19385 }, 19386 19387 _collectFileUrls : function (event) { 19388 var list = [], 19389 fileUploadError = false; 19390 19391 // Populate list to have path of all the uploaded files. The file Attachment component whose model was 19392 // loaded would have their fileNames first followed by the list of file names of unloaded file upload components. 19393 _.each(this.attachments, function (attachment) { 19394 _.each(attachment.split("\n"), function (att) { 19395 // check if att is a url and hence push it directly to list 19396 if (_.isString(att) && att.match(/\//g).length > 1) { 19397 list.push(att); 19398 } else { 19399 list.push(this.fileUrl + "/" + att); 19400 } 19401 }, this); 19402 }, this); 19403 19404 var options = { 19405 fileUrlList : list, 19406 fileUploadModelsList : this.fileAttachmentsList, 19407 lazyAttachmentMap : guideBridge._guide.internal.liveDataUtils._getLazyAttachmentMap() 19408 }; 19409 guidelib.util.GuideUtil._updateFileModelsAndLazyMap(options); 19410 19411 var submitOptions = this.options.ajaxSubmitObject; 19412 if (submitOptions && submitOptions.ajaxSubmitDataHandler) { 19413 submitOptions.ajaxSubmitDataHandler.call(this.options.context, submitOptions.fileAttachmentsList, submitOptions.submitData, list); 19414 window.guideBridge.doAjaxSubmit(submitOptions.actionUrl, submitOptions.submitData, this.options); 19415 } else if (this.options.success) { 19416 //create the guideState now as the model has been updated with the latest values. 19417 //do this only during getGuideState and not on ajax submit 19418 guideBridge._createGuideStateAndLiveXml(this.options); 19419 this.options.success.call(this.options.context, this.options.obj); 19420 } 19421 19422 }, 19423 19424 _fileUploadFailed : function (event) { 19425 $.proxy(guideBridge._handleSubmitError({ 19426 "status" : "500" 19427 }), guideBridge); 19428 }, 19429 19430 // This function extracts the form name from the guideContainerPath. 19431 _getFormName : function (guidePath) { 19432 var formName = ""; 19433 if (guidePath) { 19434 var index = guidePath.indexOf("/jcr:content/guideContainer"); 19435 guidePath = guidePath.substring(0, index); 19436 formName = guidePath.substring(guidePath.lastIndexOf("/") + 1); 19437 } 19438 return formName; 19439 }, 19440 19441 /** 19442 * returns the form element to be used for submission in case of non-ajax 19443 * submit. 19444 * The function looks in the submitConfig for a form and if not present, 19445 * creates a new form 19446 * @returns {object} jQuery object for form element 19447 * @private 19448 */ 19449 _getFormForSubmission : function () { 19450 var submitConfig = this.userConfig.submitConfig || {}, 19451 form = submitConfig.form || $("<form method='post' enctype='multipart/form-data'></form>").appendTo($("body")); 19452 return $(form); 19453 }, 19454 19455 _getThankYouPageFromConfig : function () { 19456 var submitConfig = this.userConfig.submitConfig || {}; 19457 return submitConfig.thankyouPage; 19458 }, 19459 19460 /** 19461 * This function prepare the guideValueMap and returns it. 19462 * @returns A map consisting of name and value for all the unbound components 19463 * @private 19464 */ 19465 _prepareGuideValueMap : function () { 19466 var guideValueMap = {}, visitedMap = {}; 19467 this.visit(function (node) { 19468 if (!node.bindRef && !visitedMap[node.somExpression]) { 19469 if (node instanceof guidelib.model.Field && node.value) { 19470 visitedMap[node.somExpression] = true; 19471 guideValueMap[node.getAttribute("name")] = node.value; 19472 } else if (node instanceof guidelib.model.GuideCompositeField) { 19473 var obj = guideValueMap[node.getAttribute("name")] = {}; 19474 _.each(node.items, function (childNode, index) { 19475 visitedMap[childNode.somExpression] = true; 19476 if (childNode.value) { 19477 obj[childNode.getAttribute("name")] = childNode.value; 19478 } 19479 }, this); 19480 } 19481 } 19482 }); 19483 return guideValueMap; 19484 }, 19485 19486 _showGuideLoading : function (flag, msg) { 19487 if(!flag){ 19488 if(_focusedSubmitButtonModel){ 19489 _focusedSubmitButtonModel.enabled = true; 19490 _focusedSubmitButtonModel = null; 19491 } 19492 } 19493 var util = guidelib.util.GuideUtil; 19494 if (util) { 19495 util.showGuideLoading(flag); 19496 if (msg !== undefined) { 19497 util.showMessages(msg); 19498 } else { 19499 util.removeAllMessages(); 19500 } 19501 } 19502 }, 19503 19504 _submitAfterValidation : function (options, submitSuccess, submitError) { 19505 var self = this; 19506 if (guidelib.util.GuideUtil) { 19507 var msg = guidelib.i18n.strings.submittingForm; 19508 if (options && options.submissionSelector === 'agreement') { 19509 msg = guidelib.i18n.strings.generatingSignAgreement; 19510 } 19511 guidelib.util.GuideUtil.showMessages(msg); 19512 } 19513 // Trigger submitStart before calling internal submit. 19514 if (guideBridge.isGuideLoaded() && self._guide._triggerOnBridge) { 19515 self._guide._triggerOnBridge("submitStart", "", "", "", ""); 19516 } 19517 var excludeFormState = true; 19518 if (options && options.hasOwnProperty("excludeFormState")) { 19519 excludeFormState = options.excludeFormState; 19520 } 19521 try { 19522 var guideState = getOrElse(options, "guideState", null); 19523 if (guideState || guideBridge.isGuideLoaded()) { 19524 var twoStepSubmission = getOrElse(options, "twoStepSubmission", false); 19525 if (guideState || self._guide.xdpRef || twoStepSubmission) { 19526 self._submitInternal({ 19527 guideState : guideState, 19528 success : function () { 19529 try { 19530 submitSuccess.apply(self, arguments); 19531 } catch (e) { 19532 self._handleInternalSubmitError(submitError, self, arguments); 19533 } 19534 }, 19535 error : function () { 19536 self._handleInternalSubmitError(submitError, self, arguments); 19537 }, 19538 async : true, 19539 excludeFormState : excludeFormState 19540 }); 19541 } else { 19542 self.getFormDataString({ 19543 success : function () { 19544 try { 19545 submitSuccess.apply(self, arguments); 19546 } catch (e) { 19547 self._handleInternalSubmitError(submitError, self, arguments); 19548 } 19549 } 19550 }); 19551 } 19552 } else { 19553 console.error("Form Submission failed as the form doesn't exist on the page"); 19554 } 19555 } catch (e) { 19556 self._showGuideLoading(false); 19557 if (console && console.error) { 19558 console.error(e); 19559 } 19560 } 19561 }, 19562 19563 _handleCaptchaTimeout : function () { 19564 window.alert(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.LogMessages["AEM-AF-901-025"])); 19565 window.guideBridge.setEnabledAutoSave(_isAutoSaveEnabled); 19566 guideBridge._showGuideLoading(false); 19567 return; 19568 }, 19569 19570 /** 19571 * Validate and submits the data of the Adaptive Form to the pre-configured submit action. 19572 * 19573 * The success handler provided in the argument is executed only if the Adaptive Form is configured to use AJAX 19574 * for submission using {@link GuideBridge#registerConfig|registerConfig} API 19575 * @summary submits the Adaptive Form 19576 * @param {object} options options to control the behaviour of submit API. 19577 * @param {string} [options.submissionSelector] url selector governs the submission behaviour at server 19578 * Default value is "submit", other options are "agreement", "signSubmit" 19579 * @param {function} [options.success] callback which receives the result of the API 19580 * in case of success. 19581 * {@link GuideResultObject#errors|errors} property as false. 19582 * @param {function} [options.error] callback which receives the result of the API in 19583 * case of failure. 19584 * {@link GuideResultObject#errors|errors} property as true. 19585 * @param {object} [options.context] _this_ object inside the _success_ and _error_ callback will point to this 19586 * object 19587 * @param {boolean} [options.validate=true] whether to validate the form before submission or not 19588 * @method 19589 * @memberof GuideBridge 19590 * @since 6.0 19591 * @instance 19592 * @example <caption>Submitting the form without validation</caption> 19593 * guideBridge.submit({ 19594 * validate: false, 19595 * error : function (guideResultObject) {//log message} 19596 * }); 19597 * @example <caption>Submitting the form and showing a success message</caption> 19598 * guideBridge.registerConfig("submitConfig" : {"useAjax" : true}); 19599 * guideBridge.submit({ 19600 * validate: false, 19601 * error : function (guideResultObject) {//log message} 19602 * success : function (guideResultObject) {alert("data submitted successfully") 19603 * }); 19604 */ 19605 19606 submit : function (options) { 19607 // Disabling the submit button 19608 var focusedElementSOM = guideBridge.getFocus(); 19609 if(focusedElementSOM){ 19610 _focusedSubmitButtonModel = guideBridge.resolveNode(focusedElementSOM); 19611 _focusedSubmitButtonModel.enabled = false;
19612 } 19613 _isAutoSaveEnabled = window.guideBridge.getAutoSaveEnabledStatus(); 19614 //Disable auto save till submission is not completed 19615 if (_isAutoSaveEnabled) { 19616 window.guideBridge.setEnabledAutoSave(false); 19617 } 19618 var self = this; 19619 var guideContextFromOptions, 19620 runtimeGuideContext = getOrElse(this._guide, "runtime.guideContext", {}); 19621 if (getOrElse(options, "guideState", "")) { 19622 guideContextFromOptions = options.guideState.data.guideState.guideContext; 19623 } 19624 var localGuideContext = guideContextFromOptions || runtimeGuideContext; 19625 // to submit guideContainerForm which will be stopped so that autocomplete values can be remembered 19626 $(".guideContainerFormSubmitButton").click(); 19627 19628 window.guideBridge._populateBindRefToSomMap(); 19629 19630 function submitError(data) { 19631 self._ariaLiveAnnouncement(guidelib.i18n.strings["formSubmitFail"]); 19632 if (options && options.error) { 19633 options.error.call(options.context || this, data); 19634 } else { 19635 $.proxy(guideBridge._handleSubmitError(data), guideBridge); 19636 } 19637 } 19638 19639 function submitSuccess(result) { 19640 var isAjaxSubmit = false; 19641 19642 if (options) { 19643 isAjaxSubmit = options.success ? true : false; 19644 } 19645 options = options || {}; 19646 options.success = options.success || (self.userConfig.submitConfig || {}).submitSuccessHandler; 19647 isAjaxSubmit = isAjaxSubmit || (self.userConfig.submitConfig || {useAjax : false}).useAjax || guideBridge._guide.enableAsyncSubmission; 19648 var submitData = {}; 19649 19650 if (this.isGuideLoaded()) { 19651 var guideCaptchaList = []; 19652 this.visit(function (node) { 19653 if (node.className === "guideCaptcha") { 19654 guideCaptchaList.push(node); 19655 } 19656 }); 19657 var captchaModel = guideCaptchaList[0]; 19658 if (captchaModel) { 19659 var captchaData = window.guideBridge._getCaptchaData(captchaModel); 19660 submitData['captchaData'] = captchaData; 19661 } 19662 } 19663 19664 // check if guide state is present, if yes get guide path from guide state 19665 var guidePath = getOrElse(options, "guideState.data.guideState.guideContext.guidePath", ""), 19666 guideContainerPath = guidePath || window.guideBridge.getGuidePath(), 19667 aemFormComponentPath = this.userConfig.submitConfig ? this.userConfig.submitConfig.aemFormComponentPath : "", 19668 submissionSelector = options.submissionSelector || "submit", 19669 actionUrl = window.guideBridge._getGuidePathUrl(".af." + submissionSelector + ".jsp", guideContainerPath); 19670 19671 submitData['guideContainerPath'] = guideContainerPath; 19672 submitData['aemFormComponentPath'] = aemFormComponentPath; 19673 submitData['_asyncSubmit'] = isAjaxSubmit; 19674 submitData['_charset_'] = "UTF-8"; 19675 var customPropMap = localGuideContext.customPropertyMap || {}; 19676 // need to remove lastFocusItem from being sent as a different property 19677 // as it being sent in xml and with afSubmissionInfo as well. 19678 var whiteListedProperties = ["lastFocusItem"]; 19679 for (var prop in customPropMap) { 19680 if (customPropMap.hasOwnProperty(prop) && whiteListedProperties.indexOf(prop) < 0) { 19681 submitData[prop] = customPropMap[prop]; 19682 } 19683 } 19684 // todo: Have to remove the excludeFromDor map from the submission info, is this required ? 19685 if (this.isGuideLoaded()) {
19686 submitData['afSubmissionInfo'] = this._guide.runtime.guideContext.afSubmissionInfo || {}; 19687 } 19688 var resultJson = result, 19689 guideJson, 19690 data, 19691 fileAttachmentsList, 19692 attachments = [], 19693 fileCount = 0; 19694 if (resultJson.hasOwnProperty("guideValue")) { 19695 guideJson = resultJson.guideValue; 19696 } else if (!_.isUndefined(options.guideValueMap)) { 19697 guideJson = options.guideValueMap; 19698 } else { 19699 // todo: why is this required in client ? 19700 guideJson = window.guideBridge._prepareGuideValueMap(); 19701 } 19702 if (resultJson.hasOwnProperty("data")) { 19703 data = resultJson["data"]; 19704 } 19705 19706 if (resultJson.hasOwnProperty("fileAttachmentsList")) { 19707 fileAttachmentsList = resultJson["fileAttachmentsList"]; 19708 } 19709 19710 for (var key in guideJson) { 19711 if (guideJson.hasOwnProperty(key)) { 19712 submitData[key] = guideJson[key]; 19713 } 19714 } 19715 19716 if (data) { 19717 submitData['jcr:data'] = data; 19718 submitData['jcr:data@TypeHint'] = "Binary"; 19719 if (self.isGuideLoaded()) { 19720 self._guide.internal.afdata = data; 19721 } 19722 } 19723 if (!_.isUndefined(options.fileAttachmentMap)) { 19724 submitData.fileAttachmentMap = options.fileAttachmentMap; 19725 } else { 19726 //send the fileAttachmentMap through submit data to restore submission attachments for read only viewing 19727 submitData.fileAttachmentMap = JSON.stringify(guideBridge._getFileAttachmentMapForSubmit()); 19728 } 19729 // read the additional information from the guideState if it is passed in options 19730 // otherwise get the additional information from the DOM 19731 var additionalSubmitInfo = {}; 19732 if (options.guideState && options.guideState.data.guideState.additionalSubmitInfo) { 19733 additionalSubmitInfo = options.guideState.data.guideState.additionalSubmitInfo; 19734 } else { 19735 additionalSubmitInfo = guideBridge._getAdditionalSubmitInfo(); 19736 } 19737 // append additionalSubmitInfo to the submitData 19738 $.extend(true, submitData, additionalSubmitInfo); 19739 19740 if (isAjaxSubmit && isAjaxSubmit === true) { 19741 // if the fileAttachmentMap is passed in the options, then we don't need to upload the files as the map contains the uploaded path only. 19742 // we just update the submitData with the attachment information 19743 if (options.fileAttachmentMap) { 19744 var attachmentMap = JSON.parse(options.fileAttachmentMap); 19745 var keys = _.keys(attachmentMap); 19746 for (var i = 0; i < keys.length; i++) { 19747 if (attachmentMap[keys[i]]) { 19748 var fileNames = attachmentMap[keys[i]].split("\n"); 19749 for (var j = 0; j < fileNames.length; j++) { 19750 var name = guideBridge._getRelativeFilePath(fileNames[j]); 19751 attachments[fileCount++] = name; 19752 submitData["_guideFileAttachment." + name] = fileNames[j]; 19753 } 19754 } 19755 } 19756 submitData['_guideAttachments'] = attachments; 19757 self.doAjaxSubmit(actionUrl, submitData, options); 19758 } else { 19759 var attachedFilesList = []; 19760 var currentCount = 0; 19761 // need to check if the guide is loaded, as it is not available for mobile workspace app use case 19762 if (guideBridge.isGuideLoaded()) { 19763 attachedFilesList = window.guideBridge._getFileAttachmentsList(); 19764 } 19765 _.each(attachedFilesList, function (object) { 19766 var fileNameList = object["fileAttachment"].value; 19767 if (fileNameList) { 19768 currentCount++; 19769 } 19770 }); 19771 // If a file has been attached and isAjaxSubmit is true, then a UUID is generated and 19772 // the files are uploaded at temp storage path. 19773 // The submit data is updated with the attached files and then 19774 // doAjaxSubmit is called. 19775 if (currentCount > 0) { 19776 self.doAjaxSubmitWithFileAttachment(actionUrl, submitData, options, attachedFilesList); 19777 } else { 19778 self.doAjaxSubmit(actionUrl, submitData, options); 19779 } 19780 } 19781 } else { 19782 var $form = self._getFormForSubmission(); 19783 $form.attr('action', actionUrl); 19784 $form.attr('data-name', 'afSubmissionForm'); 19785 for (var fields in submitData) { 19786 if (submitData.hasOwnProperty(fields)) { 19787 var value = submitData[fields]; 19788 $("<input>").attr("type", "hidden") 19789 .attr("name", fields) 19790 .val(_.isObject(value) ? JSON.stringify(value) : value) 19791 .appendTo($form); 19792 } 19793 } 19794 /* 19795 * This means we did not do any preprocessing 19796 * for file attachments so fileAttachment list won't be present 19797 * so posting DOM for the files. 19798 * */ 19799 var attachmentNameDomMap = guideBridge._getFileNameFileDomMap(), 19800 fileNameList = [], 19801 _guideAttachments = ""; 19802 // A string containing the names of all the files that are attached is stored in the variable _guideAttachments. 19803 // For all the files that have been uploaded already and don't have a dom element are 19804 // added to $form with prefix "_guideFileAttachment." 19805 if (attachmentNameDomMap && attachmentNameDomMap.fileDom) { 19806 fileNameList = attachmentNameDomMap.fileName; 19807 _.each(attachmentNameDomMap.fileDom, function (file, index) { 19808 if (!_.isString(file)) { 19809 file.attr("name", fileNameList[index].split["\n"]) 19810 .attr("class", "hidden") 19811 .appendTo($form); 19812 _guideAttachments += fileNameList[index] + ","; 19813 } else { 19814 if (fileNameList[index]) { 19815 var name = guideBridge._getRelativeFilePath(fileNameList[index]); 19816 $("<input>").attr("type", "hidden") 19817 .attr("name", "_guideFileAttachment." + name) 19818 .attr("value", file) 19819 .appendTo($form); 19820 _guideAttachments += name + ","; 19821 } 19822 } 19823 }); 19824 } 19825 $("<input>").attr("type", "hidden") 19826 .attr("name", "_guideAttachments") 19827 .attr("value", _guideAttachments) 19828 .appendTo($form); 19829 19830 $form.submit(); 19831 } 19832 } 19833 19834 self._showGuideLoading(true, guidelib.i18n.strings.val
19834idatingForm); 19835 // since validate is synchronous call, putting this in timeout 19836 // so that html changes can be display 19837 setTimeout(function () { 19838 // update the snapshot just before validating 19839 // so that we get true state of play before loading panels 19840 if (guideBridge.isGuideLoaded() && guideBridge._guide.allLazyChildren && guideBridge._guide.allLazyChildren.length > 0) { 19841 self._guide.internal.liveDataUtils.updateLiveData(); 19842 } 19843 var isValid = false; 19844 try { 19845 isValid = self._performConditionalValidation(options); 19846 } catch (e) { 19847 isValid = false; 19848 } finally { 19849 self._showGuideLoading(true); 19850 } 19851 if (isValid) { 19852 /* Handle Invisible Recaptcha on form submission */ 19853 var recaptchaInvisibleElement = FD.isToggleEnabled(guidelib.util.FeatureToggleConstants.FT_TURNSTILE_HCAPTCHA) ? 19854 $("#captchaInvisible") : $("#recaptchaInvisible"); 19855 if (recaptchaInvisibleElement != undefined && recaptchaInvisibleElement.attr("af-recaptcha-execute") == "") { 19856 recaptchaInvisibleElement.trigger({ 19857 type: "recaptchaExecution", 19858 submitParameters: { 19859 options: options, 19860 success: submitSuccess, 19861 error: submitError 19862 }, 19863 triggerPostSubmission: true 19864 }); 19865 return; 19866 } 19867 guideBridge._submitAfterValidation(options, submitSuccess, submitError); 19868 } else { 19869 window.guideBridge.setEnabledAutoSave(_isAutoSaveEnabled); 19870 self._showGuideLoading(false); 19871 return; 19872 } 19873 }, 1); 19874 }, 19875 19876 /** 19877 * Save draft of the current adaptive form loaded 19878 * @param saveBtnConfig {object} Optional parameter for providing 19879 * @param options {object} Optional parameter options can consist of following - 19880 * <ul> 19881 * <li> success: {function} Handler executed in case when the draft is successfully saved</li> 19882 * <li> error: {function} Handler executed in case of draft failure</li> 19883 * <li> context {object} The context with which the success or error handler needs to be executed</li> 19884 * </ul> 19885 * 19886 */ 19887 handleDraftSave : function (saveBtnConfig, custom_options) { 19888 custom_options = $.extend({ 19889 success : $.noop, 19890 error : $.noop, 19891 context : this 19892 }, custom_options); 19893 // isAutoSaveTriggered is not a documented property. 19894 //handleDraftSave method is also called via auto save component,where we pass this value as true. 19895 // This flag is just set to understand if the call is triggered by auto save strategy or not 19896 custom_options.isAutoSaveTriggered = custom_options.isAutoSaveTriggered || false; 19897 19898 var options = { 19899 success : function (result) { 19900 var draftId = result.data.draftId; 19901 window.guideBridge.customContextProperty("draftId", draftId); 19902 /** if (!isAutoSaveTriggered) { 19903 $(".__FP_Saved_Message").show(); 19904 $(".__FP_Saved_Message").fadeOut(1600, "linear"); 19905 }**/ 19906 19907 window.guideBridge.trigger( 19908 "saveCompleted", 19909 window.guidelib.event.GuideModelEvent.createEvent("saveCompleted") 19910 ); 19911 var payload = {}; 19912 payload.draftId = draftId; 19913 payload.isAutoSaveTriggered = custom_options.isAutoSaveTriggered; 19914 guideBridge._guide.executeExpression("saveSuccess", payload); // Executing Rule Editor code for save success. 19915 // window.guideBridge._defaultSaveSuccessHandler(); 19916 custom_options.success.call(custom_options.context); 19917 }, 19918 error : function (result) { 19919 if (!custom_options.isAutoSaveTriggered) { 19920 if (result.status == "503") { 19921 alert(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.LogMessages["AEM-AF-901-008"])); 19922 } else { 19923 alert(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.LogMessages["AEM-AF-901-009"])); 19924 } 19925 } 19926 var errorPayload = {}; 19927 errorPayload.result = result; 19928 errorPayload.isAutoSaveTriggered = custom_options.isAutoSaveTriggered; 19929 guideBridge._guide.executeExpression("saveError", errorPayload); //Executing Rule Editor code for saveError 19930 custom_options.error.call(custom_options.context); 19931 } 19932 }; 19933 var guidePath = window.guideBridge.getGuidePath(); 19934 var draftId = window.guideBridge.customContextProperty("draftId") || ""; 19935 19936 var contextPath = window.guideBridge._getUrl(guidePath); 19937 var self = this; 19938 guideBridge.getFormDataObject({ 19939 "success" : function (resultObj) { 19940 window.guideBridge.trigger( 19941 "saveStarted", 19942 window.guidelib.event.GuideModelEvent.createEvent("saveStarted") 19943 ); 19944 var afFormData, 19945 htmlFormData; 19946 afFormData = resultObj.data; 19947 htmlFormData = afFormData.toHTMLFormData(); 19948 htmlFormData.append('draftId', draftId); 19949 self._doAjaxSubmitWithHTMLFormData(contextPath + ".af.save.jsp", htmlFormData, options); 19950 } 19951 }); 19952 }, 19953 19954 /** 19955 * @private 19956 */ 19957 _doAjaxSubmitWithHTMLFormData : function (actionURL, htmlFormData, options) { 19958 var self = this; 19959 $.ajax({ 19960 url : actionURL, 19961 type : "POST", 19962 processData : false, 19963 cache : false, 19964 contentType : false, 19965 dataType : 'json', 19966 data : htmlFormData, 19967 success : function (data) { 19968 self.doAjaxSubmitSuccess(data, options); 19969 }, 19970 error : function (data) { 19971 self.doAjaxSubmitError(data, options); 19972 } 19973 }); 19974 }, 19975 19976 /** 19977 * @private 19978 */ 19979 _handleInternalSubmitError : function (submitError, selfVar, args
19979) { 19980 try { 19981 submitError.apply(selfVar, args); 19982 } catch (e) { 19983 //ignoring the error 19984 } finally { 19985 guideBridge._showGuideLoading(false); 19986 19987 } 19988 }, 19989 /** 19990 * @private 19991 */ 19992 _getFileAttachmentMapForSubmit : function () { 19993 var fileAttachmentMap = {}, 19994 fileAttachmentsList = window.guideBridge._getFileAttachmentsList(); 19995 for (var i = 0; i < fileAttachmentsList.length; i++) { 19996 var node = fileAttachmentsList[i]; 19997 if (!_.isUndefined(node.value) && node.value.length > 0) { 19998 var attachmentList = node.value.split("\n"); 19999 for (var j = 0; j < attachmentList.length; j++) { 20000 attachmentList[j] = node.name + "/" + attachmentList[j]; 20001 } 20002 fileAttachmentMap[node.somExpression] = attachmentList.join('\n'); 20003 } 20004 } 20005 20006 var lazyAttachmentMap = this._guide.internal.liveDataUtils._getLazyAttachmentMap(); 20007 _.each(lazyAttachmentMap, function (mapObject, key) { 20008 var attachmentList = mapObject.value.split("\n"); 20009 for (var j = 0; j < attachmentList.length; j++) { 20010 attachmentList[j] = guidelib.util.GuideUtil.guideSomToComponentName(key) + "/" + attachmentList[j]; 20011 } 20012 fileAttachmentMap[key] = attachmentList.join('\n'); 20013 }); 20014 return fileAttachmentMap; 20015 }, 20016 20017 ERROR_CAUSED_BY : { 20018 CAPTCHA_VALIDATION : "CAPTCHA_VALIDATION", 20019 SERVER_SIDE_VALIDATION : "SERVER_SIDE_VALIDATION", 20020 FORM_SUBMISSION : "FORM_SUBMISSION", 20021 AGREEMENT_CREATION : "AGREEMENT_CREATION", 20022 SERVICE_INVOCATION_FAILURE: "SERVICE_INVOCATION_FAILURE" 20023 }, 20024 20025 /** 20026 * This API displays validation error messages at the field level corresponding to the input errorJson object 20027 * @summary Displays validation error messages at field level 20028 * @memberof GuideBridge 20029 * @instance 20030 * @param {object} errorJson json object containing the error messages in the [standard format](https://helpx.adobe.com/experience-manager/6-5/forms/using/custom-validation-message-adaptive-forms.html) 20031 * @see {@link https://helpx.adobe.com/experience-manager/6-5/forms/using/custom-validation-message-adaptive-forms.html%7CCustom validation message in adaptive form} 20032 */ 20033 handleServerValidationError : function (errorJson) { 20034 var self = this; 20035 if (errorJson) { 20036 var errors = errorJson.errors; 20037 if (errors && errors.length > 0) { 20038 var firstFocusableSom; 20039 _.each(errors, function (object, i) { 20040 var errMsg; 20041 if (object.errorMessages) { 20042 errMsg = object.errorMessages.join("\n"); 20043 } else { 20044 errMsg = object.errorMessage; 20045 } 20046 var som = (object.somExpression) ? object.somExpression : self._guide._bindRefMap[object.bindRef]; 20047 var node = self.resolveNode(som); 20048 20049 if (node) { 20050 if (!firstFocusableSom) { 20051 firstFocusableSom = som; 20052 } 20053 node.markAsInvalid(errMsg); 20054 } 20055 }); 20056 // set focus to first invalid node 20057 if (firstFocusableSom) { 20058 self.setFocus(firstFocusableSom); 20059 } 20060 } 20061 } 20062 }, 20063 20064 /* Handle the server side validation failure in case of submission fails. 20065 * This function handles Captcha validation as well as server side validation. 20066 * @private 20067 */ 20068 _handleServerValidationError : function (errorJson) { 20069 var self = this; 20070 window.guideBridge.setEnabledAutoSave(_isAutoSaveEnabled); 20071 if (errorJson) { 20072 if (errorJson.errorCausedBy && errorJson.errorCausedBy === this.ERROR_CAUSED_BY.CAPTCHA_VALIDATION) { 20073 var errors = errorJson.errors, 20074 firstFocusableSom = errors[0].somExpression; 20075 _.each(errors, function (object, i) { 20076 var somExpression = object.somExpression, 20077 errorMessage = object.errorMessage, 20078 guideCaptcha; 20079 /*Setting focus to load captcha's view. 20080 This is required when panel's children get loaded later. 20081 Setting focus ensures that view is loaded properly so that model can throw 20082 'guide.errorChanged' event and view can listen the same. 20083 */ 20084 self.setFocus(somExpression); 20085 guideCaptcha = self.resolveNode(somExpression); 20086 if (guideCaptcha) { 20087 guideCaptcha.showCaptchaError(errorMessage); 20088 } 20089 });
20090 //Setting focus to the first captcha element. 20091 self.setFocus(firstFocusableSom); 20092 } else if (errorJson.errorCausedBy && errorJson.errorCausedBy === this.ERROR_CAUSED_BY.FORM_SUBMISSION 20093 || errorJson.errorCausedBy === this.ERROR_CAUSED_BY.AGREEMENT_CREATION) { 20094 if (errorJson.errors && errorJson.errors.length > 0) { 20095 window.guideBridge.handleServerValidationError(errorJson); 20096 } else { 20097 var statusCode = errorJson.originCode ? Number(errorJson.originCode) : 500, 20098 errorMessage = statusCode === 400 ? (errorJson.errorMessage ? errorJson.errorMessage : "") : ""; 20099 // show the message returned by server only if if the HTTP status code is 400 20100 // this is done so that users could act upon the error and re-submit the form 20101 $.proxy(guideBridge._handleSubmitError({ 20102 "status" : statusCode 20103 }, errorMessage), guideBridge); 20104 } 20105 } else { 20106 //Everything else is "SERVER_SIDE_VALIDATION". Calling this as it was being called. 20107 window.guideBridge.handleServerValidationError(errorJson); 20108 } 20109 } 20110 }, 20111 20112 /* 20113 * Populates bindRefToSomMap. 20114 * This function is called during submission and during unloading of a lazy fragment 20115 * @param {node} is equal to the lazy loaded fragment model if this is called during lazy fragment unloading 20116 * @private 20117 */ 20118 _populateBindRefToSomMap : function (node) { 20119 20120 /* 20121 * While populating bindRefToSomMap we basically check if any panel is repeatable panel. 20122 * If a panel is repeatable, in that node and its descendant nodes we replace the bindRef 20123 * by corresponding json-pointer in the map. 20124 * parameter {jsonp} refers to the json-pointer of the parent node. It is valid if 20125 * some ancestor of current node in the hierarchy was a repeatable panel 20126 */ 20127 var bindRefToSomMapper = function (node, map, jsonp) { 20128 var path, bindref; 20129 if (node.bindRef) { 20130 if (node.repeatable) { // current node is a repeatable panel 20131 if (jsonp) { // some ancestor panel in the hierarchy was a repeatable panel 20132 path = jsonp + "/" + node.bindRef.split("/").slice(-1)[0] + "/" + node.index; 20133 bindref = path; 20134 } else { // current node is the first repeatable panel in the hierarchy 20135 path = node.bindRef + "/" + node.index; 20136 bindref = path; 20137 } 20138 } else { 20139 if (jsonp) { // some panel in the upper level was a repeatable panel 20140 path = jsonp + "/" + node.bindRef.split("/").slice(-1)[0]; 20141 bindref = path; 20142 } else { // no repeatable panel till now 20143 bindref = node.bindRef; 20144 } 20145 } 20146 map[bindref] = node.somExpression; 20147 } 20148 20149 if (node._children) { 20150 node._children.forEach(function (element) { 20151 bindRefToSomMapper(element, map, path); 20152 }); 20153 } 20154 }; 20155 var jsonp; 20156 20157 // since we support lazy-loading for a fragment upto only two level deep, the immediate parent panel 20158 // of a lazy-loaded fragment can atmost be a repeatable panel. so we only check the repeatability for the parent 20159 if (node && node.parent && node.parent.repeatable && node.parent.bindRef) { 20160 jsonp = node.parent.bindRef + "/" + node.parent.index; 20161 } 20162 20163 if (!node) { 20164 node = window.guideBridge._guide; 20165 } 20166 20167 if (window.guideBridge.isGuideLoaded()) { 20168 if (!window.guideBridge._guide._bindRefMap) { 20169 window.guideBridge._guide._bindRefMap = {}; 20170 } 20171 bindRefToSomMapper(node, window.guideBridge._guide._bindRefMap, jsonp); 20172 } 20173 }, 20174 20175 SELECTOR_FORM_CONTAINER : "#guideContainerForm", 20176 20177 THANK_YOU_OPTION : { 20178 PAGE : "page", 20179 MESSAGE : "message" 20180 }, 20181 20182 addDorDownloadLink: function (thankYouContent, dorUri, isSubmisionId) { 20183 if(isSubmisionId) { 20184 var guidePath = window.guideBridge.getGuidePath(); 20185 var contextPath = window.guideBridge._getUrl(guidePath); 20186 dorUri = contextPath + ".af.dor.pdf?submissionId="+dorUri; 20187 } 20188 var dorVariable = "$%7BAF_DocumentOfRecord%7D"; 20189 if (thankYouContent && thankYouContent.indexOf(dorVariable) !== -1) { 20190 var tempElement = document.createElement("div"); 20191 tempElement.innerHTML = thankYouContent; 20192 var anchorTags = tempElement.querySelectorAll("a"); 20193 for (var i=0; i<anchorTags.length; i++) { 20194 var tag = anchorTags.item(i); 20195 if(tag.getAttribute("href") == dorVariable) { 20196 tag.setAttribute("href", dorUri); 20197 tag.setAttribute("download", tag.getAttribute("title")); 20198 thankYouContent = tempElement.innerHTML; 20199 } 20200 } 20201 } 20202 return thankYouContent; 20203 }, 20204 /* 20205 * default Submit Success Handler. 20206 * This function handles the Thank You Page/Message 20207 */ 20208 _defaultSubmitSuccessHandler : function (successPayload) { 20209 if (successPayload) { 20210 if (successPayload.thankYouOption === this.THANK_YOU_OPTION.MESSAGE) { 20211 if ( FD.isToggleEnabled("FT_CQ-4325048") || FD.isToggleEnabled("FT_CQ-4340778")) { 20212 successPayload.thankYouContent = this.addDorDownloadLink(successPayload.thankYouContent, successPayload.dorUri, FD.isToggleEnabled("FT_CQ-4340778")); 20213 } 20214 var tyMessage = $("<div class='tyMessage'>" + successPayload.thankYouContent + "</div>"); 20215 $(this.SELECTOR_FORM_CONTAINER).replaceWith(tyMessage); 20216 tyMessage.attr({'tabindex': '-1', 20217 'role': 'alertdialog'}); 20218 tyMessage.focus(); 20219 } else if (successPayload.thankYouOption === this.THANK_YOU_OPTION.PAGE) { 20220 window.location.href = encodeURI(successPayload.thankYouContent); 20221 } 20222 } 20223 }, 20224 20225 _defaultSaveSuccessHandler : function (successPayload) { 20226 alert(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings["formSavedMessage"])); 20227 }, 20228 20229 _defaultSaveErrorHandler : function () { 20230 alert(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings["formSaveError"])); 20231 }, 20232 20233 // This function gets the relative path of the file.
20234 // Suppose the component Name is attachment and the file name is a.jpg, 20235 // then it will return "attachment/a.jpg" as the path 20236 _getRelativeFilePath : function (fileName) { 20237 var relPath = fileName; 20238 if (fileName.indexOf("/") !== -1) { 20239 var splitPath = fileName.split("/"); 20240 if (splitPath.length > 2) { 20241 relPath = splitPath[splitPath.length - 2] + "/" + splitPath[splitPath.length - 1]; 20242 } 20243 } 20244 return relPath; 20245 }, 20246 20247 // We do not need to validate if options.validate = false. 20248 // This function makes sure that validations are not performed when validate flag is false. 20249 // Validation is performed in all the other cases. 20250 _performConditionalValidation : function (options) { 20251 if (getOrElse(options, "validate", true)) { 20252 return guideBridge.validate(null, null, true, false); 20253 } 20254 return true; 20255 }, 20256 20257 /** 20258 * This API returns the HTML content of another Adaptive Form and optionally load the Form inside an HTML 20259 * element 20260 * 20261 * The {@link GuideResultObject#data|data} property of the result passed to success handler will contain the HTML of 20262 * the Form 20263 * @summary load an Adaptive Form given its path 20264 * @param {object} options object to pass to the API 20265 * @param {function} [options.success] callback which receives the result of the API 20266 * in case of success. 20267 * {@link GuideResultObject#errors|errors} property as false. 20268 * @param {function} [options.error] callback which receives the result of the API in 20269 * case of failure. 20270 * {@link GuideResultObject#errors|errors} property as true. 20271 * @param {object} [options.context] _this_ object inside the _success_ and _error_ callback will point to this 20272 * object 20273 * @param {string} options.path Path of the Adaptive Form whose HTML is required. If sever is running at a 20274 * context path, this parameter must have the context path 20275 * @param {string} [options.dataRef] URL of the resource that returns the XML. The protocol of the URL must 20276 * match the supported URL protocols 20277 * @param {string} [options.containerSelector] jquery Selector of the HTML element where to insert the HTML 20278 * of the form. 20279 * @method 20280 * @memberof GuideBridge 20281 * @since 6.1 FP1 20282 * @instance 20283 * @example 20284 * guideBridge.loadAdaptiveForm({ 20285 * success : function (guideResultObj) {console.log("html is " + guideResultObj.data)}, 20286 * error : function (guideResultObj) { //log errors}, 20287 * dataRef : "http://url/of/the/dataRef", 20288 * path : "/contextpath/content/dam/formsanddocuments/form1" 20289 * }) 20290 * @see {@link https://api.jquery.com/category/selectors/|jQuery selectors} 20291 * @see <a href="#guidebridge-api-usage" >GuideBridge API Usage</a> 20292 */ 20293 loadAdaptiveForm : function (options) { 20294 if (options && options.path) { 20295 // Let's covert the adaptive form asset path or af path 20296 // @todo: add notion of channel type in the options to load adaptive form 20297 var path = options.path.replace(FM_DAM_ROOT, FM_AF_ROOT); 20298 path += "/jcr:content/guideContainer.html"; 20299 $.ajax({ 20300 url : path, 20301 type : "GET", 20302 data : { 20303 // lets set the wcmmode to disabled 20304 wcmmode : "disabled", 20305 // Set the data reference 20306 "dataRef" : options.dataRef 20307 }, 20308 async : false, 20309 success : function (data) { 20310 // Get the container selector and do a replaceWith HTML 20311 // not using jquery since jquery create a separate array objects for script, link etc 20312 if (options.containerSelector) { 20313 //NOCHECKMARX - data is coming from serverside preventing Reflective XSS All Clients. 20314 $(options.containerSelector).html(data); 20315 } 20316 var guideResultObject = new GuideResultObject(); 20317 // data would here be html 20318 guideResultObject.data = data; 20319 guideResultObject.completed = true; 20320 if (options.success && _.isFunction(options.success)) { 20321 options.success.call(options.context, guideResultObject); 20322 } 20323 }, 20324 error : function (data) { 20325 var guideResultObject = new GuideResultObject();
20326 // data is an object containing xhr request, status and error 20327 guideResultObject.data = data; 20328 guideResultObject.completed = false; 20329 guideResultObject.addMessage(2, "Error in getting HTML of Adaptive Form: " + options.path, ""); 20330 if (options.error && _.isFunction(options.error)) { 20331 options.error.call(options.context, guideResultObject); 20332 } 20333 } 20334 }); 20335 } else { 20336 if (typeof(console) !== "undefined") { 20337 console.log("Path of Adaptive Form not specified to loadAdaptiveForm API"); 20338 } 20339 } 20340 }, 20341 20342 /** 20343 * Unloads the Form loaded using the {@link GuideBridge#loadAdaptiveForm|loadAdaptiveForm} API 20344 * @summary Unloads an adaptive Form from the browser, removing all the existing event listeners, data, html. 20345 * @param containerSelector jQuery Selector of the container, which contains the HTML of the Adaptive Form 20346 * @method 20347 * @memberof GuideBridge 20348 * @since 6.1 FP1 20349 * @instance 20350 * @see {@link https://api.jquery.com/category/selectors/|jQuery selectors} 20351 */ 20352 unloadAdaptiveForm : function (containerSelector) { 20353 guidelib.util.GuideUtil._unloadAdaptiveForm(containerSelector); 20354 }, 20355 20356 /** 20357 * Disables all the fields and global toolbar 20358 * @private 20359 */ 20360 _disableForm : function () { 20361 var rootPanel = guideBridge.resolveNode("guide[0].guide1[0].guideRootPanel[0]"), 20362 globalToolbar = guideBridge.resolveNode("guide[0].guide1[0].toolbar[0]"); 20363 20364 // The following API disables the loaded fields 20365 rootPanel.disableAllFields(); 20366 // The following API disables the form toolbar 20367 if (globalToolbar) { 20368 globalToolbar.disableAllFields(); 20369 } 20370 }, 20371 20372 /** 20373 * @summary Disables the adaptive form, i.e. it disables all the fields and buttons, including toolbar's button 20374 * @method 20375 * @memberof GuideBridge 20376 * @since 6.3 20377 */ 20378 disableForm : function () { 20379 guideBridge._disableForm(); 20380 //Listening on guideBridge for "elementLazyLoaded" event to disable lazily loaded fields 20381 guideBridge.on("elementLazyLoaded", guideBridge._disableForm); 20382 }, 20383 20384 _playGuideJson : function (options) { 20385 this._guide.setGuideState(guidelib.model.GuideSchema.prototype.GuideStateConstants.GUIDE_STATE_MERGE_PROGRESS); 20386 /* 20387 * no need to check here since merged json will not have xfaState if
20388 * xdp is invalid 20389 */ 20390 if (this._isXfaGuide() && options.guideState.xfaState && options.guideState.xfaState.xfaDom) { 20391 var that = this; 20392 window.formBridge.restoreFormState({ 20393 formState : options.guideState.xfaState, 20394 context : this, 20395 //NOCHECKMARX - This is error callback to be provided by the user of this API. 20396 error : options.error || defaultErrorHandler, 20397 success : function () { 20398 that._playNonXfaJson(options); 20399 } 20400 }); 20401 } else { 20402 this._playNonXfaJson(options); 20403 } 20404 }, 20405 20406 _playNonXfaJson : function (options) { 20407 // try to get xml-s from restore state 1st as they will be more relevant than the prefill state 20408 var xmlStr = getOrElse(options, "guideState.guideLiveData", null) 20409 || getOrElse(options, "guideState.guidePrefillXml", null), 20410 xfaXmlStr = getOrElse(options, "guideState.xfaState.currentContext.data", null) 20411 || JSON.parse(getOrElse(options, "guideState.xfaState.xfaRenderContext", "{}")).data, 20412 jsonStr = getOrElse(options, "guideState.guidePrefillJson", null); 20413 if (xmlStr || xfaXmlStr) { 20414 this._guide.internal.liveDataUtils.initLiveData(xmlStr, xfaXmlStr, 20415 _.isString(this._guide.xdpRef), _.isString(this._guide.xsdRef), 20416 this._guide.getAttribute("xsdRootElement")); 20417 this._guide.internal.liveModel.prefillCrossFragFields(this._guide); 20418 this._guide.internal.liveDataUtils.dropXfaXml(); 20419 } else if (jsonStr) { 20420 this._guide.internal.liveDataUtils.initLiveData(jsonStr, this._guide.runtime.guideContext); 20421 } else { 20422 this._guide.internal.liveDataUtils.initLiveData(null, null, 20423 _.isString(this._guide.xdpRef), _.isString(this._guide.xsdRef), 20424 this._guide.getAttribute("xsdRootElement")); 20425 } 20426 20427 // If the restore state is not stored in local storage,then use it from the json passed from the server 20428 if (options.guideState.guideDom) { 20429 this._guide.playJson(options.guideState.guideDom, options.attachments); 20430 } 20431 if (options.guideState.unboundDataMap && options.guideState.unboundDataMap.data) { 20432 this.visit(function (node) { 20433 if ((node instanceof guidelib.model.Field || node instanceof guidelib.model.GuideCompositeField) 20434 && !node.getAttribute("bindRef") && options.guideState.unboundDataMap.data[node.name]) { 20435 var nodeValue = options.guideState.unboundDataMap.data[node.name]; 20436 //If the xml had empty tag, an empty object will come in the map, so set to null. 20437 if (_.isObject(nodeValue) && _.isEmpty(nodeValue)) { 20438 node._setGuideValue(null); 20439 } else { 20440 node._setGuideValue(nodeValue); 20441 } 20442 20443 if (node.className === "guideRadioButton") { 20444 node.prevOnItem = node.getSelectedIndex(node.jsonModel._value); 20445 } 20446 } 20447 }); 20448 } 20449 this._guide.setGuideState(guidelib.model.GuideSchema.prototype.GuideStateConstants.GUIDE_STATE_MERGE_COMPLETE); 20450 this._guide.prepare(); 20451 20452 if (options.success) { 20453 options.success.call(this); 20454 } 20455 }, 20456 20457 _postExternalMessage : function (message) { 20458 if (this.userConfig["postExternalMessageConfig"] && _.isFunction(this.userConfig["postExternalMessageConfig"]["postExternalHandler"])) { 20459 var externalHandler = this.userConfig["postExternalMessageConfig"]["postExternalHandler"]; 20460 externalHandler(message); 20461 } 20462 }, 20463 20464 _isXfaGuide : function () { 20465 if (this._guide.xdpRef) { 20466 return true; 20467 } else { 20468 return false;
20469 } 20470 }, 20471 _readRuntimeLocale : function (runtimeLocale) { 20472 return this.customContextProperty("runtimeLocale", runtimeLocale); 20473 20474 }, 20475 20476 /* 20477 * checks whether xdp present in Adaptive Form is valid or not 20478 * This is verified by checking the xdpRef property in guideContext 20479 */ 20480 _isValidXFAGuide : function () { 20481 return !_.isUndefined(this._guide.runtime.guideContext.xdpRef); 20482 }, 20483 20484 _isEditDesignMode : function () { 20485 if (window.CQ && window.CQ.WCM && (window.CQ.WCM.isEditMode() || window.CQ.WCM.isDesignMode())) { 20486 return true; 20487 } else { 20488 return false; 20489 } 20490 }, 20491 20492 /** 20493 * @private 20494 */ 20495 _getUUID : function () { 20496 if (this._formInstanceUUID) { 20497 return this._formInstanceUUID; 20498 } 20499 //Generate the UUID for the form instance on client side 20500 this._formInstanceUUID = guideBridge._produceUUID(); 20501 return this._formInstanceUUID; 20502 }, 20503 20504 /** 20505 * This will produce new UUID 20506 * @returns {string} 20507 * @private 20508 */ 20509 _produceUUID : function () { 20510 var uuid = $('div.guideContainerWrapperNode').data("tmproot"), 20511 uuidSuffix = Math.floor((Math.random() * 10000) + 1), 20512 uuidCurrentTime = new Date().getTime(); 20513 return uuid + "_" + uuidCurrentTime + uuidSuffix; 20514 }, 20515 20516 /** 20517 * Signature of the callback for the GuideBridgeEvent Listener. It must be passed as handler in the 20518 * {@link GuideBridge#on|on} API. 20519 * @callback GuideBridge~GuideBridgeEventCallback 20520 * @param {jQuery.Event} event jQuery Event Object with target property being the instance of GuideBridge 20521 * @param {Object} payload Payload containing extra information in the API 20522 * @see {@link http://api.jquery.com/category/events/event-object/|jQuery.Event} 20523 * @since 6.0 20524 */ 20525 /** 20526 * The API can be used to add an event listener for events triggered by GuideBridge object 20527 * 20528 * @summary add a listener on a GuideBridge Event. 20529 * @param eventName {string} name of the event for which listener has to be added. It must be one of the 20530 * following events 20531 * * bridgeInitializeComplete 20532 * * elementEnableChanged 20533 * * elementFocusChanged 20534 * * elementHelpShown 20535 * * elementLazyLoaded 20536 * * elementNavigationChanged 20537 * * elementValidationStatusChanged 20538 * * elementValueChanged 20539 * * elementVisibleChanged: 20540 * * guideAutoSaveStart 20541 * * submitStart 20542 * * validationComplete 20543 * @param {function} handler callback to be invoked whenever the event is triggered. The signature of the 20544 * callback is {@link GuideBridge~GuideBridgeEventCallback|GuideBridgeEventCallback} 20545 * @param {object} [context] The _this_ object in the _handler_ will point to _context_ 20546 * 20547 * @method on 20548 * @memberof GuideBridge 20549 * @instance 20550 * @since 6.0 20551 */ 20552 on : function (eventName, handler, context) { 20553 this._$target.on(eventName, handler, context); 20554 }, 20555 20556 /** 20557 * Unregister the event registered using the {@link GuideBridge#on|on} function 20558 * 20559 * @param eventName {string} name of the event to un-register. 20560 * @param [selector] {string} selector which should match the one originally passed to guideBridge's on() while registering handlers 20561 * @param [handler] {function} handler which needs to un-registered. If not provided all the event listeners 20562 * will be unregistered 20563 * 20564 * @method off 20565 * @memberof GuideBridge 20566 * @instance 20567 * @since 6.0 20568 */ 20569 20570 off : function (eventName, selector, handler) { 20571 this._$target.off(eventName, selector, handler); 20572 }, 20573 20574 /** 20575 * Internal API 20576 * @param extraParamerts 20577 * @param eventName 20578 * @private 20579 */ 20580 trigger : function (eventName, extraParamerts) { 20581 this._$target.trigger(eventName, extraParamerts); 20582 }, 20583 20584 /** 20585 * If the name of the file attachments have to be made unique then the 20586 * vaule of this function would be true else false 20587 * @returns {*} 20588 * @private 20589 */ 20590 _makeFileNameUnique : function () { 20591 if (this._guide && this._guide.runtime && this._guide.runtime.guideContext) { 20592 return this._guide.runtime.guideContext.makeFileNameUnique; 20593 } 20594 }, 20595 /*this function is used to mince out 20596 * file attachmenemts name and dom in case of 20597 * anonymous user 20598 * */ 20599 _getFileNameFileDomMap : function () { 20600 var fileAttachmentsList = this._getFileAttachmentsList(); 20601 return this._juiceOutNameAndFileDomMap(fileAttachmentsList); 20602 }, 20603 20604 /** 20605 * Returns a list of file attachment wrapper object represeting all file binaries 20606 * @returns reference of {@link guidelib.model.FileAttachmentWrapper} 20607 * @method 20608 * @memberof GuideBridge 20609 * @since FaaCS 20610 * @instance 20611 */ 20612 getFileAttachmentWrapper : function () { 20613 var fileNameDomBindRefMap = this._getFileNameFileDomMap(), 20614 attachments = [], 20615 fileDoms = fileNameDomBindRefMap.fileDom, 20616 fileNames = fileNameDomBindRefMap.fileName, 20617 bindRefs = fileNameDomBindRefMap.fileBindRef, 20618 contentTypes = fileNameDomBindRefMap.fileContentType, 20619 _getFileName = function (fileName, componentName) { 20620 // if file name contains component name 20621 if (fileName.indexOf(componentName) !== -1) { 20622 return fileName.replace(componentName + "/", ""); 20623 } else if (fileName.indexOf("/") !== -1) { 20624 // if file name is a URL 20625 return fileName.substring(fileName.lastIndexOf('/') + 1); 20626 } 20627 }; 20628 20629 var fileNamesIndex; 20630 for (fileNamesIndex = 0; fileNamesIndex < fileNames.length; fileNamesIndex++) { 20631 // multiple files inside one filedom element & draft save case is handled. 20632 var currentFileNames = fileNames[fileNamesIndex].split("\n"); 20633 for (var fileIndex = 0; fileIndex < currentFileNames.length; fileIndex++) { 20634 if (fileDoms[fileNamesIndex] && !_.isString(fileDoms[fileNamesIndex]) && fileDoms[fileNamesIndex].length > 0) { 20635 // append each file of input file element 20636 attachments.push(new guidelib.model.FileAttachmentWrapper({ 20637 name : _getFileName(currentFileNames[fileIndex], bindRefs[fileNamesIndex]), 20638 data : fileDoms[fileNamesIndex][0].files[fileIndex], 20639 contentType : fileDoms[fileNamesIndex][0].files[fileIndex].type, 20640 bindRef : bindRefs[fileNamesIndex] 20641 })); 20642 } else if (currentFileNames[fileIndex]) { 20643 //handle draft save scenario when fileDoms[fileNamesIndex] is null & currentFileNames[fileIndex] is a url 20644 attachments.push(new guidelib.model.FileAttachmentWrapper({ 20645 name : _getFileName(guideBridge._getRelativeFilePath(currentFileNames[fileIndex]), bindRefs[fileNamesIndex]), 20646 data : fileDoms[fileNamesIndex], 20647 contentType : contentTypes[fileNamesIndex], 20648 bindRef : bindRefs[fileNamesIndex] 20649 })); 20650 20651 } 20652 } 20653 } 20654 return attachments; 20655 }, 20656 20657 /** 20658 * Returns the file attachment name and dom (input type=file) element
20659 * The returned object contains a list of file Doms and a list of corresponding file Names. 20660 * If the file is already uploaded, then the file DOM is null and file Name contains the URL. 20661 * @param fileAttachmentsList object list of file attachment models 20662 * @returns {{fileName: Array, fileDom: Array}} 20663 * @private 20664 */ 20665 _juiceOutNameAndFileDomMap : function (fileAttachmentsList) { 20666 var fileDoms = [], 20667 fullFileNames = [], 20668 fullContentTypes = [], 20669 fileBindRefs = [], 20670 fileContentTypes = [], 20671 fileCount = 0, 20672 loadedFileDoms = [], 20673 loadedBindRefs = [], 20674 loadedContentTypes = [], 20675 loadedFileNames = []; 20676 20677 _.each(fileAttachmentsList, function (fileAttachmentModel, index) { 20678 var fileName = fileAttachmentModel._getFileAttachmentNames(), 20679 fileAttachmentModelValue = fileAttachmentModel.value, 20680 effectiveBindRef = fileAttachmentModel._getEffectiveBindRef(), 20681 fileNameList = fileName; // even in case of makeFileNameUnique context set, fileName has the correct unique value 20682 if (fileNameList) { 20683 var fileNames = fileNameList.split("\n"); 20684 var fileList = $.extend(true, [], fileAttachmentModel.fileList); 20685 var fileNamesIndex = 0; 20686 20687 _.each(fileList, function (inputFileDOM, currIndex) { 20688 var fileNamesOfFileDom = null; 20689 20690 // case: if there is a file dom 20691 if (!_.isString(inputFileDOM)) { 20692 _.each(inputFileDOM[0].files, function (file) { 20693 var fileName = fileNames[fileNamesIndex++]; 20694 if (fileName) { 20695 if (fileNamesOfFileDom) { 20696 fileNamesOfFileDom += "\n" + fileAttachmentModel.name + "/" + fileName; 20697 } else { 20698 fileNamesOfFileDom = fileAttachmentModel.name + "/" + fileName; 20699 } 20700 } 20701 }); 20702 if (fileNamesOfFileDom != null) { 20703 // Check if the value exist in the file, this is done because in IE9 and IE10 the list 20704 // will have an extra empty dom 20705 if ($(inputFileDOM).val().length > 0) { 20706 $(inputFileDOM).attr('name', fileNamesOfFileDom); 20707 loadedFileNames[fileCount] = fileNamesOfFileDom; 20708 loadedBindRefs[fileCount] = effectiveBindRef; 20709 // since the api is internal, we are not setting this 20710 loadedContentTypes[fileCount] = null; // we don't set "\n" separated content type here 20711 loadedFileDoms[fileCount++] = $(inputFileDOM); 20712 } 20713 } 20714 } else { 20715 // these values are nothing but field present as part of guidelib.model.FileAttachmentWrapper 20716 // @note: to minimize the refactoring, not reusing the same model 20717 // since there is no file dom in case of draft reload, make it null 20718 loadedFileNames[fileCount] = fileAttachmentModel.name + "/" + fileNames[currIndex]; 20719 loadedBindRefs[fileCount] = effectiveBindRef; // we add effective bindRef here 20720 loadedContentTypes[fileCount] = fileAttachmentModel._getContentType(fileList[currIndex]); // we add effective bindRef here 20721 loadedFileDoms[fileCount++] = fileList[currIndex]; // we add the file URL in fileDom 20722 fileNamesIndex++; 20723 } 20724 }, this); 20725 20726 } 20727 }, this); 20728 20729 // create the dom and name map for lazy file upload components as well 20730 var lazyFileMap = this._guide.internal.liveDataUtils._getLazyAttachmentMap(), 20731 lazyFileDom = [], 20732 lazyFileBindRef = [], 20733 lazyFileContentType = [], 20734 lazyFileName = []; 20735 _.each(lazyFileMap, function (mapObject, key) { 20736 var fileList = mapObject.fileList; 20737 var fileUploadValue = mapObject.value.split("\n"); 20738 var fileUploadBindRef = mapObject.bindRef; 20739 var fileNames = mapObject.fileNames.split("\n"); 20740 var fileNamesIndex = 0; 20741 _.each(fileList, function (value) { 20742 if (!_.isString(value)) { 20743 var fileNamesOfFileDom = null; 20744 _.each(value[0].files, function (file) { 20745 var fileName = fileUploadValue[fileNamesIndex++]; 20746 if (fileName) { 20747 var fullName = guidelib.util.GuideUtil.guideSomToComponentName(key) + "/" + fileName; 20748 if (fileNamesOfFileDom) { 20749 fileNamesOfFileDom += "\n" + fullName; 20750 } else { 20751 fileNamesOfFileDom = fullName; 20752 } 20753 } 20754 }); 20755 20756 lazyFileDom.push(value); 20757 lazyFileName.push(fileNamesOfFileDom); 20758 } else { 20759 var fullName = guidelib.util.GuideUtil.guideSomToComponentName(key) + "/" + fileNames[fileNamesIndex]; 20760 lazyFileDom.push(value); 20761 lazyFileName.push(fullName); 20762 fileNamesIndex++; 20763 } 20764 lazyFileBindRef.push(fileUploadBindRef); 20765 lazyFileContentType.push(null); // todo: check if this use-case would ever hit 20766 }); 20767 }); 20768 20769 // concatenate the arrays for loaded and unloaded file doms and names 20770 fileDoms = loadedFileDoms.concat(lazyFileDom); 20771 fullFileNames = loadedFileNames.concat(lazyFileName); 20772 fileBindRefs = loadedBindRefs.concat(lazyFileBindRef); 20773 fileContentTypes = loadedContentTypes.concat(lazyFileContentType); 20774 20775 return { 20776 "fileName" : fullFileNames, 20777 "fileDom" : fileDoms, 20778 "fileBindRef" : fileBindRefs,
20779 "fileContentType" : fileContentTypes 20780 }; 20781 }, 20782 20783 setValidationContext : function (context) { 20784 var ec = guidelib.util.ErrorConstants; 20785 if (typeof ec[context] === "number") { 20786 var nContext = ec[context]; 20787 if (nValidationContext < nContext) { 20788 nValidationContext = nContext; 20789 sValidationContext = context; 20790 } 20791 } 20792 }, 20793 20794 unsetValidationContext : function (context) { 20795 if (context === sValidationContext) { 20796 nValidationContext = 0; 20797 sValidationContext = ""; 20798 } 20799 }, 20800 20801 getValidationContext : function () { 20802 return sValidationContext; 20803 }, 20804 20805 /** 20806 * @summary Enable/Disable the swipe gesture for navigation on touch devices. 20807 * @param swiptLeft boolean flag to enable(true)/disable(false) the swipe left gesture to perform next item navigation 20808 * @param swipeRight boolean flag to enable(true)/disable(false) the swipe right gesture to perform previous item navigation 20809 * @method 20810 * @memberof GuideBridge 20811 * @instance 20812 * @since 6.3 20813 */ 20814 enableSwipeGesture : function (swiptLeft, swipeRight) { 20815 $guideWrapperNode = $('.guideContainerWrapperNode'); 20816 $guideWrapperNode.off('swipeleft', window.guideBridge._performItemDeepNavigationNext); 20817 $guideWrapperNode.off('swiperight', window.guideBridge._performItemDeepNavigationPrevious); 20818 if (swiptLeft) { 20819 $guideWrapperNode.on('swipeleft', window.guideBridge._performItemDeepNavigationNext); 20820 } 20821 if (swipeRight) { 20822 $guideWrapperNode.on('swiperight', window.guideBridge._performItemDeepNavigationPrevious); 20823 } 20824 }, 20825 20826 /** 20827 * Enable the next item navigation (deep) using swipe left gesture 20828 * @private 20829 */ 20830 _performItemDeepNavigationNext : function () { 20831 window.guideBridge.setFocus({ 20832 somExpression : null, 20833 focusOption : 'nextItemDeep', 20834 runCompletionScript : true, 20835 skipFieldFocus : true 20836 }); 20837 }, 20838 20839 /** 20840 * Enable the previous item navigation (deep) using swipe right gesture 20841 * @private 20842 */ 20843 _performItemDeepNavigationPrevious : function () { 20844 window.guideBridge.setFocus({ 20845 somExpression : null, 20846 focusOption : 'prevItemDeep', 20847 runCompletionScript : true, 20848 skipFieldFocus : true 20849 }); 20850 }, 20851 20852 /** 20853 * Update the model popup that appears at click of file attachment listing button 20854 * This function is currently run of the clickExp of fileAttachmentListingButton 20855 * @param node 20856 * @private 20857 */ 20858 _updateFileListing : function (node) { 20859 var somExpression = node.somExpression, 20860 viewOfListingButton = guideBridge._guideView.getView(somExpression); 20861 viewOfListingButton._clearFileListing(); 20862 guideBridge.visit($.proxy(viewOfListingButton._updateFileListing, viewOfListingButton)); 20863 20864 }, 20865 20866 registerPanelProvider : function (panelProvider) { 20867 var resultObj = new GuideResultObject(); 20868 if (this.panelProvider == null) { 20869 resultObj.data = panelProvider; 20870 this.panelProvider = panelProvider; 20871 return resultObj; 20872 } 20873 resultObj.addMessage(2, "registrationError: PanelProvider already registered", ""); 20874 return resultObj; 20875 } 20876 }); 20877 20878 window.guideBridge = new GuideBridge(); 20879 window.guideBridge._$target = $(window.guideBridge); 20880 window.guideBridge.on("af.invisibleMandatoryRecaptchaInitialization", function (event, data) { 20881 var model = data.jsonModel.target.jsonModel; 20882 var formContainerSelector = FD.isToggleEnabled("FT_FORMS-11858") ? guidelib.util.GuideUtil.GUIDE_CONTAINER_FORM_CLASS : ".guideContainer,.aemformcontainer"; 20883 if(FD.isToggleEnabled(guidelib.util.FeatureToggleConstants.FT_TURNSTILE_HCAPTCHA)) { 20884 $(formContainerSelector).append('<div id="captchaInvisible"></div>'); 20885 var captchaInvisibleElement = $("#captchaInvisible"), captchaElement = $("[data-captchaservice]"); 20886 20887 captchaInvisibleElement.attr({ 20888 "modelId" : model.id || model.templateId, 20889 "af-recaptcha-execute" : "", 20890 "data-locale" : captchaElement.attr("data-locale") 20891 }); 20892 20893 if (model.captchaService === 'turnstile') { 20894 captchaInvisibleElement.on("recaptchaExecution", guidelib.util.CaptchaUtil.captchaExecution); 20895 var turnstileParameters = { 20896 'sitekey' : model.siteKey, 20897 'theme' : model.theme || 'light', 20898 'size' : model.size, 20899 'language' : captchaElement.attr('data-locale'), 20900 'execution' : 'execute' 20901 }; 20902 guidelib.util.CaptchaUtil.renderCaptcha(captchaInvisibleElement, model, 20903 model.clientJsUrl, 'cf-turnstile-response', turnstileParameters); 20904 } else if (model.captchaService === 'hcaptcha') { 20905 captchaInvisibleElement.on("recaptchaExecution", guidelib.util.CaptchaUtil.captchaExecution); 20906 var hcaptchaParameters = { 20907 'sitekey' : model.siteKey, 20908 'theme' : model.theme || 'light', 20909 'size' : model.size, 20910 }; 20911 guidelib.util.CaptchaUtil.renderCaptcha(captchaInvisibleElement, model, 20912 model.clientJsUrl, 'h-captcha-response', hcaptchaParameters); 20913 } else { 20914 captchaInvisibleElement.attr({ 20915 "data-externaldomain" : captchaElement.attr("data-externaldomain") 20916 }); 20917 captchaInvisibleElement.on("recaptchaExecution", guidelib.util.RecaptchaUtil.recaptchaExecution); 20918 guidelib.util.RecaptchaUtil.renderRecaptcha(captchaInvisibleElement, model); 20919 } 20920 } else { 20921 $(formContainerSelector).append('<div id="recaptchaInvisible"></div>'); 20922 var recaptchaInvisibleElement = $("#recaptchaInvisible"), captchaElement = $("[data-captchaservice]"); 20923 20924 recaptchaInvisibleElement.attr({ 20925 "modelId" : model.id || model.templateId, 20926 "af-recaptcha-execute" : "", 20927 "data-externaldomain" : captchaElement.attr("data-externaldomain"), 20928 "data-locale" : captchaElement.attr("data-locale") 20929 }); 20930 recaptchaInvisibleElement.on("recaptchaExecution", guidelib.util.RecaptchaUtil.recaptchaExecution); 20931 guidelib.util.RecaptchaUtil.renderRecaptcha(recaptchaInvisibleElement, model); 20932 } 20933 }); 20934 20935 try { 20936 var evnt = document.createEvent("CustomEvent"); 20937 evnt.initCustomEvent("bridgeInitializeStart", true, true, {"guideBridge" : window.guideBridge}); 20938 window.dispatchEvent(evnt); 20939 } catch (exception) { 20940 // written for env rhino to execute(for server side validation) 20941 // todo: once env rhino implements CustomEvent and initCustomEvent remove this 20942 // this._guide.logger().log(exception); 20943 } 20944 20945 if (!window.guideBridge.userConfig["postExternalMessageConfig"]) { 20946 if (window !== window.parent) { 20947 try { 20948 window.parent.document.getElementById(window.name); 20949 //We are here means no cross domain issue. So if user has not defined custom postExternalMessageConfig and 20950 // then we'll create one which would just send event on parent. 20951 window.guideBridge.registerConfig("postExternalMessageConfig", { 20952 "postExternalHandler" : function (message) { 20953 try { 20954 var tmpEvent = document.createEvent("CustomEvent"); 20955 tmpEvent.initCustomEvent(message.name, true, true, message.data); 20956 window.parent.dispatchEvent(tmpEvent); 20957 } catch (exception) { 20958 // written for env rhino to execute 20959 //this._guide.logger().log(exception); 20960 } 20961 } 20962 }); 20963 } catch (e) { 20964 //ignore the error 20965 } 20966 } 20967 } 20968 20969 window.guideBridge._postExternalMessage({ 20970 name : "bridgeInitializeStart", 20971 data : { 20972 "guideBridge" : window.guideBridge 20973 } 20974 }); 20975})($, _); 20976 20977/** 20978 * @package guidelib.model.DataNode 20979 * @version 0.0.1 20980 */ 20981 20982(function ($, _, guideBridge, guidelib, formBridge, xfalib) { 20983 20984 var LiveDataUtils = guidelib.model.LiveDataUtils = xfalib.ut.Class.extend({ 20985 20986 constants : { 20987 SKELETON_XML : '<afData><afUnboundData><data/></afUnboundData><afBoundData><data xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/"/></afBoundData></afData>', 20988 SKELETON_JSON : '{"afData":{"afUnboundData":{"data":{}},"afBoundData":{"data":{}}}}', 20989 UNBOUND_SKELETON : '<unBound></unBound>', 20990 UNBOUND_JSON_SKELETON : '{"afUnboundData":{}}', 20991 INDEXED_XPATH_PAT : new RegExp(/\/[^\/]+\[\d+\]/), 20992 INDEXED_XPATH_PAT_JSON : new RegExp(/\/[^\/]+\/\d+/), 20993 XFA_DATA_NODE_ATTR_NAME : "xfa:dataNode", 20994 XFA_DATA_NODE_ATTR_VALUE : "dataGroup", 20995 UNKNOWN_XSD_ROOT_ELEMENT : "?", 20996 AF_ROOT_TAG : "afData", 20997 BOUND_TAG : "afBoundData", 20998 UNBOUND_TAG : "afUnboundData", 20999 XFA_TAG : "xfa", 21000 DATA_TAG : "data", 21001 BOUND_DATA_XPATH : "afBoundData/data", 21002 UNBOUND_DATA_XPATH : "afUnboundData/data", 21003 AF_DRAFT_TAG : "afSubmissionInfo/afDraft" 21004 }, 21005 21006 initialize : function () { 21007 LiveDataUtils._super.initialize.call(this); 21008 this._boundDataRoot = null; 21009 this._unboundDataRoot = null; 21010 this._xfaDataRoot = null; 21011 this._fetchingClientSideData = false; // this state indicates that we are fetching client side data, its not use-case to fetch lazy data 21012 this.lazyAttachmentMap = {}; 21013 this.attachments = []; 21014 }, 21015 21016 /** 21017 * This function updates the lazy attachment Map from 21018 * the map passed 21019 * @param fileAttachmentMap 21020 * @private 21021 */ 21022 _updateLazyAttachmentMap : function(fileAttachmentMap) { 21023 _.each(fileAttachmentMap, function (value, key) { 21024 this.lazyAttachmentMap[key] = {}; 21025 this.lazyAttachmentMap[key].fileList = value.split("\n"); 21026 this.lazyAttachmentMap[key].value = value; 21027 }, this); 21028 }, 21029 21030 /** 21031 * This function updates the lazy attachment Map from the model. 21032 * It gets the value and fileList from the model and updates the map. 21033 * If the fileUpload component is not in a lazy panel then it removes 21034 * its entry form the map(if the entry is already there). 21035 * @param model 21036 * @private 21037 */ 21038 _updateLazyAttachmentMapFromModel : function (model) { 21039 // add the component in the map only when its in a lazy panel 21040 // add the entry in map only when its not not empty 21041 if (model.parent._selfOrAncestorIsLazyReference && model.value && model.fileList && !this._fetchingClientSideData) { 21042 this.lazyAttachmentMap[model.somExpression] = { 21043 value : model.value, 21044 fileList : model.fileList, 21045 bindRef : model._getEffectiveBindRef(), 21046 fileNames : model._getFileAttachmentNames() 21047 }; 21048 } else { 21049 if (this.lazyAttachmentMap[model.somExpression]) { 21050 delete this.lazyAttachmentMap[model.somExpression]; 21051 } 21052 } 21053 }, 21054 21055 /** 21056 * This function returns the value in the lazy attachment map for the model. 21057 * It removes the entry from the map as well. This is required so that the map gets 21058 * updated with the new values when the panel unloads. 21059 * @param model 21060 * @returns {*} 21061 * @private 21062 */ 21063 _getAttachmentDataForModel : function (model) { 21064 var effectiveBindRef = model._getEffectiveBindRef(); 21065 if (model.somExpression && !_.isEmpty(this.lazyAttachmentMap)) { 21066 var data = this.lazyAttachmentMap[model.somExpression]; 21067 delete this.lazyAttachmentMap[model.somExpression]; 21068 return data; 21069 } 21070 if (effectiveBindRef && !_.isEmpty(this.attachments)) { 21071 var data = model._getCurrentFileAttachmentWrapper(this.attachments); 21072 return data; 21073 } 21074 }, 21075 21076 _getLazyAttachmentMap : function () { 21077 return this.lazyAttachmentMap; 21078 }, 21079 21080 dropXfaXml : function () { 21081 this._xfaDataRoot = null; 21082 }, 21083 21084 // only called from test framework 21085 destroy : function () { 21086 this._liveDataDoc = null; 21087 this._boundDataRoot = null; 21088 this._unboundDataRoot = null; 21089 this._xfaDataRoot = null; 21090 }, 21091 21092 initLiveData : function (prefillDataStr, xfaPrefillDataStr, isXdp, isXsd, xsdRootElement, attachments) { 21093 this.attachments = attachments; 21094 }, 21095 21096 isLiveDataInitialized : function () { 21097 }, 21098 21099 getLiveDataStr : function () { 21100 }, 21101 21102 getLiveDataDoc : function () { 21103 return this._liveDataDoc; 21104 }, 21105 21106 _isNonNaked : function () { 21107 }, 21108 21109 _getNameAndIndex : function (xpathPart) { 21110 }, 21111 21112 isIndexedPath : function (xpath) { 21113 }, 21114 21115 _createElements : function (contextNode, xpathParts) { 21116 }, 21117 21118 _createRepeatedElements : function (contextNode, xpathParts) { 21119 }, 21120 21121 _createChildElement : function (parentElement, elemName) { 21122 }, 21123 21124 _createAttributeNode : function (parentElement, attrName) { 21125 }, 21126 21127 getContextNode : function (schemaPath, dataSection, createMissingNodes, lastNodeValue) { 21128 }, 21129 21130 addIndexToPath : function (path, index) { 21131 }, 21132 21133 _getElement : function (node, xpath, options) {}, 21134 21135 hasChildNodes : function (node) { 21136 }, 21137 21138 /** 21139 * Removes a child node from its parent 21140 * @param parentNode {Node} Parent Node from which to remove the child node 21141 * @param targetNode {String} Node name of the child to remove 21142 * @param index Index of the child node to remove 21143 */ 21144 removeChild : function (parentNode, targetNodeName, index) { 21145 }, 21146 21147 insertNode : function (parentNode, childNodeName, index) { 21148 }, 21149 21150 _getDataContext : function (model, bound_indexedXpathSoFar, unBound_indexedXpathSoFar) { 21151 var bindRef = model.bindRef, 21152 liveDataUtils = this, 21153 xmlSec, 21154 indexedXpath; 21155 21156 if (model._isXfaNode()) { 21157 xmlSec = liveDataUtils.constants.XFA_TAG; 21158 indexedXpath = xfalib.ut.XMLUtils.dataSom2xpath(model.dataSom); 21159 } else if (_.isEmpty(bindRef)) { 21160 xmlSec = liveDataUtils.constants.UNBOUND_TAG; 21161 indexedXpath = unBound_indexedXpathSoFar + '/' + model.getAttribute("name").replace(/\s+/g, ''); 21162 // use attr 'name' here, as schema might have an elem called 'name' 21163 } else { 21164 xmlSec = liveDataUtils.constants.BOUND_TAG; 21165 21166 var xpathMatch = liveDataUtils.getMatchingXpathHierarchy(bou
21166nd_indexedXpathSoFar, bindRef); 21167 if (xpathMatch.isCrossHierarchy) { 21168 indexedXpath = bindRef; 21169 } else { 21170 indexedXpath = bound_indexedXpathSoFar; 21171 if (!_.isEmpty(xpathMatch.suffixParts)) { 21172 indexedXpath += '/' + xpathMatch.suffixParts.join('/'); 21173 } 21174 } 21175 } 21176 21177 return { 21178 'xmlSec' : xmlSec, 21179 'indexedXpath' : indexedXpath 21180 }; 21181 }, 21182 21183 /** 21184 * return true if both xpath parts have same element name and indices 21185 * absence of index in the templateName is ignored 21186 * @param indexedName 21187 * @param templateName 21188 * @returns {boolean} 21189 * @private 21190 * @memberof LiveDataUtils 21191 */ 21192 _cmpXpathParts : function (indexedName, templateName) { 21193 }, 21194 21195 /** 21196 * get a partition of the matching xpath part hierarchy 21197 * the matching parts have same element names and agreeable indices 21198 * @param parentXpath 21199 * @param currentXpath 21200 * @returns {{prefixParts: Array, suffixParts: (*|Array.<T>|list), isCrossHierarchy: boolean}} 21201 * @memberof LiveDataUtils 21202 */ 21203 getMatchingXpathHierarchy : function (parentXpath, currentXpath) { 21204 var isCrossHierarchy = false, 21205 prefixParts = [], 21206 suffixParts = this._sanitizedXpathParts(currentXpath); 21207 21208 _.find(this._sanitizedXpathParts(parentXpath), function (parentPart) { 21209 if (this._cmpXpathParts(parentPart, suffixParts[0])) { 21210 prefixParts.push(parentPart); 21211 suffixParts.shift(); 21212 } else { 21213 isCrossHierarchy = true; 21214 return true; 21215 } 21216 }, this); 21217 21218 return { 21219 'prefixParts' : prefixParts, 21220 'suffixParts' : suffixParts, 21221 'isCrossHierarchy' : isCrossHierarchy 21222 }; 21223 }, 21224 21225 _getXpathContext : function (targetPanel) { 21226 var boundXpath = '', 21227 unBoundXpath = '', 21228 ancestors = [], 21229 panel = targetPanel.parent; 21230 21231 while (panel instanceof guidelib.model.GuidePanel) { 21232 if (panel._preserveLazyValue()) { 21233 ancestors.unshift(panel); 21234 } 21235 panel = panel.parent; 21236 } 21237 21238 _.each(ancestors, function (ancestor) { 21239 var xmlContext = ancestor._syncModelAndData(boundXpath, unBoundXpath); 21240 boundXpath = xmlContext.bound; 21241 unBoundXpath = xmlContext.unBound; 21242 }); 21243 21244 return { 21245 'bound' : boundXpath, 21246 'unBound' : unBoundXpath 21247 }; 21248 }, 21249 21250 _applyOnLiveData : function (action, targetPanel) { 21251 if (_.isString(targetPanel)) { 21252 targetPanel = guideBridge.resolveNode(targetPanel); 21253 } 21254 21255 if (targetPanel instanceof guidelib.model.GuidePanel) { 21256 var indexedXpathsFromRoot = targetPanel._guide().internal.liveDataUtils._getXpathContext(targetPanel); 21257 targetPanel[action](indexedXpathsFromRoot.bound, indexedXpathsFromRoot.unBound); 21258 } else { 21259 guideBridge._guide.rootPanel[action]('', ''); 21260 } 21261 }, 21262 21263 /** 21264 * will capture the currently loaded model hierarchy in a xml doc to be referred to later by lazily loaded panels 21265 * @private 21266 * @memberof LiveDataUtils 21267 */ 21268 updateLiveData : function (targetPanel, fetchingClientSideData) { 21269 this._fetchingClientSideData = !_.isUndefined(fetchingClientSideData); 21270 this._applyOnLiveData('_updateLiveData', targetPanel); 21271 this._fetchingClientSideData = false; 21272 }, 21273 21274 /** 21275 * will replay the model hierarchy from the live xml, for the supplied panel 21276 * @param targetPanel 21277 * @private 21278 * @memberof LiveDataUtils 21279 */ 21280 playLiveData : function (targetPanel) { 21281 this._applyOnLiveData('_playLiveData', targetPanel); 21282 }, 21283 21284 getListOfDirtyPanels : function (dataString) { 21285 return []; 21286 }, 21287 21288 addDataNodeInfo : function (contextNode) { 21289 }, 21290 21291 /** 21292 * Set the value of the node referred by xpath in the bounded/unbounded 21293 * section as specified by section. This optionally creates the data nodes 21294 * if they are not present 21295 * @param xpath 21296 * @param section 21297 * @param createMissingNodes 21298 * @param value 21299 */ 21300 setDataValue : function (xpath, section, createMissingNodes, value) { 21301 }, 21302 21303 /** 21304 * Set the rich text(html) value of the node referred by xpath in the bounded/unbounded 21305 * section as specified by section. This optionally creates the data nodes 21306 * if they are not present 21307 * @param xpath 21308 * @param xmlSection 21309 * @param createMissingNodes 21310 * @param value 21311 */ 21312 setRichTextValue : function (xpath, xmlSection, createMissingNodes, value) { 21313 this.setDataValue(xpath, xmlSection, createMissingNodes, value); 21314 }, 21315 21316 /** 21317 * Returns the value of the node referred by xpath in the bounded/unbounded 21318 * section as specified by section. It returns undefined if the node doesn't 21319 * exist 21320 * @param xpath 21321 * @param section 21322 */ 21323 getDataValue : function (xpath, section) { 21324 }, 21325 21326 _convertModelIndexToDataIndex : function (index) { 21327 }, 21328 21329 getParentRef : function (path) { 21330 }, 21331 21332 /** 21333 * returns the parent data node for the context specified by dataNodeContext 21334 * @param dataNodeContext {object} containing xpath and section 21335 * @param createIfMissing 21336 * @returns {*} 21337 * @param parentNodeValue 21338 */ 21339 getParentDataNode : function (dataNodeContext, createIfMissing, parentNodeValue) {
21340 var parentRef = this.getParentRef(dataNodeContext.indexedXpath), 21341 parentNode; 21342 if (_.isEmpty(parentRef)) { 21343 parentNode = this.getContextNode("", dataNodeContext.xmlSec, false); 21344 } else { 21345 parentNode = this.getContextNode(parentRef, dataNodeContext.xmlSec, createIfMissing, parentNodeValue); 21346 } 21347 return parentNode; 21348 }, 21349 21350 21351 /** 21352 * Insert submission Info in the data 21353 * @param submissionInfo {object} object containing the properties to be added as submission info in data 21354 */ 21355 insertSubmissionInfo : function (submissionInfo) { 21356 21357 } 21358 21359 }); 21360 21361}($, _, window.guideBridge, window.guidelib, window.formBridge, window.xfalib)); 21362 21363/** 21364 * @package guidelib.model.DataNode 21365 * @version 0.0.1 21366 */ 21367 21368(function ($, _, guideBridge, guidelib, formBridge, xfalib) { 21369 var getOrElse = xfalib.ut.XfaUtil.prototype.getOrElse; 21370 21371 var LiveJsonUtils = guidelib.model.LiveJsonUtils = guidelib.model.LiveDataUtils.extend({ 21372 21373 initialize : function () { 21374 LiveJsonUtils._super.initialize.call(this); 21375 this._liveDataDoc = null; 21376 }, 21377 21378 initLiveData : function (prefillDataStr, guideContext) { 21379 LiveJsonUtils._super.initLiveData.apply(this, arguments); 21380 prefillDataStr = prefillDataStr || getOrElse(guideContext, "guidePrefillJson", null); 21381 21382 if (_.isString(prefillDataStr) && prefillDataStr.length > 0) { 21383 var prefillDataDoc = JSON.parse(prefillDataStr); 21384 21385 if (this._isNonNaked(prefillDataDoc)) { 21386 // non naked json, assuming full hierarchy afdata/afbounddata/data 21387 this._liveDataDoc = prefillDataDoc; 21388 this._boundDataRoot = this._getElement(this._liveDataDoc.afData, this.constants.BOUND_DATA_XPATH); 21389 this._unboundDataRoot = this._getElement(this._liveDataDoc.afData, this.constants.UNBOUND_DATA_XPATH); 21390 21391 } else { 21392 // naked json start from prefill data root 21393 this._boundDataRoot = prefillDataDoc; 21394 this._unboundDataRoot = JSON.parse(this.constants.UNBOUND_JSON_SKELETON)[this.constants.UNBOUND_TAG]; // need this for unbound data fill across lazy 21395 this._liveDataDoc = prefillDataDoc; 21396 } 21397 } else { 21398 // init default skeleton for no prefill cases 21399 this._liveDataDoc = JSON.parse(this.constants.SKELETON_JSON); 21400 this._boundDataRoot = this._getElement(this._liveDataDoc.afData, this.constants.BOUND_DATA_XPATH); 21401 this._unboundDataRoot = this._getElement(this._liveDataDoc.afData, this.constants.UNBOUND_DATA_XPATH); 21402 } 21403 if (this._boundDataRoot == null && this._isNonNaked(prefillDataDoc)) { 21404 this._liveDataDoc.afData.afBoundData = this._liveDataDoc.afData.afBoundData || {}; 21405 this._liveDataDoc.afData.afBoundData.data = this._liveDataDoc.afData.afBoundData.data || {}; 21406 this._boundDataRoot = this._liveDataDoc.afData.afBoundData.data; 21407 } 21408 }, 21409 21410 /* 21411 * This API gets the element w.r.t to the node. 21412 * Eg - path is a/b/c, then it converts the path to a.b.c and then searches for c. 21413 */ 21414 _getElement : function (node, path, options) { 21415 if (!(node instanceof Object)) { 21416 return null; 21417 } 21418 21419 if (_.isEmpty(path) || !_.isString(path)) { 21420 return node; 21421 } 21422 options = options || {}; 21423 var index = options.index; 21424 var convertedPath = path.split('/').join('.'); 21425 if (!(_.isUndefined(index) || _.isNull(index))) { 21426 convertedPath = convertedPath + "." + index; 21427 } 21428 return getOrElse(node, convertedPath, null); 21429 }, 21430 21431 /** 21432 * This function checks if the data contains naked or non naked json 21433 * @returns {boolean} returns true if there exists a afData node inside data 21434 * @private 21435 * @memberof LiveJsonUtils 21436 * @param prefillData 21437 */ 21438 _isNonNaked : function (prefillData) { 21439 prefillData = prefillData || this.getLiveDataDoc(); 21440 if (prefillData) { 21441 return prefillData.hasOwnProperty("afData"); 21442 } else { 21443 return false;
21444 } 21445 }, 21446 21447 isLiveDataInitialized : function () { 21448 return (this.getLiveDataDoc() instanceof Object); 21449 }, 21450 21451 getLiveDataStr : function () { 21452 if (this.isLiveDataInitialized()) { 21453 return JSON.stringify(this.getLiveDataDoc()); 21454 } else { 21455 return ''; 21456 } 21457 }, 21458 21459 /* 21460 * This API will remove the spaces,"\" from the path. 21461 * It will return an array after splitting the path. 21462 * Eg - for a/0/b/c, it will return ["a/0","b","c"] 21463 */ 21464 _sanitizedXpathParts : function (path) { 21465 var pathParts = (path || '').replace(/^\//, '').replace(/\s+/g, ''); 21466 pathParts = this._splitForIndex(pathParts); 21467 21468 return _.filter(pathParts, function (xpathPart) { 21469 return this._getNameAndIndex(xpathPart) !== null; 21470 }, this); 21471 }, 21472 21473 _splitForIndex : function (path) { 21474 var pathArray = []; 21475 var pathParts = path.split('/'); 21476 for (var i = 0; i < pathParts.length; i++) { 21477 var str = pathParts[i]; 21478 if ((i + 1) < pathParts.length && !isNaN(pathParts[i + 1]) && !_.isEmpty(pathParts[i + 1])) {
21479 str = str + "/" + pathParts[i + 1]; 21480 i = i + 1; 21481 } 21482 pathArray.push(str); 21483 } 21484 return pathArray; 21485 }, 21486 21487 /** 21488 * Returns the index associated with the pathPart. 21489 * Eg - if pathPart is 'a/1', then it returns {name : a, index : 1} 21490 * @param pathPart 21491 * @returns {*} 21492 * @private 21493 */ 21494 _getNameAndIndex : function (pathPart) { 21495 if (pathPart) { 21496 var elName = pathPart.match(/^([^\s\/]+)(?:\/(\d+))?$/); // match the whole string 21497 if (elName !== null) { 21498 return { 21499 name : elName[1], 21500 index : elName[2] ? parseInt(elName[2]) : -1 21501 // -1 index for depicting non repeatable element 21502 }; 21503 } 21504 } 21505 return null; 21506 }, 21507 21508 _cmpXpathParts : function (indexedName, templateName) { 21509 if (indexedName && templateName) { 21510 var match1 = this._getNameAndIndex(indexedName), 21511 match2 = this._getNameAndIndex(templateName); 21512 return !_.isEmpty(match1 && match2) 21513 && match1.name === match2.name 21514 && (match2.index === -1 || match1.index === match2.index); 21515 } 21516 return false; 21517 }, 21518 21519 /** 21520 * This function gets or creates the node if its not there. The node can be any valid JSON Value 21521 * null, string, object, array, number, boolean. 21522 * @param schemaPath 21523 * @param dataSection 21524 * @param createMissingNodes 21525 * @param lastNodeValue 21526 * @returns {*} 21527 */ 21528 getContextNode : function (schemaPath, dataSection, createMissingNodes, lastNodeValue) { 21529 var contextNode, 21530 baseContextNode, 21531 basePath = "", 21532 pathParts = this._sanitizedXpathParts(schemaPath); 21533 if (dataSection == this.constants.BOUND_TAG) { 21534 baseContextNode = this._boundDataRoot; 21535 if (this._isNonNaked(this._liveDataDoc)) { 21536 basePath = "afData/" + this.constants.BOUND_DATA_XPATH + "/"; 21537 } 21538 } else if (dataSection === this.constants.UNBOUND_TAG) { 21539 baseContextNode = this._unboundDataRoot; 21540 if (this._isNonNaked(this._liveDataDoc)) { 21541 basePath = "afData/" + this.constants.UNBOUND_DATA_XPATH + "/"; 21542 } 21543 } 21544 if (!_.isEmpty(pathParts)) { 21545 var path = (basePath + pathParts.join('/')); 21546 21547 // return baseContextNode for naked json. path can be "" only for naked json. 21548 if (path == "" && !this._isNonNaked(this._liveDataDoc)) { 21549 return baseContextNode; 21550 } 21551 21552 contextNode = this._getElement(this._liveDataDoc, path); 21553 if (!contextNode && createMissingNodes) { 21554 contextNode = this._createElements(baseContextNode, pathParts, lastNodeValue); 21555 } 21556 } else { 21557 contextNode = baseContextNode; 21558 } 21559 return contextNode; 21560 }, 21561 21562 /** 21563 * This function creates the node at the path. 21564 * 21565 * @param contextNode 21566 * @param pathParts 21567 * @returns {*} 21568 * @private 21569 * @param lastNodeValue 21570 */ 21571 _createElements : function (contextNode, pathParts, lastNodeValue) { 21572 if (!(contextNode instanceof Object)) { 21573 return null; 21574 } 21575 21576 if (_.isEmpty(pathParts)) { 21577 return contextNode; 21578 } 21579 21580 // recurse and create one level of tags at a time 21581 contextNode = this._createRepeatedElements(contextNode, pathParts, lastNodeValue); 21582 return contextNode; 21583 }, 21584 21585 // it will always return the parent node after checking the last token 21586 _createRepeatedElements : function (contextNode, pathParts, lastNodeValue) { 21587 var childContextNode = contextNode, 21588 xpathPart = this._getNameAndIndex(pathParts[0]), 21589 elemName = xpathPart.name, 21590 index = xpathPart.index || 0, 21591 i, 21592 isLastToken = (pathParts.length == 1), 21593 elementNode = contextNode[elemName]; 21594 // -1 signifies non repeating element 21595 if (index === -1) { 21596 if (elementNode == null) { 21597 childContextNode = this._createChildElement(contextNode, elemName, isLastToken, lastNodeValue); 21598 } else { 21599 childContextNode = elementNode; 21600 } 21601 // if its the last token, then stop recursion here and return the created node 21602 if (isLastToken) { 21603 return childContextNode; 21604 } 21605 } else { 21606 if (elementNode != null) { 21607 var numOfChildren = elementNode.length; 21608 if (numOfChildren < index + 1) { 21609 // create immediate 'extra' children 21610 for (i = numOfChildren; i < index + 1; ++i) { 21611 childContextNode = {}; 21612 contextNode[elemName].push(childContextNode); 21613 } 21614 } else { 21615 childContextNode = elementNode[index]; 21616 } 21617 } else { 21618 contextNode[elemName] = []; 21619 for (i = 0; i < index + 1; ++i) { 21620 childContextNode = {}; 21621 contextNode[elemName].push(childContextNode); 21622 } 21623 } 21624 } 21625 // recursively create descendants 21626 return this._createElements(childContextNode, pathParts.slice(1), lastNodeValue); 21627 }, 21628 21629 _createChildElement : function (parentElement, elemName, isLastToken, nodeValue) { 21630 if (parentElement instanceof Object) { 21631 if (isLastToken) { 21632 parentElement[elemName] = nodeValue; 21633 } else { 21634 parentElement[elemName] = {}; 21635 } 21636 return parentElement[elemName]; 21637 } 21638 }, 21639 21640 isIndexedPath : function (xpath) { 21641 return (xpath || "").match(this.constants.INDEXED_XPATH_PAT_JSON) !== null; 21642 }, 21643 21644 /** 21645 * This function sets the value of the field in the live data document. 21646 * @param xpath 21647 * @param xmlSection 21648 * @private 21649 * @param createMissingNodes 21650 * @param value 21651 */ 21652 setDataValue : function (xpath, xmlSection, createMissingNodes, value) { 21653 var lastSlash = xpath.lastIndexOf("/"), 21654 parentPath = xpath.substring(0, lastSlash), 21655 name = xpath.substring(lastSlash + 1), 21656 parent = this.getContextNode(parentPath, xmlSection, createMissingNodes, {}); 21657 if (parent instanceof Object) { 21658 if (createMissingNodes || parent.hasOwnProperty(name)) { 21659 parent[name] = value; 21660 } 21661 } 21662 }, 21663 21664 /** 21665 * This function sets the value in the model from the live data document. 21666 * @param node 21667 * @param field 21668 * @private 21669 */ 21670 getDataValue : function (xpath, xmlSection) { 21671 var lastSlash = xpath.lastIndexOf("/"), 21672 parentPath = xpath.substring(0, lastSlash), 21673 name = xpath.substring(lastSlash + 1), 21674 parent = this.getContextNode(parentPath, xmlSection, false); 21675 if (parent instanceof Object) { 21676 return parent[name] === undefined ? null : parent[name]; 21677 } 21678 return null; 21679 }, 21680 21681 getRichTextValue : function (xpath, xmlSection) { 21682 return this.getDataValue(xpath, xmlSection); 21683 }, 21684 21685 addIndexToPath : function (path, index) { 21686 if (path.match(/\/\d+$/) === null) { // only add repeat index if it doesn't already end in one 21687 path += '/' + (index); 21688 } else { 21689 this.logger().debug("AF", "Tried to add index to already indexed JSON path :" + path); 21690 } 21691 return path; 21692 }, 21693 21694 hasChildNodes : function (node) { 21695 return !_.isEmpty(node); 21696 }, 21697 21698 removeChild : function (parentNode, targetNodeName, index) { 21699 parentNode[targetNodeName].splice(index, 1); 21700 }, 21701 21702 insertNode : function (parentNode, childNodeName, index) { 21703 if (parentNode[childNodeName] == null) { 21704 parentNode[childNodeName] = []; 21705 } 21706 for (var i = 0; i < index; i++) { 21707 if (parentNode[childNodeName][i] == null) { 21708 parentNode[childNodeName][i] = {}; 21709 } 21710 } 21711 parentNode[childNodeName].splice(index, 0, {}); 21712 return parentNode[childNodeName][index]; 21713 }, 21714 21715 getDataInstances : function (dataContext, dataNodeName) { 21716 return this.getContextNode(dataContext.indexedXpath, dataContext.xmlSec); 21717 }, 21718 21719 _convertModelIndexToDataIndex : function (index) { 21720 if (index < 0) { 21721 return 0; 21722 } 21723 return index; 21724 }, 21725 21726 getParentRef : function (path) { 21727 return path.replace(/\/[^\/]+(?:\/\d+)?$/, ""); 21728 }, 21729 21730 insertSubmissionInfo : function (submissionInfo, rootNode) { 21731 if (this._isNonNaked()) { 21732 var node = rootNode, 21733 self = this, 21734 finalValue, insert, keyNode; 21735 if (node == null) { 21736 node = this._liveDataDoc.afData.afSubmissionInfo; 21737 } 21738 if (node == null && this._liveDataDoc.afData.afSubmissionInfo == null) { 21739 node = {}; 21740 this._liveDataDoc.afData.afSubmissionInfo = node; 21741 } 21742 _.each(submissionInfo, function (value, key) { 21743 if (value instanceof Array) { 21744 // we only support string items in json array 21745 finalValue = []; 21746 insert = true; 21747 _.each(value, function (arrItem, index) { 21748 if (typeof arrItem === "string") { 21749 finalValue.push(arrItem); 21750 } else { 21751 //ignore this. we currently do not support anything other than string 21752 } 21753 }); 21754 if (insert) { 21755 node[key] = finalValue.join(','); 21756 } 21757 } else if (typeof (value) === "object" && value != null) { 21758 keyNode = node[key]; 21759 if (keyNode == null) { 21760 keyNode = {}; 21761 node[key] = keyNode; 21762 } 21763 self.insertSubmissionInfo(value, keyNode); 21764 } else { 21765 node[key] = value; 21766 } 21767 }); 21768 } 21769 } 21770 21771 }); 21772 21773}($, _, window.guideBridge, window.guidelib, window.formBridge, window.xfalib)); 21774 21775/** 21776 * @package guidelib.model.DataNode 21777 * @version 0.0.1 21778 */ 21779 21780(function ($, _, guideBridge, guidelib, formBridge, xfalib) { 21781 var isXdp, isXsd, isNone; 21782 21783 var LiveXmlUtils = guidelib.model.LiveXmlUtils = guidelib.model.LiveDataUtils.extend({ 21784 21785 initialize : function () { 21786 LiveXmlUtils._super.initialize.call(this); 21787 21788 if (_.isUndefined(document.evaluate)) { 21789 wgxpath.install(); 21790 } 21791 this._liveDataDoc = null; 21792 }, 21793 21794 initLiveData : function (prefillXmlStr, xfaPrefillXmlStr, isXdp, isXsd, xsdRootElement) { 21795 LiveXmlUtils._super.initLiveData.apply(this, arguments); 21796 isXdp = isXdp || false; 21797 isXsd = isXsd || false; 21798 isNone = !(isXdp || isXsd); 21799 this.xsdRootElement = xsdRootElement; 21800 // init default skeleton for no pefill cases 21801 this._liveDataDoc = $.parseXML(this.constants.SKELETON_XML); 21802 this._boundDataRoot = this._getElement(this._liveDataDoc.documentElement, this.constants.BOUND_DATA_XPATH); 21803 this._unboundDataRoot = this._getElement(this._liveDataDoc.documentElement, this.constants.UNBOUND_DATA_XPATH); 21804 21805 if (_.isString(prefillXmlStr) && prefillXmlStr.length > 0) { 21806 var prefillXmlDoc = $.parseXML(prefillXmlStr); 21807 21808 // find data root 21809 if (this._isNonNaked(prefillXmlDoc)) { 21810 // non naked xml, assuming full hierarchy afdata/afbounddata/data 21811 21812 var prefillBoundDataRoot, 21813 prefillUnBoundDataRoot, 21814 newDataNode; 21815 21816 if (!isXdp) { //capture bound data from prefill, for both none(may contain bound form/frag) and xsd 21817 prefillBoundDataRoot = this._getElement(prefillXmlDoc.documentElement, this.constants.BOUND_DATA_XPATH); 21818 if (null == prefillBoundDataRoot) { 21819 prefillBoundDataRoot = this._getElement(prefillXmlDoc.documentElement, this.constants.BOUND_TAG + 21820 "/" + guideBridge._guide.jsonModel.xsdRootElement); 21821 } 21822 if (prefillBoundDataRoot) { 21823 newDataNode = this._liveDataDoc.importNode(prefillBoundDataRoot, true); 21824 this._boundDataRoot.parentNode.replaceChild(newDataNode, this._boundDataRoot); 21825 this._boundDataRoot = newDataNode; 21826 } 21827 } 21828 21829 prefillUnBoundDataRoot = this._getElement(prefillXmlDoc.documentElement, this.constants.UNBOUND_DATA_XPATH); 21830 if (prefillUnBoundDataRoot) { 21831 newDataNode = this._liveDataDoc.importNode(prefillUnBoundDataRoot, true); 21832 this._unboundDataRoot.parentNode.replaceChild(newDataNode, this._unboundDataRoot); 21833 this._unboundDataRoot = newDataNode; 21834 } 21835 21836 } else { 21837 // naked xml start from prefill data root 21838 21839 if (isNone) { 21840 this._unboundDataRoot = prefillXmlDoc.documentElement; 21841 this._boundDataRoot = null; 21842 } else { 21843 if (isXsd) { 21844 this._boundDataRoot = prefillXmlDoc.documentElement; 21845 } 21846 21847 var unBoundXmlDoc = $.parseXML(this.constants.UNBOUND_SKELETON); 21848 this._unboundDataRoot = unBoundXmlDoc.documentElement; // need this for unbound data fill across lazy 21849 } 21850 this._liveDataDoc = prefillXmlDoc; 21851 } 21852 } 21853 21854 if (isXdp) { // don't need the bound data sec, model is always loaded & server will fill during submission 21855 if (_.isString(xfaPrefillXmlStr) && xfaPrefillXmlStr.length > 0) { 21856 this._xfaDataRoot = xfalib.ut.XMLUtils.getXFARootFormElementFromXML($.parseXML(xfaPrefillXmlStr)); 21857 } 21858 this._boundDataRoot.parentNode.parentNode.removeChild(this._boundDataRoot.parentNode); 21859 this._boundDataRoot = null; 21860 } 21861 }, 21862 21863 isLiveDataInitialized : function () { 21864 return (this.getLiveDataDoc() instanceof Node); 21865 }, 21866 21867 getLiveDataStr : function () { 21868 if (this.isLiveDataInitialized()) { 21869 return (new XMLSerializer()).serializeToString(this.getLiveDataDoc()); 21870 } else { 21871 return ''; 21872 } 21873 }, 21874 21875 _ignoreXpathRoot : function (xpathRoot) { 21876 return this.xsdRootElement === this.cons
21876tants.UNKNOWN_XSD_ROOT_ELEMENT 21877 || this.xsdRootElement === xpathRoot; 21878 }, 21879 21880 /** 21881 * will return the apt node, in the AF xml, based on the xml context passed in. 21882 * Will create nodes if it doesn't exist and createMissingNodes is passed as true 21883 * @param schemaPath 21884 * @param dataSection 21885 * @param createMissingNodes 21886 * @returns {*} 21887 * @memberof LiveXmlUtils 21888 */ 21889 getContextNode : function (schemaPath, dataSection, createMissingNodes) { 21890 var contextNode, 21891 baseContextNode, 21892 xpathParts = this._sanitizedXpathParts(schemaPath); 21893 if (dataSection === this.constants.BOUND_TAG) { 21894 baseContextNode = this._boundDataRoot; 21895 } else if (dataSection === this.constants.UNBOUND_TAG) { 21896 baseContextNode = this._unboundDataRoot; 21897 } else if (dataSection === this.constants.XFA_TAG) { 21898 baseContextNode = this._xfaDataRoot; 21899 } 21900 if (!_.isEmpty(xpathParts)) { 21901 if (dataSection === this.constants.BOUND_TAG) { 21902 if (this._ignoreXpathRoot(xpathParts[0])) { 21903 xpathParts = xpathParts.slice(1); // discard xsd schema root 21904 if (xpathParts.length === 0) { 21905 return baseContextNode; 21906 } 21907 } 21908 } 21909 21910 contextNode = this._getElement(baseContextNode, xpathParts.join('/')); 21911 21912 if (!contextNode && createMissingNodes) { 21913 contextNode = this._createElements(baseContextNode, xpathParts); 21914 } 21915 } else if (_.isEmpty(schemaPath)) { 21916 contextNode = baseContextNode; 21917 } 21918 return contextNode; 21919 }, 21920 21921 addIndexToPath : function (path, index) { 21922 if (path.match(/\[\d+\]$/) === null) { // only add repeat index if it doesn't already end in one 21923 path += '[' + (index + 1) + ']'; // indices in xpath 1 based} 21924 } else { 21925 this.logger().debug("AF", "Tried to add index to already indexed xpath :" + path); 21926 } 21927 return path; 21928 }, 21929 21930 getDataInstances : function (dataContext, dataNodeName) { 21931 var node = this.getContextNode(dataContext.indexedXpath, dataContext.xmlSec); 21932 if (node != null) { 21933 return _.filter(node.parentNode.childNodes, function (child) { 21934 return (child instanceof Element) && child.nodeName === dataNodeName; 21935 }, this); 21936 } 21937 return null; 21938 }, 21939 21940 _findLastDataNode : function (parentContextNode, dataNodeName) { 21941 var xmlUtils = xfalib.ut.XMLUtils, 21942 iterator = xmlUtils.evaluateXPath(dataNodeName, parentContextNode, null, null, null), 21943 result = xmlUtils.iteratorToArray(iterator); 21944 if (result.length > 0) { 21945 return result[result.length - 1]; 21946 } 21947 return null; 21948 }, 21949 21950 hasChildNodes : function (node) { 21951 return node.hasChildNodes(); 21952 }, 21953 21954 removeChild : function (parentNode, targetNodeName, index) { 21955 var childNode = this._getElement(parentNode, targetNodeName + "[" + (index + 1) + "]", null); 21956 if (childNode) { 21957 parentNode.removeChild(childNode); 21958 } 21959 }, 21960 21961 insertNode : function (parentNode, childNodeName, index) { 21962 var childNode = this._getElement(parentNode, childNodeName + "[" + (index + 1) + "]", null), 21963 node = parentNode.ownerDocument.createElement(childNodeName); 21964 if (childNode) { 21965 parentNode.insertBefore(node, childNode); 21966 } else { 21967 var lastNode = this._findLastDataNode(parentNode, childNodeName); 21968 if (lastNode && lastNode.nextSibling) { 21969 parentNode.insertBefore(node, lastNode.nextSibling); 21970 } else if (lastNode && !lastNode.nextSibling) { 21971 // for the case when the last node is there but there is no next sibling. 21972 // we don't need to create all the nodes for this scenario. 21973 parentNode.appendChild(node); 21974 } else { 21975 // we need to create all the nodes till the count reaches the index. 21976 for (var i = 0; i <= index; i++) { 21977 var newNode = parentNode.ownerDocument.createElement(childNodeName); 21978 parentNode.appendChild(newNode); 21979 } 21980 } 21981 } 21982 return node; 21983 }, 21984 21985 /** 21986 * Form an xpath part returns the index as well as the tagName. 21987 * Index returned is 0 if not present 21988 * @param xpathName 21989 * @returns {*} 21990 * @private 21991 * @memberof LiveXmlUtils 21992 */ 21993 _getNameAndIndex : function (xpathPart) { 21994 if (xpathPart) { 21995 var elName = xpathPart.match(/^([^[\s\/]+)(?:\[(\d+)\])?$/); // match the whole string 21996 if (elName !== null) { 21997 return { 21998 name : elName[1], 21999 index : elName[2] ? parseInt(elName[2]) : 0 22000 }; 22001 } 22002 } 22003 return null; 22004 }, 22005 22006 _cmpXpathParts : function (indexedName, templateName) { 22007 if (indexedName && templateName) { 22008 var match1 = this._getNameAndIndex(indexedName), 22009 match2 = this._getNameAndIndex(templateName); 22010 return !_.isEmpty(match1 && match2) 22011 && match1.name === match2.name 22012 && (match2.index === 0 || match1.index === match2.index); 22013 } 22014 return false;
22015 }, 22016 22017 /** 22018 * Will split an xpath string into an array containing one xml element/node per part 22019 * This expects only the simple xpath syntax allowed in bindRefs of xsd bound fields 22020 * of the form /a/b/c/@d 22021 * @param xpath 22022 * @returns {*|Array.<T>|list} 22023 * @private 22024 * @memberof LiveXmlUtils 22025 */ 22026 _sanitizedXpathParts : function (xpath) { 22027 var xpathParts = (xpath || '').replace(/^\//, '').replace(/\s+/g, '').split('/'); 22028 22029 if (_.last(xpathParts) === "text()") { // ignore "/text()" appended to bindRef for SimpleType schema element 22030 xpathParts.splice(-1, 1); // drop last element 22031 } 22032 22033 return _.filter(xpathParts, function (xpathPart) { 22034 return this._getNameAndIndex(xpathPart) !== null; 22035 }, this); 22036 }, 22037 22038 /** 22039 * returns true if the xpath uses indices 22040 * @param xpath 22041 * @returns {boolean} 22042 * @memberof LiveXmlUtils 22043 */ 22044 isIndexedPath : function (xpath) { 22045 return (xpath || "").match(this.constants.INDEXED_XPATH_PAT) !== null; 22046 }, 22047 22048 _createElements : function (contextNode, xpathParts) { 22049 if (!(contextNode instanceof Node)) { 22050 return null; 22051 } 22052 22053 if (_.isEmpty(xpathParts)) { 22054 return contextNode; 22055 } 22056 22057 if (xpathParts[0][0] === '@') { // xpath parts having '@' as 1st char must be and attr 22058 var attrName = xpathParts[0].slice(1); 22059 // in bindrefs attributes are the last xpath part, so no need to recurse 22060 contextNode = this._createAttributeNode(contextNode, attrName); 22061 } else { 22062 // recurse and create one level of tags at a time 22063 contextNode = this._createRepeatedElements(contextNode, xpathParts); 22064 } 22065 22066 return contextNode; 22067 }, 22068 22069 /** 22070 * This will update the xml with the required tags, 22071 * and return the context node matching the xpath query. 22072 * Further if xml has lesser number of tags than the index in each part, 22073 * it'll fill those gaps with empty tags. 22074 * @param contextNode node beneath which tags are to be created 22075 * @param xpathParts 22076 * @returns {*} 22077 * @private 22078 * @memberof LiveXmlUtils 22079 */ 22080 _createRepeatedElements : function (contextNode, xpathParts) { 22081 var childContextNode = contextNode, 22082 xpathPart = this._getNameAndIndex(xpathParts[0]), 22083 elemName = xpathPart.name, 22084 index = xpathPart.index || 1, 22085 i, 22086 children = _.filter(contextNode.childNodes, function (child) { 22087 return (child instanceof Element) && child.nodeName === elemName; 22088 }); 22089 22090 if (children.length < index) { 22091 // create immediate 'extra' children 22092 for (i = children.length; i < index; ++i) { 22093 childContextNode = this._createChildElement(contextNode, elemName); 22094 } 22095 } else { 22096 childContextNode = children[index - 1]; // indices are 1 based in xml 22097 } 22098 // recursively create descendants 22099 return this._createElements(childContextNode, xpathParts.slice(1)); 22100 }, 22101 22102 _createChildElement : function (parentElement, elemName) { 22103 if (parentElement instanceof Element) { 22104 var childElem = parentElement.ownerDocument.createElement(elemName); 22105 parentElement.appendChild(childElem); 22106 return childElem; 22107 } 22108 }, 22109 22110 _createAttributeNode : function (parentElement, attrName) { 22111 if (parentElement instanceof Element) { 22112 var attrNode = parentElement.ownerDocument.createAttribute(attrName); 22113 parentElement.setAttributeNode(attrNode); 22114 return attrNode; 22115 } 22116 }, 22117 22118 /** 22119 * finds xml node/element based on current context node and xpath 22120 * @param node 22121 * @param xpath 22122 * @param options 22123 * @returns {*} 22124 * @private 22125 * @memberof LiveXmlUtils 22126 */ 22127 _getElement : function (node, xpath, options) { 22128 if (!(node instanceof Node)) { 22129 return null; 22130 } 22131 22132 if (_.isEmpty(xpath) || !_.isString(xpath)) { 22133 return node; 22134 } 22135 options = options || {}; 22136 var nsResolver = options.nsResolver; 22137 var index = options.index; 22138 // in IE singleNodeValue maybe null for attribute queries, 22139 // so find parent element of attribute, and then explicitly check for attribute node's presence 22140 22141 var xpathParts = xpath.split('/@'), 22142 checkAttr = false, 22143 attributeName; 22144 22145 if (xpathParts.length > 2) { // more than 1 attr unsupported 22146 xfalib.ut.XfaUtil.prototype.getLogger().error("BindRefs must be Xpaths ending in atmost one attribute"); // TODO localize 22147 return null; 22148 } else if (xpathParts.length === 2) { 22149 xpath = xpathParts[0]; // find parent el and seek attribute there 22150 attributeName = xpathParts[1]; // attr can only be in the last part 22151 checkAttr = true; 22152 } 22153 if (!(_.isUndefined(index) || _.isNull(index))) { 22154 xpath = xpath + "[" + index + "]"; 22155 } 22156 if (!window.XPathResult) { 22157 document.evaluate = undefined; 22158 wgxpath.install(window, true); 22159 } 22160 var result = xfalib.ut.XMLUtils.evaluateXPath(xpath, node, nsResolver, XPathResult.FIRST_ORDERED_NODE_TYPE, null), 22161 el; 22162 22163 if (result && result.resultType === XPathResult.FIRST_ORDERED_NODE_TYPE) { 22164 el = result.singleNodeValue; 22165 if (el instanceof Node) { 22166 if (!checkAttr) { 22167 return el; 22168 } else if (el.hasAttribute(attributeName)) { 22169 el = el.getAttributeNode(attributeName); 22170 if (el instanceof Node) { 22171 return el; 22172 } 22173 } 22174 } 22175 } 22176 }, 22177 22178 /** 22179 * This function checks if the document was naked or non naked xml 22180 * @param doc 22181 * @returns {boolean} returns true if there exists a afData node inside data false otherwise 22182 * @private 22183 * @memberof LiveXmlUtils 22184 */ 22185 _isNonNaked : function (doc) { 22186 doc = doc || this.getLiveDataDoc(); 22187 if (doc) { 22188 return doc.documentElement.tagName === this.constants.AF_ROOT_TAG; 22189 } else { 22190 return false;
22191 } 22192 }, 22193 22194 /** 22195 * Returns list of panels touched by the end user before saving the draft 22196 * @param dataString 22197 */ 22198 getListOfDirtyPanels : function (dataString) { 22199 if (dataString == null || dataString === "") { 22200 return []; 22201 } 22202 var livePrefillXmlDoc = $.parseXML(dataString), 22203 draftDoc = this._getElement(livePrefillXmlDoc.documentElement, this.constants.AF_DRAFT_TAG); 22204 if (_.isUndefined(draftDoc) || draftDoc.childNodes.length === 0) { 22205 return []; 22206 } 22207 var draftStr = draftDoc.firstChild.textContent.replace(/\"/g, ""), 22208 retVal = []; 22209 // not using filter here explicitly, due to ES4 syntax 22210 if (draftStr) { 22211 retVal = draftStr.split(","); 22212 } 22213 return retVal; 22214 }, 22215 22216 /** 22217 * This function sets the rich text value of the field in the live data. 22218 * @param xpath 22219 * @param xmlSection 22220 * @param createMissingNodes 22221 * @param value 22222 * @private 22223 */ 22224 setRichTextValue : function (xpath, xmlSection, createMissingNodes, value) { 22225 var node = this.getContextNode(xpath, xmlSection, createMissingNodes); 22226 if (node instanceof Node) { 22227 var richTextNode = $.parseXML(value); 22228 // clear the text content before appending child 22229 node.textContent = ""; 22230 node.appendChild(richTextNode.documentElement); 22231 } 22232 }, 22233 22234 setDataValue : function (xpath, xmlSection, createMissingNodes, value) { 22235 var node = this.getContextNode(xpath, xmlSection, createMissingNodes); 22236 if (node instanceof Node) { 22237 node.textContent = value; 22238 } 22239 }, 22240 22241 getDataValue : function (xpath, xmlSection) { 22242 var node = this.getContextNode(xpath, xmlSection, false); 22243 if (node instanceof Node) { 22244 return node.textContent || null; 22245 } 22246 return undefined; 22247 }, 22248 22249 getRichTextValue : function (xpath, xmlSection) { 22250 var node = this.getContextNode(xpath, xmlSection, false); 22251 if (node instanceof Node) { 22252 return node.innerHTML.trim(); 22253 } 22254 return undefined; 22255 }, 22256 22257 _convertModelIndexToDataIndex : function (index) { 22258 if (index < 0) { 22259 return 1; 22260 } 22261 return index + 1; 22262 }, 22263 22264 getParentRef : function (path) { 22265 return path.substring(0, path.lastIndexOf("/")); 22266 }, 22267 22268 insertSubmissionInfo : function (submissionInfo, rootNode) { 22269 if (this._isNonNaked()) { 22270 var xmlutils = xfalib.ut.XMLUtils, 22271 node = rootNode === undefined 22272 ? xmlutils.findOrCreateElement("afSubmissionInfo", this._liveDataDoc.documentElement) 22273 : rootNode, 22274 self = this; 22275 _.each(submissionInfo, function (value, key) { 22276 var keyNode; 22277 if (value instanceof Array) { 22278 // we only support string items in json array 22279 var finalValue = [], insert = true; 22280 _.each(value, function (arrItem, index) { 22281 if (typeof arrItem === "string") { 22282 finalValue.push(arrItem); 22283 } else if (arrItem instanceof Object && arrItem != null) { 22284 insert = false; 22285 var el = node.ownerDocument.createElement(key); 22286 node.appendChild(el); 22287 self.insertSubmissionInfo(arrItem, el); 22288 } 22289 }); 22290 if (insert) { 22291 keyNode = xmlutils.findOrCreateElement(key, node); 22292 keyNode.textContent = finalValue.join(','); 22293 node.appendChild(keyNode); 22294 } 22295 } else if (typeof (value) === "object" && value != null) { 22296 keyNode = xmlutils.findOrCreateElement(key, node); 22297 self.insertSubmissionInfo(value, keyNode); 22298 node.appendChild(keyNode); 22299 } else { 22300 keyNode = xmlutils.findOrCreateElement(key, node); 22301 keyNode.textContent = value; 22302 node.appendChild(keyNode); 22303 } 22304 }); 22305 } 22306 } 22307 }); 22308 22309}($, _, window.guideBridge, window.guidelib, window.formBridge, window.xfalib)); 22310 22311/* 22312 * *********************************************************************** 22313 * ADOBE CONFIDENTIAL 22314 * __________________ 22315 * 22316 * Copyright 2015 Adobe Systems Incorporated 22317 * All Rights Reserved. 22318 *
22319 * NOTICE: All information contained herein is, and remains 22320 * the property of Adobe Systems Incorporated and its suppliers, 22321 * if any. The intellectual and technical concepts contained 22322 * herein are proprietary to Adobe Systems Incorporated and its 22323 * suppliers and may be covered by U.S. and Foreign Patents, 22324 * patents in process, and are protected by trade secret or copyright law. 22325 * Dissemination of this information or reproduction of this material 22326 * is strictly forbidden unless prior written permission is obtained 22327 * from Adobe Systems Incorporated. 22328 * *********************************************************************** 22329 */ 22330 22331/** 22332 * @package guidelib.model.LiveModel 22333 * @version 0.0.1 22334 */ 22335 22336(function ($, _, guideBridge, guidelib) { 22337 var LiveModel = guidelib.model.LiveModel = xfalib.ut.Class.extend({ 22338 initialize : function () { 22339 LiveModel._super.initialize.call(this); 22340 this._crossFragmentFields = {}; // 2 level map: name => { bindRef => abstract model } 22341 this._dataNodes = {}; 22342 }, 22343 22344 // only called from test framework 22345 destroy : function () { 22346 this._crossFragmentFields = {}; 22347 this._dataNodes = {}; 22348 }, 22349 22350 getCrossFragmentFields : function () { 22351 return this._crossFragmentFields; 22352 }, 22353 22354 add : function (key, model) { 22355 if (key) { 22356 var dn = this._dataNodes[key] || new guidelib.model.DataNode(); 22357 dn.addField(model); 22358 this._dataNodes[key] = dn; 22359 } 22360 }, 22361 22362 isLive : function (key) { 22363 return _.isString(key) && _.has(this._dataNodes, key); 22364 }, 22365 22366 remove : function (key, model) { 22367 if (this.isLive(key)) { 22368 var dn = this._dataNodes[key]; 22369 dn.removeField(model); 22370 } 22371 }, 22372 22373 getAllFieldModels : function (keys) { 22374 return _.flatten(_.map(keys, function (key) { 22375 var result, 22376 dataNode = this._dataNodes[key]; 22377 if (dataNode) { 22378 result = dataNode.getFieldModels(); 22379 } 22380 return result; 22381 }, this)); 22382 }, 22383 22384 getAllAbstractFieldModels : function (keys) { 22385 return _.flatten(_.map(keys, function (key) { 22386 return this._dataNodes[key].getAbstractFieldModels(); 22387 }, this)); 22388 }, 22389 22390 resetData : function () { 22391 // all loaded models in data nodes dataNodes will be reset by the respective fields 22392 // just need to reset the abstract cross frag fields 22393 _.each(this._crossFragmentFields, function (fields) { 22394 _.each(fields, function (abstractField) { 22395 abstractField.resetData(); 22396 }); 22397 }); 22398 }, 22399 22400 createDataNodes : function (duplicateBindRefs) { 22401 _.each(duplicateBindRefs, function (bindRef) { 22402 this.add(bindRef); 22403 }, this); 22404 }, 22405 22406 createCrossFragFields : function (crossFragFields, guide) { 22407 _.each(crossFragFields, function (field) { 22408 var effectiveBindRef = field.bindRef || field.name, 22409 value = field._value || null,// default value, keep null because js is quirky with operations on undefined 22410 absModel = new guidelib.model.AbstractField({ 22411 'name' : field.name, 22412 'className' : field.guideNodeClass, 22413 'bindRef' : field.bindRef, 22414 'dataSom' : field.dataSom, 22415 'afDataSom' : field.afDataSom, 22416 'jsonModel' : { 22417 '_value' : value, 22418 "{default}" : value 22419 }, 22420 '_guideContainer' : guide 22421 }); 22422 22423 if (_.isEmpty(this._crossFragmentFields[field.name])) { 22424 this._crossFragmentFields[field.name] = {}; 22425 } 22426 this._crossFragmentFields[field.name][effectiveBindRef] = absMo
22426del; 22427 22428 this.add(effectiveBindRef, absModel); // unbound globals with same name linked together 22429 22430 }, this); 22431 }, 22432 22433 prefillCrossFragFields : function (guide) { 22434 var dataUtils = guide.internal.liveDataUtils; 22435 if (dataUtils.isLiveDataInitialized()) { 22436 _.each(this._crossFragmentFields, function (fields, name) { 22437 _.each(fields, function (absModel, bindRef) { 22438 var dataContext = dataUtils._getDataContext(absModel, '', ''); 22439 // fill value from prefill data or saved lazy live data 22440 absModel.value = dataUtils.getDataValue(dataContext.indexedXpath, dataContext.xmlSec); 22441 }, this); 22442 }, this); 22443 } 22444 } 22445 }); 22446}($, _, window.guideBridge, window.guidelib)); 22447 22448/** 22449 * @package guidelib.model.FormData 22450 * @version 0.0.1 22451 */ 22452 22453(function ($, _, guidelib) { 22454 22455 /** 22456 * JavaScript class to represent form data 22457 * @class FormData 22458 * @since Forms As A Cloud service (FaaCS) 22459 */ 22460 var AfFormData = guidelib.model.FormData = xfalib.ut.Class.extend({ 22461 22462 initialize : function () { 22463 AfFormData._super.initialize.call(this); 22464 }, 22465 22466 toJsObject : function() { 22467 return { 22468 "data" : this.data, 22469 "contentType" : this.contentType, 22470 "attachments" : this.attachments 22471 } 22472 }, 22473 22474 /** 22475 * This returns the html form data representation of adaptive form data. This could be used to submit the adaptive form data to 22476 * external end point from the client. The HTML form data contains the following the key / value pairs: 22477 * 1. data -> contains form data represented as string 22478 * 2. contentType -> contains content type of form data (it would be application/xml or application/json) 22479 * 2. fileAttachments -> list of blobs containing the file (in case of fileUrl's the type of blob would be application/json) 22480 * 3. fileAttachmentBindRefs -> list of string containing file bindRef's, this has one to one mapping with fileAttachments 22481 * @returns {*} 22482 */ 22483 toHTMLFormData : function() { 22484 // using native formData class 22485 var formData = new FormData(); 22486 // appending data of adaptive form in data key 22487 // data could be JSON or XML 22488 if (this.contentType) { 22489 formData.append("contentType", this.contentType); 22490 } 22491 formData.append("data", this.data); 22492 for (var index = 0; index < this.attachments.length; index++) { 22493 var fileAttachmentWrapper = this.attachments[index]; 22494 // 2nd parameter should be of blob type, hence adding an explicit check here 22495 // we could have created dataURL for all the files in the client, but this would cause the browser 22496 // to slow down since it would serialize the binary, hence following the below approach 22497 if (fileAttachmentWrapper.isFile()) { 22498 formData.append("fileAttachments", fileAttachmentWrapper.data, fileAttachmentWrapper.name); 22499 } else { 22500 // blob is supported on all major browsers 22501 var urlBlob = new Blob([ 22502 JSON.stringify({ 22503 "data" : fileAttachmentWrapper.data, 22504 "name" : fileAttachmentWrapper.name, 22505 "contentType" : fileAttachmentWrapper.contentType 22506 }) 22507 ], { type: 'application/json' }); 22508 formData.append("fileAttachments", urlBlob); 22509 } 22510 formData.append("fileAttachmentBindRefs", fileAttachmentWrapper.bindRef); 22511 } 22512 return formData; 22513 } 22514 }); 22515 22516 AfFormData.defineProps({ 22517 /** 22518 * Actual form data (could be JSON or xml) 22519 */ 22520 data : { 22521 get : function () { 22522 return this.options.data; 22523 } 22524 }, 22525 22526 /** 22527 * List of {FileAttachmentWrapper} {@link FileAttachmentWrapper} 22528 */ 22529 attachments : { 22530 get : function () { 22531 return this.options.attachments; 22532 } 22533 }, 22534 22535 /** 22536 * Content type of form data (it could be application/xml or application/json) 22537 */ 22538 contentType : { 22539 get : function () { 22540 return this.options.contentType; 22541 } 22542 } 22543 }); 22544 22545 22546}($, _, window.guidelib)); 22547 22548/** 22549 * @package guidelib.model.FileAttachmentWrapper 22550 * @version 0.0.1 22551 */ 22552 22553(function ($, _, guidelib) { 22554 22555 /** 22556 * JavaScript class to represent the each file data present in the form. 22557 * Data could be URI (URI could be a file URL or dataURL) 22558 * @class FileAttachmentWrapper 22559 * @since Forms As A Cloud service (FaaCS) 22560 */ 22561 var FileAttachmentWrapper = guidelib.model.FileAttachmentWrapper = xfalib.ut.Class.extend({ 22562 22563 initialize : function () { 22564 FileAttachmentWrapper._super.initialize.call(this); 22565 }, 22566 22567 /** 22568 * Converts file attachment wrapper to a javascript object
22569 * @returns {{name: *, contentType: *, bindRef: *, data: *}} 22570 */ 22571 toJsObject : function () { 22572 return { 22573 name : this.name, 22574 contentType : this.contentType, 22575 bindRef : this.bindRef, 22576 data : this.data 22577 } 22578 }, 22579 22580 /** 22581 * Checks if the file data is native JS File object 22582 * @returns {boolean} 22583 */ 22584 isFile : function() { 22585 return this.data instanceof File; 22586 }, 22587 22588 22589 /** 22590 * Returns blob for the data URL present in data 22591 * @returns {*} 22592 */ 22593 dataURLtoBlob : function() { 22594 var dataurl = this.data, // data should be a data url 22595 arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1], 22596 bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); 22597 while(n--){ 22598 u8arr[n] = bstr.charCodeAt(n); 22599 } 22600 return new Blob([u8arr], {type: mime}); 22601 } 22602 }); 22603 22604 FileAttachmentWrapper.defineProps({ 22605 /** 22606 * Actual name of the file associated with data 22607 */ 22608 name : { 22609 get : function () { 22610 return this.options.name; 22611 } 22612 }, 22613 22614 /** 22615 * Content type of file 22616 */ 22617 contentType : { 22618 get : function () { 22619 return this.options.contentType; 22620 } 22621 }, 22622 22623 /** 22624 * This would be effective bindRef meaning bindRef in case of data model or component name in case of unbound data 22625 */ 22626 bindRef : { 22627 get : function () { 22628 return this.options.bindRef; 22629 } 22630 }, 22631 22632 /** 22633 * This would represent the name of the form element to which the file binary is associated. 22634 * In case of unbound form, bindRef and component name would be the same 22635 */ 22636 formElementName : { 22637 get : function () { 22638 return this.options.formElementName || this.options.bindRef; 22639 } 22640 }, 22641 22642 /** 22643 * Data could be URI (URI could be file URL or dataURL) or native JavaScript File object 22644 */ 22645 data : { 22646 get : function () { 22647 return this.options.data; 22648 } 22649 } 22650 }); 22651 22652 22653}($, _, window.guidelib)); 22654 22655/************************************************************************* 22656 * 22657 * ADOBE CONFIDENTIAL 22658 * __________________ 22659 * 22660 * Copyright 2014 Adobe Systems Incorporated 22661 * All Rights Reserved. 22662 *
22663 * NOTICE: All information contained herein is, and remains 22664 * the property of Adobe Systems Incorporated and its suppliers, 22665 * if any. The intellectual and technical concepts contained 22666 * herein are proprietary to Adobe Systems Incorporated and its 22667 * suppliers and may be covered by U.S. and Foreign Patents, 22668 * patents in process, and are protected by trade secret or copyright law. 22669 * Dissemination of this information or reproduction of this material 22670 * is strictly forbidden unless prior written permission is obtained 22671 * from Adobe Systems Incorporated. 22672 **************************************************************************/ 22673 22674 22675(function (_, $) { 22676 "use strict"; 22677 22678 22679 var isBrowserIE = xfalib.ut.XfaUtil.prototype.detectIE(); 22680 22681 var _defaults = { 22682 'showLink' : false, 22683 'scrollMode' : 'vertical', 22684 textAreaClass : ".guide-tnc-content", 22685 checkBoxClass : ".guide-tnc-checkbox", 22686 checkBoxDisableClass : ".guide-tnc-checkbox-disabled", 22687 checkBoxReviewedClass : ".guide-tnc-checkbox-reviewed", 22688 linkClass : ".guide-tnc-link", 22689 documentVisitedClass : ".guide-tnc-document-visited", 22690 documentUnVisitedClass : ".guide-tnc-document-unvisited" 22691 }; 22692 22693 var _reviewStatusMap = { 22694 REVIEWED : "reviewed", 22695 UNREVIEWD : "unreviewed", 22696 AGREE : "agree" 22697 }; 22698 22699 var AfTnc = function (element, options) { 22700 this.options = options; 22701 this.$element = $(element); 22702 22703 22704 this.enters = this.leaves = 0; 22705 this.inside = false;
22706 22707 22708 this.reviewdoc = this.status = _reviewStatusMap.UNREVIEWD; 22709 22710 22711 this.$elementCheckBox = this.$element.find(this.options.checkBoxClass || _defaults.checkBoxClass); 22712 22713 this.$elementTextArea = $(this.textArea()); 22714 22715 this.$elementLink = $(this.link()); 22716 22717 this.isTextContentVisible = false; 22718 22719 if (this.options.showLink) { 22720 22721 this.$elementLink.find('a').click($.proxy(this.handleReviewStatusChange, this)); 22722 } else { 22723 var setCheckBoxState = function () { 22724 if (this.hasScrollBar(this.$elementTextArea.parent().get(0))) { 22725 22726 22727 this.$elementTextArea.parent().scroll($.proxy(this.handleReviewStatusChange, this)); 22728 } else { 22729 22730 if (this.$elementTextArea.css('display') !== 'none') { 22731 this.status = _reviewStatusMap.REVIEWED; 22732 this.isTextContentVisible = true; 22733 22734 if (!this.options.showAsPopUp) { 22735 this.enableCheckBox(); 22736 } 22737 this.reviewDoc = this.$elementTextArea.text(); 22738 } 22739 } 22740 }; 22741 22742 22743 if (document.readyState === "complete") { 22744 setCheckBoxState.call(this); 22745 } else { 22746 22747 22748 $($.proxy(setCheckBoxState, this)); 22749 } 22750 } 22751 22752 22753 if (this.options.showAsPopUp) { 22754 var unvisitedClass = this.options.documentUnVisitedClass || _defaults.documentUnVisitedClass, 22755 visitedClass = this.options.documentVisitedClass || _defaults.documentVisitedClass; 22756 var _self = this, 22757 dialogId = this.$elementCheckBox.find('a') 22758 .keydown(function (e) { 22759 if (e.keyCode === 13 || e.which == 13 || e.charCode === 32) { 22760 $(this).click(); 22761 return false; 22762 } 22763 }) 22764 .click(function (event) { 22765 if ($(this).hasClass(unvisitedClass.substring(1))) { 22766 $(this).toggleClass(visitedClass.substring(1) + " " + unvisitedClass.substring(1)); 22767 } 22768 22769 22770 if (isBrowserIE || _self.isTextContentVisible) { 22771 _self.enableCheckBox(); 22772 } 22773 }).attr("href"); 22774 22775 $(dialogId).on('hidden.bs.modal', function (e) { 22776 _self.$elementCheckBox.find('input').focus(); 22777 }); 22778 } else { 22779 22780 this._updateScreenReaderText(); 22781 } 22782 22783 22784 this.$elementCheckBox.find('input').change($.proxy(this.handleCheckBoxChange, this)); 22785 }; 22786 22787 AfTnc.prototype = { 22788 22789 clear : function () { 22790 this.$element.val(''); 22791 }, 22792 22793 destroy : function () { 22794 this.$element.val(''); 22795 this.$element.empty(); 22796 }, 22797 22798 _updateScreenReaderText : function () { 22799 if (!this.options.showAsPopUp) { 22800 var _self = this; 22801 22802 this.$element.find(".guide-tnc-sr-only").each(function (i, obj) { 22803 $(this).html(_self.options.screenReaderText); 22804 }); 22805 } 22806 }, 22807 22808 _restoreClickState : function (value) { 22809 if (this.options.showLink) { 22810 var arr = value.split("\n"), 22811 linkState = []; 22812 22813 _.each(arr, function (linkText, index) { 22814 22815 linkState.push(_.last(linkText.split('='))); 22816 }); 22817 var unvisitedClass = this.options.documentUnVisitedClass || _defaults.documentUnVisitedClass, 22818 visitedClass = this.options.documentVisitedClass || _defaults.documentVisitedClass; 22819 this.$elementLink.find('a').each(function (index) { 22820 $(this).data("clicked", linkState[index]); 22821 if (linkState[index] === "1") { 22822 $(this).addClass(visitedClass.substring(1)); 22823 } else { 22824 $(this).addClass(unvisitedClass.substring(1)); 22825 } 22826 }); 22827 } 22828 }, 22829 22830 value : function (value) { 22831 if (value) { 22832 22833 if (this.options.showLink) { 22834 this._restoreClickState(value); 22835 } 22836 this.reviewDoc = value; 22837 } else { 22838 return this.reviewDoc; 22839 } 22840 22841 }, 22842 22843 reviewStatus : function (value) { 22844 var val = this.getClickState(); 22845 if (!_.isUndefined(value)) { 22846 if (value == "true") { 22847 this.enableCheckBox(); 22848 this.$elementCheckBox.find('input').attr("checked", "checked"); 22849 this.$elementCheckBox.find('input').prop("checked", true); 22850 } else if (value == null || value == "false") { 22851 22852 this.$elementCheckBox.find('input').removeAttr("checked"); 22853 this.$elementCheckBox.find('input').removeProp("checked"); 22854 } 22855 this.approvalStatus = value; 22856 } else { 22857 if (this.status == _reviewStatusMap.REVIEWED || this.status == _reviewStatusMap.UNREVIEWD) { 22858 return null; 22859 } else if (this.status == _reviewStatusMap.AGREE) { 22860 return true; 22861 } 22862 } 22863 }, 22864 22865 clickStatus : function (value) { 22866 if (value) { 22867 if (value === _reviewStatusMap.REVIEWED) { 22868 var arr = this.getClickState(); 22869 if (_.isArray(arr) && arr.length > 0) { 22870 arr = arr.join("\n"); 22871 this._restoreClickState(arr); 22872 } 22873 this.enableCheckBox(); 22874 } 22875 this.status = value; 22876 } else { 22877 return this.status; 22878 } 22879 }, 22880 22881 showLink : function (value) { 22882 if (value !== undefined) { 22883 this.options.showLink = value; 22884 } else { 22885 return this.options.showLink; 22886 } 22887 }, 22888 22889 access : function (value) { 22890 this.accessOption = value; 22891 if (value == "readOnly") { 22892 this.disableCheckBox(); 22893 if (this.options.showLink) { 22894 this.$elementLink.find('a').each(function (index, elem) {
22895 $(elem).css('pointer-events', 'none'); 22896 22897 $(elem).attr('disabled', 'disabled'); 22898 }); 22899 } 22900 } else if (value == "open") { 22901 22902 22903 if ((this.status == _reviewStatusMap.REVIEWED || this.status == _reviewStatusMap.AGREE) && !this.options.showAsPopUp) { 22904 this.enableCheckBox(); 22905 } 22906 if (this.options.showLink) { 22907 this.$element.find('a').each(function (index, elem) { 22908 $(elem).css('pointer-events', ''); 22909 $(elem).removeAttr('disabled'); 22910 }); 22911 } 22912 } 22913 }, 22914 22915 link : function () { 22916 return this.$element.find(this.options.linkClass || _defaults.linkClass); 22917 }, 22918 22919 textArea : function () { 22920 return this.$element.find(this.options.textAreaClass || _defaults.textAreaClass); 22921 }, 22922 22923 getClickState : function () { 22924 if (this.options.showLink) { 22925 var arr = []; 22926 this.$elementLink.find('a').each(function (index) { 22927 arr.push({ 22928 'displayText' : $(this).text(), 22929 'linkText' : $(this).attr('href'), 22930 'clicked' : $(this).data("clicked") 22931 }); 22932 }); 22933 return arr; 22934 } 22935 }, 22936 22937 enableCheckBox : function () { 22938 if (this.accessOption !== "readOnly") { 22939 this.$elementCheckBox.find('input').removeAttr("disabled"); 22940 this.$elementCheckBox.removeClass(this.options.checkBoxDisableClass.substring(1)); 22941 } 22942 }, 22943 22944 disableCheckBox : function () { 22945 this.$elementCheckBox.find('input').attr('disabled', 'disabled'); 22946 this.$elementCheckBox.addClass(this.options.checkBoxDisableClass.substring(1)); 22947 }, 22948 22949 handleReviewStatusChange : function (event) { 22950 var arr = [], 22951 visitedClass = this.options.documentVisitedClass || _defaults.documentVisitedClass; 22952 if (this.options.showLink) { 22953 this.status = _reviewStatusMap.REVIEWED; 22954 22955 $(event.target).data("clicked", 1); 22956 $(event.target).addClass(visitedClass.substring(1)); 22957 this.linkStateMap = this.getClickState(); 22958 _.each(this.linkStateMap, function (element, index) { 22959 if (!element.clicked) { 22960 this.status = _reviewStatusMap.UNREVIEWD; 22961 } 22962 22963 arr.push(element.displayText + "=" + element.linkText + "=" + (_.isUndefined(element.clicked) ? "0" : "1")); 22964 }, this); 22965 if (arr.length > 0) { 22966 this.reviewDoc = arr.join("\n"); 22967 } 22968 22969 if (this.status == _reviewStatusMap.REVIEWED) { 22970 this.enableCheckBox(); 22971 } 22972 22973 22974 this.$element.trigger('reviewComplete.tnc'); 22975 22976 } else { 22977 22978 var position = this.getScroll(this.$elementTextArea.parent().get(0)), 22979 xy = position[this.options.scrollMode == 'vertical' ? 'y' : 'x']; 22980 var isScrolledToEnd = this.getScrollSize(this.$elementTextArea.parent().get(0)).y <= (this.getSize(this.$elementTextArea.parent().get(0)).y + xy); 22981 22982 this.reviewDoc = this.$elementTextArea.text(); 22983 22984 22985 if (isScrolledToEnd) { 22986 22987 if (!this.inside) { 22988 22989 this.inside = true; 22990 this.enters++; 22991 22992 this.status = _reviewStatusMap.REVIEWED; 22993 if (!this.approvalStatus) { 22994 this.enableCheckBox(); 22995 22996 this.$element.trigger('reviewComplete.tnc', [position,this.enters,event]); 22997 } 22998 } 22999 } 23000 23001 else if (this.inside) { 23002 this.inside = false;
23003 this.leaves++; 23004 23005 } 23006 } 23007 23008 }, 23009 23010 handleCheckBoxChange : function (event) { 23011 if ($(event.target).is(':checked')) { 23012 this.status = _reviewStatusMap.AGREE; 23013 this.$elementCheckBox.addClass(this.options.checkBoxReviewedClass.substring(1)); 23014 } else { 23015 this.status = _reviewStatusMap.UNREVIEWD; 23016 this.$elementCheckBox.removeClass(this.options.checkBoxReviewedClass.substring(1)); 23017 } 23018 this.$element.trigger('checkboxStateChange.tnc'); 23019 }, 23020 23021 getScrollSize : function (elem) { 23022 return {x : elem.scrollWidth, y : elem.scrollHeight}; 23023 }, 23024 23025 getScroll : function (elem) { 23026 return {x : elem.scrollLeft, y : elem.scrollTop}; 23027 }, 23028 23029 getSize : function (elem) { 23030 return {x : elem.offsetWidth, y : elem.offsetHeight}; 23031 }, 23032 23033 hasScrollBar : function (container) { 23034 23035 if (isBrowserIE) { 23036 23037 return ((container.scrollHeight - 2) > container.clientHeight) || ((container.scrollWidth - 2) > container.clientWidth); 23038 } else { 23039 return container.scrollHeight > container.clientHeight || container.scrollWidth > container.clientWidth; 23040 } 23041 } 23042 }; 23043 23044 $.fn.afTnc = function (option, value) { 23045 var get = '', 23046 element = this.each(function () { 23047 23048 var $this = $(this), 23049 data = $this.data('AfTnc'), 23050 options = $.extend({}, _defaults, typeof option === 'object' && option); 23051 23052 23053 if (!data) { 23054 $this.data('AfTnc', (data = new AfTnc(this, options))); 23055 } 23056 23057 23058 if (typeof option === 'string') { 23059 get = data[option](value); 23060 } 23061 }); 23062 23063 if (typeof get !== undefined) { 23064 return get; 23065 } else { 23066 return element; 23067 } 23068 }; 23069 23070})(_, $); 23071(function ($) { 23072 var xfaUtil = xfalib.ut.XfaUtil.prototype; 23073 $.widget("xfaWidget.tnc", $.xfaWidget.abstractWidget, { 23074 23075 _widgetName : "tnc", 23076 _superPrototype : $.xfaWidget.abstractWidget.prototype, 23077 getOptionsMap : function () { 23078 var parentOptionsMap = this._superPrototype.getOptionsMap.apply(this, arguments), 23079 newMap = $.extend({}, parentOptionsMap, $.extend({}, this.options, { 23080 "value" : function (value) { 23081 this.$userControl.afTnc("value", value); 23082 }, 23083 "reviewStatus" : function (value) { 23084 this.$userControl.afTnc("reviewStatus", value); 23085 }, 23086 23087 "clickStatus" : function (value) { 23088 this.$userControl.afTnc("clickStatus", value); 23089 }, 23090 23091 "access" : function (value) { 23092 this.$userControl.afTnc("access", value); 23093 } 23094 })); 23095 return newMap; 23096 }, 23097 23098 _getReviewStatus : function () { 23099 return $(this.element).afTnc("reviewStatus"); 23100 }, 23101 23102 _getClickStatus : function () { 23103 return $(this.element).afTnc("clickStatus"); 23104 }, 23105 23106 getEventMap : function () { 23107 var parentEventMap = this._superPrototype.getEventMap.apply(this, arguments), 23108 newMap = $.extend({}, parentEventMap, 23109 { 23110 "change" : null, 23111 "reviewComplete.tnc" : xfaUtil.XFA_CHANGE_EVENT, 23112 "checkboxStateChange.tnc" : xfaUtil.XFA_CHANGE_EVENT 23113 }); 23114 return newMap; 23115 }, 23116 render : function () { 23117 this._superPrototype.render.apply(this, arguments); 23118 $(this.element).afTnc(this.getOptionsMap()); 23119 return $(this.element); 23120 }, 23121 showDisplayValue : function () { 23122 23123 }, 23124 showValue : function () { 23125 23126 }, 23127 getCommitValue : function () { 23128 this.options.reviewStatus = this._getReviewStatus(); 23129 this.options.clickStatus = this._getClickStatus(); 23130 return $(this.element).afTnc("value"); 23131 } 23132 }); 23133})($); 23134 23135(function (_, guidelib) { 23136 var orderGetAttribute = { 23137 "Guide" : "XFA", 23138 "XFA" : "Guide" 23139 }, 23140 23141 newlyAddedProperties = ["enabled", "visible"]; 23142 23143 var GuideNode = guidelib.model.GuideNode = xfalib.ut.EventClass.extend({ 23144 msClassName : "guideNode", 23145 guideUtil : guidelib.util.GuideUtil, 23146 23147 initialize : function () { 23148 23149 23150 this.className = this.jsonModel.guideNodeClass || this.msClassName; 23151 this.parent = null; 23152 this._isItem = false;
23153 this._index = 0; 23154 }, 23155 23156 _postInitialize : function () { 23157 23158 }, 23159 23160 _triggerOnBridge : function (eventName, target, property, oldVal, newVal) { 23161 if (window.guideBridge) { 23162 window.guideBridge.trigger(eventName, 23163 guidelib.event.GuideModelEvent.createEvent(eventName, target, property, 23164 oldVal, newVal)); 23165 } 23166 }, 23167 23168 _getEffectiveBindRef : function() { 23169 return this.bindRef || this.getAttribute("name"); 23170 }, 23171 23172 validate : function (errorList) { 23173 23174 }, 23175 23176 23177 23178 _getXFAOptionStringFromGuideItems : function (guideItems) { 23179 var optionsStr = "", indexOfSeparator = 0; 23180 if (!_.isEmpty(guideItems) && !_.isArray(guideItems)) { 23181 guideItems = [guideItems]; 23182 } 23183 _.each(guideItems, function (item, index, list) { 23184 if(item.indexOf(",") > -1){ 23185 item = item.replace(/,/g, "\\,"); 23186 } 23187 indexOfSeparator = item.indexOf('='); 23188 23189 23190 if (indexOfSeparator > -1) { 23191 optionsStr += item.substring(indexOfSeparator + 1) + "," + item.substring(0, indexOfSeparator); 23192 } else { 23193 optionsStr += item + "," + item; 23194 } 23195 if (index < guideItems.length - 1) { 23196 optionsStr += ","; 23197 } 23198 }); 23199 return optionsStr; 23200 }, 23201 23202 _compareXFAItemsWithGuideItems : function (xfaItems, guideItems) { 23203 var match = true; 23204 if (xfaItems.length !== guideItems.length) { 23205 match = false; 23206 } 23207 if (match) { 23208 var bndNode = this.bindNode; 23209 _.each(guideItems, function (item, index, list) { 23210 if (item.indexOf('=') > -1) { 23211 if ((bndNode.getSaveItem(index) + "=" + bndNode.getDisplayItem(index)) == item) { 23212 match = false; 23213 } 23214 } else { 23215 if ((bndNode.getSaveItem(index) + "=" + bndNode.getDisplayItem(index)) == (item + "=" + item)) { 23216 match = false; 23217 } 23218 } 23219 }); 23220 } 23221 return match; 23222 }, 23223 23224 23225 syncXFAProps : function () { 23226 if (this.bindNode) { 23227 _.each(this._guide()._guideSchema.getAttributes(this.className), 23228 function (attr, attrName) { 23229 var xfaProp = attr.xfaProp, 23230 propChain = (xfaProp || "").split("."), 23231 xfaAttr = propChain.length > 0 ? propChain[propChain.length - 1] 23232 : undefined; 23233 23234 23235 23236 23237 23238 23239 if (!xfaAttr || (newlyAddedProperties.indexOf(attrName) != -1 && _.isUndefined(this.jsonModel[attrName]))) { 23240 return; 23241 } 23242 var objChain = propChain.splice(0, propChain.length - 1), 23243 obj = _.reduce(objChain, 23244 function (obj, prop) { 23245 if (_.isObject(obj)) { 23246 return obj[prop]; 23247 } 23248 return undefined; 23249 }, this.bindNode), 23250 val = this.getGuideProp(attrName, attr), 23251 convertor = this._guide()._guideSchema.getConvertor(attrName), 23252 cVal = convertor ? convertor.guideToXfa.apply(this, [val]) : val, 23253 xfaVal; 23254 try { 23255 if (obj) { 23256 xfaVal = obj[xfaAttr]; 23257 if (cVal !== undefined) { 23258 if (xfaAttr === "items") { 23259 var match = this._compareXFAItemsWithGuideItems(obj, cVal); 23260 var SET_ITEMS_INSERT_MODE_PAIR = 2; 23261 if (!match) { 23262 var optionsStr = this._getXFAOptionStringFromGuideItems(cVal); 23263 if (optionsStr !== "") { 23264 obj.setItems(optionsStr, SET_ITEMS_INSERT_MODE_PAIR); 23265 } else { 23266 obj.clearItems(); 23267 } 23268 } 23269 } else if (cVal !== xfaVal) { 23270 obj[xfaAttr] = cVal; 23271 } 23272 } 23273 } 23274 } catch (e) { 23275 this.logger().error("AF", "setting {0}(guide {1}) for {2} is not supported in xfa", 23276 [xfaProp, attrName, this.bindNode.somExpression]); 23277 if (e.stack) { 23278 this.logger().error("AF", e.stack); 23279 } 23280 } 23281 }, this); 23282 } 23283 }, 23284 23285 23286 prepare : function () { 23287 23288 }, 23289 23290 23291 nakedChildReferences : function (nIndex, obj) { 23292 return; 23293 }, 23294 23295 23296 getNaked : function (nIndex, container, scope) { 23297 var nodeName = this.getAttribute("name"), 23298 oldReference = container._private["_" + nodeName + "_"],
23299 canOverride = (container._isOverriden && !container._isOverriden["_" + nodeName + "_"]), 23300 isGlobalFieldRef = this.isGlobal && (container === guidelib.__runtime__ || container === this._guide().runtime) 23301 && (container[nodeName] instanceof guidelib.model.AbstractField); 23302 23303 if ((scope && scope._nameArray[nodeName] === 1) || (nIndex === this.index)) { 23304 if (oldReference === null || oldReference === undefined || canOverride || isGlobalFieldRef) { 23305 guidelib.util.GuideUtil._createGetterSetter(container, nodeName, this); 23306 if (canOverride === true) { 23307 container._isOverriden["_" + nodeName + "_"] = true; 23308 } 23309 } 23310 } 23311 }, 23312 23313 _getReducedJSON : function () { 23314 var whitelistedProperties = ["name", "templateId", "_value", "guideNodeClass"], 23315 reducedJsonObject = {}; 23316 guidelib.model.util.CommonUtils.returnMinimalJSON(whitelistedProperties, reducedJsonObject, this); 23317 return reducedJsonObject; 23318 }, 23319 23320 _getNakedThis : function () { 23321 return this; 23322 }, 23323 23324 _xfa : function () { 23325 if (window.xfalib) { 23326 return window.xfalib.runtime.xfa; 23327 } 23328 return null; 23329 }, 23330 23331 _guide : function () { 23332 return this.options._guideContainer; 23333 }, 23334 23335 23336 playJson : function (pJsonModel) { 23337 23338 }, 23339 23340 23341 23342 visit : function (callback, context) { 23343 callback.apply(context, [this]); 23344 }, 23345 23346 _collectValues : function (keyValue) { 23347 23348 }, 23349 23350 _setParentAccess : function (value) { 23351 23352 }, 23353 23354 _unloadModel : function () { 23355 this.trigger(guidelib.event.GuideModelEvent.OBJECT_DESTROYED, 23356 guidelib.event.GuideModelEvent.createEvent( 23357 guidelib.event.GuideModelEvent.OBJECT_DESTROYED, 23358 this, 23359 "destroy", 23360 null, 23361 this 23362 ) 23363 ); 23364 this._guide()._modelTemplateCacheStore.removeModel(this.id); 23365 this.off(); 23366 23367 if (_.isObject(guidelib.__runtime__[this.name]) && (guidelib.__runtime__[this.name] === this || guidelib.__runtime__[this.name].somExpression === this.somExpression)) { 23368 guidelib.__runtime__[this.name] = undefined; 23369 if (_.isObject(guidelib.__runtime__._private['_' + this.name + '_'])) { 23370 guidelib.__runtime__._private['_' + this.name + '_'] = undefined; 23371 } 23372 } 23373 23374 if (_.isObject(this._guide().runtime[this.name]) && (this._guide().runtime[this.name] === this || this._guide().runtime[this.name].somExpression === this.somExpression)) { 23375 this._guide().runtime[this.name] = undefined; 23376 if (_.isObject(this._guide().runtime._private['_' + this.name + '_'])) { 23377 this._guide().runtime._private['_' + this.name + '_'] = undefined; 23378 } 23379 } 23380 }, 23381 23382 _triggerEvent : function (event, propName, prevText, newText) { 23383 this.trigger(event, 23384 guidelib.event.GuideModelEvent.createEvent(event, this, propName, 23385 prevText, newText)); 23386 }, 23387 23388 23389 dispatchEvent : function (eventName, payload) { 23390 this._triggerEvent(eventName, payload); 23391 if(this.parent !== null){ 23392 this.parent.dispatchEvent(eventName, payload); 23393 } 23394 }, 23395 23396 23397 setAttribute : function (value, attrName) { 23398 if (this.jsonModel[attrName] !== value) { 23399 var oldValue = this.jsonModel[attrName]; 23400 this.jsonModel[attrName] = value; 23401 this._triggerEvent(guidelib.event.GuideModelEvent.MODEL_CHANGED, attrName, oldValue, value); 23402 } 23403 }, 23404 23405 _getSomExpression : function () { 23406 if (this.parent == null) { 23407 return "guide[0]." + this._escapeQualifiedName(); 23408 } else { 23409 return this.parent.somExpression + "." + this._escapeQualifiedName(); 23410 } 23411 }, 23412 23413 _escapeQualifiedName : function () { 23414 var name = this.getAttribute("name"); 23415 var index = this._index; 23416 var qname = name + "[" + index + "]"; 23417 return qname.replace(/\./, "\\."); 23418 }, 23419 23420 23421 getGuideProp : function (attrName, attr) { 23422 var val = this.getOrElse(this.jsonModel, attrName, attr["default"]); 23423 if (val === undefined) { 23424 return undefined; 23425 } 23426 return guidelib.model.GuideSchema.prototype.getTypedValue(attr.type, val); 23427 23428 }, 23429 23430 23431 getXFAProp : function (attrName, attr) { 23432 var xfaName = attr.xfaProp, 23433 convertor = guidelib.model.GuideSchema.prototype.getConvertor(attrName), 23434 val; 23435 if (this.bindNode && xfaName !== undefined) { 23436 val = this.bindNode.getOrElse(this.bindNode, xfaName, undefined); 23437 if (convertor) { 23438 val = convertor.xfaToGuide.apply(this, [val]); 23439 } 23440 if (val !== undefined) { 23441 return val; 23442 } 23443 } 23444 return undefined; 23445 }, 23446 23447 23448 getAttribute : function (attrName) { 23449 var attr = guidelib.model.GuideSchema.prototype.getAttributeProps(this.className, attrName), 23450 priority = attr.priority || (attr.xfaProp !== undefined ? "XFA" : "Guide"), 23451 23452 val = this["get" + priority + "Prop"].apply(this, [attrName, attr]); 23453 23454 if (val === undefined) { 23455 23456 val = this["get" + orderGetAttribute[priority] + "Prop"].apply(this, [attrName, attr]); 23457 } 23458 return val; 23459 }, 23460 23461 23462 resetData : function () { 23463 23464 } 23465 }); 23466 23467 GuideNode.defineProps({ 23468 23469 23470 "name" : { 23471 get : function () { 23472 return (this.getAttribute("name") || "").replace(/\s+/g, ''); 23473 } 23474 }, 23475 23476 "templateId" : { 23477 get : function () { 23478 return this.getAttribute("templateId"); 23479 } 23480 }, 23481 23482 23483 "id" : { 23484 get : function () { 23485 return this.getAttribute("id") || this.templateId; 23486 } 23487 }, 23488 23489 23490 somExpression : { 23491 get : function () { 23492 return this._getSomExpression(); 23493 } 23494 }, 23495 23496 23497 "title" : { 23498 get : function () { 23499 return this.getAttribute("jcr:title"); 23500 } 23501 }, 23502 23503 23504 "nonLocalizedTitle" : { 23505 get : function () { 23506 return this.getAttribute("nonLocalizedTitle"); 23507 } 23508 }, 23509 23510 23511 panel : { 23512 get : function () { 23513 return this.parent.panel; 23514 } 23515 }, 23516 23517 viewVisited : { 23518 get : function () { 23519 return this.getAttribute("viewVisited"); 23520 }, 23521 set : function (visit) { 23522 this.setAttribute(visit, "viewVisited"); 23523 } 23524 }, 23525 23526 23527 index : { 23528 get : function () { 23529 return this._index; 23530 } 23531 }, 23532 23533 23534 visible : { 23535 get : function () { 23536 return true; 23537 }, 23538 set : function (value) { 23539 23540 } 23541 }, 23542 23543 23544 enabled : { 23545 get : function () { 23546 return true; 23547 }, 23548 set : function (value) { 23549 23550 } 23551 }, 23552 23553 23554 cssClassName : { 23555 get : function () { 23556 return this.getAttribute("css"); 23557 } 23558 }, 23559 23560 enableLayoutOptimization : { 23561 get : function () { 23562 return false;
23563 } 23564 }, 23565 23566 jcrPath : { 23567 get : function () { 23568 return this.jsonModel["jcr:path"]; 23569 } 23570 }, 23571 23572 23573 targetVersion : { 23574 get : function () { 23575 return this.getAttribute("fd:targetVersion"); 23576 } 23577 } 23578 }); 23579}(_, guidelib)); 23580(function (_, guidelib, $) { 23581 var Verify = guidelib.model.Verify = guidelib.model.GuideNode.extend({ 23582 msClassName : "verify", 23583 23584 initialize : function () { 23585 Verify._super.initialize.call(this); 23586 this.validationStatus = true; 23587 }, 23588 23589 validate : function (errorList) { 23590 23591 23592 var iframeFormBridge = null, validationStatus = true; 23593 23594 if (this.jsonModel.interactive !== undefined && this.jsonModel.interactive === "true") { 23595 23596 23597 23598 23599 23600 if (guideBridge.hostName === "client") { 23601 iframeFormBridge = $('#verifiable_form').get(0).contentWindow.formBridge; 23602 } 23603 23604 23605 if (iframeFormBridge !== undefined && iframeFormBridge !== null) { 23606 validationStatus = iframeFormBridge.validateForm(); 23607 if (!validationStatus) { 23608 errorList.push({som : this.somExpression, errorText : "XFA validation errors."}); 23609 } 23610 this.validationStatus = validationStatus; 23611 } 23612 } 23613 23614 return validationStatus; 23615 } 23616 }); 23617 Verify.defineProps({ 23618 forceElementFocusChange : { 23619 get : function () { 23620 return true; 23621 } 23622 } 23623 }); 23624})(_, guidelib, $); 23625(function (_, guidelib) { 23626 var Esign = guidelib.model.Esign = guidelib.model.GuideNode.extend({ 23627 msClassName : "esign", 23628 23629 initialize : function () { 23630 Esign._super.initialize.call(this); 23631 this.validationStatus = true; 23632 }, 23633 23634 validate : function (errorList) { 23635 23636 23637 var validationStatus = true; 23638 if (!_.isUndefined(FD) && 23639 !_.isUndefined(FD.AFaddon) && 23640 FD.AFaddon.Signing) { 23641 validationStatus = FD.AFaddon.Signing.isDocumentSigned(this.jsonModel.signingService); 23642 if (!validationStatus) { 23643 errorList.push({som : this.somExpression, errorText : "Signing not complete."}); 23644 } 23645 } 23646 this.validationStatus = validationStatus; 23647 return validationStatus; 23648 } 23649 }); 23650 Esign.defineProps({ 23651 forceElementFocusChange : { 23652 get : function () { 23653 return true; 23654 } 23655 } 23656 }); 23657})(_, guidelib); 23658(function (_, xfalib, guidelib) { 23659 23660 var expressionContent = "with(this) {" + 23661 "\n\t with(guidelib.__runtime__) {" + 23662 "\n\t with(this._guide().runtime) {" + 23663 "\n\t\t var _guide_result = this[${affectedProp}] = eval(\"${expression}\");" + 23664 "\n\t\t return _guide_result ;" + 23665 "\n\t }" + 23666 "\n}};", 23667 scriptContent = "with(this) {" + 23668 "\n\t with(guidelib.__runtime__) {" + 23669 "\n\t with(this._guide().runtime) {" + 23670 "\n\t var result = eval(\"${expression}\");" + 23671 "\n\t\t return result; " + 23672 "\n\t }" + 23673 "\n}}"; 23674 23675 var Scriptable = guidelib.model.Scriptable = guidelib.model.GuideNode.extend({ 23676 msClassName : "scriptable", 23677 23678 initialize : function () { 23679 Scriptable._super.initialize.call(this); 23680 23681 this.className = this.jsonModel.guideNodeClass || this.msClassName; 23682 this._compiledExpressions = {}; 23683 this._compiledScripts = {}; 23684 this.mActiveEvents = []; 23685 this.dependants = []; 23686 23687 if (this.initScript) { 23688 this._isInitScriptExecuted = false;
23689 } 23690 this._collectExpressions(); 23691 }, 23692 23693 _postInitialize : function () { 23694 23695 if (this._isXfaNode()) { 23696 this.bindNode = this.options.bindNode || this._getBindNode(); 23697 if (this.bindNode) { 23698 this.bindNode.on(xfalib.script.XfaModelEvent.FORM_MODEL_CHANGED, this); 23699 } 23700 } 23701 23702 this._parentAccess = this.getOrElse(this, "parent.enabled", true); 23703 }, 23704 23705 _unloadModel : function () { 23706 if (this._isXfaNode && this._isXfaNode()) { 23707 if (this.bindNode) { 23708 this.bindNode.off(xfalib.script.XfaModelEvent.FORM_MODEL_CHANGED, this); 23709 } 23710 } 23711 23712 Scriptable._super._unloadModel.call(this); 23713 }, 23714 23715 _collectExpressions : function () { 23716 if (this.visibleExp) { 23717 this._compiledExpressions["visibleExp"] = this._compileExpression(this.visibleExp, "visible"); 23718 } 23719 if (this.enabledExp) { 23720 this._compiledExpressions["enabledExp"] = this._compileExpression(this.enabledExp, "enabled"); 23721 } 23722 23723 if (this.initScript) { 23724 this._compiledScripts.initScript = this._compileExpression(this.initScript, null); 23725 } 23726 }, 23727 23728 _compileExpression : function (expression, affectedProp) { 23729 if (expression) { 23730 try { 23731 23732 var content = affectedProp ? expressionContent.replace(/\${affectedProp}/g, '"' + affectedProp + '"') 23733 .replace(/\${expression}/g, expression.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/(?:\r\n|\r|\n)/g, " ")) 23734 : scriptContent.replace(/\${expression}/g, 23735 expression.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/(?:\r\n|\r|\n)/g, " ")); 23736 23737 return new Function(content); 23738 } catch (exception) { 23739 this.logger().error("AF", "Error in compiling expression:" + expression); 23740 } 23741 } 23742 return null; 23743 }, 23744 23745 _isXfaNode : function () { 23746 return (this._xfa() && this.getOrElse(this, "jsonModel.bindRef", "").indexOf("xfa[0].form[0].") === 0); 23747 }, 23748 23749 _xfa : function () { 23750 return this.getOrElse(window, "xfalib.runtime.xfa", null); 23751 }, 23752 23753 prepare : function () { 23754 Scriptable._super.prepare.apply(this); 23755 23756 23757 23758 23759 23760 if (this.initScript && !this._isInitScriptExecuted) { 23761 this.executeExpression("initScript"); 23762 this._isInitScriptExecuted = true; 23763 } 23764 var expressionTypes = _.keys(this._compiledExpressions); 23765 this._guide().queueExpressions(this, expressionTypes); 23766 }, 23767 23768 23769 handleEvent : function (evnt) { 23770 if (evnt instanceof xfalib.script.XfaModelEvent) { 23771 switch (evnt.name) { 23772 case xfalib.script.XfaModelEvent.FORM_MODEL_CHANGED: 23773 this._handleXfaModelChanged(evnt); 23774 break; 23775 default: 23776 23777 } 23778 } else if (evnt instanceof guidelib.event.GuideModelEvent) { 23779 this.handleGuideEvent(evnt); 23780 } 23781 }, 23782 23783 handleGuideEvent : function (evnt) { 23784 }, 23785 23786 23787 executeExpression : function (eventName, detail) { 23788 var guideContainerNode = this._guide(); 23789 if (this._isXfaNode() && this.bindNode instanceof xfalib.script.EventContainerNode) { 23790 if (guidelib.util.GuideUtil.xfaExprMap[eventName] !== null) { 23791 this.bindNode.execEvent(guidelib.util.GuideUtil.xfaExprMap[eventName] || eventName, detail); 23792 } 23793 } 23794 if (_.isUndefined(this._compiledExpressions[eventName]) && _.isUndefined(this._compiledScripts[eventName])) { 23795 if (!guideContainerNode._currentContext) { 23796 guideContainerNode.runPendingExpressions(); 23797 } else { 23798 this.logger().log("AF", "executeExpression called withing from another executeExpression. Should NEVER happen "); 23799 } 23800 return true; 23801 } 23802 23803 if (this.mActiveEvents[eventName]) { 23804 return; 23805 } 23806 this.mActiveEvents[eventName] = true; 23807 var managedExp = this._compiledExpressions[eventName] ? true : false, 23808 oldContext = guideContainerNode._currentContext; 23809 23810 guideContainerNode._currentContext = {contextNode: this, expression: eventName, managedExp: managedExp}; 23811 this._setExpressionContext(this, this.index); 23812 var $event = { 23813 name: eventName, 23814 target: this, 23815 data: detail 23816 }; 23817 guideContainerNode.runtime.$event = $event;
23818 var expResult = this._expressionHandler(eventName); 23819 this.mActiveEvents[eventName] = false; 23820 23821 23822 guideContainerNode._currentContext = oldContext; 23823 if (oldContext && oldContext.contextNode) { 23824 oldContext.contextNode._setExpressionContext(oldContext.contextNode, oldContext.contextNode.index); 23825 } 23826 guideContainerNode.runtime.$event = null; 23827 guideContainerNode.runPendingExpressions(); 23828 return expResult; 23829 }, 23830 23831 _setExpressionContext : function (startNode, currentIndex) { 23832 23833 var currentSom = this.somExpression; 23834 function somCommonPrefixLen(field) { 23835 return guidelib.util.GuideUtil.commonPrefixLen(currentSom, field.somExpression); 23836 } 23837 23838 if (this._guide().internal.liveModel) { 23839 _.each(this._guide().internal.liveModel.getCrossFragmentFields(), function (fields, name) { 23840 var loadedFields, 23841 nearestField; 23842 23843 23844 loadedFields = this._guide().internal.liveModel.getAllFieldModels(_.keys(fields)); 23845 23846 23847 if (!_.isEmpty(loadedFields)) { 23848 nearestField = _.max(loadedFields, somCommonPrefixLen); 23849 } 23850 23851 23852 23853 23854 23855 guidelib.util.GuideUtil._createGetterSetter(guidelib.__runtime__, name, nearestField || fields[_.keys(fields)[0]]); 23856 guidelib.util.GuideUtil._createGetterSetter(this._guide().runtime, name, nearestField || fields[_.keys(fields)[0]]); 23857 }, this); 23858 } 23859 23860 23861 this._guide().runtime._isOverriden = {}; 23862 guidelib.__runtime__._isOverriden = {}; 23863 while (startNode) { 23864 23865 startNode.nakedChildReferences(currentIndex, guidelib.__runtime__); 23866 startNode.nakedChildReferences(currentIndex, this._guide().runtime); 23867 currentIndex = startNode.index; 23868 startNode = startNode.parent; 23869 } 23870 }, 23871
23872 _expressionHandler : function (expressionName) { 23873 var expFn, returnValue; 23874 if (this._compiledExpressions[expressionName]) { 23875 expFn = this._compiledExpressions[expressionName]; 23876 try { 23877 returnValue = expFn.apply(this); 23878 } catch (exception) { 23879 23880 this.logger().error("AF", "Error in compiling expression:" + this.name + ":" + expressionName + ":" + exception.stack); 23881 } 23882 } else if (this._compiledScripts[expressionName]) { 23883 expFn = this._compiledScripts[expressionName]; 23884 try { 23885 return expFn.apply(this); 23886 } catch (scriptException) { 23887 23888 this.logger().error("AF", "Error in compiling expression:" + this.name + ":" + expressionName + ":" + scriptException.stack); 23889 } 23890 } 23891 return returnValue; 23892 }, 23893 23894 _handleXfaModelChanged : function (event) { 23895 if (event._property == "presence") { 23896 23897 var newText = !(event.newText != "visible"); 23898 this._triggerEvent(guidelib.event.GuideModelEvent.MODEL_CHANGED, "visible", event.prevText, newText); 23899 } else if (event._property == "access") { 23900 this.trigger(guidelib.event.GuideModelEvent.MODEL_CHANGED, 23901 guidelib.event.GuideModelEvent.createEvent( 23902 guidelib.event.GuideModelEvent.MODEL_CHANGED, 23903 this, 23904 "enabled", 23905 event.prevText == "open", 23906 event.newText == "open" 23907 ) 23908 ); 23909 } 23910 }, 23911 23912 _getScreenReaderText : function (index) { 23913 var screenReaderText, assistPriority = this._getAssistPriority(); 23914 if (assistPriority == "custom") { 23915 screenReaderText = this._getCustomAssist(index) || this._getToolTip(index) || this._getCaption(index) || this._getName(index); 23916 } else if (assistPriority == "shortDescription") { 23917 screenReaderText = this._getToolTip(index) || this._getCaption(index) || this._getName(index); 23918 } else if (assistPriority == "label") { 23919 screenReaderText = this._getCaption(index) || this._getName(index); 23920 } else if (assistPriority == "name") { 23921 screenReaderText = this._getName(index); 23922 } 23923 return screenReaderText; 23924 }, 23925 23926 _getAssistPriority : function () { 23927 23928 return this.getAttribute("assistPriority") || "custom"; 23929 }, 23930 23931 _getCustomAssist : function () { 23932 var customAssist; 23933 if (this.bindNode && this.bindNode.assist && this.bindNode.assist.speak && this.bindNode.assist.speak.value) { 23934 customAssist = this.bindNode.assist.speak.value; 23935 } else if (this.jsonModel.custom) { 23936 customAssist = this.jsonModel.custom; 23937 } 23938 return customAssist; 23939 }, 23940 23941 _getToolTip : function () { 23942 return this.shortDescription; 23943 }, 23944 23945 _getCaption : function () { 23946 return this.getAttribute("jcr:title"); 23947 }, 23948 23949 _getName : function (index) { 23950 return this.getAttribute("name"); 23951 }, 23952 23953 _getBindNode : function () { 23954 var bindRef = this.getAttribute("bindRef"); 23955 if (!bindRef) { 23956 return null; 23957 } 23958 var bindNode = null; 23959 var bindParent = this.parent ? this.parent._bindParent() : null; 23960 if (bindParent) { 23961 var bindParentRef = bindParent.getAttribute("bindRef"); 23962 if (bindRef.substring(0, bindParentRef.length) == bindParentRef) { 23963 23964 23965 var relativeBindRef = bindRef.substring(bindParentRef.length + 1);
23966 bindNode = bindParent.bindNode.resolveNode(relativeBindRef); 23967 } 23968 } 23969 if (!bindNode && this._isXfaNode()) { 23970 bindNode = this._xfa().resolveNode(bindRef); 23971 } 23972 return bindNode; 23973 }, 23974 23975 _bindParent : function () { 23976 if (this.bindNode) { 23977 return this; 23978 } else if (this.parent) { 23979 return this.parent._bindParent(); 23980 } 23981 return null; 23982 }, 23983 23984 23985 _getEnabled : function () { 23986 if (this.bindNode) { 23987 return this.bindNode.access == "open"; 23988 } else { 23989 return this.getAttribute("enabled") && this._parentAccess; 23990 } 23991 }, 23992 23993 23994 _setEnabled : function (value) { 23995 if (!this.bindNode) { 23996 if (this.getAttribute("enabled") !== value) { 23997 var oldEnabled = this.getAttribute("enabled"); 23998 this.setAttribute(value, "enabled"); 23999 this.trigger(guidelib.event.GuideModelEvent.MODEL_CHANGED, 24000 guidelib.event.GuideModelEvent.createEvent( 24001 guidelib.event.GuideModelEvent.MODEL_CHANGED, 24002 this, 24003 "enabled", 24004 oldEnabled, 24005 this.jsonModel.enabled 24006 ) 24007 ); 24008 this._triggerOnBridge("elementEnableChanged", this, "enablement", oldEnabled, this.jsonModel.enabled); 24009 } 24010 24011 } else { 24012 var convertor = this._guide()._guideSchema.getConvertor("enabled"); 24013 if (convertor) { 24014 this.bindNode.access = convertor.guideToXfa.apply(this, [value]); 24015 } 24016 } 24017 }, 24018 24019 24020 _setParentAccess : function (value) { 24021 var oldValue = this._parentAccess; 24022 this._parentAccess = value; 24023 this.trigger(guidelib.event.GuideModelEvent.MODEL_CHANGED, 24024 guidelib.event.GuideModelEvent.createEvent( 24025 guidelib.event.GuideModelEvent.MODEL_CHANGED, 24026 this, 24027 "enabled", 24028 oldValue, 24029 this.enabled 24030 ) 24031 ); 24032 }, 24033 24034 24035 _addStateOverride : function (key, values) { 24036 if (key !== null && _.isString(key) && values !== null) { 24037 var somExpr = this.somExpression; 24038 somExpr = somExpr.substring(this._guide().somExpression.length + 1); 24039 this.jsonModel.stateOverrides = this.jsonModel.stateOverrides || {"somExpr" : somExpr}; 24040 this.jsonModel.stateOverrides[key] = values; 24041 this._guide()._addToStateOverrideMap(this.id + this.name, this.jsonModel.stateOverrides); 24042 } 24043 } 24044 }); 24045 24046 Scriptable.defineProps({ 24047 24048 shortDescription : { 24049 get : function () { 24050 return this.getAttribute("shortDescription"); 24051 } 24052 }, 24053 24054 24055 longDescription : { 24056 get : function () { 24057 return this.getAttribute("longDescription"); 24058 } 24059 }, 24060 24061 visibleExp : { 24062 get : function () { 24063 return this.getAttribute("visibleExp"); 24064 } 24065 }, 24066 24067 initScript : { 24068 get : function () { 24069 return this.jsonModel.initScript; 24070 } 24071 }, 24072 24073 enabledExp : { 24074 get : function () { 24075 return this.getAttribute("enabledExp"); 24076 } 24077 }, 24078 24079 24080 visible : { 24081 get : function () { 24082 return this.getAttribute("visible"); 24083 }, 24084 24085 set : function (value) { 24086 if (!this.bindNode) { 24087 if (this.getAttribute("visible") !== value) { 24088 var oldVisible = this.getAttribute("visible"), 24089 dorExclusionFlag; 24090 this.setAttribute(value, "visible"); 24091 24092 24093 if (this.getAttribute("dorExclusion") !== null) { 24094 if ((this._guide().getAttribute("excludeFromDoRIfHidden") === "true") 24095 || (this._guide().print 24096 && this._guide().print["excludeFromDoRIfHidden"] === "true")) { 24097 dorExclusionFlag = !value; 24098 24099 24100 this.dorExclusion = dorExclusionFlag; 24101 } 24102 } 24103 this.trigger(guidelib.event.GuideModelEvent.MODEL_CHANGED, 24104 guidelib.event.GuideModelEvent.createEvent( 24105 guidelib.event.GuideModelEvent.MODEL_CHANGED, 24106 this, 24107 "visible", 24108 oldVisible, 24109 this.jsonModel.visible 24110 ) 24111 ); 24112 this._triggerOnBridge("elementVisibleChanged", this, "visible", oldVisible, this.jsonModel.visible); 24113 24114 } 24115 } else { 24116 if (value == true) { 24117 this.bindNode.presence = "visible"; 24118 } else { 24119 this.bindNode.presence = "hidden"; 24120 } 24121 } 24122 } 24123 }, 24124 24125 24126 dorExclusion : { 24127 get : function () { 24128 24129 if (this.jsonModel.dorExclusion != null) { 24130 if (_.isString(this.jsonModel.dorExclusion)) { 24131 24132 return this.jsonModel.dorExclusion === "true"; 24133 } else { 24134 return this.jsonModel.dorExclusion; 24135 } 24136 } 24137 24138 else if ((this._guide().getAttribute("excludeFromDoRIfHidden") === "true") 24139 || (this._guide().print 24140 && this._guide().print["excludeFromDoRIfHidden"] === "true")) { 24141 return !this.visible; 24142 } else { 24143 24144 return false;
24145 } 24146 }, 24147 24148 set : function (value) { 24149 24150 24151 24152 var somExpr = this.somExpression; 24153 somExpr = somExpr.substring(this._guide().somExpression.length + 1); 24154 this._guide()._addToExcludeFromDorMap(somExpr, value); 24155 this.jsonModel.dorExclusion = value; 24156 } 24157 }, 24158 24159 24160 stateOverrides : { 24161 get : function () { 24162 return this.jsonModel.stateOverrides; 24163 } 24164 }, 24165 24166 24167 enabled : { 24168 get : function () { 24169 return this._getEnabled(); 24170 }, 24171 24172 set : function (value) { 24173 24174 this._setEnabled(!!value); 24175 } 24176 }, 24177 24178 24179 bindRef : { 24180 get : function () { 24181 return (this.getAttribute("bindRef") || "").replace(/\s+/g, ''); 24182 } 24183 }, 24184 24185 24186 isXsd : { 24187 24188 get : function () { 24189 return _.isString(guideBridge._guide.xsdRef) && !_.isEmpty(this.bindRef) && this.bindRef[0] === '/'; 24190 } 24191 } 24192 }); 24193})(_, window.xfalib, guidelib); 24194(function (_, guidelib) { 24195 var GuideImage = guidelib.model.GuideImage = guidelib.model.Scriptable.extend({ 24196 msClassName : "guideImage" 24197 }); 24198 24199 GuideImage.defineProps({ 24200 value : { 24201 get : function () { 24202 if (this.bindNode) { 24203 return this.bindNode.rawValue; 24204 } else { 24205 return null; 24206 } 24207 } 24208 } 24209 }); 24210})(_, guidelib); 24211(function (_, guidelib) { 24212 var GuideAdModule = guidelib.model.GuideAdModule = guidelib.model.Scriptable.extend({ 24213 msClassName : "guideAdModule", 24214 24215 initialize : function () { 24216 GuideAdModule._super.initialize.call(this); 24217 this.jsonModel["{default}"] = this.getOrElse(this.jsonModel, "{default}", this.jsonModel._value); 24218 this.layoutConfigs = []; 24219 24220 if (typeof this.jsonModel.layoutConfig === "string") { 24221 this.layoutConfigs.push(JSON.parse(this.jsonModel.layoutConfig)); 24222 } else { 24223 _.each(this.jsonModel.layoutConfig, function (layoutConfig) { 24224 this.layoutConfigs.push(JSON.parse(layoutConfig)); 24225 }, this); 24226 } 24227 }, 24228 24229 _getTypedValue : function (value) { 24230 if (_.isUndefined(value) || value === null || value === "") { 24231 return null; 24232 } 24233 return value + ""; 24234 }, 24235 24236 playJson : function (pJsonModel) { 24237 var olval = this.jsonModel._value; 24238 this.jsonModel._value = pJsonModel._value; 24239 this._triggerOnBridge("elementValueChanged", this, "value", olval, this.jsonModel._value); 24240 } 24241 }); 24242 24243 GuideAdModule.defineProps({ 24244 24245 value : { 24246 get : function () { 24247 return this._getTypedValue(this.jsonModel._value); 24248 }, 24249 set : function (newValue) { 24250 var oldValue = this._getTypedValue(this.jsonModel._value), 24251 newTypedValue = this._getTypedValue(newValue); 24252 24253 if (newTypedValue !== undefined && (newTypedValue !== oldValue)) { 24254 if (this.jsonModel._value !== newValue) { 24255 this.jsonModel._value = newTypedValue || ""; 24256 } 24257 this._triggerOnBridge("elementValueChanged", this, "value", oldValue, newTypedValue); 24258 } 24259 } 24260 } 24261 }); 24262}(_, guidelib)); 24263(function (_, $) { 24264 24265 var Responsive = { 24266 breakpoints : [], 24267 controlRowDefaults : {} 24268 }, 24269 isPad = navigator.userAgent.match(/iPad/i) !== null, 24270 isIphone = (navigator.userAgent.match(/iPhone/i) !== null) || (navigator.userAgent.match(/iPod/i) !== null), 24271 isIphoneOrIpad = isPad || isIphone; 24272 24273 Responsive.breakpoints = [ 24274 { 24275 name : 'desktop', 24276 width : Infinity 24277 }, 24278 { 24279 name : 'tablet-landscape', 24280 width : 1024 24281 }, 24282 { 24283 name : 'tablet-potrait', 24284 width : 768 24285 }, 24286 { 24287 name : 'mobile-landscape', 24288 width : 480 24289 }, 24290 { 24291 name : 'mobile-potrait', 24292 width : 320 24293 } 24294 ]; 24295 24296 24297 Responsive.controlRowDefaults = { 24298 24299 breakpoints : Responsive.breakpoints, 24300 24301
24302 controlRowDetails : { 24303 renderer : function (tablePlugin, row) { 24304 var cells = null; 24305 if (tablePlugin.options.bControlRowHiddenCells) { 24306 cells = row.$tableRowElement.find("td:hidden"); 24307 } else { 24308 cells = row.$tableRowElement.find("td"); 24309 24310 if (tablePlugin.options.bDisableControlRowCells) { 24311 24312 row.$tableRowElement.find("input, select, textarea, button").attr("disabled", "disabled"); 24313 } 24314 } 24315 var data = cells.map(function (index, cell) { 24316 var $cell = $(cell), 24317 header = tablePlugin.header($cell), 24318 $clickedTableRow = row.$tableRowElement, 24319 cellIdx = null, 24320 cellData = null; 24321 cellIdx = { 24322 24323 row : $clickedTableRow.index(), 24324 column : $cell.index() 24325 }; 24326 24327 cellData = tablePlugin._getCellData(cellIdx); 24328 return $("<li></li>").attr("data-rtp-index", cellIdx.column).addClass("clearfix").append( 24329 $("<div></div>").addClass("rtp-title").text($.trim(header.text())) 24330 ).append( 24331 $("<div></div>").addClass("rtp-data").append(cellData) 24332 ); 24333 }); 24334 24335 return $('<ul data-rtp-index="' + row.index + '"></ul>').append(data.get()); 24336 }, 24337 24338 target : 0, 24339 24340 type : 'inline' 24341 } 24342 }; 24343 24344 var ResponsiveTablePlugin = function (element, options) { 24345 this.options = options; 24346 this.$element = $(element); 24347 this.columns = []; 24348 }; 24349 24350 24351 var TableColumn = function ($tableElement, colIdx, bIsResize) { 24352 var $colHeaderElement = $tableElement.find("th").eq(colIdx); 24353 24354 this.minWidth = (bIsResize ? (parseInt($colHeaderElement.css("min-width"), 10)) : $colHeaderElement.outerWidth()); 24355 this.header = $colHeaderElement; 24356 this.colIndex = colIdx; 24357 this.$tableElement = $tableElement; 24358 }; 24359 24360 24361 TableColumn.prototype = { 24362 24363 cells : function () { 24364 24365 var headerValue = this.header.attr("id"); 24366 return this.$tableElement.find("tr td").filter(function () { 24367 var id = $(this).attr("headers"); 24368 if (id) { 24369 if (id.indexOf(headerValue) > -1) { 24370 return $(this); 24371 } 24372 } 24373 }); 24374 }, 24375 24376 visible : function (bFlag) { 24377 var cells = this.cells(); 24378 this.isVisible = bFlag; 24379 if (bFlag === true) { 24380 cells.show(); 24381 this.header.show(); 24382 } else { 24383 this.header.hide(); 24384 24385 var headers = this.header.prevAll().filter(":visible"), 24386 headerLen = headers.length; 24387 24388 $.each(cells, function () { 24389 if (!$(this).data("shown")) { 24390 $(this).hide(); 24391 } 24392 var colSpan = $(this).data("colspan") || $(this).attr("colspan"); 24393 24394 if (colSpan > 1) { 24395 var totalColSpan = 0; 24396 $(this).prevAll().each(function () { 24397 totalColSpan += (+($(this).data("colspan") || $(this).attr("colspan"))); 24398 }); 24399 24400 if (totalColSpan == 0) { 24401 $(this).show(); 24402 $(this).data("shown", true); 24403 24404 if ($(this).data("colspan") == null) { 24405 $(this).data("colspan", $(this).attr("colspan")); 24406 } 24407 $(this).attr("colspan", headerLen); 24408 } 24409 24410 else if (totalColSpan < headerLen) { 24411 $(this).show(); 24412 $(this).data("shown", true);
24413 if ($(this).data("colspan") == null) { 24414 $(this).data("colspan", $(this).attr("colspan")); 24415 } 24416 $(this).attr("colspan", (headerLen - totalColSpan)); 24417 } 24418 } 24419 }); 24420 } 24421 } 24422 }; 24423 24424 24425 var TableRow = function ($tableRowElement) { 24426 this.$tableRowElement = $tableRowElement; 24427 this.index = $tableRowElement.index(); 24428 24429 this.child = { 24430 $element : null, 24431 isShown : false 24432 }; 24433 $tableRowElement.data("tableRow", this); 24434 }; 24435 24436 TableRow.prototype = { 24437 24438 updateChild : function (info, colSpan) { 24439 24440 if (this.child.$element && this.child.$element.length > 0) { 24441 this.child.$element.empty(); 24442 this.child.$element.append($("<td></td>").addClass(ResponsiveTablePlugin.prototype.defaults.CONTROL_ROW_CLASS).attr("colspan", colSpan).append($(info))); 24443 } else if (this.$tableRowElement.next(ResponsiveTablePlugin.prototype.defaults.CONTROL_ROW_SELECTOR).length > 0) { 24444 this.child.$element = this.$tableRowElement.next(); 24445 this.child.$element.append($("<td></td>").addClass(ResponsiveTablePlugin.prototype.defaults.CONTROL_ROW_CLASS).attr("colspan", colSpan).append($(info))); 24446 } else { 24447 24448 this.child.$element = $("<tr></tr>").addClass(ResponsiveTablePlugin.prototype.defaults.CONTROL_ROW_CLASS).append($("<td></td>").addClass(ResponsiveTablePlugin.prototype.defaults.CONTROL_ROW_CLASS).attr("colspan", colSpan).append($(info))); 24449 24450 this.$tableRowElement.after(this.child.$element); 24451 } 24452 24453 }, 24454 24455 showChild : function () { 24456 24457 this.child.$element.get(0).style.display = ""; 24458 this.child.isShown = true; 24459 }, 24460 24461 hideChild : function () { 24462 this.child.$element.hide(); 24463 this.child.isShown = false; 24464 } 24465 }; 24466 24467 ResponsiveTablePlugin.prototype = { 24468 24469 _getCellData : function (index) { 24470 24471 var tableRow = this.$element.find("tbody tr").eq(index.row), 24472 tableCell = tableRow.find("td").eq(index.column); 24473 24474 if (this.options.viewCallback) { 24475 24476 var id = tableCell.find(ResponsiveTablePlugin.prototype.defaults.GUIDE_ID_SELECTOR).attr("id"); 24477 24478 return this.options.viewCallback(id); 24479 } else { 24480 return tableCell.html(); 24481 } 24482 }, 24483 24484 24485 header : function (cell) { 24486 24487 24488 var id = cell.attr("headers").split(" ")[0]; 24489 24490 return this.$element.find("#" + id); 24491 }, 24492 24493 initializeColumns : function (bIsResize) { 24494 var columns = []; 24495 24496 24497 24498 this.colLength = this.$element.find("th").length; 24499 for (var colIdx = 0; colIdx < this.colLength; colIdx++) { 24500 24501 24502 columns.push(new TableColumn(this.$element, colIdx, bIsResize)); 24503 } 24504 return columns; 24505 }, 24506 24507 24508 _initializeColumnWidth : function () { 24509 24510 24511 24512 var display = this._getColumnsVisibility(), 24513 24514 visibleColumns = _.filter(display, function (item) { 24515 return item == true; 24516 }).length, 24517 $allTableHeaders = this.$element.find("th"), 24518 $tableHeader = null, 24519 width = null, 24520 sum = 0; 24521 if (!this.options.bAutoWidth) { 24522 24523 24524 for (var i = 0; i < visibleColumns; i++) { 24525 sum += parseInt(this.options.aWidth[i], 10); 24526 } 24527 } else { 24528 sum = visibleColumns; 24529 } 24530 24531 if (display.length == this.colLength) { 24532 for (var i = 0; i < visibleColumns; i++) { 24533 if (this.options.aWidth) { 24534 24535 width = ((Math.floor((this.options.aWidth[i] * 100) / sum)) + "%"); 24536 } else { 24537 width = ((Math.floor((1 * 100) / sum)) + "%"); 24538 } 24539 $tableHeader = $allTableHeaders.eq(i); 24540 24541 24542 $tableHeader[0].style.width = width; 24543 } 24544 } 24545 }, 24546 24547 _constructor : function () { 24548 var that = this; 24549 24550 this.controlRow = $.extend(true, {}, Responsive.controlRowDefaults); 24551 this.columns = this.initializeColumns(); 24552 24553 $(window).on("resize orientationchange", function (event) { 24554 that._initializeColumnVisibility(event); 24555 }); 24556 24557 24558 24559 this.controlRow.breakpoints.sort(function (a, b) { 24560 return a.width < b.width ? 1 : 24561 a.width > b.width ? -1 : 0; 24562 }); 24563 this._initializeColumnVisibility(); 24564 24565 this._controlRowInitialization(); 24566 }, 24567 24568 _initializeColumnVisibility : function (event) { 24569 var that = this; 24570 24571 if (event) { 24572 24573 24574 this.$element.find("td").each(function () { 24575 $(this).removeData("shown"); 24576
24577 if ($(this).data("colspan") != null) { 24578 24579 $(this).attr("colspan", $(this).data("colspan")); 24580 } 24581 }); 24582 24583 24584 24585 this.columns = this.initializeColumns(event); 24586 } 24587 24588 24589 24590 24591 this._initializeColumnWidth(); 24592 this.display = this._resize(); 24593 24594 24595 this.$element.find("tbody tr:not(.child)").each(function () { 24596 if ($(this).next(ResponsiveTablePlugin.prototype.defaults.CONTROL_ROW_SELECTOR).length == 0) { 24597 $(this).after($("<tr></tr>").addClass(ResponsiveTablePlugin.prototype.defaults.CONTROL_ROW_CLASS).hide()); 24598 } 24599 }); 24600 24601 24602 var details = this.controlRow.controlRowDetails; 24603 24604 if (details.type) { 24605 24606 this._controlRowVisibility(event); 24607 24608 24609 this.$element.on(ResponsiveTablePlugin.prototype.defaults.EVENT_COLUMN_VISIBILITY, function () { 24610 that._controlRowVisibility(); 24611 }); 24612 24613 this.$element.addClass('rtp-' + details.type); 24614 } 24615 24616 if (this.options.fixTableControls) { 24617 24618 24619 24620 if (_.isUndefined(event) || event.type === "orientationchange" || (event.type === "resize" && !isIphoneOrIpad)) { 24621 24622 this.options.fixTableControls(event); 24623 } 24624 } 24625 }, 24626 24627 24628 _fixControlRows : function () { 24629 this.$element.find(ResponsiveTablePlugin.prototype.defaults.CONTROL_ROW_SELECTOR).remove(); 24630 }, 24631 24632 24633 isColumnHidden : function () { 24634 return this.bColumnHidden || false; 24635 }, 24636 24637 24638 _rearrangeTableRuntimeControls : function (lastVisibleColumn, event) { 24639 24640 24641 var $runtimeAddControls = this.$element.find(".guideTableRuntimeControls .guideTableRuntimeAddControl"), 24642 runtimeControlIndex = 0, 24643 that = this, 24644 index = null; 24645 $runtimeAddControls.each(function () { 24646 24647 if ($(this).is(":visible")) { 24648 runtimeControlIndex = $(this).closest("td").index(); 24649 return false; 24650 } 24651 }); 24652 24653 if ((runtimeControlIndex <= lastVisibleColumn)) { 24654 24655 24656 $runtimeAddControls.each(function () { 24657 24658 24659 var $runtimeControl = $(this).closest(".guideTableRuntimeControls"), 24660 $runtimeControlTableRow = $(this).closest("tr"); 24661 if ($runtimeControl.hasClass("guideTableRuntimeRightControls")) { 24662 24663 $runtimeControl.appendTo($runtimeControlTableRow.find("td").eq(lastVisibleColumn)); 24664 if (runtimeControlIndex !== lastVisibleColumn) { 24665 var $component = $runtimeControl.prev(); 24666 $component.css("display", "block"); 24667 $component.css("float", "none"); 24668 } 24669 } 24670 24671 }); 24672 } 24673 }, 24674 24675 24676 _controlRowVisibility : function (event) { 24677 var that = this, 24678 24679 hiddenColumns = _.filter(this.columns, function (element) { 24680 return (element.isVisible) !== true; 24681 }), 24682 lastVisibleColumn = this.columns.length - hiddenColumns.length; 24683 24684 24685 this._rearrangeTableRuntimeControls(lastVisibleColumn - 1, event); 24686 24687 if (hiddenColumns && hiddenColumns.length > 0) { 24688 24689 this.$element.addClass('collapsed'); 24690 24691 this.bColumnHidden = true; } else { 24692 24693 this.$element.removeClass('collapsed'); 24694 24695 this.bColumnHidden = false;
24696 } 24697 }, 24698 24699 24700 _controlRowInitialization : function () { 24701 var that = this; 24702 var details = this.controlRow.controlRowDetails; 24703 24704 24705 if (details.type === 'inline') { 24706 24707 details.target = ("." + (this.options.tableRuntimeEditControlClass || "tableRuntimeEditControl")); 24708 } 24709 24710 24711 24712 24713 var target = details.target; 24714 var selector = typeof target === 'string' ? target : 'td'; 24715 24716 24717 this.$element.on('click keypress', selector, function (e) { 24718 24719 24720 if ((e.type == "keypress" && e.keyCode == 13) || e.type == "click") { 24721 24722 if (!that.$element.hasClass('collapsed')) { 24723 return; 24724 } 24725 24726 var $row = $(this).closest('tr'), 24727 rowData = $row.data("tableRow"), 24728 row = rowData; 24729 24730 24731 24732 if (row == null || row.child.$element.parent().length === 0) { 24733 row = new TableRow($row); 24734 $row.data("tableRow", row); 24735 } 24736 if (row.child.isShown) { 24737 row.hideChild(); 24738 row.$tableRowElement.removeClass('parent'); 24739 } else { 24740 var info = that.controlRow.controlRowDetails.renderer(that, row); 24741 row.updateChild(info, that.colLength); 24742 row.showChild(); 24743 row.$tableRowElement.addClass('parent'); 24744 24745 row.child.$element.find("input, select, textarea, button").eq(0).focus(); 24746 } 24747 } 24748 }); 24749 }, 24750 24751 24752 _resize : function () { 24753 var width = $(window).width(); 24754 var breakpoints = this.controlRow.breakpoints; 24755 var breakpoint = breakpoints[0].name; 24756 24757 24758 for (var i = breakpoints.length - 1 ; i >= 0 ; i--) { 24759 if (width <= breakpoints[i].width) { 24760 breakpoint = breakpoints[i].name; 24761 break; 24762 } 24763 } 24764 24765 24766 var display = this._getColumnsVisibility(breakpoint); 24767 24768 _.each(this.columns, function (item, index) { 24769 item.visible(display[index]); 24770 }); 24771 24772 return display; 24773 }, 24774 24775 24776 _getColumnsVisibility : function (breakpoint) { 24777 var columns = this.columns, 24778 i, 24779 len = this.$element.find("th"), 24780 display = []; 24781 24782 24783 var widthAvailable = this.$element.parent().outerWidth(); 24784 var usedWidth = widthAvailable; 24785 24786 24787 24788 display = _.map(columns, function (item) { 24789 usedWidth -= item.minWidth; 24790 return ((usedWidth < 0) ? false : true); 24791 }); 24792 24793 24794 display[0] = true; 24795 return display; 24796 } 24797 24798 }; 24799 24800 $.fn.responsiveTablePlugin = function (option, value) { 24801 var get = '', 24802 element = this.each(function () { 24803 24804 if ($(this).is('table') === true) { 24805 var $this = $(this), 24806 data = $this.data('responsiveTablePlugin'), 24807 options = $.extend({}, ResponsiveTablePlugin.prototype.defaults, typeof option === 'object' && option); 24808 24809 24810 if (!data) { 24811 $this.data('responsiveTablePlugin', (data = new ResponsiveTablePlugin(this, options))); 24812 data._constructor(); 24813 } 24814 24815 24816 if (typeof option === 'string') { 24817 get = data[option](value); 24818 } 24819 } 24820 }); 24821 24822 if (get != "") { 24823 return get; 24824 } else { 24825 return element; 24826 } 24827 }; 24828 24829 ResponsiveTablePlugin.prototype.defaults = { 24830 24831 EVENT_COLUMN_VISIBILITY : "responsiveTablePlugin.columnVisibility", 24832 GUIDE_ID_SELECTOR : "div[data-guide-view-bind]", 24833 CONTROL_ROW_CLASS : "child", 24834 CONTROL_ROW_SELECTOR : "tr.child" 24835 }; 24836 24837})(_, $); 24838(function ($, _, guidelib) { 24839 24840 24841 var getPanelsWithNumericFields = function (panels, fieldName) { 24842 if (_.isUndefined(panels) || panels === null) { 24843 return []; 24844 } 24845 if (!_.isArray(panels)) { 24846 panels = [panels]; 24847 } 24848 return _.filter(panels, function (panel) { 24849 return panel instanceof guidelib.model.GuidePanel 24850 && panel[fieldName] instanceof guidelib.model.GuideNumericBox; 24851 }); 24852 }, 24853 24854 sum = function (numPanels, fieldName) { 24855 return _.reduce(numPanels, 24856 function (memo, currentItem) { 24857 var curValue = parseFloat(currentItem.getOrElse(currentItem, fieldName + ".value", 0)); 24858 if (isNaN(curValue)) { 24859 curValue = 0; 24860 } 24861 return memo + curValue; 24862 }, 0); 24863 }; 24864 24865 24866 guidelib.__runtime__.af.sum = function (panels, fieldName) { 24867 return sum(getPanelsWithNumericFields(panels, fieldName), fieldName); 24868 }; 24869 24870 24871 guidelib.__runtime__.af.avg = function (panels, fieldName) { 24872 var n_panels = getPanelsWithNumericFields(panels, fieldName), 24873 total = sum(n_panels, fieldName); 24874 if (n_panels.length === 0) { 24875 return 0; 24876 } 24877 return total / n_panels.length; 24878 }; 24879 24880 24881 guidelib.__runtime__.af.max = function (panels, fieldName) { 24882 var panel = _.max(getPanelsWithNumericFields(panels, fieldName), function (panel) { 24883 return panel.getOrElse(panel, fieldName + ".value", Number.NEGATIVE_INFINITY); 24884 }); 24885 if (panel instanceof guidelib.model.GuidePanel) { 24886 return panel[fieldName]; 24887 } 24888 return null; 24889 }; 24890 24891 24892 guidelib.__runtime__.af.min = function (panels, fieldName) { 24893 var panel = _.min(getPanelsWithNumericFields(panels, fieldName), function (panel) { 24894 return panel.getOrElse(panel, fieldName + ".value", Number.POSITIVE_INFINITY); 24895 }); 24896 if (panel instanceof guidelib.model.GuidePanel) { 24897 return panel[fieldName]; 24898 } 24899 return null; 24900 }; 24901 24902}($, _, guidelib)); 24903(function ($, _, guidelib) { 24904 24905 24906 24907 guidelib.__runtime__.af.reduce = function (panels, fieldName, iterator, memo, context) { 24908 if (!_.isArray(panels)) { 24909 panels = [panels]; 24910 } 24911 return _.reduce(panels, function (memo, panel) { 24912 if (panel instanceof guidelib.model.GuidePanel && !_.isUndefined(panel[fieldName])) { 24913 if (_.isFunction(iterator)) { 24914 return iterator.apply(context, [memo, panel, panel[fieldName]]); 24915 } 24916 } 24917 return memo; 24918 }, memo); 24919 }; 24920 24921 24922 24923 guidelib.__runtime__.af.filter = function (panels, fieldName, predicate, context) { 24924 if (!_.isArray(panels)) { 24925 panels = [panels]; 24926 } 24927 return _.map( 24928 _.filter(panels, function (panel) { 24929 if (panel instanceof guidelib.model.GuidePanel && !_.isUndefined(panel[fieldName])) { 24930 if (_.isFunction(predicate)) { 24931 return predicate.apply(context, [panel, panel[fieldName]]); 24932 } 24933 return false;
24934 } 24935 }), 24936 function (panel) { 24937 return panel[fieldName]; 24938 } 24939 ); 24940 }; 24941 24942 guidelib.__runtime__.af.formatDateToISOString = function (dateObject) { 24943 var day, month, year; 24944 if (!_.isUndefined(dateObject) && _.isObject(dateObject)) { 24945 day = dateObject.getDate().toString(); 24946 24947 month = (dateObject.getMonth() + 1).toString(); 24948 year = dateObject.getFullYear().toString(); 24949 if (month.length === 1) { 24950 month = "0" + month.toString(); 24951 } 24952 24953 return year + "-" + month + "-" + day; 24954 24955 } 24956 }; 24957}($, _, guidelib)); 24958(function (_, guidelib) { 24959 24960 var GuideNavigationContext = guidelib.model.util.GuideNavigationContext = xfalib.ut.Class.extend({ 24961 msClassName : "guideNavigationContext", 24962 initialize : function () { 24963 GuideNavigationContext._super.initialize.call(this); 24964 this._currentItem = this.options.currentItem; 24965 this._parentPanel = this.options.parentPanel; 24966 this.guideUtil = guidelib.util.GuideUtil; 24967 }, 24968 24969 getQualifiedNamedItem : function (qName) { 24970 var navItems = this._getNavigableItems(); 24971 var qItem = _.find(navItems, function (item) { 24972 return (item._escapeQualifiedName() == qName); 24973 }, this); 24974 return qItem; 24975 }, 24976 24977 getItemForNav : function (navToken) { 24978 if (navToken == "prevItem" || navToken == "nextItem" || navToken == "firstItem" || navToken == "lastItem") { 24979 return this[navToken]; 24980 } else { 24981 return this.getQualifiedNamedItem(navToken); 24982 } 24983 }, 24984 24985 24986 _isNavigableItem : function (item) { 24987 return item.visible; 24988 }, 24989 24990 24991 _isNavigablePanel : function (item) { 24992 if (item && item instanceof guidelib.model.GuidePanel) { 24993 return item.visible && item.isNavigable; 24994 } 24995 }, 24996 24997 _getNavigableItems : function () { 24998 var navItems = _.filter(this._parentPanel.items, function (item) { 24999 return this._isNavigableItem(item); 25000 }, this); 25001 return navItems; 25002 }, 25003 25004 _getNavigableDescendant : function (navigableAncestor) { 25005 25006 25007 if (navigableAncestor && navigableAncestor != this._parentPanel) { 25008 var currentItem = navigableAncestor.parent._navigationContext.currentItem, 25009 deepItem = null; 25010 while (currentItem instanceof guidelib.model.GuidePanel) { 25011 deepItem = currentItem; 25012 currentItem = currentItem._navigationContext.currentItem; 25013 } 25014 return deepItem; 25015 } 25016 return null; 25017 }, 25018 25019 25020 _getSomOnNavigableAncestor : function (somExpression) { 25021 if (_.isEmpty(somExpression)) { 25022 return null; 25023 } 25024 25025 var index = somExpression.lastIndexOf("."), 25026 parentModel, 25027 parentSom, 25028 isNavigable, 25029 guideModel = this._parentPanel._guide(); 25030 25031 if (index !== -1) { 25032 parentSom = somExpression.substring(0, index); 25033 parentModel = guideModel.resolveNode(parentSom); 25034 if (parentModel) { 25035 isNavigable = this._isNavigablePanel(parentModel); 25036 } 25037 if (isNavigable) { 25038 return somExpression; 25039 } 25040 return this._getSomOnNavigableAncestor(parentSom); 25041 } 25042 25043 return guideModel.rootPanel.somExpression; 25044 }, 25045 25046 25047 _getNavigableAncestor : function (navOrder) { 25048 25049 25050 25051 var guideModel = this._parentPanel._guide(), 25052 navigableAncestorSom = this._getSomOnNavigableAncestor(guideModel._currentNavigablePanelSom), 25053 navigableAncestorItem = guideModel.resolveNode(navigableAncestorSom); 25054 25055 while (navigableAncestorItem 25056 && navigableAncestorItem != this._parentPanel && !navigableAncestorItem.parent._navigationContext[navOrder] 25057 && this.guideUtil.isChildPartOfContainer(this._parentPanel, navigableAncestorItem)) { 25058 25059 var navigableParentItemSom = this._getSomOnNavigableAncestor(navigableAncestorItem.parent.somExpression); 25060 navigableAncestorItem = guideModel.resolveNode(navigableParentItemSom); 25061 } 25062 return navigableAncestorItem; 25063 }, 25064 25065 _getNakedThis : function () { 25066 return this; 25067 } 25068 }); 25069 25070 GuideNavigationContext.defineProps({ 25071 25072 currentItem : { 25073 get : function () { 25074 if (this._currentItem) { 25075 return this._currentItem; 25076 } else { 25077 return this.firstItem; 25078 } 25079 }, 25080 set : function (value) { 25081 this._currentItem = value; 25082 } 25083 }, 25084 25085 prevItem : { 25086 get : function () { 25087 var navItems = this._getNavigableItems(); 25088 var item = this.currentItem; 25089 if (navItems.indexOf(item) > 0) { 25090 return navItems[navItems.indexOf(item) - 1]; 25091 } else { 25092 return null; 25093 } 25094 } 25095 }, 25096 25097 nextItem : { 25098 get : function () { 25099 var navItems = this._getNavigableItems(); 25100 var item = this.currentItem; 25101 if (navItems.indexOf(item) < (navItems.length - 1)) { 25102 return navItems[navItems.indexOf(item) + 1]; 25103 } else { 25104 return null; 25105 } 25106 } 25107 }, 25108 25109 nextNavigablePanel : { 25110 get : function () { 25111 var navigableAncestor = this._getNavigableAncestor("nextItem"), 25112 25113 navigableDescendant = this._getNavigableDescendant(navigableAncestor); 25114 return navigableDescendant; 25115 } 25116 }, 25117 25118 25119 prevNavigablePanel : { 25120 get : function () { 25121 var navigableAncestor = this._getNavigableAncestor("prevItem"), 25122 25123 navigableDescendant = this._getNavigableDescendant(navigableAncestor); 25124 return navigableDescendant; 25125 } 25126 }, 25127 25128 25129 firstItem : { 25130 get : function () { 25131 var navItems = this._getNavigableItems(); 25132 return navItems[0] || null; 25133 } 25134 }, 25135 25136 lastItem : { 25137 get : function () { 25138 var navItems = this._getNavigableItems(); 25139 if (navItems.length) { 25140 return navItems[navItems.length - 1]; 25141 } else { 25142 return null; 25143 } 25144 } 25145 }, 25146 25147 hasNextItem : { 25148 get : function () { 25149 return this.nextItem != null; 25150 } 25151 }, 25152 25153 hasPrevItem : { 25154 get : function () { 25155 return this.prevItem != null; 25156 } 25157 }, 25158 25159 25160 hasNextNavigablePanel : { 25161 get : function () { 25162 return this.nextNavigablePanel != null; 25163 } 25164 }, 25165 25166 25167 hasPrevNavigablePanel : { 25168 get : function () { 25169 return this.prevNavigablePanel != null; 25170 } 25171 }, 25172 25173 25174 isFirstItem : { 25175 get : function () { 25176 return this.currentItem == this.firstItem; 25177 } 25178 }, 25179 25180 isLastItem : { 25181 get : function () { 25182 return this.currentItem == this.lastItem; 25183 } 25184 } 25185 }); 25186 25187})(_, guidelib); 25188(function (_, guidelib) { 25189 25190 25191 var GuideModelEvent = guidelib.event.GuideModelEvent = xfalib.ut.Class.extend({ 25192 msClassName : "guideModelEvent" 25193 }); 25194 25195 GuideModelEvent.defineProps({ 25196 25197 "prevText" : { 25198 get : function () { 25199 return this.jsonModel.prevText; 25200 } 25201 }, 25202 25203 "newText" : { 25204 get : function () { 25205 return this.jsonModel.newText; 25206 } 25207 }, 25208 25209 "name" : { 25210 get : function () { 25211 return this.jsonModel.name; 25212 } 25213 }, 25214 "keyDown" : { 25215 get : function () { 25216 return this.jsonModel.keyDown; 25217 } 25218 }, 25219 "modifier" : { 25220 get : function () { 25221 return this.jsonModel.modifier; 25222 } 25223 }, 25224 25225 "target" : { 25226 get : function () { 25227 return this.jsonModel.target; 25228 } 25229 }, 25230 "shift" : { 25231 get : function () { 25232 return this.jsonModel.shift; 25233 } 25234 }, 25235 "change" : { 25236 get : function () { 25237 return this.jsonModel.change; 25238 }, 25239 set : function (value) { 25240 this.jsonModel.change = value; 25241 } 25242 }, 25243 25244 "_property" : { 25245 get : function () { 25246 return this.jsonModel._property; 25247 } 25248 } 25249 }); 25250 25251 GuideModelEvent.createEvent = function (nm, tgt, prop, oldVal, newVal) { 25252 var evnt = { 25253 name : nm, 25254 target : tgt, 25255 _property : prop, 25256 prevText : oldVal, 25257 newText : newVal 25258 }; 25259 return new GuideModelEvent({"jsonModel" : evnt}); 25260 }; 25261 25262 GuideModelEvent.MODEL_REFRESH = "guide.modelRefresh"; 25263 GuideModelEvent.CHILD_CHANGED = "guide.childChanged"; 25264 GuideModelEvent.MULTIPLE_CHILD_ADDED = "guide.multipleChildAdded"; 25265 GuideModelEvent.MODEL_CHANGED = "guide.modelChanged"; 25266 GuideModelEvent.VALUE_CHANGED = "guide.valueChanged"; 25267 GuideModelEvent.ERROR_CHANGED = "guide.errorChanged"; 25268 GuideModelEvent.ERROR_RESET = "guide.errorReset"; 25269 GuideModelEvent.VISIBLE_CHANGED = "guide.visibleChanged"; 25270 GuideModelEvent.ENABLED_CHANGED = "guide.enabledChanged"; 25271 GuideModelEvent.ITEMS_CHANGED = "guide.itemsChanged"; 25272 GuideModelEvent.OBJECT_DESTROYED = "guide.objectDestroyed"; 25273 GuideModelEvent.NAVIGATE_SECTION = "guide.navigateSection";
25274 GuideModelEvent.LAZY_LOADED = "guide.lazyLoaded"; 25275}(_, guidelib)); 25276(function ($, _, guidelib) { 25277 var GuideViewRegistry = guidelib.view.GuideViewRegistry = xfalib.ut.Class.extend({ 25278 25279 25280 _findWidget : function (config, name, className) { 25281 var result = _.find(config, function (widgetName, identifier) { 25282 return name === identifier; 25283 }); 25284 if (result === undefined) { 25285 result = _.find(config, function (widgetName, identifier) { 25286 return className === identifier; 25287 }); 25288 } 25289 return result; 25290 }, 25291 25292 25293 _findWidgetNameFromCSS : function (cssClasses) { 25294 var result = null; 25295 if (_.isString(cssClasses)) { 25296 _.find(cssClasses.split(" "), 25297 function (cssClass, index) { 25298 var match = cssClass.match(/^widget_([\w\W]+)$/); 25299 if (match && match.length === 2) { 25300 result = match[1]; 25301 return true; 25302 } 25303 return false; 25304 }); 25305 } 25306 return result; 25307 }, 25308 25309 createView : function (element, parentView) { 25310 var $element = $(element); 25311 var options = { 25312 'element' : $element.get(0), 25313 'widgetName' : $element.data("guideViewWidget"), 25314 'parentView' : parentView 25315 }; 25316 var guideViewBind = $element.data("guideViewBind"); 25317 var model = window.guideBridge._resolveId(guideViewBind); 25318 25319 25320 if (model) { 25321 options.model = model; 25322 var clsName = model.className; 25323 var nodeClass = clsName.charAt(0).toUpperCase() + clsName.substr(1) + "View"; 25324 var viewClass = guidelib.view[nodeClass], 25325 widgetConfig = window.guideBridge.userConfig.widgetConfig; 25326 if (model instanceof guidelib.model.Field || model instanceof guidelib.model.GuideCompositeField) { 25327 options.widgetName = this._findWidgetNameFromCSS(model.cssClassName) 25328 || this._findWidget(widgetConfig, model.name, model.className); 25329 } 25330 if (!viewClass && model instanceof guidelib.model.GuideContainerNode) { 25331 viewClass = guidelib.view.GuideContainerView; 25332 } 25333 if (!viewClass && model instanceof guidelib.model.Field) { 25334 viewClass = guidelib.view.GuideFieldView; 25335 } 25336 if (!viewClass && model instanceof guidelib.model.GuidePanel) { 25337 viewClass = guidelib.view.GuidePanelView; 25338 } 25339 if (!viewClass && model instanceof guidelib.model.GuideItemsContainer) { 25340 viewClass = guidelib.view.GuideItemsView; 25341 } 25342 if (!viewClass) { 25343 viewClass = guidelib.view.GuideBaseView; 25344 } 25345 25346 var bindView = new viewClass(options); 25347 return bindView; 25348 } 25349 } 25350 }); 25351 25352})($, _, guidelib); 25353(function (_, guidelib, xfalib) { 25354 var DataNode = guidelib.model.DataNode = xfalib.ut.Class.extend({ 25355 initialize : function () { 25356 this.linkedFields = []; 25357 this.isUpdateInProgress = false; 25358 }, 25359 25360 addField : function (model) { 25361 if (!_.isEmpty(model) && !_.contains(this.linkedFields, model)) { 25362 this.linkedFields.push(model); 25363 model.on(guidelib.event.GuideModelEvent.VALUE_CHANGED, this); 25364 } 25365 }, 25366 25367 removeField : function (model) { 25368 if (!_.isEmpty(model)) { 25369 model.off(guidelib.event.GuideModelEvent.VALUE_CHANGED, this); 25370 this.linkedFields = _.without(this.linkedFields, model); 25371 } 25372 }, 25373 25374 getFieldModels : function () { 25375 return _.filter(this.linkedFields, function (field) { 25376 return (field instanceof guidelib.model.Field); 25377 }); 25378 }, 25379 25380 getAbstractFieldModels : function () { 25381 return _.filter(this.linkedFields, function (field) { 25382 return (field instanceof guidelib.model.AbstractField); 25383 }); 25384 }, 25385 25386 handleEvent : function (event) { 25387 switch (event.name) { 25388 case guidelib.event.GuideModelEvent.VALUE_CHANGED: 25389 if (!_.contains(['guideButton', 'guideTextDraw', 'guideAdobeSignBlock'], event.target.className)) { 25390 this.updateLinkedFieldsValue(event); 25391 } 25392 break; 25393 default: 25394 event.target.logger().warn("AF", "Unexpected Event type on Data Node", event); 25395 } 25396 }, 25397 25398 updateLinkedFieldsValue : function (event) { 25399 if (this.isUpdateInProgress) { 25400 return; 25401 } 25402 25403 this.isUpdateInProgress = true; 25404 var newValue = event.target._getValue(); 25405 25406 try { 25407 _.each(this.linkedFields, function (field) { 25408 if (field !== event.target) { 25409 field.value = newValue; 25410 } 25411 }, this); 25412 } catch (ex) { 25413 event.target.logger().error("AF", "Unable to set Linked Field value" + ex); 25414 } finally { 25415 this.isUpdateInProgress = false;
25416 } 25417 } 25418 }); 25419 25420}(_, guidelib, xfalib)); 25421 25422 25423(function (guidelib, $) { 25424 25425 var VERSION_AEM_61 = "AEM6.1", 25426 VERSION_AEM_62 = "AEM6.2", 25427 VERSION_AEM_63 = "AEM6.3", 25428 VERSION_AEM_65 = "AEM6.5", 25429 flagsStatus = {}, 25430 getMinorMajor = function (version) { 25431 var match = version.match(/AEM(\d+)(?:\.(\d+))?/); 25432 if (match == null) { 25433 return null; 25434 } 25435 return { 25436 major : match[1], 25437 minor : match[2] === undefined ? "0" : match[2] 25438 }; 25439 }, 25440 compareNumbers = function (num1, num2) { 25441 return (num1 - num2); 25442 }, 25443 compareVersions = function (version1, version2) { 25444 if (typeof version1 !== "string" || typeof version2 !== "string") { 25445 throw "Comparing Invalid Versions"; 25446 } 25447 var v1 = getMinorMajor(version1), 25448 v2 = getMinorMajor(version2); 25449 if (v1 == null || v2 == null) { 25450 throw "Comparing Invalid Versions"; 25451 } 25452 var c = compareNumbers(+v1.major, +v2.major); 25453 return c !== 0 ? c : compareNumbers(+v1.minor, +v2.minor); 25454 }, 25455 Version = guidelib.util.Version = xfalib.ut.Class.extend({ 25456 initialize : function (options) { 25457 flagsStatus = {}; 25458 var compat = options.scriptingBehaviourVersion; 25459 if (compat === "None") { 25460 compat = this.current(); 25461 } 25462 this.scriptingBehaviourVersion = compat || VERSION_AEM_65; 25463 var majorMinor = getMinorMajor(this.scriptingBehaviourVersion); 25464 if (majorMinor == null) { 25465 throw "Invalid Version number"; 25466 } 25467 this.major = majorMinor.major; 25468 this.minor = majorMinor.minor; 25469 }, 25470 25471 current : function () { 25472 return VERSION_AEM_65; 25473 }, 25474 25475 compatibleVersion : function () { 25476 return this.scriptingBehaviourVersion; 25477 }, 25478 25479 isPrevious : function (version) { 25480 return compareVersions(this.scriptingBehaviourVersion, version) < 0; 25481 }, 25482 25483 isPreviousOrSame : function (version) { 25484 var c = compareVersions(this.scriptingBehaviourVersion, version); 25485 return c < 0 || c == 0; 25486 }, 25487 25488 isAfter : function (version) { 25489 return compareVersions(this.scriptingBehaviourVersion, version) > 0; 25490 }, 25491 25492 isAfterOrSame : function (version) { 25493 var c = compareVersions(this.scriptingBehaviourVersion, version); 25494 return c > 0 || c == 0; 25495 }, 25496 25497 isSame : function (version) { 25498 return compareVersions(this.scriptingBehaviourVersion, version) == 0; 25499 }, 25500 25501 isOn : function (flag) { 25502 switch (flag) { 25503 case this.Flags.RUN_VALUE_COMMMIT_ON_SCRIPT_CHANGE: 25504 if (flagsStatus[flag] == undefined) { 25505 flagsStatus[flag] = this.isAfter(this.AEM_61); 25506 } 25507 return flagsStatus[flag]; 25508 case this.Flags.RUN_VALUE_COMMMIT_ON_PREFILL: 25509 if (flagsStatus[flag] == undefined) { 25510 flagsStatus[flag] = this.isAfter(this.AEM_63); 25511 } 25512 return flagsStatus[flag]; 25513 } 25514 throw "Invalid Flag"; 25515 } 25516 }); 25517 25518 Version.prototype.Flags = {}; 25519 Object.defineProperties(Version.prototype.Flags, { 25520 RUN_VALUE_COMMMIT_ON_SCRIPT_CHANGE : { 25521 value : "manageValueCommit", 25522 writable : false 25523 }, 25524 RUN_VALUE_COMMMIT_ON_PREFILL : { 25525 value : "manageValueCommitOnPrefill", 25526 writable : false 25527 } 25528 }); 25529 Version.defineProps({ 25530 AEM_61 : { 25531 value : VERSION_AEM_61, 25532 writable : false 25533 }, 25534 25535 AEM_62 : { 25536 value : VERSION_AEM_62, 25537 writable : false 25538 }, 25539 25540 AEM_63 : { 25541 value : VERSION_AEM_63, 25542 writable : false 25543 }, 25544 25545 AEM_65 : { 25546 value : VERSION_AEM_65, 25547 writable : false 25548 } 25549 }); 25550}(guidelib, $)); 25551(function ($, guidelib, _) { 25552 var GuideBaseView = guidelib.view.GuideBaseView = xfalib.ut.Class.extend({ 25553 guideUtil : guidelib.util.GuideUtil, 25554 _triggerOnBridge : function (eventName, target, property, oldVal, newVal) { 25555 var evnt = guidelib.event.GuideModelEvent.createEvent(eventName, target, 25556 property, oldVal, newVal); 25557 window.guideBridge.trigger(eventName, evnt); 25558 }, 25559 25560 initialize : function () { 25561 GuideBaseView._super.initialize.call(this); 25562 this.$element = $(this.options.element); 25563 this.id = this.$element.attr("id"); 25564 this._model = this.options.model; 25565 this.parentView = this.options.parentView; 25566 this.$element.data("guideView", this); 25567 this._$item = null; 25568 this._$itemNav = null; 25569 if (this._model && this._model != null) { 25570 this._model.on(guidelib.event.GuideModelEvent.MODEL_CHANGED, this.handleModelChanged, this); 25571 } 25572 this._syncPending = true; 25573 this._visibleHelpElement = "none"; 25574 this._polyfills(); 25575 }, 25576
25577 _polyfills: function () { 25578 var IEpolyfillForObjectDotEntries = function() { 25579 if(!Object.entries) { 25580 Object.entries = function (obj) { 25581 var ownProps = Object.keys(obj), 25582 i = ownProps.length, 25583 resArray = new Array(i); 25584 while (i--) 25585 resArray[i] = [ownProps[i], obj[ownProps[i]]]; 25586 25587 return resArray; 25588 }; 25589 } 25590 }; 25591 25592 var polyfills = [IEpolyfillForObjectDotEntries]; 25593 25594 for (var i = 0; i < polyfills.length; ++i) { 25595 polyfills[i](); 25596 } 25597 }, 25598 25599 postInitialize : function () { 25600 }, 25601 25602 _unloadView : function () { 25603 25604 this._model.off(guidelib.event.GuideModelEvent.MODEL_CHANGED, this.handleModelChanged, this); 25605 25606 this.$element = null; 25607 this.$widget = null; 25608 this._model = null; 25609 this._$item = null; 25610 this._$itemNav = null; 25611 this.parentView = null; 25612 }, 25613 25614 handleVisibleChanged : function (event) { 25615 25616 25617 if (!event.newText) { 25618 this.$item.addClass("hidden"); 25619 this.$itemNav.addClass("hidden"); 25620 if (this.parentView.currentActiveItemView == this) { 25621 this.parentView.setActive("nextItem"); 25622 } 25623 } else { 25624 25625 this.$item.removeClass("hidden"); 25626 this.$itemNav.removeClass("hidden"); 25627 } 25628 }, 25629 25630 handleModelChanged : function (event) { 25631 switch (event._property) { 25632 case "viewVisited": 25633 if (event.newText) { 25634 this.$item.addClass("stepped"); 25635 this.$itemNav.addClass("stepped"); 25636 }else { 25637 this.$item.removeClass("stepped"); 25638 this.$itemNav.removeClass("stepped"); 25639 } 25640 break; 25641 25642 case "visible": 25643 this.handleVisibleChanged(event); 25644 break; 25645 } 25646 }, 25647 25648 setActive : function (activeItemToken, focus, muteScripts) { 25649 if (focus && (this._model.className === "guideNode" || this._model.forceElementFocusChange)) { 25650 if (this.$element !== null && typeof this.$element.focus === "function" && !this._guideView.skipFieldFocus) { 25651 25652 this.$element.focus(); 25653 25654 this._guideView.currentFocusItemSom = this._model.somExpression; 25655 } 25656 25657 } 25658 return true; 25659 }, 25660 25661 focusable : function () { 25662 return this._model.visible; 25663 }, 25664 25665 _find : function (selector) { 25666 return this._guideView.$element.find(selector); 25667 }, 25668 25669 _syncGuideNodeToHtml : function (deepSync) { 25670 this._syncPending = false; 25671 25672 25673 this.handleVisibleChanged(guidelib.event.GuideModelEvent.createEvent( 25674 guidelib.event.GuideModelEvent.MODEL_CHANGED, 25675 this, 25676 "visible", 25677 this._model.visible, 25678 this._model.visible 25679 )); 25680 }, 25681 25682 _updateIds : function ($el, oldId, newId) { 25683 if (oldId == newId) { 25684 return; 25685 } 25686 25687 var idSelector = "#" + oldId, 25688 modelBindSelector = this.guideUtil.modelElSelector(oldId), 25689 attrSelector = '[id^="' + oldId + '"]', 25690 longDescriptionSelector = '[data-guide-longDescription^="' + oldId + '"]', 25691 labelSelector = 'label[for^="' + oldId + '"]', 25692 targetIdSelector = "[data-guide-id^='" + oldId + "']", 25693 $elById = $el.find(idSelector).addBack(idSelector), 25694 selectorAttrObject = { 25695 "id" : attrSelector , 25696 "for" : labelSelector, 25697 "data-guide-longDescription" : longDescriptionSelector, 25698 "data-guide-id" : targetIdSelector 25699 }; 25700 25701 25702 25703 if ($elById.attr(guidelib.util.GuideUtil.DATA_GUIDE_ITEM_CONTAINER) !== undefined) { 25704 $elById.attr(guidelib.util.GuideUtil.DATA_GUIDE_ITEM_CONTAINER, newId + guidelib.util.GuideUtil.GUIDE_ITEM_CONTAINER_SUFFIX); 25705 } 25706 25707 if ($elById.attr(guidelib.util.GuideUtil.DATA_GUIDE_ITEM) !== undefined) { 25708 $elById.attr(guidelib.util.GuideUtil.DATA_GUIDE_ITEM, newId + guidelib.util.GuideUtil.GUIDE_ITEM_SUFFIX); 25709 } 25710 $elById.attr("id", newId); 25711 $el.find(modelBindSelector).addBack(modelBindSelector).attr(this.guideUtil.GUIDE_VIEW_BIND_ATTR, newId); 25712 25713 _.each(_.keys(selectorAttrObject), function (item, index) { 25714 var selector = selectorAttrObject[item]; 25715 $el.find(selector).addBack(selector).each(function () { 25716 25717 var $this = $(this), 25718 prevId = $this.attr(item), 25719 nextId = newId + prevId.substring(oldId.length); 25720 $this.attr(item, nextId); 25721 }); 25722 }, this); 25723 }, 25724 25725 getSiblingItemView : function (siblingType) { 25726 if (this.parentView instanceof guidelib.view.GuidePanel
25726View) { 25727 var siblingItem = this.parentView._model.navigationContext.getItemForNav(siblingType); 25728 if (siblingItem) { 25729 return this.parentView.getQualifiedNamedView(siblingItem._escapeQualifiedName()); 25730 } 25731 } 25732 return null; 25733 } 25734 }); 25735 25736 GuideBaseView.defineProps({ 25737 _guideView : { 25738 get : function () { 25739 return window.guideBridge._guideView; 25740 } 25741 }, 25742 25743 _guide : { 25744 get : function () { 25745 return window.guideBridge._guide; 25746 } 25747 }, 25748 25749 $item : { 25750 get : function () { 25751 if (!this._$item || this._$item.length == 0) { 25752 var itemSelector = this.guideUtil.itemSelector(this._model.id, this._model); 25753 this._$item = this._find(itemSelector); 25754 25755 25756 if (this._$item && this._$item.length == 0) { 25757 return this.$element; 25758 } 25759 } 25760 return this._$item; 25761 } 25762 }, 25763 25764 $itemNav : { 25765 get : function () { 25766 if (!this._$itemNav) { 25767 var itemNavSelector = this.guideUtil.itemNavSelector(this._model.id); 25768 this._$itemNav = this._find(itemNavSelector); 25769 } 25770 return this._$itemNav; 25771 } 25772 }, 25773 visibleHelpElement : { 25774 get : function () { 25775 return this._visibleHelpElement; 25776 }, 25777 set : function (helpType) { 25778 this._visibleHelpElement = helpType; 25779 } 25780 }, 25781 25782 25783 isItem : { 25784 get : function () { 25785 return this._model._isItem; 25786 } 25787 }, 25788 25789 qualifiedName : { 25790 get : function () { 25791 return this._model._escapeQualifiedName(); 25792 } 25793 } 25794 25795 }); 25796}($, guidelib, _)); 25797(function ($, guidelib, _) { 25798 25799 var xfaUtil = xfalib.ut.XfaUtil.prototype, 25800 GuideFieldView = guidelib.view.GuideFieldView = guidelib.view.GuideBaseView.extend({ 25801 _defaultWidgetName : "defaultWidget", 25802 25803 25804 autofillFieldKeywordToName : { 25805 "name" : "name", 25806 "given-name" : "fname", 25807 "additional-name" : "mname", 25808 "family-name" : "lname", 25809 "email" : "email", 25810 "street-address" : "address", 25811 "address-line1" : "address", 25812 "address-line2" : "address", 25813 "address-level1" : "state", 25814 "address-level2" : "city", 25815 "postal-code" : "zip", 25816 "country" : "country", 25817 "tel" : "phone", 25818 "cc-name" : "ccname", 25819 "cc-number" : "cardnumber", 25820 "cc-csc" : "cvc", 25821 "cc-exp-month" : "ccmonth", 25822 "cc-exp-year" : "ccyear", 25823 "cc-exp" : "exp-date", 25824 "cc-type" : "card-type" 25825 }, 25826 25827 initialize : function () { 25828 GuideFieldView._super.initialize.call(this); 25829 this._initializeWidget(); 25830 this._defineModelEvents(); 25831 this._markMandatory(); 25832 this._updateEmptyStatus(); 25833 this.oldValue = null; 25834 25835 if (this._guide.jsonModel.textReplacementMap) { 25836 var footnoteArr = Object.entries(this._guide.jsonModel.textReplacementMap); 25837 var tempArray = []; 25838 for (var i = 0; i < footnoteArr.length; i++) { 25839 25840 25841 25842 if(!tempArray[footnoteArr[i][1]]){ 25843 tempArray[footnoteArr[i][1]] = footnoteArr[i][0]; 25844 } 25845 var selector = $("span[data-af-footnote-id=" + "\"" + footnoteArr[i][0] + "\"]"); 25846 for (var j = 0; j < $(selector).length; j++) { 25847 var supTag = document.createElement("sup"); 25848 var anchorTag = document.createElement("a"); 25849 anchorTag.setAttribute("href", "#" + tempArray[footnoteArr[i][1]] + "_ftn"); 25850 anchorTag.setAttribute("data-footnote-id", tempArray[footnoteArr[i][1]]); 25851 anchorTag.setAttribute("title", $('#' + tempArray[footnoteArr[i][1]]).text()); 25852 anchorTag.innerHTML = footnoteArr[i][1]; 25853 supTag.appendChild(anchorTag); 25854 $($(selector)[j]).html(supTag.outerHTML); 25855 } 25856 } 25857 } 25858 }, 25859 25860 postInitialize : function () { 25861 this._syncGuideNodeToHtml(true); 25862 }, 25863 25864 createWidgetOptions : function () { 25865 return { 25866 name : this._model.getAttribute("autocomplete") ? this.autofillFieldKeywordToName[this._model.getAttribute("autofillFieldKeyword")] : this._model.id + "_jqName", 25867 value : this._model.value, 25868 displayValue : this._model.formattedValue, 25869 commitEvent : this.getCommitEvent(), 25870 access : this._model.enabled ? "open" : "readOnly", 25871 screenReaderText : this._model._getScreenReaderText(), 25872 mandatory : this._model.mandatory 25873 }; 25874 }, 25875 25876 getCommitEvent : function () { 25877 return xfalib.ut.XfaUtil.prototype.XFA_EXIT_EVENT; 25878 }, 25879
25880 getWidgetName : function () { 25881 var widgetName; 25882 if (this.$widget) { 25883 var $elem = this.$widget.find('[data-af-widgetname]').addBack('[data-af-widgetname]'); 25884 25885 if ($elem && $elem.length > 0) { 25886 widgetName = $elem.attr("data-af-widgetname"); 25887 } 25888 } 25889 if (!widgetName) { 25890 this.logger().warn("AF", "widget name is not specified for field " + this._model.somExpression + 25891 ", falling back to other widget"); 25892 } 25893 return widgetName || this.options.widgetName || this._defaultWidgetName; 25894 }, 25895 25896 _unloadView : function () { 25897 if (this._model) { 25898 this._model.off(guidelib.event.GuideModelEvent.VALUE_CHANGED, this.handleValueChanged, this); 25899 this._model.off(guidelib.event.GuideModelEvent.ERROR_CHANGED, this.handleErrorChanged, this); 25900 this._model.off(guidelib.event.GuideModelEvent.ERROR_RESET, this.handleErrorReset, this); 25901 } 25902 25903 this.jqwidget = null; 25904 GuideFieldView._super._unloadView.apply(this, arguments); 25905 }, 25906 25907 _initializeWidget : function () { 25908 if (this.$element.find('div.guideFieldWidget').length) { 25909 this.$widget = this.$element.find('div.guideFieldWidget'); 25910 } else { 25911 this.$widget = null; 25912 } 25913 25914 25915 if (this.$widget) { 25916 $(this.$widget).on(this.getCommitEvent(), $.proxy(this.handleCommit, this)) 25917 .on(xfaUtil.XFA_CLICK_EVENT, $.proxy(this.handleClick, this)) 25918 .on(xfaUtil.XFA_EXIT_EVENT, $.proxy(this.handleFocusOut, this)) 25919 .on(xfaUtil.XFA_ENTER_EVENT, $.proxy(this.handleEnter, this)); 25920 } 25921 }, 25922 25923 _defineModelEvents : function () { 25924 if (this._model) { 25925 25926 25927 this._model.on(guidelib.event.GuideModelEvent.VALUE_CHANGED, this.handleValueChanged, this); 25928 25929 this._model.on(guidelib.event.GuideModelEvent.ERROR_CHANGED, this.handleErrorChanged, this); 25930 this._model.on(guidelib.event.GuideModelEvent.ERROR_RESET, this.handleErrorReset, this); 25931 25932 } 25933 }, 25934 25935 _syncGuideNodeToHtml : function (deepSync) { 25936 GuideFieldView._super._syncGuideNodeToHtml.apply(this, arguments); 25937 if (this._model) { 25938 var propsToSync = { 25939 "visible" : this._model.visible, 25940 "jcr:title" : this._model.title 25941 }; 25942 _.each(propsToSync, function (value, key, list) { 25943 this.handleModelChanged(guidelib.event.GuideModelEvent.createEvent( 25944 guidelib.event.GuideModelEvent.MODEL_CHANGED, this, key, value, value 25945 )); 25946 }, this); 25947 this.$element.attr("data-disabled", !this._model.enabled + ""); 25948 } 25949 if (this.$widget) { 25950 var widgetOptions = this.createWidgetOptions(); 25951 if (!this.jqwidget) { 25952 this.createWidget(this.getWidgetName(), widgetOptions); 25953 } else { 25954 this.setWidgetOptions(widgetOptions); 25955 } 25956 } 25957 25958 if (this._model.forceErrorShow && this._model._errorText) { 25959 this.handleErrorChanged({prevText : this._model.validationState, newText : this._model._errorText}); 25960 } 25961 }, 25962 25963 setWidgetOptions : function (widgetOptions) { 25964 this.jqwidget.option(widgetOptions); 25965 25966 }, 25967 25968 25969 _markMandatory : function (value) { 25970 if (this._model.mandatory && this.$element) { 25971 this.$element.attr("data-mandatory", "true"); 25972 } else { 25973 this.$element.removeAttr("data-mandatory"); 25974 25975 if (this._model._failedTest === this.guideUtil.MANDATORY_TEST) { 25976 this._model._guide().runtime.errorManager.unMarkError(this.$element, this._model.somExpression); 25977 } 25978 } 25979 if (this.jqwidget) { 25980 this.setWidgetOptions({ 25981 "mandatory" : value 25982 }); 25983 } 25984 }, 25985 25986 25987 _updateEmptyStatus : function (event) { 25988 var val = event ? event.newText : this._model.value; 25989 if (val == null || typeof val === 'string' && val.length == 0) { 25990 this.$element.removeClass("af-field-filled").addClass("af-field-empty"); 25991 } else { 25992 this.$element.removeClass("af-field-empty").addClass("af-field-filled"); 25993 } 25994 }, 25995 25996 handleValueChanged : function (event) { 25997 switch (event._property) { 25998 case "value": 25999 this.jqwidget.option("value", event.prevText); 26000 this.jqwidget.option("displayValue", event.newText); 26001 break; 26002 } 26003 this._updateEmptyStatus(event); 26004 }, 26005 26006 handleErrorChanged : function (event) { 26007 var value = event.prevText, 26008 errorMessage = event.newText; 26009 if (value === true) { 26010 this._model._guide().runtime.errorManager.unMarkError(this.$element, this._model.somExpression);
26011 this.$element.addClass("validation-success").removeClass("validation-failure"); 26012 this.updateWidgetOption("isValid", true); 26013 } else { 26014 this._model._guide().runtime.errorManager.markError(errorMessage, this.$element, this._model.somExpression, 26015 guideBridge.getValidationContext()); 26016 this.$element.addClass("validation-failure").removeClass("validation-success"); 26017 this.updateWidgetOption("isValid", false); 26018 } 26019 }, 26020 26021 handleErrorReset : function (event) { 26022 this._model._guide().runtime.errorManager.unMarkError(this.$element, this._model.somExpression); 26023 this.$element.removeClass("validation-failure").removeClass("validation-success"); 26024 this.updateWidgetOption("isValid", undefined); 26025 }, 26026 26027 handleCommit : function () { 26028 if (this._model.enabled) { 26029 this.commitValue(this.jqwidget.option("value")); 26030 } 26031 }, 26032 26033 handleClick : function (event) { 26034 window.guideBridge.clickedOnWindow = false; 26035 }, 26036 26037 handleFocusOut : function (event) { 26038 var gb = window.guideBridge; 26039 26040 if (this.getCommitEvent() !== xfaUtil.XFA_EXIT_EVENT) { 26041 this._model.executeExpression("exit"); 26042 } 26043 if (gb && gb.clickedOnWindow) { 26044 this._guideView.currentFocusItemSom = null; 26045 } 26046 gb.clickedOnWindow = false; 26047 if (!(this._model.className === 'guideRadioButton' || this._model.className === 'guideCheckBox' || this._model.className === 'guideButton')) { 26048 this._triggerOnBridge("elementFocusOut", "", "", "", ""); 26049 } 26050 26051 if ((this.oldValue !== this._model.value) && this._model._errorText) { 26052 this.handleErrorChanged({prevText : this._model.validationState, newText : this._model._errorText}); 26053 } 26054 this.$element.removeClass('guideActiveField'); 26055 }, 26056 26057 handleModelChanged : function (event) { 26058 switch (event._property) { 26059 case "enabled": 26060 26061 26062 var prop = event.newText ? "open" : "readOnly"; 26063 if (this.jqwidget) { 26064 this.jqwidget.option("access", prop); 26065 } 26066 this.$element.attr("data-disabled", !event.newText + ""); 26067 break; 26068 case "mandatory": 26069 26070 this._markMandatory(this._model.mandatory); 26071 break; 26072 case "validateExpMessage": 26073 var newText = event.jsonModel.newText; 26074 this._changeValidationMessage(newText); 26075 break; 26076 case "jcr:title": 26077 26078 var newText = event.jsonModel.newText; 26079 this._changeTitle(newText); 26080 break; 26081 default: 26082 GuideFieldView._super.handleModelChanged.apply(this, arguments); 26083 } 26084 }, 26085 26086 26087 _changeTitle : function (newText) { 26088 var $field = $("#" + this.id), 26089 $guideFieldLabelDiv = $field.children(".guideFieldLabel"), 26090 $labelDiv = $guideFieldLabelDiv.children("label"); 26091 if ($labelDiv) { 26092 newText = DOMPurify.sanitize(newText); 26093 $labelDiv.html(newText); 26094 } 26095 }, 26096 26097 26098 _changeValidationMessage : function (newText) { 26099 var $fieldNode = $("#" + this.id), 26100 $errorDiv = $fieldNode.children(".guideFieldError"); 26101 $errorDiv.html(newText); 26102 }, 26103 26104 26105 commitValue : function (value) { 26106 this._model.value = value; 26107 var _version = this._model._guide().version; 26108 if (!(_version.isOn(_version.Flags.RUN_VALUE_COMMMIT_ON_SCRIPT_CHANGE))) { 26109 this._model.executeExpression("valueCommitScript"); 26110 } 26111 26112 26113 if (this.getCommitEvent() === xfaUtil.XFA_CHANGE_EVENT) { 26114 this._model.executeExpression("change"); 26115 } else { 26116 this._model.executeExpression("exit"); 26117 } 26118 }, 26119 26120 26121 tempXfaFixes : function () { 26122 26123 26124 26125 if (this.$element) { 26126 this.$element.find("input").css("position", "relative"); 26127 } 26128 this.handleAccessibility(); 26129 }, 26130 26131 handleAccessibility : function () { 26132 26133 if (this._model.mandatory) { 26134 this.$widget.find("input,textarea,select,button").attr("aria-required", true); 26135 } 26136 if(this._model._getToolTip()) { 26137 this.$element.find("input,textarea,select,button").attr("aria-labelledby",this._model.id + "_widget" + " " + this._model.id + "_guideFieldShortDescription"); 26138 } 26139 if (this._model._getScreenReaderText() === this._model._getToolTip()) { 26140 this.$element.find("input,textarea,select,button").removeAttr("aria-label"); 26141 this.$element.find("input,textarea,select,button").attr("aria-labelledby",this._model.id + "_guideFieldShortDescription"); 26142 } 26143 }, 26144 26145 26146 _getWidgetInitialOptions : function ($widget) { 26147 var $elem = $widget.find('[data-af-widgetname]').addBack('[data-af-widgetname]'); 26148 if ($elem.length > 0) { 26149 this.logger().info("AF", "Getting widget options for " + this._model.somExpression); 26150 var optionsMap = $elem.data('af-widgetoptions') || {}; 26151 _.each($elem[0].attributes, function (attr) { 26152 var nm = attr.name.match(/data-af-widgetoption-([^-]+)$/); 26153 if (nm != null && nm.length > 1) { 26154 this.logger().info("AF", "adding option " + nm[1] + " with value " + " "); 26155 optionsMap[nm[1]] = attr.value; 26156 } 26157 }, this); 26158 return optionsMap; 26159 } 26160 return {}; 26161 }, 26162 26163 _newWidget : function (widgetname, options, $widgetElem) { 26164 var jqwidget = null, 26165 fixesRequired = widgetname == this._defaultWidget
26165Name; 26166 try { 26167 26168 $widgetElem[widgetname](options); 26169 26170 26171 jqwidget = $widgetElem.data(widgetname) || $widgetElem.data('xfaWidget-' + widgetname); 26172 } catch (e) { 26173 this.logger().error("AF", "widget " + widgetname + " doesn't exists. Falling back to default widget"); 26174 fixesRequired = true; 26175 jqwidget = $widgetElem[this._defaultWidgetName](options).data('xfaWidget-' + widgetname); 26176 } 26177 26178 if (fixesRequired) { 26179 this.tempXfaFixes(); 26180 } 26181 return jqwidget; 26182 }, 26183 26184 createWidget : function (widgetname, options) { 26185 var initialOptions = this._getWidgetInitialOptions(this.$widget); 26186 var _options = $.extend({}, options, initialOptions); 26187 this.jqwidget = this._newWidget(widgetname, _options, this.$widget); 26188 }, 26189 26190 handleEnter : function () { 26191 this._guideView.currentFocusItemSom = this._model.somExpression; 26192 var gb = window.guideBridge; 26193 if (gb) { 26194 gb.clickedOnWindow = false; 26195 } 26196 if (!(this._model.className === 'guideRadioButton' || this._model.className === 'guideCheckBox' || this._model.className === 'guideButton')) { 26197 this._triggerOnBridge("elementFocus", "", "", "", ""); 26198 } 26199 this.oldValue = this._model.value; 26200 this.$element.addClass('guideActiveField'); 26201 }, 26202 26203 handleChange : function () { 26204 26205 }, 26206
26207 setActive : function (activeItemToken, focus, muteScripts) { 26208 GuideFieldView._super.setActive.call(this, activeItemToken, focus, muteScripts); 26209 if (focus) { 26210 26211 if (!this._guideView.skipFieldFocus && this.jqwidget && this.jqwidget.focus) { 26212 this.jqwidget.focus(); 26213 this._guideView.currentFocusItemSom = this._model.somExpression; 26214 } 26215 26216 } 26217 return true; 26218 }, 26219 26220 updateWidgetOption : function (optionName, optionValue) { 26221 26222 if (this.jqwidget) { 26223 this.jqwidget.option(optionName, optionValue); 26224 } 26225 } 26226 26227 }); 26228}($, guidelib, _)); 26229(function ($, guidelib) { 26230 var GuideCaptchaView = guidelib.view.GuideCaptchaView = guidelib.view.GuideFieldView.extend({ 26231 26232 _defaultWidgetName : "afcaptcha", 26233 26234 syncGuideNodeToHtml : true, 26235 26236 initialize : function () { 26237 26238 if (!FD.isToggleEnabled(guidelib.util.FeatureToggleConstants.FT_TURNSTILE_HCAPTCHA) || this.options.model.isWidgetRecaptcha) { 26239 if ((this.options.model.captchaEnterprise && !this.options.model.checkBoxkey) || 26240 (this.options.model.captchaInvisible && this.options.model.mandatory)) { 26241 this._model = this.options.model; 26242 this.syncGuideNodeToHtml = false; 26243 return; 26244 } else if (this.options.model.captchaInvisible) { 26245 this.options.element.classList.add("af-hideRecaptchaView"); 26246 this.options.model.captchaValidate = false; 26247 } 26248 } else if ((this.options.model.isWidgetTurnstile || this.options.model.isWidgetHcaptcha) && this.options.model.captchaInvisible) { 26249 this._model = this.options.model; 26250 this.syncGuideNodeToHtml = false; 26251 return; 26252 } 26253 GuideCaptchaView._super.initialize.apply(this, arguments); 26254 if (this._model.captchaWidget) { 26255 26256 this._defaultWidgetName = this._model.captchaWidget; 26257 } 26258 }, 26259 26260 _initializeWidget : function () { 26261 GuideCaptchaView._super._initializeWidget.apply(this, arguments); 26262 if (this.$widget.length > 0) { 26263 this.$widget.on("tokenChange.captcha", $.proxy(this.handleTokenChange, this)); 26264 } 26265 }, 26266 26267 _syncGuideNodeToHtml : function (deepSync) { 26268 if(!this.syncGuideNodeToHtml) 26269 return; 26270 GuideCaptchaView._super._syncGuideNodeToHtml.call(this, deepSync); 26271 }, 26272 26273 handleTokenChange : function (event) { 26274 this._model.value = event.token; 26275 }, 26276 26277 createWidgetOptions : function () { 26278 var options = GuideCaptchaView._super.createWidgetOptions.apply(this, arguments); 26279 return $.extend({}, options, { 26280 "captchaConfigData" : this.options.model.jsonModel 26281 }); 26282 }, 26283 26284 handleErrorChanged : function (event) { 26285 var value = event.prevText, 26286 errorMessage = event.newText; 26287 if (value === false) { 26288 this._model._guide().runtime.errorManager.markError(errorMessage, this.$element, this._model.somExpression, 26289 guideBridge.getValidationContext()); 26290 this.$element.addClass("validation-failure").removeClass("validation-success"); 26291 } else { 26292 this.$element.addClass("validation-success").removeClass("validation-failure"); 26293 } 26294 } 26295 }); 26296}($, guidelib)); 26297(function ($, guidelib, _) { 26298 var xfaUtil = xfalib.ut.XfaUtil.prototype, 26299 GuideCompositeFieldView = guidelib.view.GuideCompositeFieldView = guidelib.view.GuideFieldView.extend({ 26300 _defaultWidgetName : "defaultField", 26301 26302 26303 getModelNameOptionsMap : function () { 26304 return {}; 26305 }, 26306 26307 initialize : function () { 26308 GuideCompositeFieldView._super.initialize.call(this); 26309 this._defineChildModelEvents(); 26310 }, 26311 26312 postInitialize : function () { 26313 GuideCompositeFieldView._super.postInitialize.call(this); 26314 var _self = this; 26315 if (this.getModelNameOptionsMap()) { 26316 _.each(this.getModelNameOptionsMap(), function (value, modelName) { 26317 var childModel = _self._model[modelName]; 26318 if (childModel._errorText) { 26319 childModel._triggerEvent(guidelib.event.GuideModelEvent.ERROR_CHANGED, 26320 "validationStatus", childModel.validationState, childModel._errorText); 26321 } 26322 }); 26323 } 26324 }, 26325 26326 _unloadView : function () { 26327 var _self = this; 26328 if (this.getModelNameOptionsMap()) { 26329 _.each(this.getModelNameOptionsMap(), function (value, modelName) { 26330 var obj = _self._model[modelName]; 26331 26332 obj.off(guidelib.event.GuideModelEvent.VALUE_CHANGED, _self.handleValueChanged, _self);
26333 if (obj.mandatory || obj.validateExp) { 26334 obj.off(guidelib.event.GuideModelEvent.ERROR_CHANGED, _self.handleErrorChanged, _self); 26335 obj.off(guidelib.event.GuideModelEvent.ERROR_RESET, _self.handleErrorReset, _self); 26336 } 26337 }); 26338 26339 } 26340 GuideCompositeFieldView._super._unloadView.call(_self); 26341 }, 26342 26343 _defineChildModelEvents : function () { 26344 var _self = this; 26345 if (this.getModelNameOptionsMap()) { 26346 _.each(this.getModelNameOptionsMap(), function (value, modelName) { 26347 var obj = _self._model[modelName]; 26348 26349 obj.on(guidelib.event.GuideModelEvent.VALUE_CHANGED, _self.handleValueChanged, _self); 26350 26351 26352 if (obj.mandatory || obj.validateExp) { 26353 obj.on(guidelib.event.GuideModelEvent.ERROR_CHANGED, _self.handleErrorChanged, _self); 26354 obj.on(guidelib.event.GuideModelEvent.ERROR_RESET, _self.handleErrorReset, _self); 26355 } 26356 }); 26357 26358 } 26359 }, 26360 26361 handleCommit : function () { 26362 var _self = this; 26363 if (!_.isEmpty(this.getModelNameOptionsMap())) { 26364 _.each(this.getModelNameOptionsMap(), function (value, modelName) { 26365 var obj = _self._model[modelName]; 26366 if (!_.isUndefined(obj)) { 26367 var val = _self.jqwidget.option(value); 26368 if (_.isArray(val)) { 26369 val = val.join("\n"); 26370 } 26371 obj.value = val; 26372 } 26373 }); 26374 } else { 26375 this._model.value = this.jqwidget.option("value"); 26376 } 26377 this._model.executeExpression("valueCommitScript"); 26378 this.execCommitExpression(); 26379 }, 26380 26381 handleValueChanged : function (event) { 26382 26383 26384 switch (event._property) { 26385 case "value": 26386 var map = this.getModelNameOptionsMap(); 26387 this.jqwidget.option(map[event.target.name], event.prevText); 26388 break; 26389 } 26390 }, 26391 26392 execCommitExpression : function () { 26393 26394 if (this.getCommitEvent() == xfaUtil.XFA_CHANGE_EVENT) { 26395 this._model.executeExpression("change"); 26396 } else { 26397 this._model.executeExpression("exit"); 26398 } 26399 } 26400 }); 26401}($, guidelib, _)); 26402(function ($, guidelib) { 26403 var GuideFileUploadView = guidelib.view.GuideFileUploadView = guidelib.view.GuideCompositeFieldView.extend({ 26404 _defaultWidgetName : "fileUpload", 26405 26406 getModelNameOptionsMap : function () { 26407 var map = GuideFileUploadView._super.getModelNameOptionsMap.apply(this, arguments); 26408 return $.extend({}, map, { 26409 "fileAttachment" : "value", 26410 "comment" : "comment" 26411 }); 26412 }, 26413 26414 createWidgetOptions : function () { 26415 var options = GuideFileUploadView._super.createWidgetOptions.apply(this, arguments), 26416 fileNamesStr = this._model._getFileAttachmentNames(), 26417 fileNamesArr = []; 26418 if (fileNamesStr) { 26419 fileNamesArr = fileNamesStr.split("\n"); 26420 } 26421 return $.extend({}, options, { 26422 fileList : this._model.fileList, 26423 buttonText : this._model.buttonText, 26424 multiSelect : this._model.multiSelection, 26425 fileSizeLimit : this._model.fileSizeLimit, 26426 mimeType : this._model.getOrElse(this._model.jsonModel, "mimeType", ""), 26427 buttonClass : "button.guide-fu-attach-button", 26428 fileItemListClass : "ul.guide-fu-fileItemList",
26429 iframeContainer : "div.guideContainerWrapperNode", 26430 showComment : this._model.showComment, 26431 value : this._model.fileAttachment.value, 26432 fileNames : fileNamesArr, 26433 comment : this._model.comment.value, 26434 _uuidGenerator : function () { return guideBridge._getUUID.apply(this); }, 26435 _filePath : "/tmp/fd/af", 26436 _getUrl : guideBridge._getUrl(""), 26437 disablePreview : false, 26438 uploaderPluginName : guideBridge.userConfig.uploaderPluginName || "adobeFileUploader" 26439 }); 26440 }, 26441 26442 handleCommit : function () { 26443 26444 26445 26446 this._model.fileList = this.jqwidget.option("fileList"); 26447 GuideFileUploadView._super.handleCommit.apply(this, arguments); 26448 }, 26449 26450 handleModelChanged : function (event) { 26451 switch (event._property) { 26452 case "fileList": 26453 this.jqwidget.option("fileList", event.prevText); 26454 break; 26455 default: 26456 GuideFileUploadView._super.handleModelChanged.apply(this, arguments); 26457 break; 26458 } 26459 }, 26460 26461 handleAccessibility : function () { 26462 26463 26464 var isBrowserIE9OrIE10 = ($.browser.msie && ($.browser.version === '9.0' || $.browser.version === '10.0')); 26465 if (isBrowserIE9OrIE10) { 26466 if (this._model.mandatory) { 26467 this.$widget.attr("aria-required", true); 26468 } 26469 if (this._model._getScreenReaderText() === this._model._getToolTip()) { 26470 this.$widget.removeAttr("aria-label"); 26471 this.$widget.attr("aria-labelledby", this._model.id + "_guideFieldShortDescription"); 26472 } 26473 } else { 26474 GuideFileUploadView._super.handleAccessibility.apply(this, arguments); 26475 } 26476 }, 26477 26478 setActive : function (activeItemToken, focus, muteScripts) { 26479 guidelib.view.GuideFieldView._super.setActive.call(this, activeItemToken, focus, muteScripts); 26480 if (focus) { 26481 this._guideView.currentFocusItemSom = this._model.somExpression; 26482 this.$element.find("button").focus(); 26483 } 26484 return true; 26485 }, 26486 26487 26488 26489 tempXfaFixes : function () { 26490 26491 this.handleAccessibility(); 26492 }, 26493 26494 getCommitEvent : function () { 26495 return xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT; 26496 } 26497 }); 26498}($, guidelib)); 26499(function ($, guidelib) { 26500 var GuideTermsAndConditionsView = guidelib.view.GuideTermsAndConditionsView = guidelib.view.GuideCompositeFieldView.extend({ 26501 _defaultWidgetName : "tnc", 26502 26503 getModelNameOptionsMap : function () { 26504 var map = GuideTermsAndConditionsView._super.getModelNameOptionsMap.apply(this, arguments); 26505 return $.extend({}, map, { 26506 "reviewDocument" : "value", 26507 "reviewStatus" : "reviewStatus" 26508 }); 26509 }, 26510 26511 createWidgetOptions : function () { 26512 var options = GuideTermsAndConditionsView._super.createWidgetOptions.apply(this, arguments); 26513 return $.extend({}, options, { 26514 textAreaClass : ".guide-tnc-content", 26515 checkBoxClass : ".guide-tnc-checkbox", 26516 linkClass : ".guide-tnc-link", 26517 checkBoxDisableClass : ".guide-tnc-checkbox-disabled", 26518 checkBoxReviewedClass : ".guide-tnc-checkbox-reviewed", 26519 showLink : this._model.showLink, 26520 showAsPopUp : this._model.showAsPopUp, 26521 value : this._model.reviewDocument.value, 26522 reviewStatus : this._model.reviewStatus.value, 26523 clickStatus : this._model.clickStatus 26524 }); 26525 }, 26526 26527 26528 tempXfaFixes : function () { 26529 26530 26531 26532 if (this.$widget) { 26533 this.$widget.css("position", "relative"); 26534 } 26535 26536 }, 26537 26538 handleCommit : function (event) { 26539 26540 this._model.clickStatus = this.jqwidget.option("clickStatus"); 26541 26542 GuideTermsAndConditionsView._super.handleCommit.apply(this, arguments); 26543 }, 26544 26545 handleModelChanged : function (event) { 26546 26547 26548 switch (event._property) { 26549 case "clickStatus": 26550 this.jqwidget.option("clickStatus", event.prevText); 26551 break; 26552 default: 26553 GuideTermsAndConditionsView._super.handleModelChanged.apply(this, arguments); 26554 break; 26555 } 26556 }, 26557 26558 getCommitEvent : function () { 26559 return xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT; 26560 } 26561 }); 26562}($, guidelib)); 26563(function ($, guidelib) { 26564 var GuideTelephoneView = guidelib.view.GuideTelephoneView = guidelib.view.GuideFieldView.extend({ 26565
26566 _defaultWidgetName : "telephoneWidget", 26567 26568 createWidgetOptions : function () { 26569 var options = GuideTelephoneView._super.createWidgetOptions.apply(this, arguments); 26570 return $.extend({}, options, { 26571 placeholder : this._model.placeholderText 26572 }); 26573 } 26574 26575 }); 26576}($, guidelib)); 26577 26578(function ($, guidelib) { 26579 var GuideTextDrawView = guidelib.view.GuideTextDrawView = guidelib.view.GuideFieldView.extend({ 26580 _defaultWidgetName : "abstractWidget", 26581 26582 initialize : function () { 26583 GuideTextDrawView._super.initialize.call(this); 26584 if (this.$element && this.$element.length > 0) { 26585 $(this.$element) 26586 .on("focus.guideTextDraw", $.proxy(this.handleEnter, this)) 26587 .on("click.guideTextDraw", $.proxy(this.handleClick, this)); 26588 } 26589 }, 26590 26591 _syncGuideNodeToHtml : function (deepSync) { 26592 GuideTextDrawView._super._syncGuideNodeToHtml.call(this, deepSync); 26593 26594 26595 var isFloatingField = this._model._isFloatingField(); 26596 var isParentLazy = guidelib.util.GuideUtil._checkIfAncestorIsALazyReference(this); 26597 if (!isParentLazy && this._model.value === this._model.jsonModel._value && this.$element.html() !== this._model.value && !isFloatingField) { 26598 26599 26600 } else { 26601 this.handleValueChanged({ 26602 _property : "value", 26603 newText : this._model.value ? this._model.value : "" 26604 }); 26605 } 26606 }, 26607 26608 handleValueChanged : function (event) { 26609 switch (event._property) { 26610 case "value": 26611 this.$element.html(event.newText); 26612 break; 26613 } 26614 }, 26615 26616 setActive : function (activeItemToken, focus, muteScripts) { 26617 guidelib.view.GuideFieldView._super.setActive.call(this, activeItemToken, focus, muteScripts); 26618 if (focus && !this._guideView.skipFieldFocus) { 26619 if (this.$element) { 26620 this.$element.focus(); 26621 } 26622 this._guideView.currentFocusItemSom = this._model.somExpression; 26623 } 26624 return true; 26625 } 26626 }); 26627}($, guidelib)); 26628 26629 26630(function ($, guidelib) { 26631 var GuideAdobeSignBlockView = guidelib.view.GuideAdobeSignBlockView = guidelib.view.GuideTextDrawView.extend({ 26632 }); 26633}($, guidelib)); 26634(function ($, guidelib) { 26635 var GuideButtonView = guidelib.view.GuideButtonView = guidelib.view.GuideFieldView.extend({ 26636 _defaultWidgetName : "xfaButton", 26637 26638 handleClick : function (event) { 26639 this._triggerOnBridge("elementButtonClicked", this._model, "click", "", ""); 26640 this._model.executeExpression("clickExp"); 26641 GuideButtonView._super.handleClick.call(this); 26642 }, 26643 26644 _changeTitle : function (newText) { 26645 var $fieldTitleSpan = $("#" + this.id + "_widget"); 26646 var $buttonLabel = $fieldTitleSpan.children("[data-guide-button-label]"); 26647 newText = xfalib.ut.XfaUtil.prototype.encodeScriptableTags(newText); 26648 $buttonLabel.html(newText); 26649 }, 26650 26651 tempXfaFixes : function () { 26652 26653 26654 26655 if (this.$element) { 26656 this.$element.find("button").css("position", "relative"); 26657 } 26658 this.handleAccessibility(); 26659 } 26660 26661 }); 26662}($, guidelib)); 26663(function ($, guidelib, _) { 26664 var fileInputIdCounter = 0; 26665 var GuideListFileAttachmentButtonView = guidelib.view.GuideListFileAttachmentButtonView = guidelib.view.GuideButtonView.extend({ 26666 26667 _clearFileListing : function () { 26668 $('#fileAttachment .modal-list', window.document).children().remove(); 26669 _.each(this._fileListViews, function (childView) { 26670 childView._unloadView(); 26671 }, this); 26672 this._fileListViews = []; 26673 fileInputIdCounter = 0; 26674 }, 26675 _updateFileListing : function (fileAttachmentModel) { 26676 if (fileAttachmentModel.className == "guideFileUpload") { 26677 var $htmlTemplate = this._guideView.$element.find("#" + fileAttachmentModel.id), 26678 inputFileSelector = "#" + fileAttachmentModel.id + "_widget", 26679 26680 26681 26682 26683 26684 $cloneHtmlTemplate = $htmlTemplate.clone(); 26685 26686 $cloneHtmlTemplate.find(inputFileSelector).attr("id", fileAttachmentModel.id + "_widget" + (++fileInputIdCounter)); 26687 this._addSuffixToHelpIds($cloneHtmlTemplate, fileInputIdCounter); 26688 var $fluidDesign = $('<div></div>').addClass("row").append('<div class="col-md-12"></div>');
26689 $('#fileAttachment .modal-list', window.document).append($cloneHtmlTemplate.appendTo($fluidDesign)); 26690 var view = guidelib.view.GuideViewRegistry.prototype.createView($cloneHtmlTemplate, this); 26691 this._fileListViews.push(view); 26692 view.postInitialize(); 26693 26694 } 26695 }, 26696 _addSuffixToHelpIds : function ($html, suffix) { 26697 var $questionMarkElement = $html.find("[data-guide-longDescription]"), 26698 $shortHelpElement; 26699 if ($questionMarkElement.length > 0) { 26700 var idForLongHelp = $questionMarkElement.attr("data-guide-longDescription"), 26701 $longHelpElement = $(".guideFieldDescription.long", $html); 26702 idForLongHelp = idForLongHelp + suffix; 26703 $longHelpElement.attr("id", idForLongHelp); 26704 $questionMarkElement.attr("data-guide-longDescription", idForLongHelp); 26705 } 26706 26707 26708 }, 26709 26710 26711 _markFileListing : function () { 26712 if (this.$element) { 26713 this.$element.find("button").attr("data-guide-fileListing", true); 26714 } 26715 }, 26716 26717 initialize : function () { 26718 GuideListFileAttachmentButtonView._super.initialize.apply(this, arguments); 26719 this._markFileListing(); 26720 26721 26722 this._fileListViews = []; 26723 } 26724 }); 26725}($, guidelib, _)); 26726(function ($, guidelib, _) { 26727 var xfaUtil = xfalib.ut.XfaUtil.prototype, 26728 GuideDropDownListView = guidelib.view.GuideDropDownListView = guidelib.view.GuideFieldView.extend({ 26729 26730 _defaultWidgetName : "dropDownList", 26731 26732 initialize : function () { 26733 GuideDropDownListView._super.initialize.apply(this, arguments); 26734 if (this._model.multiSelect) { 26735 this._defaultWidgetName = "listBox"; 26736 } 26737 }, 26738 26739 _valueToArray : function (value) { 26740 var valueArray; 26741 if (value !== null && !_.isUndefined(value)) { 26742 if (_.isString(value)) { 26743 valueArray = value.split("\n"); 26744 } else if (_.isNumber(value)) { 26745 valueArray = [value.toString()]; 26746 } 26747 } else { 26748 valueArray = [null]; 26749 } 26750 return valueArray; 26751 }, 26752 26753 createWidgetOptions : function () { 26754 var options = GuideDropDownListView._super.createWidgetOptions.apply(this, arguments); 26755 26756 26757 return $.extend({}, options, { 26758 multiSelect : this._model.multiSelect, 26759 editable : false, 26760 items : this._model._getOptionsArray("save", "display"), 26761 value : this._valueToArray(this._model.value), 26762 placeholder : this._model.placeholderText 26763 }); 26764 }, 26765 26766 26767 handleCommit : function () { 26768 var val = this.jqwidget.option("value"); 26769 if (_.isArray(val)) { 26770 val = val.join("\n"); 26771 } 26772 26773 this.commitValue(val); 26774 }, 26775 26776 26777 commitValue : function (value) { 26778 var oldValue = this._model.value; 26779 this._model.value = value; 26780 26781 26782 26783 var _version = this._model._guide().version; 26784 if (!(_version.isOn(_version.Flags.RUN_VALUE_COMMMIT_ON_SCRIPT_CHANGE))) { 26785 this._model.executeExpression("valueCommitScript"); 26786 } 26787 if (this.getCommitEvent() === xfaUtil.XFA_CHANGE_EVENT) { 26788 26789 26790 26791 26792 26793 this._model.executeExpression("change", { 26794 "prevText" : oldValue, 26795 "newText" : this._model.value 26796 }); 26797 } else { 26798 26799 this._model.executeExpression("exit"); 26800 } 26801 }, 26802 26803 handleValueChanged : function (event) { 26804 this.jqwidget.option("value", this._valueToArray(event.prevText)); 26805 this.jqwidget.option("displayValue", this._valueToArray(event.
26805newText)); 26806 this._updateEmptyStatus(event); 26807 }, 26808 26809 getCommitEvent : function () { 26810 return xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT; 26811 }, 26812 26813 handleModelChanged : function (event) { 26814 if (event._property === "addItem") { 26815 this._handleAddItem(event); 26816 } 26817 if (event._property === "clearItems") { 26818 this._handleClearItems(event); 26819 } 26820 if (event._property === "deleteItem") { 26821 this._handleDeleteItem(event); 26822 } else { 26823 GuideDropDownListView._super.handleModelChanged.apply(this, arguments); 26824 } 26825 }, 26826 26827 _handleAddItem : function (event) { 26828 var itemValues = { 26829 sDisplayVal : event.newText, 26830 sSaveVal : event.prevText 26831 }; 26832 this.jqwidget.addItem(itemValues); 26833 }, 26834 26835 _handleClearItems : function (event) { 26836 this.jqwidget.clearItems(); 26837 }, 26838 26839 _handleDeleteItem : function (event) { 26840 this.jqwidget.deleteItem(event.newText); 26841 }, 26842 26843 handleItemsChanged : function (event) { 26844 var items = this._model._getOptionsArray("save", "display"); 26845 this.jqwidget.option("items", items); 26846 this.jqwidget.option("value", this._valueToArray(this._model.jsonModel._value)); 26847 this.jqwidget.option("displayValue", this._valueToArray(this._model.formattedValue)); 26848 }, 26849 26850 _defineModelEvents : function () { 26851 GuideDropDownListView._super._defineModelEvents.apply(this, arguments); 26852 if (this._model) { 26853 26854 this._model.on(guidelib.event.GuideModelEvent.ITEMS_CHANGED, this.handleItemsChanged, this); 26855 } 26856 }, 26857 26858 26859 tempXfaFixes : function () { 26860 26861 26862 if (this.$element) { 26863 if (!this._model.multiSelect) { 26864 this.$element.find("select") 26865 .css("position", "relative") 26866 .attr("id", this._model.id + "_widget") 26867 .attr("aria-describedby", this._model.id + "_widget_desc"); 26868 } else { 26869 26870 if (this._model.height) { 26871 this.$element.find("ol").css("max-height", "none"); 26872 } 26873 this.$element.find("ol") 26874 .css("position", "relative") 26875 .attr("id", this._model.id + "_widget"); 26876 } 26877 } 26878 this.handleAccessibility(); 26879 } 26880 }); 26881 26882}($, guidelib, _)); 26883(function ($, guidelib, _) { 26884 var GuideCheckBoxView = guidelib.view.GuideCheckBoxView = guidelib.view.GuideFieldView.extend({ 26885 _defaultWidgetName : "XfaCheckBox", 26886 initialize : function () { 26887 GuideCheckBoxView._super.initialize.apply(this, arguments); 26888 this._setListenersForLabelClick(); 26889 this._setListenersForRadioButtonKeyPress(); 26890 }, 26891 26892 _setListenersForLabelClick : function () { 26893 var self = this; 26894 this.$element 26895 .find(".guideWidgetLabel") 26896 .each(function (index, item) { 26897 $(item).click( 26898 (function (index) { 26899 return function () { 26900 26901 if (self._model.enabled) { 26902 self.jqwidget[self.getJQWidgetIdentifier(index)].click(); 26903 } 26904 }; 26905 }(index)) 26906 ); 26907 }); 26908 }, 26909 26910 _setListenersForRadioButtonKeyPress : function () { 26911 var self = this; 26912 this.$element 26913 .find(".guideRadioButtonItem") 26914 .each(function (index, item) { 26915 $(item).keypress(function (e){ 26916 if(e.keyCode == "13" || e.keyCode == "32"){ 26917 e.preventDefault(); 26918 if (self._model.enabled) { 26919 self.jqwidget[self.getJQWidgetIdentifier(index)].click(); 26920 } 26921 } 26922 }); 26923 }); 26924 }, 26925 _syncGuideNodeToHtml : function (deepSync) { 26926 if (this._model._isStateOverridden("options")) { 26927 this._replaceGroupItemsWithNewOptions(this._model._getOptionsArray(), this._model.getAttribute("alignment")); 26928 26929 26930 26931 26932 this.jqwidget = null; 26933 26934 } 26935 GuideCheckBoxView._super._syncGuideNodeToHtml.apply(this, arguments); 26936 }, 26937 getJQWidgetIdentifier : function (index) { 26938 return index; 26939 }, 26940 26941 createWidgetOptions : function () { 26942 var options = GuideCheckBoxView._super.createWidgetOptions.apply(this, arguments); 26943 26944 return $.extend({}, options, { 26945 states : 2 26946 }); 26947 }, 26948 26949 getCommitEvent : function () { 26950 return xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT; 26951 }, 26952 26953 getStateFromValue : function (value, items) { 26954 if (value === null) { 26955 return 1; 26956 } 26957 var valuesArray = null; 26958 if (value && value.indexOf && value.indexOf("\\,") > -1) { 26959 valuesArray = this.splitOnNonEscapedCommas(value); 26960 } else { 26961 valuesArray = (value + "").split(","); 26962 } 26963 if (valuesArray && valuesArray.indexOf(items[0] + "") !== -1) { 26964 return 0; 26965 } 26966 return 1; 26967 }, 26968 26969 getOnOffValueFromModelValue : function (val, items) {
26970 return items[this.getStateFromValue(val, items)]; 26971 }, 26972 26973 splitOnNonEscapedCommas : function (string) { 26974 var splitArray = []; 26975 var currentSubstring = ''; 26976 var escaped = false; 26977 26978 for (var i = 0; i < string.length; i++) { 26979 var char = string[i]; 26980 26981 if (char === ',' && !escaped) { 26982 splitArray.push(currentSubstring.trim()); 26983 currentSubstring = ''; 26984 } else { 26985 currentSubstring += char; 26986 escaped = (char === '\\' && !escaped); 26987 } 26988 } 26989 splitArray.push(currentSubstring.trim()); 26990 return splitArray; 26991 }, 26992 26993 handleValueChanged : function (event) { 26994 _.each(this.jqwidget, function (jqwidget) { 26995 var setVal = this.getOnOffValueFromModelValue(event.prevText, this._escapeCommas(jqwidget.option("values"))); 26996 setVal = this._unescapeCommas(setVal); 26997 jqwidget.option("value", setVal); 26998 jqwidget.option("displayValue", setVal); 26999 }, this); 27000 this.$widget.find("[checked!=checked]").parents(".guideCheckBoxItem").removeClass('guideItemSelected'); 27001 this.$widget.find("[checked=checked]").parents(".guideCheckBoxItem").addClass('guideItemSelected'); 27002 }, 27003 27004 _escapeCommas : function (items) { 27005 var temp = _.clone(items); 27006 if(temp[0] && temp[0].indexOf && temp[0].indexOf(',') > -1 && temp[0].indexOf('\\,') === -1) { 27007 temp[0] = temp[0].replace(/,/g, "\\,"); 27008 } 27009 return temp; 27010 }, 27011 27012 _unescapeCommas : function (value) { 27013 if(value && value.indexOf && value.indexOf('\\,') > -1) { 27014 value = value.replace(/\\,/g, ','); 27015 } 27016 return value; 27017 }, 27018 27019 handleCommit : function () { 27020 var temp = ""; 27021 _.each(this.jqwidget, function (jqwidget, index) { 27022 var items = this._escapeCommas(jqwidget.option("values")); 27023 if (jqwidget.option("state") === 0) { 27024 27025 temp = temp + items[0] + ","; 27026 } 27027 }, this); 27028 temp = temp.substring(0, temp.length - 1); 27029 this.commitValue(this._unescapeCommas(temp)); 27030 }, 27031 27032 handleEnabledChanged : function (event) { 27033 27034 if (!this.$element.hasClass("dontSyncEnabled")) { 27035 var prop = event.newText ? "open" : "readOnly"; 27036 _.each(this.jqwidget, function (jqwidget) { 27037 jqwidget.option("access", prop); 27038 }); 27039 } 27040 27041 this.$element.attr("data-disabled", !this._model.enabled); 27042 }, 27043 27044 handleModelChanged : function (evnt) { 27045 switch (evnt._property) { 27046 case "enabled": 27047 this.handleEnabledChanged(evnt); 27048 break; 27049 default: 27050 GuideCheckBoxView._super.handleModelChanged.apply(this, arguments); 27051 } 27052 }, 27053 27054 handleItemsChanged : function (event) { 27055 this._replaceGroupItemsWithNewOptions(this._model._getOptionsArray(), this._model.jsonModel.alignment); 27056 this.createWidget(this.getWidgetName(), this.createWidgetOptions()); 27057 }, 27058 27059 _getGroupItemIdentifier : function () { 27060 return '.guideCheckBoxGroupItems'; 27061 }, 27062 27063 _getWidgetType : function () { 27064 return 'checkbox'; 27065 }, 27066 27067 _getItemName : function () { 27068 return "CheckBoxItem"; 27069 }, 27070 27071 _getItemSkeleton : function () { 27072 var guideWidgetItemName = "guide" + this._getItemName(); 27073 var afWidgetItemName = "af" + this._getItemName(); 27074 return '<div class="' + guideWidgetItemName + ' ' + afWidgetItemName + ' {NAME_PLACEHOLDER} {CSS_PLACEHOLDER}" data-original-title="" title="">\n' + 27075 ' <div class="guideFieldWidget left XfaCheckBox" data-id="{COUNTER_PLACEHOLDER}" data-original-title="" title="">\n' + 27076 ' <input type="' + this._getWidgetType() + '" id="{TEMPLATE_ID_PLACEHOLDER}_{COUNTER_PLACEHOLDER}_widget" name="{TEMPLATE_ID_PLACEHOLDER}_jqName" value="-100" tabindex="0" placeholder="" style="position: relative;">\n' + 27077 ' </div>\n' + 27078 ' <div class="guideWidgetLabel right">\n' + 27079 ' <label>{LABEL_PLACEHOLDER}</label>\n' + 27080 ' </div>\n' + 27081 ' </div>'; 27082 }, 27083 27084 _renderGroupItem : function (options) { 27085 var itemSkeleton = this._getItemSkeleton(), 27086 namePlaceHolder = "{NAME_PLACEHOLDER}", 27087 cssPlaceHolder = "{CSS_PLACEHOLDER}", 27088 counterPlaceHolder = "{COUNTER_PLACEHOLDER}" , 27089 templateIDPlaceHolder = "{TEMPLATE_ID_PLACEHOLDER}", 27090 labelPlaceHolder = "{LABEL_PLACEHOLDER}", 27091 guideUtil = guidelib.util.GuideUtil; 27092 itemSkeleton = guideUtil.replaceAll(itemSkeleton, namePlaceHolder, options.modelName); 27093 itemSkeleton = guideUtil.replaceAll(itemSkeleton, templateIDPlaceHolder, options.modelTemplateId); 27094 itemSkeleton = guideUtil.replaceAll(itemSkeleton, cssPlaceHolder, options.cssValue);
27095 itemSkeleton = guideUtil.replaceAll(itemSkeleton, counterPlaceHolder, options.itemIndex); 27096 itemSkeleton = guideUtil.replaceAll(itemSkeleton, labelPlaceHolder, options.displayValue); 27097 return itemSkeleton; 27098 }, 27099 27100 _replaceGroupItemsWithNewOptions : function (items, cssValue) { 27101 var groupItem = this.$element.find(this._getGroupItemIdentifier()), 27102 options = {}, 27103 widgetName = this.getWidgetName(), 27104 self = this; 27105 27106 27107 groupItem.empty(); 27108 options.widgetType = this._getWidgetType(); 27109 options.modelName = this._model.name; 27110 options.modelTemplateId = this._model.id; 27111 27112 if (this._model.css !== null && !_.isUndefined(this._model.css)) { 27113 cssValue += " " + this._model.css; 27114 } 27115 options.cssValue = cssValue; 27116 27117 _.each(items, function (value, index) { 27118 options.itemIndex = index; 27119 options.displayValue = value.displayValue; 27120 options.saveValue = value.saveValue; 27121 groupItem.append(self._renderGroupItem(options)); 27122 }); 27123 this._initializeWidget(); 27124 this._setListenersForLabelClick(); 27125 }, 27126 27127 _replaceAll : function (stringToReplaceIn, textToReplace, replacementString) { 27128 return stringToReplaceIn.split(textToReplace).join(replacementString); 27129 }, 27130 27131 _defineModelEvents : function () { 27132 GuideCheckBoxView._super._defineModelEvents.apply(this, arguments); 27133 if (this._model) { 27134 27135 this._model.on(guidelib.event.GuideModelEvent.ITEMS_CHANGED, this.handleItemsChanged, this); 27136 } 27137 }, 27138 27139 setWidgetOptions : function (options) { 27140 var index = 0; 27141 _.each(this.jqwidget, function (jqwidget, id) { 27142 this._initOrUpdateWidget(id, this._getOptions(options, index++)); 27143 }, this); 27144 }, 27145 27146 _getOptions : function (options, index) { 27147 var items = this._model.getOnOffValues(index), 27148 val = this.getOnOffValueFromModelValue(this._model.value, items), 27149 optionsCopy = _.extend(options, { 27150 value : val, 27151 displayValue : val, 27152 values : items, 27153 state : this.getStateFromValue(this._model.value, items), 27154 screenReaderText : this._model._getScreenReaderText(index) 27155 }); 27156 return optionsCopy; 27157 }, 27158 27159 _initOrUpdateWidget : function (id, options, widgetname, $widget, initialOptions) { 27160 if (this.jqwidget[id]) { 27161 this.jqwidget[id].option(options); 27162 } else { 27163 var _options = $.extend({}, options, initialOptions); 27164 this.jqwidget[id] = this._newWidget(widgetname, _options, $widget); 27165 } 27166 this.$widget.find("[checked!=checked]").parents(".guideCheckBoxItem").removeClass('guideItemSelected'); 27167 this.$widget.find("[checked=checked]").parents(".guideCheckBoxItem").addClass('guideItemSelected'); 27168 }, 27169 27170 initializeJqWidget : function () { 27171 this.jqwidget = []; 27172 }, 27173 27174 createWidget : function (widgetname, options) { 27175 var self = this; 27176 this.initializeJqWidget(); 27177 if (this.$widget) { 27178 this.$widget.each(function (index, widget) { 27179 self._initOrUpdateWidget(self.getJQWidgetIdentifier(index), 27180 self._getOptions(options, index), 27181 widgetname, 27182 $(widget), 27183 self._getWidgetInitialOptions($(widget))); 27184 }); 27185 this.tempXfaFixes(); 27186 } 27187 }, 27188 27189 setActive : function (activeItemToken, focus, muteScripts) { 27190 guidelib.view.GuideFieldView._super.setActive.call(this, activeItemToken, focus, muteScripts); 27191 if (focus && !this._guideView.skipFieldFocus) { 27192 if (this.jqwidget && this.jqwidget[this.getJQWidgetIdentifier(0)]) { 27193 this.jqwidget[this.getJQWidgetIdentifier(0)].focus(); 27194 } 27195 this._guideView.currentFocusItemSom = this._model.somExpression; 27196 } 27197 return true; 27198 }, 27199 27200 updateWidgetOption : function (optionName, optionValue) { 27201 _.each(this.jqwidget, function (jqwidget, index) { 27202 if (optionName == "isValid") { 27203 jqwidget.option(optionName, optionValue); 27204 } 27205 }, this); 27206 }, 27207 27208 handleAccessibility : function () { 27209 GuideCheckBoxView._super.handleAccessibility.apply(this, arguments); 27210 this.$element.attr("role", "group"); 27211 if (this._model.jsonModel.assistPriority && this._model.jsonModel.custom && this._model.jsonModel.assistPriority === "custom"){ 27212 this.$element.attr("aria-label", this._model.jsonModel.custom[0]); 27213 } else { 27214 var $label = this.$element.find(".guideFieldLabel label"), 27215 label = $label.get(0); 27216 if (label && label.id) { 27217 this.$element.attr("aria-labelledby", label.id); 27218 } 27219 } 27220 } 27221 27222 }); 27223}($, guidelib, window._)); 27224 27225(function ($, guidelib, _) { 27226 var GuideRadioButtonView = guidelib.view.GuideRadioButtonView = guidelib.view.GuideCheckBoxView.extend({ 27227
27228 _defaultWidgetName : "XfaCheckBox", 27229 27230 _prevOnWidget : null, 27231 27232 _getWidgetType : function () { 27233 return 'radio'; 27234 }, 27235 27236 _getItemName : function () { 27237 return "RadioButtonItem"; 27238 }, 27239 27240 _getGroupItemIdentifier : function () { 27241 return '.guideRadioButtonGroupItems'; 27242 }, 27243 27244 getJQWidgetIdentifier : function (index) { 27245 return this._model.getItemIdentifier(index); 27246 }, 27247 27248 handleValueChanged : function (event) { 27249 var somExpression = event.prevText; 27250 if (this.jqwidget[somExpression]) { 27251 this.jqwidget[somExpression].option("value", event.newText); 27252 this.jqwidget[somExpression].option("displayValue", event.newText); 27253 if (event.newText === null) { 27254 this._prevOnWidget = null; 27255 } else { 27256 this._prevOnWidget = this.jqwidget[somExpression]; 27257 } 27258 } 27259 this.$widget.find("[checked!=checked]").parents(".guideRadioButtonItem").removeClass('guideItemSelected').attr("aria-checked", false); 27260 this.$widget.find("[checked=checked]").parents(".guideRadioButtonItem").addClass('guideItemSelected').attr("aria-checked", true); 27261 this._updateEmptyStatus(); 27262 }, 27263 27264 handleCommit : function () { 27265 var jqwidgettochange = _.find(this.jqwidget, function (jqwidget) { 27266 return jqwidget.option("state") === 0 && jqwidget !== this._prevOnWidget; 27267 }, this); 27268 this.commitValue(jqwidgettochange.option("value")); 27269 this._prevOnWidget = jqwidgettochange; 27270 }, 27271 27272 _initOrUpdateWidget : function (id, options, widgetname, widget) { 27273 GuideRadioButtonView._super._initOrUpdateWidget.apply(this, arguments); 27274 if (options.state === 0) { 27275 this._prevOnWidget = this.jqwidget[id]; 27276 } 27277 this.$widget.find("[checked!=checked]").parents(".guideRadioButtonItem").removeClass('guideItemSelected'); 27278 this.$widget.find("[checked=checked]").parents(".guideRadioButtonItem").addClass('guideItemSelected'); 27279 }, 27280 27281 initializeJqWidget : function () { 27282 this.jqwidget = {}; 27283 27284 27285 27286 this.$widget.find("[checked]").removeAttr("checked"); 27287 this.$widget.find("[checked=checked]").removeAttr("checked"); 27288 27289 }, 27290 27291 handleAccessibility : function () { 27292 GuideRadioButtonView._super.handleAccessibility.apply(this, arguments); 27293 this.$element.attr("role", "radiogroup"); 27294 } 27295 }); 27296}($, guidelib, _)); 27297(function ($, guidelib, _) { 27298 var GuideSwitchView = guidelib.view.GuideSwitchView = guidelib.view.GuideCheckBoxView.extend({ 27299 _defaultWidgetName : "guideSwitch", 27300 27301 createWidgetOptions : function () { 27302 var options = GuideSwitchView._super.createWidgetOptions.apply(this, arguments), 27303 items = this._model.jsonModel.options, checkedLabel, uncheckedLabel; 27304 27305 if (Array.isArray(items) && items.length > 0) { 27306 checkedLabel = items[0]; 27307 } else if (!_.isUndefined(items) && items.length > 0) { 27308 checkedLabel = items; 27309 } else { 27310 checkedLabel = " "; 27311 } 27312 if (Array.isArray(items) && items.length > 1) { 27313 uncheckedLabel = items[1]; 27314 } else { 27315 uncheckedLabel = " "; 27316 } 27317 return $.extend({}, options, { 27318 checkedLabel : checkedLabel.substring(checkedLabel.indexOf("=") + 1), 27319 uncheckedLabel : uncheckedLabel.substring(uncheckedLabel.indexOf("=") + 1) 27320 }); 27321 }, 27322 27323 handleValueChanged : function (event) { 27324 27325 var jqwidget = this.jqwidget[0], 27326 jqwidgetOptions = jqwidget.options; 27327 var setVal = this.getOnOffValueFromModelValue(event.prevText, jqwidget.option("values")); 27328 if (jqwidgetOptions.value !== setVal) { 27329 jqwidget.option("value", setVal); 27330 27331 var userControl = jqwidget.$userControl; 27332 var checked = jqwidgetOptions.value === jqwidgetOptions.values[0]; 27333 userControl.prop("checked", checked); 27334 userControl.parent().toggleClass('ui-state-active', checked); 27335 userControl.change(); 27336 } 27337 }, 27338 27339 handleCommit : function () { 27340 var jqwidget = this.jqwidget[0], 27341 items = jqwidget.option("values"), 27342 state = jqwidget.option("state"); 27343 this.commitValue(items[state]); 27344 } 27345 }); 27346}($, guidelib, _)); 27347 27348(function ($, guidelib) { 27349 var GuideNumericBoxView = guidelib.view.GuideNumericBoxView = guidelib.view.GuideFieldView.extend({
27350 _defaultWidgetName : "numericInput", 27351 createWidgetOptions : function () { 27352 var options = GuideNumericBoxView._super.createWidgetOptions.apply(this, arguments); 27353 return $.extend({}, options, { 27354 dataType : this._model.dataType, 27355 leadDigits : this._model.leadDigits, 27356 fracDigits : this._model.fracDigits, 27357 27358 zero : guidelib.i18n.numberSymbols.zero, 27359 decimal : guidelib.i18n.numberSymbols.decimal, 27360 commitEvent : this.getCommitEvent(), 27361 placeholder : this._model.placeholderText 27362 }); 27363 } 27364 }); 27365 27366}($, guidelib)); 27367(function ($, guidelib) { 27368 var GuidePasswordBoxView = guidelib.view.GuidePasswordBoxView = guidelib.view.GuideFieldView.extend({ 27369 _defaultWidgetName : "defaultWidget", 27370 27371 createWidgetOptions : function () { 27372 var options = GuidePasswordBoxView._super.createWidgetOptions.apply(this, arguments); 27373 27374 return $.extend({}, options, { 27375 placeholder : this._model.placeholderText 27376 }); 27377 } 27378 }); 27379}($, guidelib)); 27380(function ($, guidelib) { 27381 var GuideDatePickerView = guidelib.view.GuideDatePickerView = guidelib.view.GuideFieldView.extend({ 27382 _defaultWidgetName : "dateTimeEdit", 27383 27384 createWidgetOptions : function () { 27385 var options = GuideDatePickerView._super.createWidgetOptions.apply(this, arguments), 27386 useNativeWidget = (this._model.displayPictureClause === null && this._model.editPictureClause == null); 27387 27388 return $.extend({}, options, { 27389 days : guidelib.i18n.calendarSymbols.abbrdayNames, 27390 months : guidelib.i18n.calendarSymbols.monthNames, 27391 zero : guidelib.i18n.numberSymbols.zero, 27392 clearText : xfalib.locale.Strings.clearText, 27393 useNativeWidget : useNativeWidget, 27394 showCalendarIcon : true, 27395 editPattern : this._model.editPictureClause, 27396 placeholder : this._model.placeholderText, 27397 minValidDate : this._model.minimum, 27398 maxValidDate : this._model.maximum, 27399 exclMaxDate : this._model.exclusiveMaximum, 27400 exclMinDate : this._model.exclusiveMinimum, 27401 allowNonIsoValue : true 27402 }); 27403 }, 27404 27405 27406 tempXfaFixes : function () { 27407 GuideDatePickerView._super.tempXfaFixes.apply(this, arguments); 27408 27409 if (this.$widget) { 27410 this.$widget.children("not:input[type=date]").height("100%"); 27411 } 27412 }, 27413 27414 handleAccessibility : function () { 27415 GuideDatePickerView._super.handleAccessibility.apply(this, arguments); 27416 this.$widget.children("div[tabIndex]").removeAttr("tabIndex"); 27417 } 27418 }); 27419}($, guidelib)); 27420 27421 (function ($, guidelib) { 27422 var GuideFootnotePlaceHolderView = guidelib.view.GuideFootnotePlaceHolderView = guidelib.view.GuideTextDrawView.extend({ 27423 _defaultWidgetName : "abstractWidget", 27424 27425 initialize : function () { 27426 GuideFootnotePlaceHolderView._super.initialize.call(this); 27427 var that = this; 27428 $(function () { 27429 that._renderFootnotes(); 27430 }) 27431 guideBridge.on("elementNavigationChanged", function(event, payload) { 27432 that._renderFootnotes(); 27433 }) 27434 $(window.document).on('click.guidetab.data-api', '[data-guide-toggle$="accordion-tab"]', 27435 function(e) { 27436 that._renderFootnotes(); 27437 }) 27438 27439 }, 27440 27441 _renderFootnotes: function () { 27442 27443 27444 if(!this.$element.is(":visible")) { 27445 this._model.value = ""; 27446 return; 27447 } 27448 27449 var footnoteMap = this._model.footnoteMap; 27450 var footnoteArr = Object.entries(footnoteMap); 27451 if (footnoteArr.length > 0) { 27452 var value = '<div>'; 27453 var nodes = new Map(); 27454 for (footnoteID in footnoteMap) { 27455 var selector = "a[data-footnote-id=\"" + footnoteID + "\"]"; 27456 if ($(selector).is(":visible")) { 27457 var mapKey = $(selector)[0].innerHTML; 27458 if (!nodes.has(mapKey)) { 27459 nodes.set(mapKey, footnoteMap[footnoteID]); 27460 } 27461 } 27462 }; 27463 var tupleArray = [];
27464 nodes.forEach(function(value, key) { 27465 tupleArray.push([key, value]); 27466 }); 27467 tupleArray.sort(function(a, b) { 27468 return a[0] - b[0]; 27469 }); 27470 tupleArray.forEach(function(el) { 27471 value += el[1]; 27472 }); 27473 value += '</div>'; 27474 this._model.value = value; 27475 } 27476 }, 27477 27478 setActive: function () { 27479 this._renderFootnotes(); 27480 } 27481 }); 27482}($, guidelib)); 27483 27484 27485 27486 27487(function ($, guidelib) { 27488 var GuideScribbleView = guidelib.view.GuideScribbleView = guidelib.view.GuideFieldView.extend({ 27489 _defaultWidgetName : "ScribbleImageField", 27490 27491 createWidgetOptions : function () { 27492 var options = GuideScribbleView._super.createWidgetOptions.apply(this, arguments); 27493 return $.extend({}, options, { 27494 commitProperty : "src", 27495 geoLocMandatoryOnIpad : "false", 27496 aspectRatio : this._valueOfAspectRatioToBeUsed() 27497 }); 27498 }, 27499 27500 _valueOfAspectRatioToBeUsed : function () { 27501 var aspectRatio ; 27502 if (this._model.jsonModel.aspectRatio) { 27503 aspectRatio = this._model.jsonModel.aspectRatio; 27504 } else { 27505 27506 if (!this._presenceOfHeight()) { 27507 aspectRatio = "6.8888"; 27508 } 27509 } 27510 return aspectRatio ; 27511 }, 27512 27513 _presenceOfHeight : function () { 27514 return (this._model.jsonModel.hasOwnProperty('height') && this._model.jsonModel.height.toString().length > 0); 27515 }, 27516 27517 postInitialize : function () { 27518 GuideScribbleView._super.postInitialize.call(this); 27519 var that = this; 27520 27521 if (!this._presenceOfHeight()) { 27522 setTimeout(function () {guidelib.util.GuideUtil._computeHeightAndWidthForScribble(that.$widget);}, guidelib.util.GuideUtil.SCRIBBLE_RESIZE_TIME_INTERVAL); 27523 $(window).off("resize", guidelib.util.GuideUtil._resizeScribbleField); 27524 $(window).on("resize", guidelib.util.GuideUtil._resizeScribbleField); 27525 } 27526 }, 27527 27528 handleAccessibility : function () { 27529 27530 if (this._model.mandatory) { 27531 this.$widget.find("img").attr("aria-required", true); 27532 } 27533 if (this._model._getScreenReaderText() === this._model._getToolTip()) { 27534 this.$element.find("img").removeAttr("aria-label"); 27535 this.$element.find("img").attr("aria-labelledby", this._model.id + "_guideFieldShortDescription"); 27536 } else if (this._model._getAssistPriority() === "none") { 27537 this.$element.find("img").attr("aria-label", " "); 27538 } 27539 }, 27540 27541 27542 tempXfaFixes : function () { 27543 if (this.$widget) { 27544 this.$widget.css("position", "relative").find("img").css("position", "relative"); 27545 } 27546 this.handleAccessibility(); 27547 } 27548 }); 27549}($, guidelib)); 27550(function ($, guidelib) { 27551 var GuideTextBoxView = guidelib.view.GuideTextBoxView = guidelib.view.GuideFieldView.extend({ 27552 _defaultWidgetName : "textField", 27553 27554 initialize : function () { 27555 GuideTextBoxView._super.initialize.apply(this, arguments); 27556 if (this._model.allowRichText) { 27557 this._defaultWidgetName = "richTextField"; 27558 } 27559 }, 27560 27561 createWidgetOptions : function () { 27562 var options = GuideTextBoxView._super.createWidgetOptions.apply(this, arguments), 27563 html5Type = this._model.getAttribute("html5Type"); 27564 return $.extend({}, options, { 27565 multiLine : this._model.multiLine, 27566 minLength : this._model.allowRichText ? null : this._model.minLength, 27567 length : this._model.allowRichText ? null : this._model.length, 27568 maxChars : this._model.allowRichText ? null : this._model.maxChars, 27569 required : this._model.mandatory, 27570 27571 html5Type : html5Type ? html5Type : "", 27572 totalLengthMessage : this.guideUtil.getLocalizedMessage("", guidelib.i18n.strings.totalLengthMessage, [this._model.length]), 27573 minimumLengthMessage : this.guideUtil.getLocalizedMessage("", guidelib.i18n.strings.minimumLengthMessage, [this._model.minLength]), 27574 allowRichText : this._model.allowRichText, 27575 placeholder : this._model.placeholderText 27576 }); 27577 }, 27578 27579 27580 27581 27582 tempXfaFixes : function () { 27583 if (this._model.jsonModel.multiLine) { 27584 this.$element.find("textarea").css("position", "relative"); 27585 this.handleAccessibility(); 27586 } else { 27587 GuideTextBoxView._super.tempXfaFixes.apply(this); 27588 } 27589 }, 27590 27591 handleAccessibility : function () { 27592 GuideTextBoxView._super.handleAccessibility.apply(this); 27593 if (this._model.jsonModel.multiLine) { 27594 this.$element.find("textarea").attr("aria-multiLine", true); 27595 } 27596 } 27597 }); 27598}($, guidelib)); 27599(function ($, guidelib) { 27600 var xfaUtil = xfalib.ut.XfaUtil.prototype, 27601 GuideImageView = guidelib.view.GuideImageView = guidelib.view.GuideBaseView.extend({ 27602 initialize : function () { 27603 GuideImageView._super.initialize.call(this); 27604 if (this._model.value != null) { 27605 var srcString = "data:image/*;base64," + this._model.value; 27606 this.$element.children('img').attr('src', srcString); 27607 } 27608 }, 27609 27610 postInitialize : function () { 27611 this._syncGuideNodeToHtml(); 27612 }, 27613
27614 setActive : function (activeItemToken, focus, muteScripts) { 27615 guidelib.view.GuideFieldView._super.setActive.call(this, activeItemToken, focus, muteScripts); 27616 if (focus && !this._guideView.skipFieldFocus) { 27617 if (this.$element) { 27618 this.$element.focus(); 27619 } 27620 this._guideView.currentFocusItemSom = this._model.somExpression; 27621 } 27622 return true; 27623 } 27624 27625 }); 27626}($, guidelib)); 27627 27628(function ($, guidelib) { 27629 var GuideChartView = guidelib.view.GuideChartView = guidelib.view.GuideBaseView.extend({ 27630 27631 initialize : function () { 27632 GuideChartView._super.initialize.call(this); 27633 var chartView = this; 27634 $(window).on("resize orientationchange", function () { 27635 chartView.renderChart.apply(chartView); 27636 }); 27637 }, 27638 27639 postInitialize : function () { 27640 this._syncGuideNodeToHtml(true); 27641 }, 27642 27643 handleModelChanged : function (event) { 27644 switch (event._property) { 27645 case "data": 27646 case "chartType": 27647 this.renderChart(); 27648 break; 27649 27650 case "visible": 27651 this.handleVisibleChanged(event); 27652 break; 27653 } 27654 }, 27655 27656 handleVisibleChanged : function (event) { 27657 27658 27659 if (!event.newText) { 27660 27661 this.$element.addClass("hidden"); 27662 if (this.parentView.currentActiveItemView == this) { 27663 this.parentView.setActive("nextItem"); 27664 } 27665 } else { 27666 27667 this.$element.removeClass("hidden"); 27668 } 27669 }, 27670 27671 _generateChart : function () { 27672 var $chartElement = this.$element, chartModel = this._model, isChartVisible, chart; 27673 27674 var plottedChartSelector = chartModel.jsonModel.isInteractiveCommunicationChartResource ? '.highcharts-container' 27675 : '.dv-chart-container'; 27676 var $plottedChart = $chartElement 27677 .find(plottedChartSelector); 27678 isChartVisible = ($chartElement.parent().width() > 0) 27679 && ($chartElement.width() > 0) ? true : false; 27680 27681 27682 27683 27684 if ((isChartVisible || $plottedChart.length == 0) 27685 && chartModel.repeatableItem) { 27686 try { 27687 27688 $plottedChart.remove(); 27689 if (chartModel.jsonModel.isInteractiveCommunicationChartResource) { 27690 chart = new fd.chart.ChartInstanceGenerator() 27691 .generate(chartModel.jsonModel, 27692 chartModel.jsonModel.data); 27693 Highcharts.chart($chartElement.attr('id'), 27694 chart); 27695 } else { 27696 chart = guidelib.chartUtils.constructChart( 27697 chartModel, $chartElement); 27698 if (chart) { 27699 chart.render(); 27700 } 27701 } 27702 } catch (exception) { 27703 this.logger().error("AF Chart view", 27704 "Error while rendering chart " + exception); 27705 } 27706 } 27707 }, 27708 27709 renderChart : function () { 27710 if (this._model.data) { 27711 var chartView = this; 27712 window.requestAnimationFrame(function () { 27713 chartView._generateChart.apply(chartView); 27714 }); 27715 } 27716 }, 27717 27718 _syncGuideNodeToHtml : function (deepSync) { 27719 this.renderChart(); 27720 guidelib.view.GuideChartView._super._syncGuideNodeToHtml.call(this, deepSync); 27721 }, 27722 27723 setActive : function (activeItemToken, focus, muteScripts) { 27724 guidelib.view.GuideChartView._super.setActive.call(this, activeItemToken, focus, muteScripts); 27725 if (focus && !this._guideView.skipFieldFocus) { 27726 if (this.$element) { 27727 this.$element.focus(); 27728 } 27729 this._guideView.currentFocusItemSom = this._model.somExpression; 27730 } 27731 return true; 27732 } 27733 }); 27734}($, guidelib)); 27735(function ($, guidelib) { 27736 var GuideAdModuleView = guidelib.view.GuideAdModuleView = guidelib.view.GuideBaseView.extend({ 27737 27738 initialize : function () { 27739 GuideAdModuleView._super.initialize.call(this); 27740 if (this._model) { 27741 27742 this._model.on(guidelib.event.GuideModelEvent.VALUE_CHANGED, this.handleValueChanged, this); 27743 } 27744 this.oldValue = null; 27745 }, 27746 27747 postInitialize : function () { 27748 this._syncGuideNodeToHtml(true); 27749 }, 27750 27751 handleValueChanged : function (event) { 27752 switch (event._property) { 27753 case "value": 27754 this.$element.html(event.newText); 27755 break; 27756 } 27757 }, 27758 27759 handleVisibleChanged : function (event) { 27760 27761 27762 if (!event.newText) { 27763 27764 this.$element.addClass("hidden"); 27765 if (this.parentView.currentActiveItemView == this) {
27766 this.parentView.setActive("nextItem"); 27767 } 27768 } else { 27769 27770 this.$element.removeClass("hidden"); 27771 } 27772 }, 27773 27774 handleModelChanged : function (event) { 27775 GuideAdModuleView._super.handleModelChanged.apply(this, arguments); 27776 }, 27777 _syncGuideNodeToHtml : function (deepSync) { 27778 if (this._model.value) { 27779 this.$element 27780 .html(this._model.value) 27781 .find('img') 27782 .attr('src', function (idx, val) { 27783 return Granite.HTTP.externalize(val); 27784 }); 27785 } 27786 27787 if (this._model.layoutConfigs) { 27788 var options = { 27789 $element : this.$element, 27790 layoutConfigs : this._model.layoutConfigs 27791 }; 27792 guidelib.util.AdUtil.applyLayouts(options); 27793 } 27794 if (this._model) { 27795 this.handleModelChanged(guidelib.event.GuideModelEvent.createEvent( 27796 guidelib.event.GuideModelEvent.MODEL_CHANGED, 27797 this, 27798 "visible", 27799 this._model.visible, 27800 this._model.visible 27801 )); 27802 } 27803 }, 27804 27805 setActive : function (activeItemToken, focus, muteScripts) { 27806 guidelib.view.GuideFieldView._super.setActive.call(this, activeItemToken, focus, muteScripts); 27807 if (focus) { 27808 if (this.$element) { 27809 this.$element.focus(); 27810 } 27811 this._guideView.currentFocusItemSom = this._model.somExpression; 27812 } 27813 return true; 27814 } 27815 }); 27816}($, guidelib)); 27817(function ($, _, guidelib) { 27818 var GuideItemsView = guidelib.view.GuideItemsView = guidelib.view.GuideBaseView.extend({ 27819 initialize : function () { 27820 GuideItemsView._super.initialize.call(this); 27821 this.childViews = []; 27822 }, 27823 27824 27825 _unloadView : function () { 27826 if (this._model._selfOrAncestorIsLazyReference) { 27827 var fragmentPlaceHolderSelector = "#" + this.id, 27828 ind; 27829 27830 $(fragmentPlaceHolderSelector).children().remove(); 27831 27832 var queueForLazyItems = this._guideView._queueViewForLazyItems; 27833 27834 if ((ind = _.indexOf(queueForLazyItems, this)) !== -1) { 27835 queueForLazyItems[ind] = undefined; 27836 } 27837 _.each(this.childViews, function (view) { 27838 27839 view._unloadView(); 27840 }, this); 27841 27842 this.childViews = []; 27843 27844 this._currentActiveItemView = null; 27845 27846 this._guideView._domTemplateCacheStore.removeDomElement("#" + this._model.templateId); 27847 27848 this._guideView._reInitializeGuideContainerDom(); 27849 } 27850 }, 27851 postInitialize : function () { 27852 this.childViews = _.reduce(this._model.children, function (childViews, childModel) { 27853 var childView = this._createNonRepeatChildView(childModel); 27854 if (childView) { 27855 childViews.push(childView); 27856 } 27857 return childViews; 27858 }, [], this); 27859 27860 this._syncGuideNodeToHtml(false); 27861 }, 27862 27863 _createNonRepeatChildView : function (childModel) { 27864 27865 27866 27867 27868 var childElSelector = this.guideUtil.modelElSelector(childModel.id); 27869 var $childEl = this.$element.find(childElSelector); 27870 if (!$childEl.length) { 27871 $childEl = this.$element.find(this.guideUtil.modelElSelector(childModel.templateId)); 27872 this._updateIds($childEl, childModel.templateId, childModel.id); 27873 } 27874 if ($childEl.length) { 27875 var childView = guidelib.view.GuideViewRegistry.prototype.createView($childEl, this); 27876 childView.postInitialize(); 27877 return childView; 27878 } 27879 return null; 27880 }, 27881 27882 _syncGuideNodeToHtml : function (deepSync) { 27883 if (deepSync) { 27884 _.each(this.childViews, function (childView) { 27885 childView._syncGuideNodeToHtml(true); 27886 }, this); 27887 } 27888 GuideItemsView._super._syncGuideNodeToHtml.call(this, deepSync); 27889 }, 27890 27891 _findChildView : function (childModel) { 27892 var view = _.find(this.childViews, function (childView) { 27893 return childView._model == childModel; 27894 }, this); 27895 return view; 27896 } 27897 }); 27898 27899 GuideItemsView.defineProps({ 27900 itemsView : { 27901 get : function () { 27902 var views = _.filter(this.childViews, function (childView) { 27903 return childView.isItem; 27904 }, this); 27905 return views; 27906 } 27907 } 27908 }); 27909}($, _, guidelib)); 27910 27911(function ($, guidelib) { 27912 var GuideAdModuleGroupView = guidelib.view.GuideAdModuleGroupView = guidelib.view.GuideItemsView.extend({ 27913 initialize : function () { 27914 GuideAdModuleGroupView._super.initialize.call(this); 27915 if (this._model) { 27916 27917 this._model.on(guidelib.event.GuideModelEvent.VALUE_CHANGED, this.handleValueChanged, this); 27918 } 27919 }, 27920 27921 postInitialize : function () { 27922 if (this._model.value || this._model.value === "") { 27923 this._syncGuideNodeToHtml(true); 27924 } else { 27925 GuideAdModuleGroupView._super.postInitialize.call(this); 27926 } 27927 }, 27928 27929 handleValueChanged : function (event) { 27930 switch (event._property) { 27931 case "value": 27932 this.$element.html(event.newText); 27933 break; 27934 } 27935 }, 27936 27937 _syncGuideNodeToHtml : function (deepSync) { 27938 if (this._model.value || this._model.value === "") { 27939 this.$element 27940 .html(this._model.value) 27941 .find('img') 27942 .attr('src', function (idx, val) { 27943 return Granite.HTTP.externalize(val); 27944 }); 27945 } else { 27946 GuideAdModuleGroupView._super._syncGuideNodeToHtml.call(this, deepSync); 27947 } 27948 }, 27949
27950 setActive : function (activeItemToken, focus, muteScripts) { 27951 guidelib.view.GuideAdModuleGroupView._super.setActive.call(this, activeItemToken, focus, muteScripts); 27952 if (focus) { 27953 if (this.$element) { 27954 this.$element.focus(); 27955 } 27956 this._guideView.currentFocusItemSom = this._model.somExpression; 27957 } 27958 return true; 27959 } 27960 27961 }); 27962}($, guidelib)); 27963(function ($, _, guidelib) { 27964 27965 var GuidePanelView = guidelib.view.GuidePanelView = guidelib.view.GuideItemsView.extend({ 27966 initialize : function () { 27967 GuidePanelView._super.initialize.call(this); 27968 this._currentActiveItemView = null; 27969 this._$itemsContainer = null; 27970 this._$itemsNavContainer = null; 27971 this._$summary = null; 27972 this._$title = null; 27973 27974 this._childInitializeWaiting = true; 27975 27976 this._model.on(guidelib.event.GuideModelEvent.CHILD_CHANGED, this.handleChildChanged, this); 27977 this._model.on(guidelib.event.GuideModelEvent.MULTIPLE_CHILD_ADDED, this.multipleChildAdded, this); 27978 this._summarySelector = this.guideUtil.summarySelector(this._model.id); 27979 this._titleSelector = this.guideUtil.propSelector("title", this._model.id); 27980 }, 27981 27982 addRemoveTemplateMarker : function () { 27983 27984 _.each(this._model.children, function (childModel) { 27985 if (childModel instanceof guidelib.model.GuideInstanceManager) { 27986 27987 var imId = childModel.id, 27988 instanceId = (childModel._instances[0] || {}).id || childModel.instanceTemplateId, 27989 gTemplateMarker = '<div id="' + imId + '" style="display: none" data-guide-template-marker="true"></div>', 27990 instanceItem = this.guideUtil.itemSelector(instanceId, childModel), 27991 navItem = this.guideUtil.itemNavSelector(instanceId); 27992 this.$itemsContainer.find(instanceItem).before(gTemplateMarker); 27993 this.$itemsNavContainer.find(navItem).before(gTemplateMarker); 27994 if (childModel._instances && childModel._instances.length === 0) { 27995 $(navItem, this.$element).remove(); 27996 $(instanceItem, this.$element).remove(); 27997 } 27998 } 27999 }, this); 28000 28001 }, 28002 28003 postInitialize : function () { 28004 28005 28006 28007 28008 this.handleSummaryChanged(); 28009 this.handleTitleChanged(); 28010 if (this._model.repeatable) { 28011 this._toggleAddRemoveButtons(); 28012 } 28013 if (!this.parentView._model.enableLayoutOptimization) { 28014 28015 this._postInitializeChildren(); 28016 } else { 28017 28018 28019 28020 28021 28022 28023 this.handleVisibleChanged(guidelib.event.GuideModelEvent.createEvent( 28024 guidelib.event.GuideModelEvent.MODEL_CHANGED, 28025 this, 28026 "visible", 28027 this._model.visible, 28028 this._model.visible 28029 )); 28030 } 28031 28032 28033 28034 28035 28036 this.addRemoveTemplateMarker(); 28037 }, 28038 28039 _postInitializeChildren : function () { 28040 this._childInitializeWaiting = false; 28041 this._syncGuideNodeToHtml(true); 28042 this.handleAccessibility(); 28043 28044 28045 28046 if (this.parentView.$itemsNavContainer && this.parentView.$itemsNavContainer.filter(":not(.tab-navigators-mobile)").length === 0) { 28047 this.setActive("firstItem", false, true); 28048 } 28049 }, 28050 28051 _syncGuideNodeToHtml : function (deepSync, currentAddedChildIndex) { 28052 if (this._childInitializeWaiting) { 28053 return; 28054 } 28055 28056 28057 28058 28059 28060 28061 28062 28063 var that = this; 28064 var htmlTemplateCache = this._guideView._domTemplateCacheStore; 28065 var oldItems = {}; 28066 var oldNonItems = {}; 28067 var newChildren = {}; 28068 28069 28070 _.each(this.childViews, function (childView) { 28071 if (childView.isItem) { 28072 oldItems[childView.id] = childView; 28073 } else { 28074 oldNonItems[childView.id] = childView; 28075 } 28076 }, this); 28077 28078 28079 28080 28081 28082 28083 28084 28085 _.each(this._model.items, function (childModel) { 28086 var cTemplateId = childModel.templateId; 28087 var childId = childModel.id, 28088 $childItem = null, 28089 $childItemNav = null; 28090 28091 28092 $childItem = this._find(this.guideUtil.itemSelector(childId, childModel)); 28093 $childItemNav = this._find(this.guideUtil.itemNavSelector(childId)); 28094 28095 28096 28097 if (!$childItem.length && !newChildren[cTemplateId] && currentAddedChildIndex !== 0) { 28098 28099 28100 $childItem = this.$itemsContainer.find(this.guideUtil.itemSelector(cTemplateId, childModel)); 28101 $childItemNav = this.$itemsNavContainer.find(this.guideUtil.itemNavSelector(cTemplateId)); 28102 } 28103 if (!$childItem.length) { 28104 28105 $childItem = htmlTemplateCache.cloneDomElement(this.guideUtil.itemSelector(cTemplateId, childModel)); 28106 $childItemNav = htmlTemplateCache.cloneDomElement(this.guideUtil.itemNavSelector(cTemplateId)); 28107 if (!$childItem.length) { 28108 this.logger().error("AF", "Html template could not be found. cTemplateId:" + cTemplateId + ", som:" + childModel.somExpression); 28109 return; 28110 } 28111 } 28112 this._updateIds($childItem, cTemplateId, childId); 28113 this._updateIds($childItemNav, cTemplateId, childId); 28114 28115 28116 $childItem.attr("data-guide-parent-id", this._model.id); 28117 $childItemNav.attr("data-guide-parent-id", this._model.id); 28118 var view = null; 28119 if (oldItems.hasOwnProperty(childId)) { 28120 view = oldItems[childId]; 28121 if (view instanceof guidelib.view.GuidePanel
28121View && view._model.instanceManager.repeatable && !_.isUndefined(that._model.bindNode)) { 28122 28123 this._fixChildDom(view); 28124 } 28125 if (deepSync) { 28126 view._syncGuideNodeToHtml(deepSync); 28127 } 28128 } else { 28129 var $childEl = this._find("#" + childId); 28130 if ($childEl.length) { 28131 view = this._createChild($childEl); 28132 } else { 28133 $childEl = $childItem.find("#" + childId).addBack("#" + childId); 28134 if ($childEl.length) { 28135 view = this._createChild($childEl, $childItem, $childItemNav); 28136 } else { 28137 this.logger().debug("AF", "Skip creating view. could not find el for id:" + childId); 28138 } 28139 } 28140 if (this._model.repeatable) { 28141 guidelib.util.GuideUtil._initializeShortDescription($childEl); 28142 } 28143 } 28144 if (view) { 28145 newChildren[childId] = view; 28146 } 28147 }, this 28148 ); 28149 28150 28151 this.$itemsContainer.find('[data-guide-parent-id="' + that._model.id + '"]').each(function () { 28152 var $this = $(this); 28153 var thisId = $this.attr("id"); 28154 28155 if (thisId.indexOf(that.guideUtil.GUIDE_ITEM_SUFFIX) === -1) { 28156 thisId = $this.attr(that.guideUtil.DATA_GUIDE_ITEM); 28157 } 28158 var childId = thisId.substring(0, thisId.length - that.guideUtil.GUIDE_ITEM_SUFFIX.length); 28159 if (!newChildren.hasOwnProperty(childId) && !window.guideBridge._resolveId(childId)) { 28160 that.logger().log("guideView", 5, "removing element as no corresponding form dom node found. id:" + thisId + ", parent id:" + that.id); 28161 $this.remove(); 28162 that._find(that.guideUtil.itemNavSelector(childId)).remove(); 28163 } 28164 }); 28165 28166 this.childViews = []; 28167 _.each(this._model.children, function (childModel) { 28168 var childIsItem = childModel._isItem; 28169 var childId = childModel.id; 28170 if (childIsItem && newChildren.hasOwnProperty(childId)) { 28171 28172 this.childViews.push(newChildren[childId]); 28173 } else if (!childIsItem) { 28174 var nonItemChildView = null; 28175 if (oldNonItems.hasOwnProperty(childId)) { 28176 nonItemChildView = oldNonItems[childId]; 28177 } else { 28178 nonItemChildView = this._createNonRepeatChildView(childModel); 28179 } 28180 if (nonItemChildView) { 28181 if (deepSync) { 28182 nonItemChildView._syncGuideNodeToHtml(deepSync); 28183 } 28184 this.childViews.push(nonItemChildView); 28185 } 28186 } 28187 }, this); 28188 28189 guidelib.view.GuideBaseView.prototype._syncGuideNodeToHtml.apply(this, arguments); 28190 }, 28191 28192 _createChild : function ($childEl, $item, $itemNav) { 28193 var guideViewBind = $childEl.data("guideViewBind"); 28194 var model = window.guideBridge._resolveId(guideViewBind); 28195 if (model && model.getAttribute('skipViewCreation') !== 'true') { 28196 var view = guidelib.view.GuideViewRegistry.prototype.createView($childEl, this); 28197 this._fixChildDom(view, $item, $itemNav); 28198 view.postInitialize(); 28199 return view; 28200 } 28201 }, 28202 28203 _fixChildDom : function (view, $item, $itemNav) { 28204 28205 28206 28207 var newChild = view._model; 28208 if (!(newChild instanceof guidelib.model.GuidePanel) || !newChild.repeatable) { 28209 return; 28210 } 28211 var $childItem = $item || view.$item; 28212 var $childItemNav = $itemNav || view.$itemNav; 28213 var children = this._model.children; 28214 var insertAfterId = (newChild.instanceIndex > 0) ? children[children.indexOf(newChild) - 1].id : null; 28215 28216 var insertAfterItemSelector = insertAfterId ? this.guideUtil.itemSelector(insertAfterId, newChild) : "#" + newChild.instanceManager.id; 28217 var insertAfterNavSelector = insertAfterId ? this.guideUtil.itemNavSelector(insertAfterId) : "#" + newChild.instanceManager.id; 28218 var that = this; 28219 28220 28221 this.$itemsContainer.each(function (index) { 28222 var insertEl = $childItem.get(index) || $childItem.get(0), 28223 $insertAfterItem = $(this).find(insertAfterItemSelector); 28224 28225 if ($insertAfterItem.length == 0) { 28226 insertAfterItemSelector = "[data-guide-template-marker=" + newChild.instanceManager.id + "]"; 28227 $insertAfterItem = $(this).find(insertAfterItemSelector); 28228 28229 if (newChild.instanceIndex === 0 && $insertAfterItem.length > 0) { 28230 $insertAfterItem.removeAttr("data-guide-template-marker"); 28231 $(insertEl).attr("data-guide-template-marker", newChild.instanceManager.id); 28232 } 28233 } 28234 28235 if ($insertAfterItem.get(0) !== insertEl) { 28236 28237 $insertAfterItem.after($(insertEl)); 28238 } 28239 }); 28240 28241 28242 28243 this.$itemsNavContainer.each(function (index) { 28244 var insertNavEl = $childItemNav.get(index) || $childItemNav.get(0); 28245 $(this).find(insertAfterNavSelector).after($(insertNavEl)); 28246 }); 28247 }, 28248 28249 multipleChildAdded : function (event) { 28250 if (event.jsonModel.newText && event.jsonModel.newText.length > 0) { 28251 this._syncGuideNodeToHtml(true); 28252 this.childViews.forEach(function (childView) { 28253 if (childView._model.repeatable) { 28254 childView._toggleAddRemoveButtons(); 28255 } 28256 }); 28257 } 28258 }, 28259
28260 handleChildChanged : function (event) { 28261 var newlyCreatedInstance = null, 28262 currentAddedInstanceIndex = -1; 28263 if (event._property == "childRemoved") { 28264 var $elementRemoved = this.$element.find("#" + event.prevText.id), 28265 index = $elementRemoved.index(); 28266 } 28267 if (event._property == "childAdded") { 28268 newlyCreatedInstance = event.newText; 28269 currentAddedInstanceIndex = newlyCreatedInstance.instanceIndex; 28270 } 28271 28272 this._syncGuideNodeToHtml(true, currentAddedInstanceIndex); 28273 this.childViews.forEach(function (childView) { 28274 if (childView._model.repeatable) { 28275 childView._toggleAddRemoveButtons(); 28276 } 28277 }); 28278 if (event._property == "childRemoved") { 28279 28280 28281 this.$element.trigger("panelRemoved.af", [$elementRemoved, index]); 28282 if (this.currentActiveItemView && event.prevText == this.currentActiveItemView._model) { 28283 28284 this._currentActiveItemView = null; 28285 this.setActive("nextItem"); 28286 } 28287 } 28288 if (newlyCreatedInstance != null) { 28289 28290 28291 this.$element.trigger("panelAdded.af", [this.$element.find("#" + newlyCreatedInstance.id)]); 28292 } 28293 }, 28294 28295 handleSummaryChanged : function () { 28296 if (this.$summary.length > 0) { 28297 if (this._model.summary) { 28298 this.$summary.text(this._model.summary); 28299 } else { 28300 var title = this._model.title; 28301 if (this._model.instanceIndex && this._model.repeatable) { 28302 title += " " + this._model.instanceIndex; 28303 } 28304 this.$summary.text(title); 28305 } 28306 } 28307 }, 28308 28309 handleTitleChanged : function () { 28310 if (this.$title.length > 0) { 28311 this.$title.text(this._model.title); 28312 } 28313 28314 var isPanelActive = $("#" + this.id + "_guide-item").hasClass("active"); 28315 if (isPanelActive) { 28316 $("[data-target-guide-content]").text(this._model.title); 28317 } 28318 }, 28319 28320 handleModelChanged : function (event) { 28321 switch (event._property) { 28322 case "summary": 28323 this.handleSummaryChanged(); 28324 break; 28325 case "title": 28326 this.handleTitleChanged(); 28327 break; 28328 default: 28329 GuidePanelView._super.handleModelChanged.apply(this, arguments); 28330 } 28331 }, 28332 28333 _createReferredView : function () { 28334 28335 this._postInitializeChildren(); 28336 }, 28337 28338 _loadLazyFragment : function () { 28339 28340 28341 28342 28343 28344 28345 var that = this; 28346 this._model._guide().internal.liveDataUtils.updateLiveData(); 28347 28348 this._guideView._clearInactiveLazyViews(this); 28349 28350 this._viewCreationInProgress = true; 28351 28352 this._model._loadLazyFragment({ 28353 "preFetch" : function () { 28354 $("#loadingPage").addClass("guideLoading"); 28355 }, 28356 "postFetch" : function () { 28357 $("#loadingPage").removeClass("guideLoading"); 28358 }, 28359 "success" : function () { 28360 28361 that._createReferredView(); 28362 28363 28364 that._viewCreationInProgress = undefined; 28365 that._itemsLoaded = true; 28366 } 28367 }); 28368 28369 28370 }, 28371 28372 28373 setActive : function (activeItemToken, focus, muteScripts) { 28374 28375 28376 28377 if (this._model._lazyReference && this._model.getAttribute('autoLoad') !== false) { 28378 28379 28380 28381 28382 28383 if (_.isUndefined(this._viewCreationInProgress) && _.isUndefined(this._itemsLoaded) 28384 && this._guideView._currentActiveItemView !== this) { 28385 this._loadLazyFragment(); 28386 } 28387 } 28388 28389 var currentActiveItemQName = this.getOrElse(this.currentActiveItemView, "qualifiedName", null); 28390 28391 activeItemToken = activeItemToken || currentActiveItemQName || "firstItem"; 28392 if (activeItemToken != currentActiveItemQName) { 28393 var newActiveItemModel = this._model.navigationContext.getItemForNav(activeItemToken); 28394 if (!newActiveItemModel) { 28395 this.logger().log("AF", "activeItemToken not found:" + activeItemToken + ",currentActiveItem:" + 28396 currentActiveItemQName + ":" + this._model.somExpression); 28397 return false;
28398 } 28399 var newActiveItemView = this.getQualifiedNamedView(newActiveItemModel._escapeQualifiedName()); 28400 if (!muteScripts && this._model.completionExpReq && this.currentActiveItemView && this.currentActiveItemView.focusable() && (this.childViews.indexOf(newActiveItemView) > this.childViews.indexOf(this.currentActiveItemView))) { 28401 var completed = true; 28402 if (this._model.getAttribute("validateOnStepCompletion")) { 28403 completed = window.guideBridge.validate([], this._model.panel.navigationContext.currentItem.somExpression); 28404 } 28405 28406 completed = completed && this._model.executeExpression("completionExp"); 28407 if (!completed) { 28408 return false; 28409 } else if (this.currentActiveItemView) { 28410 this.currentActiveItemView.$item.addClass("completed"); 28411 this.currentActiveItemView.$itemNav.addClass("completed"); 28412 } 28413 } 28414 this.currentActiveItemView = newActiveItemView; 28415 28416 28417 28418 28419 28420 } 28421 if (this.currentActiveItemView) {
28422 this.currentActiveItemView.setActive(null, focus, muteScripts); 28423 } 28424 return true; 28425 }, 28426 28427 _clearInactiveLazyViews : function (that) { 28428 _.each(this.childViews, function (item) { 28429 if (item && item._model.className === "guidePanel" && item._ancestorHasNavigableLayout) { 28430 if (item._model._itemsLoaded && !that._isSelfOrAncestor(item) && !item._hasEffectiveActiveClass() 28431 && item._model._lazyReference) { 28432 item._model._unloadLazyReferenceModel(); 28433 item._unloadView(); 28434 28435 item._itemsLoaded = undefined; 28436 28437 item._model._itemsLoaded = undefined; 28438 } else { 28439 item._clearInactiveLazyViews(that); 28440 } 28441 } 28442 }, this); 28443 }, 28444 28445 _isSelfOrAncestor : function (panelView) { 28446 28447 var selfOrParentView = this; 28448 while (!_.isUndefined(selfOrParentView) && selfOrParentView._model.className !== "rootPanelNode") { 28449 if (panelView === selfOrParentView) { 28450 return true; 28451 } 28452 selfOrParentView = selfOrParentView.parentView; 28453 } 28454 return false; 28455 }, 28456 28457 _hasEffectiveActiveClass : function () { 28458 var hierarchy = this; 28459 while (!_.isUndefined(hierarchy) && this._model.className !== "rootPanelNode") { 28460 if (hierarchy.$item.hasClass("active")) { 28461 hierarchy = hierarchy.parentView; 28462 } else { 28463 return false; 28464 } 28465 } 28466 return true; 28467 }, 28468 28469 handleAccessibility : function () { 28470 var role, screenReaderText; 28471 screenReaderText = this._model._getScreenReaderText(); 28472 role = this._model._getRole(); 28473 if (screenReaderText) { 28474 this.$itemNav.attr("aria-label", screenReaderText); 28475 } 28476 this.$itemNav.find('a').attr("tabindex", function (index, currentValue) { 28477 return (currentValue == -1 ? currentValue : 0); 28478 }); 28479 }, 28480 28481 getQualifiedNamedView : function (qName) { 28482 var view = _.find(this.childViews, function (childView) { 28483 return (childView._model._escapeQualifiedName() == qName); 28484 }, this); 28485 return view; 28486 }, 28487 28488 _toggleAddRemoveButtons : function () { 28489 var panelModel = this._model, 28490 instanceManager = panelModel.instanceManager; 28491 $('[data-guide-id="' + panelModel.id + '"][data-guide-addremove="remove"]').toggleClass("hidden", instanceManager.instanceCount == instanceManager.minOccur); 28492 $('[data-guide-id="' + panelModel.id + '"][data-guide-addremove="add"]').toggleClass("hidden", instanceManager.instanceCount == instanceManager.maxOccur); 28493 } 28494 }); 28495 28496 GuidePanelView.defineProps({ 28497 hasNavigableLayout : { 28498 get : function () { 28499 return this.$itemsNavContainer.length > 0; 28500 } 28501 }, 28502 $itemsContainer : { 28503 get : function () { 28504 28505 if (this._model._selfOrAncestorIsLazyReference || !this._$itemsContainer || this._$itemsContainer.length === 0) { 28506 this._$itemsContainer = this._find(this.guideUtil.itemContainerSelector(this._model.id)); 28507 28508 if (this._$itemsContainer.length === 0) { 28509 this._$itemsContainer = this._find(this.guideUtil.alternateItemContainerSelector(this._model.id)); 28510 } 28511 } 28512 return this._$itemsContainer; 28513 } 28514 }, 28515 $itemsNavContainer : { 28516 get : function () { 28517 if (this._model._selfOrAncestorIsLazyReference || !this._$itemsNavContainer || this._$itemsNavContainer.length === 0) { 28518 this._$itemsNavContainer = this._find(this.guideUtil.itemNavContainerSelector(this._model.id)); 28519 } 28520 return this._$itemsNavContainer; 28521 } 28522 }, 28523 $summary : { 28524 get : function () { 28525 if (!this._$summary) { 28526 this._$summary = this._find(this._summarySelector); 28527 } 28528 return this._$summary; 28529 } 28530 }, 28531 $title : { 28532 get : function () { 28533 if (!this._$title) { 28534 this._$title = this._find(this._titleSelector); 28535 } 28536 return this._$title; 28537 } 28538 }, 28539 currentActiveItemView : { 28540 get : function () { 28541 return this._currentActiveItemView; 28542 }, 28543 set : function (value) { 28544 if (value != this._currentActiveItemView) { 28545 if (this._currentActiveItemView) { 28546 28547 this._currentActiveItemView._model.viewVisited = true; 28548 } 28549 if (!value) { 28550 var itemModel = this._model.navigationContext.firstItem; 28551 if (itemModel) { 28552 value = this.getQualifiedNamedView(itemModel._escapeQualifiedName()); 28553 } 28554 } 28555 this._currentActiveItemView = value; 28556 28557 this._model.navigationContext.currentItem = (this._currentActiveItemView || {})._model; 28558 _.each(this.childViews, function (childView) { 28559 if (childView == this._currentActiveItemView) { 28560 childView.$item.addClass("active"); 28561 childView.$itemNav.addClass("active"); 28562 childView.$itemNav.attr("aria-selected", true); 28563 childView.$itemNav.attr("aria-disabled", false); 28564 childView.$itemNav.removeClass("wizard-tab-disabled"); 28565 } else { 28566 childView.$item.removeClass("active"); 28567 childView.$itemNav.removeClass("active"); 28568 childView.$itemNav.attr("aria-selected", false); 28569 } 28570 }, this); 28571 28572 28573 28574 28575 if (this._currentActiveItemView instanceof guidelib.view.GuidePanel
28575View && this._currentActiveItemView._childInitializeWaiting) { 28576 this._currentActiveItemView._postInitializeChildren(); 28577 } 28578 28579 if (true && _.isUndefined(this._model._ajaxCallDone)) { 28580 28581 28582 var model = this._model; 28583 28584 while (model && !(model instanceof guidelib.model.RootPanelNode)) { 28585 if (model.toolbar) { 28586 model.toolbar.execNavigationChangeExpression(); 28587 } 28588 model = model.parent; 28589 } 28590 28591 if (model && model.toolbar && model instanceof guidelib.model.RootPanelNode) { 28592 model.toolbar.execNavigationChangeExpression(); 28593 } 28594 } 28595 } 28596 } 28597 }, 28598 28599 _ancestorHasNavigableLayout : { 28600 get : function () { 28601 var parentView = this.parentView; 28602 while (parentView) { 28603 if (parentView.$itemsNavContainer && parentView.$itemsNavContainer.length > 0) { 28604 return true; 28605 } 28606 parentView = parentView.parentView; 28607 } 28608 return false; 28609 } 28610 } 28611 }); 28612}($, _, guidelib)); 28613(function ($, _, guidelib) { 28614 28615 var cloneCounter = 0; 28616 28617 var tableMobileLayoutConstants = { 28618 COLLAPSIBLE_COLUMNS : "collapsibleColumns", 28619 HEADERS_LEFT : "headersLeft", 28620 COLLAPSIBLE_COLUMNS_CONTROL_ROW_SELECTOR : "tr.child", 28621 RUNTIME_TABLE_CONTROL : "guideTableRuntimeControls", 28622 RUNTIME_TABLE_RIGHT_CONTROL : "guideTableRuntimeRightControls", 28623 RUNTIME_TABLE_LEFT_CONTROL : "guideTableRuntimeLeftControls", 28624 RUNTIME_TABLE_ADD_CONTROL : "guideTableRuntimeAddControl", 28625 RUNTIME_TABLE_DELETE_CONTROL : "guideTableRuntimeDeleteControl", 28626 RUNTIME_TABLE_EDIT_CONTROL : "guideTableRuntimeEditControl" 28627 }; 28628 28629 var tableSortingComponents = { 28630 GUIDE_INSTANCE_MANAGER : "guideInstanceManager", 28631 WEB_CHANNEL_HEADER_COMPONENT : "fd/ccm/web-channel/components/tableHeader/v1/tableHeader", 28632 AF_TABLE_HEADER_COMPONENT : "fd/af/components/tableHeader", 28633 SORTING_ENABLED : "sortingEnabled" 28634 }; 28635 28636 var GuideTableView = guidelib.view.GuideTableView = guidelib.view.GuidePanelView.extend({ 28637 28638 28639 TABLE_WIDTH_BUFFER : 23, 28640 28641 _getPluginOptions : function () { 28642 var defaultOptions = { 28643 "bAutoWidth" : this.bAutoWidth 28644 }, columnWidthArray = null, 28645 sum = 0, 28646 sWidthArray = null, 28647 numOfTableCol = this.$tableElement.find("th").length; 28648 28649 if (this.bAutoWidth === false) { 28650 columnWidthArray = this._model.columnWidth.split(","); 28651 if (columnWidthArray.length === numOfTableCol) { 28652 28653 _.each(columnWidthArray, function (item) { 28654 sum += parseInt(item, 10); 28655 }); 28656 28657 sWidthArray = _.map(columnWidthArray, function (item) { 28658 return { 28659 "pWidth" : Math.floor((item * 100) / sum) 28660 }; 28661 }); 28662 } 28663 28664 defaultOptions = _.extend({}, defaultOptions, { 28665 aWidthPercentage : sWidthArray, 28666 aWidth : columnWidthArray 28667 }); 28668 } 28669 return defaultOptions; 28670 28671 }, 28672 28673 28674 setAutoWidth : function () { 28675 if (this._model.columnWidth && this._model.columnWidth.length > 0) { 28676 this.bAutoWidth = false; 28677 } else { 28678 this.bAutoWidth = true; 28679 } 28680 }, 28681 28682 28683 createView : function (id) { 28684 var $htmlTemplate = this._guideView._domTemplateCacheStore.cloneDomElement("#" + id), 28685 formElemSelector = "#" + id + "_widget", 28686 counter = ++cloneCounter; 28687 if ($htmlTemplate.length == 0) { 28688 28689 $htmlTemplate = this.$element.find("#" + id).clone(); 28690 } 28691 28692 $htmlTemplate.find(formElemSelector).attr("id", id + "_widget" + counter); 28693 28694 var view = guidelib.view.GuideViewRegistry.prototype.createView($htmlTemplate, this); 28695 view.postInitialize(); 28696 return $htmlTemplate; 28697 }, 28698 28699 initializeTableColumnWidth : function (pluginOptions) { 28700 28701 if (this.bAutoWidth == false && this._model.mobileLayout === tableMobileLayoutConstants.HEADERS_LEFT) { 28702 28703 28704 this.$tableElement.css("table-layout", "fixed"); 28705 var widthArray = pluginOptions["aWidthPercentage"], 28706 numOfTableCol = this.$tableElement.find("th").length; 28707 if (widthArray && widthArray.length == numOfTableCol) { 28708 28709 this.$tableElement.find("th").each(function (index) { 28710 $(this).css("width", widthArray[index]["pWidth"] + "%"); 28711 }); 28712 } 28713 } 28714 }, 28715 28716 _checkIfTableSortingEnabled : function () { 28717 var jsonModel = this._model.jsonModel; 28718 return (jsonModel[tableSortingComponents.SORTING_ENABLED] === "true"); 28719 }, 28720 28721
28722 handleParentVisibleChanged : function (event) { 28723 switch (event._property) { 28724 case "visible": 28725 this.handleTableShown(); 28726 break; 28727 } 28728 }, 28729 28730 28731 _checkParentModelChanged : function() { 28732 var currentParent = this.parentView; 28733 while(currentParent != null) { 28734 currentParent._model.on(guidelib.event.GuideModelEvent.MODEL_CHANGED, this.handleParentVisibleChanged, this); 28735 currentParent = currentParent.parentView; 28736 } 28737 }, 28738 28739 28740 initialize : function () { 28741 GuideTableView._super.initialize.apply(this, arguments); 28742 28743 this._checkParentModelChanged(); 28744 28745 this.$tableElement = this.$element.find("> table"); 28746 28747 this.setAutoWidth(); 28748 28749 var widgetOptions = this._getPluginOptions(), 28750 that = this; 28751 28752 this.initializeTableColumnWidth(widgetOptions); 28753 this._fixTableControls(true); 28754 if (this._model.mobileLayout === tableMobileLayoutConstants.COLLAPSIBLE_COLUMNS) { 28755 widgetOptions = _.extend({}, widgetOptions, { 28756 28757 bControlRowHiddenCells : false, 28758 28759 28760 bDisableControlRowCells : true, 28761 28762 viewCallback : $.proxy(this.createView, this), 28763 28764 tableRuntimeEditControlClass : tableMobileLayoutConstants.RUNTIME_TABLE_EDIT_CONTROL, 28765 28766 fixTableControls : $.proxy(this._fixTableControls, this) 28767 }); 28768 28769 this.jqwidget = this.$tableElement.responsiveTablePlugin(widgetOptions).data("responsiveTablePlugin"); 28770 } else { 28771 28772 $(window).on("resize orientationchange", function (event) { 28773 that._fixTableControls(event); 28774 }); 28775 } 28776 28777 if (this._checkIfTableSortingEnabled()) { 28778 this.$tableElement.tableSorting = this.guideTableSorter.initialize; 28779 this.$tableElement.tableSorting({ 28780 model : this._model, 28781 tableContext : this 28782 }); 28783 } 28784 }, 28785 28786 handleVisibleChanged : function (event) { 28787 GuideTableView._super.handleVisibleChanged.apply(this, arguments); 28788 28789 this.handleTableShown(); 28790 this._resetTableCellWidth(); 28791 }, 28792 28793 handleTableShown : function () { 28794 if (this._model.mobileLayout === tableMobileLayoutConstants.COLLAPSIBLE_COLUMNS) { 28795 28796 this.jqwidget._initializeColumnVisibility(); 28797 28798 if (this.jqwidget.isColumnHidden()) { 28799 28800 this.$tableElement.find(".guideFieldNode").addClass("dontSyncEnabled"); 28801 28802 this.$tableElement.find("input, select, textarea, button").attr("disabled", "disabled"); 28803 } 28804 } 28805 }, 28806 28807 _resetTableCellWidth : function () { 28808 var that = this, 28809 tableWidthBuffer = this.TABLE_WIDTH_BUFFER; 28810 28811 this.$tableElement.find("." + tableMobileLayoutConstants.RUNTIME_TABLE_CONTROL).each(function () { 28812 var element = this; 28813 setTimeout(function () { 28814 that._resetTableCell($(element), tableWidthBuffer); 28815 }, 1); 28816 }); 28817 }, 28818 28819 _resetTableCell : function ($element, tableWidthBuffer) { 28820 var componentWidth; 28821 28822 if ($element.hasClass(tableMobileLayoutConstants.RUNTIME_TABLE_RIGHT_CONTROL)) { 28823 var $component = $element.prev(), 28824 $td = $element.parent(); 28825 28826 28827 if ($element.is(":visible")) { 28828 28829 $component.css("display", "inline-block"); 28830 $component.css("float", "left"); 28831 componentWidth = $td.width() - $element.outerWidth() - tableWidthBuffer; 28832 var percentage = ((componentWidth / $td.width()) * 100); 28833 28834 28835 $component.width(percentage + "%"); 28836 } else { 28837 28838 28839 $component.css("display", "block"); 28840 $component.css("float", "none"); 28841 $component.width($td.width()); 28842 } 28843 } else if ($element.hasClass(tableMobileLayoutConstants.RUNTIME_TABLE_LEFT_CONTROL)) { 28844 28845 if ($element.is(":visible")) { 28846 $element.next().css("display", "inline-block"); 28847 componentWidth = $element.parent().width() - $element.outerWidth() - tableWidthBuffer; 28848 var percentage = ((componentWidth / $element.parent().width()) * 100); 28849 $element.next().width(percentage + "%"); 28850 } else { 28851 28852 $element.next().css("display", "block"); 28853 } 28854 } 28855 }, 28856 28857 _fixTableControls : function (event) { 28858 28859 28860 28861 if ((this._model.mobileLayout === tableMobileLayoutConstants.COLLAPSIBLE_COLUMNS) && (this.jqwidget)) { 28862 28863 if (this.jqwidget.isColumnHidden()) { 28864 28865 this.$tableElement.find("tr:not(.child)").find(".guideFieldNode").addClass("dontSyncEnabled"); 28866 28867 this.$tableElement.find("tr:not(.child)").find("input, select, textarea, button").attr("disabled", "disabled"); 28868 } else { 28869 28870 this.$tableElement.find(".guideFieldNode").removeClass("dontSyncEnabled"); 28871 28872 this.$tableElement.find("input, select, textarea, button").removeAttr("disabled"); 28873 } 28874 } 28875 28876 28877 if (event) { 28878 this._resetTableCellWidth(); 28879 } 28880 }, 28881 28882 28883 _fixChildDom : function (view, $item, $itemNav) { 28884 GuideTableView._super._fixChildDom.apply(this, arguments); 28885 28886 28887 if (this._model.mobileLayout === tableMobileLayoutConstants.COLLAPSIBLE_COLUMNS) { 28888 28889 this.jqwidget._fixControlRows(); 28890 } 28891 28892 this._fixTableControls(); 28893 28894 this._resetTableCellWidth(); 28895 }, 28896 28897 _postInitializeChildren : function () { 28898 28899 GuideTableView._super._postInitializeChildren.call(this); 28900 28901 28902 28903 28904 28905 if (this._model.mobileLayout === tableMobileLayoutConstants.COLLAPSIBLE_COLUMNS) { 28906 28907 this.handleTableShown(); 28908 } 28909 28910 28911 else if (this._model.mobileLayout === tableMobileLayoutConstants.HEADERS_LEFT) { 28912 this._fixTableCellForHeaderLeftLayout(); 28913 } 28914 this._resetTableCellWidth(); 28915 }, 28916 28917 _fixTableCellForHeaderLeftLayout : function () { 28918 var that = this, 28919 guideUtil = guidelib.util.GuideUtil; 28920 this.$tableElement.find("tr td").each(function () { 28921 guideUtil._setGuideDataHeader($(this), that.$tableElement); 28922 }); 28923 }, 28924 28925
28926 handleChildChanged : function (event) { 28927 GuideTableView._super.handleChildChanged.apply(this, arguments); 28928 28929 28930 if (this._model.mobileLayout === tableMobileLayoutConstants.HEADERS_LEFT) { 28931 this._fixTableCellForHeaderLeftLayout(); 28932 } 28933 if (event._property == "childAdded") { 28934 this._resetTableCellWidth(); 28935 } 28936 }, 28937 28938 addRemoveTemplateMarker : function () { 28939 28940 _.each(this._model.children, function (childModel) { 28941 if (childModel instanceof guidelib.model.GuideInstanceManager) { 28942 28943 var imId = childModel.id, 28944 instanceId = (childModel._instances[0] || {}).id || childModel.instanceTemplateId, 28945 gTemplateMarker = null, 28946 28947 instanceItem = this.guideUtil.itemSelector(instanceId, childModel._instances[0]), 28948 navItem = this.guideUtil.itemNavSelector(instanceId), 28949 $instanceItem = this.$itemsContainer.find(instanceItem); 28950 if ($instanceItem.is("tr")) { 28951 $instanceItem.attr("data-guide-template-marker", imId); 28952 } 28953 28954 28955 28956 28957 28958 } 28959 }, this); 28960 }, 28961 28962 tableSortComparator : { 28963 DATE : function (tableModelDataRows, sortList, tableContext) { 28964 return tableModelDataRows.sort(function (a, b) { 28965 var currColumn = sortList[0][0], currOrder = sortList[0][1], 28966 guideTableSorter = tableContext.guideTableSorter, 28967 value_a = guideTableSorter.formatDateValue(guideTableSorter.getValueFromJsonModel(a, currColumn)), 28968 value_b = guideTableSorter.formatDateValue(guideTableSorter.getValueFromJsonModel(b, currColumn)); 28969 return guideTableSorter.ComparedOrder(value_a, value_b, currOrder); 28970 }); 28971 }, 28972 NUMBER : function (tableModelDataRows, sortList, tableContext) { 28973 return tableModelDataRows.sort(function (a, b) { 28974 var currColumn = sortList[0][0], currOrder = sortList[0][1], 28975 guideTableSorter = tableContext.guideTableSorter, 28976 value_a = guideTableSorter.formatRegexFloatData(guideTableSorter.getValueFromJsonModel(a, currColumn)), 28977 value_b = guideTableSorter.formatRegexFloatData(guideTableSorter.getValueFromJsonModel(b, currColumn)); 28978 return guideTableSorter.ComparedOrder(value_a, value_b, currOrder); 28979 }); 28980 28981 }, 28982 STRING : function (tableModelDataRows, sortList, tableContext) { 28983 return tableModelDataRows.sort(function (a, b) { 28984 var currColumn = sortList[0][0], currOrder = sortList[0][1], 28985 guideTableSorter = tableContext.guideTableSorter, 28986 value_a = guideTableSorter.formatRichTextString(guideTableSorter.getValueFromJsonModel(a, currColumn, true)), 28987 value_b = guideTableSorter.formatRichTextString(guideTableSorter.getValueFromJsonModel(b, currColumn, true)); 28988 return guideTableSorter.ComparedOrder(value_a, value_b, currOrder); 28989 }); 28990 } 28991 }, 28992 28993 28994 guideTableSorter : new function () { 28995 this.initialize = function (tableSortingConfig) { 28996 return this.each(function () { 28997 this.tableConfig = {}; 28998 var defaultSortingConfig = {sortList : [], selectorsHeaders : 'thead th', 28999 headerCss : {asc : "asc", desc : "desc", random : "random"} 29000 }; 29001 if (!this.tHead || !this.tBodies) {return;} 29002 var table = $(this), tableConfig = {}; 29003 tableConfig = $.extend(this.tableConfig, defaultSortingConfig, tableSortingConfig); 29004 var tableHeaderModel, tableModel = tableConfig.model; 29005 for (var index = 0 ; index < tableModel.children.length ; index++) { 29006 if (isTableHeaderRow(tableModel.children[index])) { 29007 tableHeaderModel = tableModel.children[index]; 29008 tableConfig.tableHeader = tableHeaderModel; 29009 break; 29010 } 29011 } 29012 var $tableHeaders = filterSortableHeaders(tableConfig, this); 29013 $tableHeaders.click(function () { 29014 if (this.sortingAllowed) { 29015 sortCurrentColumn(this, table, tableConfig, $tableHeaders); 29016 } 29017 }); 29018 29019 $tableHeaders.each(function (index) { 29020 if (this.sortingAllowed) {
29021 sortOnFirstColumn(this, tableModel); 29022 return false; 29023 } 29024 }); 29025 }); 29026 }; 29027 29028 29029 function sortOnFirstColumn(firstColumn, tableModel) { 29030 if (typeof tableModel._guide !== "undefined" && tableModel._guide()) { 29031 var isSubmittedData = guidelib.util.GuideUtil._fetchJSONNodeValue(tableModel._guide().runtime.guideContext.guidePrefillJson, "afSubmissionInfo"); 29032 isSubmittedData = isSubmittedData || guidelib.util.GuideUtil.fetchXMLNodeValue(tableModel._guide().runtime.guideContext.guidePrefillXml, "afSubmissionInfo"); 29033 if (!isSubmittedData) { 29034 $(firstColumn).trigger("click"); 29035 } 29036 } 29037 } 29038 29039 29040 function filterSortableHeaders(tableConfig, tableDom) { 29041 var $tableHeaders = $(tableConfig.selectorsHeaders, tableDom).each(function (index) { 29042 this.column = index; 29043 this.order = 1; 29044 }); 29045 for (var column = 0 ; column < tableConfig.tableHeader.children.length ; column++) { 29046 var currColumnModel = tableConfig.tableHeader.children[column]; 29047 $tableHeaders[column].sortingAllowed = true; 29048 var sortDataType = currColumnModel.jsonModel["sortingDataType"]; 29049 sortDataType = !sortDataType ? "STRING" : sortDataType; 29050 currColumnModel.jsonModel.sortingDataType = sortDataType; 29051 if (!tableConfig.tableHeader.visible || sortDataType === "noSort") { 29052 $tableHeaders[column].sortingAllowed = false; 29053 $($tableHeaders[column]).removeClass("sortEnabled"); 29054 var $sortingButton = $($tableHeaders[column]).find(".sortingButton").remove(); 29055 } 29056 } 29057 return $tableHeaders; 29058 } 29059 29060 29061 function sortCurrentColumn(currentHeader, table, tableConfig, $tableHeaders) { 29062 var tableRows = (table[0].tBodies[0] && table[0].tBodies[0].rows.length) || 0; 29063 if (tableRows > 0) { 29064 currentHeader.order = (++(currentHeader.order) % 2); 29065 tableConfig.sortList = []; 29066 tableConfig.sortList.push([currentHeader.column, currentHeader.order]); 29067 setTimeout(function () { 29068 updateTableHeaderStyles($tableHeaders, tableConfig.sortList, tableConfig); 29069 sortGuideTableDataModel(tableConfig, tableConfig.sortList, tableConfig.model); 29070 }, 1); 29071 } 29072 } 29073 29074 29075 function updateTableHeaderStyles($headers, sortingList, tableConfig) { 29076 var order, headerCSS = [tableConfig.headerCss.asc, tableConfig.headerCss.desc, tableConfig.headerCss.random]; 29077 $headers.each(function (index) { 29078 var $sortingButton = $(this).find(".sortingButton"); 29079 $sortingButton.removeClass(headerCSS[0]).removeClass(headerCSS[1]).removeClass(headerCSS[2]); 29080 if ($headers[index].sortingAllowed) { 29081 if (index === sortingList[0][0]) { 29082 order = sortingList[0][1]; 29083 $sortingButton.addClass(headerCSS[order]); 29084 } else { 29085 $sortingButton.addClass(tableConfig.headerCss.random); 29086 } 29087 } 29088 }); 29089 } 29090 29091 29092 function sortGuideTableDataModel(tableConfig, sortList, tableModel) { 29093 var i,j = 0,tableModelChildren = tableModel.children, tableDataRows = [], prevTableModel = tableModel, 29094 modifiedGuideTableModel = [], tableContext = tableConfig.tableContext; 29095 29096 for (i = 0; i < tableModelChildren.length; i++) { 29097 if (tableModelChildren[i].className !== tableSortingComponents.GUIDE_INSTANCE_MANAGER) { 29098 if (isTableRowsWithData(tableModelChildren[i])) { 29099 tableDataRows.push(tableModelChildren[i]); 29100 } 29101 } 29102 } 29103 var dataType = tableConfig.tableHeader.children[[sortList[0][0]]].jsonModel.sortingDataType; 29104 tableDataRows = tableContext.tableSortComparator[dataType].call(tableConfig, tableDataRows, sortList, tableContext); 29105 for (i = 0; i < tableModel.children.length; i++) { 29106 if (isTableRowsWithData(tableModel.children[i])) { 29107 modifiedGuideTableModel.push(tableDataRows[j]); 29108 j++; 29109 } else { 29110 modifiedGuideTableModel.push(tableModel.children[i]); 29111 } 29112 } 29113 tableModel.children = modifiedGuideTableModel; 29114 tableModel._triggerEvent(guidelib.event.GuideModelEvent.MODEL_CHANGED, "tableModelSorted", prevTableModel, tableModel); 29115 syncNewModelToHTML(tableConfig.tableContext, tableModel); 29116 } 29117 29118 29119 function isTableRowsWithData(tableModelChildElement) { 29120 var resourceType = tableModelChildElement.options.jsonModel["sling:resourceType"], 29121 childElementClassName = tableModelChildElement.className; 29122 return !((childElementClassName === tableSortingComponents.GUIDE_INSTANCE_MANAGER) || (resourceType === tableSortingComponents.AF_TABLE_HEADER_COMPONENT) || (resourceType === tableSortingComponents.WEB_CHANNEL_HEADER_COMPONENT)); 29123 } 29124 29125 function isTableHeaderRow(tableModelChildElement) { 29126 var resourceType = tableModelChildElement.options.jsonModel["sling:resourceType"]; 29127 return ((resourceType === tableSortingComponents.AF_TABLE_HEADER_COMPONENT) || (resourceType === tableSortingComponents.WEB_CHANNEL_HEADER_COMPONENT)); 29128 } 29129 29130 this.formatRegexFloatData = function (data) { 29131 return (isNaN(parseFloat(data))) ? 0 : parseFloat(data); 29132 }; 29133 29134 this.formatDateValue = function (data) { 29135 return (isNaN(new Date(data).getTime())) ? 0 : new Date(data).getTime(); 29136 }; 29137 29138 this.formatRichTextString = function (data) { 29139 data = "<div>" + data + "</div>"; 29140 return $(data).text().trim(); 29141 }; 29142 29143 this.ComparedOrder = function (value_a, value_b, currOrder) { 29144 if (value_a > value_b) { 29145 return (currOrder === 0) ? 1 : -1; 29146 } else if (value_a < value_b) { 29147 return (currOrder === 0) ? -1 : 1; 29148 } else { 29149 return -1; 29150 } 29151 }; 29152 29153 this.getValueFromJsonModel = function (tableRow, currColumn, isString) { 29154 var jsonModel = tableRow.children[getValidCurrentColumn(tableRow.children, currColumn)].jsonModel, value = null; 29155 if (!isString && jsonModel.defaultValue && jsonModel.defaultValue.length === 1) { 29156 value = jsonModel.defaultValue[0]; 29157 } 29158 if (!value) { 29159 value = jsonModel._value; 29160 } 29161 return value === null ? "" : this.formatRichTextString(value); 29162 }; 29163 29164 29165 function getValidCurrentColumn(tableRowModel, currColumn) {
29166 var validCurrColumn = currColumn, index = 0 ; 29167 while (currColumn > 0) { 29168 if (tableRowModel[index].jsonModel.guideNodeClass === tableSortingComponents.GUIDE_INSTANCE_MANAGER) { 29169 validCurrColumn++; 29170 } else { 29171 currColumn--; 29172 } 29173 index++; 29174 } 29175 return validCurrColumn; 29176 } 29177 29178 29179 function syncNewModelToHTML(tableContext, tableModel) { 29180 var tableItemsViews = {}, childView, index; 29181 29182 for (index = 0; index < tableContext.childViews.length; index++) { 29183 childView = tableContext.childViews[index]; 29184 if (childView.isItem) { 29185 tableItemsViews[childView.id] = childView; 29186 } 29187 } 29188 for (index = 1; index < tableContext._model.items.length; index++) { 29189 var childModel = tableContext._model.items[index], childId = childModel.id, view = tableItemsViews[childId],newChild = view._model, 29190 $childItem = view.$item, $childItemNav = view.$itemNav, insertBeforeId, insertAfterId; 29191 if (index === 1) { 29192 if (tableModel.items.length > 2) { 29193 insertBeforeId = tableModel.items[index + 1].id; 29194 } 29195 } else { 29196 insertAfterId = tableModel.items[index - 1].id; 29197 } 29198 var insertAfterItemSelector = insertAfterId ? tableContext.guideUtil.itemSelector(insertAfterId, newChild) : "#" + newChild.instanceManager.id, 29199 insertBeforeItemSelector = insertBeforeId ? tableContext.guideUtil.itemSelector(insertBeforeId, newChild) : "#" + newChild.instanceManager.id; 29200 tableContext.$itemsContainer.each(function (index) { 29201 var insertEl = $childItem.get(index) || $childItem.get(0), 29202 $insertBeforeItem, 29203 $insertAfterItem = $(this).find(insertAfterItemSelector); 29204 if ($insertAfterItem.get(0) !== insertEl) { 29205 $insertAfterItem.after($(insertEl)); 29206 } else { 29207 $insertBeforeItem = $(this).find(insertBeforeItemSelector); 29208 $insertBeforeItem.before($(insertEl)); 29209 } 29210 }); 29211 } 29212 } 29213 } 29214 }); 29215}($, _, guidelib)); 29216 29217(function ($, guidelib) { 29218 var GuideTableRowView = guidelib.view.GuideTableRowView = guidelib.view.GuidePanelView.extend({ 29219 29220 handleChildChanged : function (event) { 29221 29222 } 29223 29224 }); 29225}($, guidelib)); 29226(function ($, guidelib, _) { 29227 var GuideContainerView = guidelib.view.GuideContainerView = guidelib.view.GuideItemsView.extend({ 29228 initialize : function () { 29229 this._queueViewForLazyItems = []; 29230 29231 window.guideBridge._guideView = this; 29232 var $htmlTemplateDom = $(this.options.element).clone(); 29233 this._domTemplateCacheStore = 29234 new guidelib.view.util.DomTemplateCacheStore({$htmlTemplateDom : $htmlTemplateDom}); 29235 this._lastFocussedPanelForNonActionFields = null; 29236 GuideContainerView._super.initialize.call(this); 29237 this._currentFocusItemSom = null; 29238 29239 29240 this._previousFocusItemSom = "FIRST_TIME"; 29241 $(window).on("keydown.guides", $.proxy(this.hotKeys, this)); 29242 this.postInitialize(); 29243 this._model.on(guidelib.event.GuideModelEvent.MODEL_REFRESH, function (evnt) { 29244 switch (evnt._property) { 29245 case "jsonModel": 29246 this._syncGuideNodeToHtml(true); 29247 break; 29248 default: 29249 this._model.logger().error("unexpected event property " + evnt._property); 29250 } 29251 }, this); 29252 }, 29253 29254 _reInitializeGuideContainerDom : function () { 29255 var $guideContainerDom = $('div.guideContainerWrapperNode'); 29256 this.$element = $guideContainerDom; 29257 }, 29258 29259 setFocus : function (somExp, focusOpt, runNavScr) { 29260 var options, 29261 focusOption, 29262 runNavScript, 29263 somExpression, 29264 muteScripts; 29265 if (_.isObject(somExp)) { 29266 options = somExp; 29267 somExpression = options.somExpression; 29268 focusOption = options.focusOption; 29269 runNavScript = options.runCompletionScript; 29270 } else { 29271 somExpression = somExp; 29272 focusOption = focusOpt; 29273 runNavScript = runNavScr; 29274 } 29275 muteScripts = !runNavScript; 29276 if (focusOption == "nextItemDeep" || focusOption == "prevItemDeep") { 29277 29278 if (somExpression) { 29279 this.logger().warn("AF", "somExpression is currently not supported for deepNavigation:" + somExpression + ":" + focusOption); 29280 return false;
29281 } 29282 var existingFocusNavItem = this.getSomOnNavigableAncestor(this._lastFocussedPanelForNonActionFields); 29283 var existingNavView = this.getView(existingFocusNavItem); 29284 var siblingNavName = (focusOption == "nextItemDeep") ? "nextItem" : "prevItem"; 29285 29286 while (existingNavView && (existingNavView.parentView != this) && !existingNavView.getSiblingItemView(siblingNavName)) { 29287 var navigableParentItem = this.getSomOnNavigableAncestor(existingNavView.parentView._model.somExpression); 29288 existingNavView = this.getView(navigableParentItem); 29289 } 29290 if (existingNavView && existingNavView.parentView != this && existingNavView.getSiblingItemView(siblingNavName)) { 29291 var madeActive = existingNavView.parentView.setActive(siblingNavName, false, muteScripts); 29292 if (!madeActive) { 29293 this.logger().log("AF", "could not setActive for the deepNav:" + existingNavView._model.somExpression); 29294 return false; 29295 } 29296 29297 var deepChildNav = (siblingNavName == "nextItem") ? "firstItem" : "lastItem"; 29298 var currentActiveChildView = existingNavView.parentView.currentActiveItemView; 29299 while (currentActiveChildView) { 29300 currentActiveChildView.setActive(deepChildNav, !currentActiveChildView.currentActiveItemView, true); 29301 currentActiveChildView = currentActiveChildView.currentActiveItemView; 29302 } 29303 return true; 29304 } else { 29305 this.logger().warn("AF", "could not locate view for given somExpression:" + somExpression + ":" + focusOption); 29306 return false; 29307 } 29308 } 29309 29310 if (!somExpression) { 29311 29312 somExpression = this.guideModel.rootPanel.somExpression; 29313 } 29314 var currentView = this.rootPanelView; 29315 29316 29317 if (currentView) { 29318 var relativeSom = this.guideUtil.relativeSom(this.guideModel.rootPanel.somExpression, somExpression); 29319 if (relativeSom) { 29320 var somTokens = relativeSom.split("."); 29321 var error = 29322 _.find(somTokens, function (qName) { 29323 currentView.setActive(qName, false, muteScripts); 29324 if (currentView instanceof guidelib.view.GuidePanelView && (currentView.currentActiveItemView == null || currentView.currentActiveItemView.qualifiedName != qName)) { 29325 this.logger().log("AF", "could not find token:" + qName + ", som:" + somExpression); 29326 return true; 29327 } else { 29328 if (currentView.currentActiveItemView != null) { 29329 currentView = currentView.currentActiveItemView; 29330 } 29331 } 29332 }, this); 29333 if (error) { 29334 return false; 29335 } 29336 } 29337 } else { 29338 29339 var $element = this._getGuideDomElement(somExpression); 29340 29341 29342 if ($element && $element.length > 0) { 29343 29344 29345 currentView = $element.data("guideView"); 29346 } 29347 } 29348 29349 if (currentView) { 29350 return currentView.setActive(focusOption, true, muteScripts); 29351 } else { 29352 return false; 29353 } 29354 }, 29355 29356 _getGuideDomElement : function (somExpression, option) { 29357 var nav = "", res, node, nodeElSelector; 29358 if (somExpression && typeof somExpression === 'string') { 29359 node = this.guideModel.resolveNode(somExpression); 29360 if (!node) { 29361 return; 29362 } 29363 nodeElSelector = "#" + node.id; 29364 if (option === "nav") { 29365 nodeElSelector = this.guideUtil.itemNavSelector(node.id); 29366 } 29367 res = this.$element.find(nodeElSelector); 29368 return res; 29369 } 29370 }, 29371 29372 getView : function (somExpression) { 29373 if (!somExpression) { 29374 return null; 29375 }
29376 var $focusEl = this._getGuideDomElement(somExpression), 29377 view = null, 29378 ancestorView = null; 29379 if ($focusEl && $focusEl.length > 0) { 29380 if (!$focusEl.data("guideView")) { 29381 var rootPanelSom = this.guideModel.rootPanel.somExpression; 29382 var relativeSom = guidelib.util.GuideUtil.relativeSom(rootPanelSom, somExpression) || ""; 29383 29384 _.reduce(relativeSom.split("."), function (currentSom, somToken) { 29385 currentSom = currentSom ? currentSom + "." + somToken : somToken; 29386 ancestorView = this.getView(currentSom); 29387 if (ancestorView instanceof guidelib.view.GuidePanelView && ancestorView._childInitializeWaiting) { 29388 ancestorView._postInitializeChildren(); 29389 } 29390 return currentSom; 29391 }, rootPanelSom, this); 29392 } 29393 view = $focusEl.data("guideView"); 29394 if (view instanceof guidelib.view.GuidePanelView && view._childInitializeWaiting) { 29395 view._postInitializeChildren(); 29396 } 29397 29398 return view; 29399 } 29400 return null; 29401 }, 29402 29403 hotKeys : function (evnt) { 29404 var handled = false, currentFocusItemSom; 29405 29406 switch (evnt.keyCode) { 29407 case 37: 29408 if (evnt.altKey) { 29409 window.guideBridge.setFocus(null, 'prevItemDeep', true); 29410 handled = true; 29411 } 29412 break; 29413 case 39: 29414 if (evnt.altKey) { 29415 window.guideBridge.setFocus(null, 'nextItemDeep', true); 29416 handled = true; 29417 } 29418 break; 29419 case 82: 29420 if (evnt.altKey) { 29421 window.guideBridge.reset(); 29422 handled = true; 29423 } 29424 break; 29425 case 83: 29426 if (evnt.altKey) { 29427 window.guideBridge.submit(); 29428 handled = true; 29429 } 29430 break; 29431 } 29432 if (handled) { 29433 evnt.preventDefault(); 29434 } 29435 }, 29436 29437 getSomOnNavigableAncestor : function (somExpression) { 29438 if (!somExpression || somExpression === "") { 29439 return null; 29440 } 29441 29442 var index, parentView, parentSom, isNavigable; 29443 index = somExpression.lastIndexOf("."); 29444 29445 if (index !== -1) { 29446 parentSom = somExpression.substring(0, index); 29447 parentView = this.getView(parentSom); 29448 if (parentView) { 29449 isNavigable = parentView.hasNavigableLayout; 29450 } 29451 if (isNavigable) { 29452 return somExpression; 29453 } 29454 return this.getSomOnNavigableAncestor(parentSom); 29455 } 29456 29457 return this.guideModel.rootPanel.somExpression; 29458 }, 29459 29460 __printSyncPending : function () { 29461 29462 _.each(this.childViews, function (childView) { 29463 if (childView._syncPending) { 29464 this.logger().error("AF", childView._model.somExpression); 29465 } else { 29466 GuideContainerView.prototype.__printSyncPending.call(childView); 29467 } 29468 }, this); 29469 }, 29470 29471 _clearInactiveLazyViews : function (that) { 29472 _.each(this.childViews, function (item) { 29473 if (item._model.className === "rootPanelNode") { 29474 item._clearInactiveLazyViews(that); 29475 } 29476 }); 29477 } 29478 29479 }); 29480 29481 GuideContainerView.defineProps({ 29482 guideModel : { 29483 get : function () { 29484 return this._model; 29485 } 29486 }, 29487 29488 rootPanelView : { 29489 get : function () { 29490 return this._findChildView(this.guideModel.rootPanel); 29491 } 29492 }, 29493 29494 currentFocusItemSom : { 29495 get : function () { 29496 return this._currentFocusItemSom; 29497 }, 29498 set : function (newSom) { 29499 if (this._currentFocusItemSom !== newSom) { 29500 var oldValue = this._currentFocusItemSom; 29501 if (oldValue) { 29502 this._previousFocusItemSom = oldValue; 29503 } 29504 this._currentFocusItemSom = newSom; 29505 29506 if (newSom != null && this._model.resolveNode(newSom).parent.className !== "guideToolbar") { 29507 this._lastFocussedPanelForNonActionFields = this.get
29507SomOnNavigableAncestor(this._currentFocusItemSom); 29508 29509 29510 this._model._currentNavigablePanelSom = this._lastFocussedPanelForNonActionFields; 29511 } 29512 if (newSom) { 29513 this._triggerOnBridge("elementFocusChanged", this._model.resolveNode(newSom), "focus", this._previousFocusItemSom, newSom); 29514 if (this._previousFocusItemSom) { 29515 var getPreviousItemNavigableSom = this.getSomOnNavigableAncestor(this._previousFocusItemSom), 29516 getCurrentItemNavigableSom = this.getSomOnNavigableAncestor(newSom); 29517 if (getCurrentItemNavigableSom !== getPreviousItemNavigableSom) { 29518 this._triggerOnBridge("elementNavigationChanged", this._model.resolveNode(getCurrentItemNavigableSom), 29519 "navigate", getPreviousItemNavigableSom, getCurrentItemNavigableSom); 29520 } 29521 } 29522 } 29523 } 29524 } 29525 }, 29526 29527 skipFieldFocus : { 29528 29529 get : function () { 29530 return this._skipFieldFocus; 29531 }, 29532 29533 set : function (newVal) { 29534 this._skipFieldFocus = newVal; 29535 } 29536 } 29537 }); 29538}($, guidelib, _)); 29539(function (_, guidelib) { 29540 guidelib.model.mixin.ValidationsDisabled = { 29541 normalProperties : { 29542 setParentValidationsDisabled : function (bParentValidationsDisabled) { 29543 var oldValidationsDisabled = this.validationsDisabled, 29544 newValidationsDisabled; 29545 this._bParentValidationsDisabled = bParentValidationsDisabled; 29546 newValidationsDisabled = this.validationsDisabled; 29547 this.handleChildValidationsDisabled(newValidationsDisabled, oldValidationsDisabled); 29548 }, 29549 29550 handleChildValidationsDisabled : function (newValidationsDisabled, oldValidationsDisabled) { 29551 if (newValidationsDisabled !== oldValidationsDisabled) { 29552 if (this instanceof guidelib.model.Field) { 29553 if (newValidationsDisabled === true) { 29554 if (this.validationState === false) { 29555 this._errorText = ""; 29556 this.validationState = true; 29557 this._triggerEvent(guidelib.event.GuideModelEvent.ERROR_CHANGED, 29558 "validationStatus", this.validationState, this._errorText); 29559 } 29560 } 29561 } 29562 _.each(this._children, function (child) { 29563 if (child instanceof guidelib.model.Field || child instanceof guidelib.model.GuideItemsContainer) { 29564 child.setParentValidationsDisabled(newValidationsDisabled); 29565 } 29566 }); 29567 } 29568 } 29569 }, 29570 propertyDescriptors : { 29571 validationsDisabled : { 29572 get : function () { 29573 return this._bParentValidationsDisabled || this._validationsDisabled; 29574 }, 29575 set : function (bValidationsDisabled) { 29576 var oldValidationsDisabled = this.validationsDisabled, 29577 newValidationsDisabled; 29578 this._validationsDisabled = bValidationsDisabled; 29579 newValidationsDisabled = this.validationsDisabled; 29580 this.handleChildValidationsDisabled(newValidationsDisabled, oldValidationsDisabled); 29581 } 29582 } 29583 } 29584 }; 29585 29586}(_, guidelib)); 29587(function (_, guidelib) { 29588 29589 29590 var GuideItemsContainer = guidelib.model.GuideItemsContainer = guidelib.model.Scriptable.extend({ 29591 msClassName : "guideItemsContainer", 29592 29593 initialize : function () { 29594 GuideItemsContainer._super.initialize.call(this); 29595 this._children = []; 29596 this._nameArray = {}; 29597 this._private = {}; 29598 this._initChildren(); 29599 this._normalizeChildren(); 29600 this._bParentValidationsDisabled = false;
29601 this._validationsDisabled = false; 29602 }, 29603 29604 _postInitialize : function () { 29605 29606 29607 GuideItemsContainer._super._postInitialize.call(this); 29608 _.each(this._children, function (childNode) { 29609 childNode._postInitialize(); 29610 }, this); 29611 }, 29612 29613 29614 validate : function (errorList) { 29615 var validationStatus = true, 29616 tempValidationStatus; 29617 29618 if (!this.visible) { 29619 return true; 29620 } 29621 if (_.isUndefined(errorList)) { 29622 errorList = []; 29623 } 29624 29625 var subContainerErrorArray = [], 29626 arrLen; 29627 _.each(this.children, function (child) { 29628 tempValidationStatus = child.validate(subContainerErrorArray); 29629 if (tempValidationStatus === false) { 29630 validationStatus = false; 29631 } 29632 }, this); 29633 29634 tempValidationStatus = GuideItemsContainer._super.validate.call(this, subContainerErrorArray); 29635 if (tempValidationStatus === false) { 29636 validationStatus = false; 29637 } 29638 arrLen = subContainerErrorArray.length; 29639 while (arrLen > 0) { 29640 errorList[errorList.length] = subContainerErrorArray[subContainerErrorArray.length - arrLen]; 29641 arrLen--; 29642 } 29643 return validationStatus; 29644 }, 29645 29646 prepare : function () { 29647 _.each(this._children, function (childNode) { 29648 childNode.prepare(); 29649 }, this); 29650 GuideItemsContainer._super.prepare.call(this); 29651 }, 29652 29653 syncXFAProps : function () { 29654 GuideItemsContainer._super.syncXFAProps.apply(this, arguments); 29655 _.each(this._children, function (childNode) { 29656 childNode.syncXFAProps(); 29657 }); 29658 }, 29659 29660 _initChildren : function (bLazyInitialization) { 29661 var panelItems = [], 29662 jsonModelItemsWithoutRepeatJson = {}, 29663 keyLengthForJsonWithoutRepeat = 0, 29664 keyLengthJsonItemsOriginal = 0; 29665 29666 29667 29668 29669 29670 _.each(this.jsonModel.items, function (item) { 29671 29672 29673 29674 if (item.templateId && item.templateId.indexOf("GUID") === -1) { 29675 jsonModelItemsWithoutRepeatJson[item.templateId] = item; 29676 } 29677 }); 29678 keyLengthForJsonWithoutRepeat = _.keys(jsonModelItemsWithoutRepeatJson).length; 29679 29680 keyLengthJsonItemsOriginal = _.keys(this.jsonModel.items || {}).length; 29681 if (keyLengthForJsonWithoutRepeat > 0 && keyLengthForJsonWithoutRepeat !== keyLengthJsonItemsOriginal) { 29682 this.jsonModel.items = jsonModelItemsWithoutRepeatJson; 29683 } 29684 _.each(this.jsonModel.items, 29685 function (item) { 29686 if (_.isObject(item)) { 29687 29688 29689 29690 29691 var options = {}; 29692 if (this.options._guideContainer) { 29693 options = _.extend({}, options, {"_guideContainer" : this.options._guideContainer}); 29694 } 29695 var panelItemModel = guidelib.model.GuideModelRegistry.prototype.createModel(item, options); 29696 panelItemModel._isItem = true; 29697 this._initializeChild(panelItemModel); 29698 panelItems.push(panelItemModel); 29699 } 29700 }, 29701 this); 29702 this._children = panelItems; 29703 }, 29704 29705 _initializeChild : function (childItem) { 29706 childItem.parent = this; 29707 }, 29708 29709 _normalizeChildren : function () { 29710 this._nameArray = {}; 29711 this._private = {}; 29712 _.each(this.children, function (child) { 29713 child._index = this._addProperty(child); 29714 29715 child.getNaked(child._index, guidelib.__runtime__, null); 29716 child.getNaked(child._index, this._guide().runtime, null); 29717 }, this); 29718 }, 29719 29720 nakedChildReferences : function (nIndex, obj) { 29721 var i, oNode; 29722 for (i = 0; i < this._children.length; i++) { 29723 oNode = this._children[i]; 29724 oNode.getNaked(nIndex, obj, this); 29725 } 29726 }, 29727 _getReducedJSON : function (isRepeatable) { 29728 var reducedJSONChildren, 29729 that = this, 29730 index = 0; 29731 29732 reducedJSONChildren = GuideItemsContainer._super._getReducedJSON.call(this); 29733 reducedJSONChildren.items = {}; 29734 29735 29736 29737 29738 _.each(this.jsonModel.items, function (childNode, key) { 29739 reducedJSONChildren.items[key] = that.items[index]._getReducedJSON(isRepeatable); 29740 index += 1; 29741 }); 29742 return reducedJSONChildren; 29743 }, 29744 29745 _addProperty : function (oValueObject) { 29746 var sName = oValueObject.getAttribute("name"), 29747 nIndex = 0; 29748 29749 29750 29751 this._nameArray[sName] = this._nameArray[sName] || nIndex; 29752 nIndex = this._nameArray[sName]++; 29753 if (nIndex === 0) { 29754 29755 29756 29757 29758 guidelib.util.GuideUtil._createGetterSetter(this, sName, oValueObject); 29759 } 29760 return nIndex; 29761 }, 29762 29763 _getTitle : function () { 29764 return this.jsonModel["jcr:title"]; 29765 }, 29766 29767 visit : function (callback, context) { 29768 GuideItemsContainer._super.visit.apply(this, arguments); 29769 _.each(this._children, function (child, index) { 29770 child.visit(callback, context); 29771 }); 29772 }, 29773 29774 playJson : function (pJsonModel) { 29775 if (pJsonModel) { 29776 var pJsonItems = _.filter(pJsonModel.items, function (item) { 29777 if (_.isObject(item)) { 29778 return true; 29779 } 29780 return false;
29781 }, this); 29782 29783 _.each(this.items, function (childNode, index) { 29784 childNode.playJson(pJsonItems[index]); 29785 }, this); 29786 GuideItemsContainer._super.playJson.call(this, pJsonModel); 29787 } 29788 29789 }, 29790 29791 _collectValues : function (keyValue) { 29792 _.each(this._children, function (childNode) { 29793 childNode._collectValues(keyValue); 29794 }, this); 29795 }, 29796 29797 getElement : function (elClassName) { 29798 var element = _.find(this._children, function (childModel) { 29799 return childModel.className === elClassName; 29800 }, this); 29801 return element; 29802 }, 29803 29804 29805 _unloadModel : function () { 29806 _.each(this.children, function (child) { 29807 child._unloadModel(); 29808 }, this); 29809 GuideItemsContainer._super._unloadModel.call(this); 29810 }, 29811 29812 _findChildren : function (oSOM, bMultiple) { 29813 var arr = [], 29814 elemFound = false; 29815 _.find(this._children, function (child) { 29816 if (oSOM === child._escapeQualifiedName()) { 29817 arr.push(child._getNakedThis()); 29818 elemFound = true; 29819 } 29820 if (elemFound && !bMultiple) { 29821 return true; 29822 } 29823 if (elemFound && oSOM.indexOf("[*]") < 0) { 29824 return true; 29825 } 29826 }, this); 29827 return arr; 29828 }, 29829 29830 29831 resetData : function () { 29832 _.each(this._children, function (childNode) { 29833 childNode.resetData(); 29834 }, this); 29835 }, 29836 29837 29838 _changeDescendantsAccess : function (value) { 29839 _.each(this.items, function (child) { 29840 child._setParentAccess(value); 29841 if (child instanceof guidelib.model.GuideItemsContainer) { 29842 child._changeDescendantsAccess(value); 29843 } 29844 }, this); 29845 }, 29846 29847 29848 _changeContainerAccess : function (value) { 29849 this._changeDescendantsAccess(value); 29850 }, 29851 29852 29853 _changeDescendantsProperty : function (value, property, leafNodesOnly) { 29854 _.each(this.items, function (child) { 29855 if (child instanceof guidelib.model.GuideItemsContainer) { 29856 if (!leafNodesOnly) { 29857 child[property] = value; 29858 } 29859 child._changeDescendantsProperty(value, property); 29860 } else { 29861 child[property] = value; 29862 } 29863 }, this); 29864 }, 29865 29866 29867 disableAllFields : function () { 29868 this.enabled = false; 29869 var property = "enabled"; 29870 this._changeDescendantsProperty(false, property, true); 29871 } 29872 29873 }); 29874 29875 GuideItemsContainer.defineProps({ 29876 children : { 29877 get : function () { 29878 return (this._children || []).slice(0); 29879 }, 29880 set : function (value) { 29881 this._children = value; 29882 } 29883 }, 29884 29885 29886 items : { 29887 get : function () { 29888 var itemChildren = _.filter(this._children, function (child) { 29889 if (child._isItem) { 29890 return true; 29891 } 29892 return false; 29893 }, this); 29894 return itemChildren; 29895 } 29896 }, 29897 29898 _selfOrAncestorIsLazyReference : { 29899 get : function () { 29900 if (this._lazyReference) { 29901 return true; 29902 } 29903 return guidelib.util.GuideUtil._checkIfAncestorIsALazyReference(this); 29904 } 29905 }, 29906 _lazyReference : { 29907 get : function () { 29908 return !_.isUndefined(this.jsonModel["fragRef"]) 29909 && !_.isUndefined(this.jsonModel["optimizeRenderPerformance"]); 29910 } 29911 } 29912 }); 29913 29914 GuideItemsContainer.addMixins([ 29915 guidelib.model.mixin.ValidationsDisabled 29916 ]); 29917 29918}(_, guidelib)); 29919 29920(function (_, guidelib) { 29921 var GuideToolbar = guidelib.model.GuideToolbar = guidelib.model.GuideItemsContainer.extend({ 29922 msClassName : "guideToolbar", 29923 29924 initialize : function () { 29925 GuideToolbar._super.initialize.call(this); 29926 }, 29927 29928 execNavigationChangeExpression : function () { 29929 _.each(this.items, function (childModel) { 29930 if (childModel.navigationChangeExp) { 29931 this._guide().queueExpressions(childModel, "navigationChangeExp"); 29932 } 29933 }, this); 29934 } 29935 29936 }); 29937 29938})(_, guidelib); 29939 29940(function (_, guidelib) { 29941 29942 29943 var GuideCompositeField = guidelib.model.GuideCompositeField = guidelib.model.GuideItemsContainer.extend({ 29944 msClassName : "guideCompositeField", 29945 initialize : function () { 29946 this._uuid = guideBridge._produceUUID(); 29947 GuideCompositeField._super.initialize.call(this); 29948 }, 29949 29950 _setGuideValue : function (value) { 29951 if (!_.isEmpty(value)) { 29952 _.each(this.items, function (item) { 29953 if (value.hasOwnProperty(item.name) && _.isFunction(item._setGuideValue)) { 29954 item._setGuideValue(value[item.name]); 29955 } 29956 }, this); 29957 } 29958 }, 29959 29960 _collectExpressions : function () { 29961 GuideCompositeField._super._collectExpressions.apply(this); 29962 if (this.valueCommitScript) { 29963 29964 this._compiledScripts.valueCommitScript = this._compileExpression(this.valueCommitScript, null); 29965 } 29966 } 29967 }); 29968 29969 GuideCompositeField.defineProps({ 29970 valueCommitScript : { 29971 get : function () { 29972 return this.getAttribute("valueCommitScript"); 29973 } 29974 }, 29975 uuid : { 29976 get : function () { 29977 return this._uuid; 29978 }, 29979 set : function (newUuid) { 29980 if (this._uuid != newUuid) { 29981 this._uuid = newUuid; 29982 } 29983 } 29984 } 29985 }); 29986 29987})(_, guidelib); 29988 29989(function (_, guidelib) { 29990 29991 var GuideTermsAndConditions = guidelib.model.GuideTermsAndConditions = guidelib.model.GuideCompositeField.extend({ 29992 msClassName : "guideTermsAndConditions", 29993 29994 playJson : function (pJsonModel) { 29995 this.jsonModel.clickStatus = pJsonModel.clickStatus; 29996 GuideTermsAndConditions._super.playJson.apply(this, arguments); 29997 }, 29998 29999 _updateLiveData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar) { 30000 this._syncModelAndData(bound_indexedXpathSoFar, unBound_indexedXpathSoFar, '_updateLiveData'); 30001 }, 30002 30003 _playLiveData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar) { 30004 this._syncModelAndData(bound_indexedXpathSoFar, unBound_indexedXpathSoFar, '_playLiveData'); 30005 if (this.reviewStatus.value === "true") { 30006 this.clickStatus = "agree"; 30007 } else { 30008 this.clickStatus = "unreviewed"; 30009 } 30010 }, 30011 30012 _syncModelAndData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar, recurse) { 30013 if (_.isString(recurse)) { 30014 var dataContext = this._guide().internal.liveDataUtils._getDataContext(this, bound_indexedXpathSoFar, unBound_indexedXpathSoFar); 30015 if (dataContext.xmlSec === this._guide().internal.liveDataUtils.constants.BOUND_TAG) { 30016 bound_indexedXpathSoFar = dataContext.indexedXpath; 30017 } else { 30018 unBound_indexedXpathSoFar = dataContext.indexedXpath; 30019 } 30020 _.each(this.items, function (item) { 30021 if (_.isFunction(item[recurse])) { 30022 item[recurse](bound_indexedXpathSoFar, unBound_indexedXpathSoFar); 30023 } 30024 }); 30025 } 30026 } 30027 }); 30028 30029 GuideTermsAndConditions.defineProps({ 30030 showLink : { 30031 get : function () { 30032 return this.getAttribute("showLink"); 30033 } 30034 }, 30035 30036 30037 clickStatus : { 30038 get : function () { 30039 return this.getAttribute("clickStatus"); 30040 }, 30041 set : function (status) { 30042 this.setAttribute(status, "clickStatus"); 30043 } 30044 }, 30045 30046 showAsPopUp : { 30047 get : function () { 30048 return this.getAttribute("showAsPopUp"); 30049 } 30050 } 30051 }); 30052 30053})(_, guidelib); 30054(function (_, guidelib) { 30055 30056 30057 var GuideFileUpload = guidelib.model.GuideFileUpload = guidelib.model.GuideCompositeField.extend({ 30058 msClassName : "guideFileUpload", 30059 30060 _getReducedJSON : function () { 30061 this._syncModelToAttachments(); 30062 var reducedJSONChildren = GuideFileUpload._super._getReducedJSON.call(this), 30063 addtionalWhitelistedProperties = ["id", "files"]; 30064 guidelib.model.util.CommonUtils.returnMinimalJSON(addtionalWhitelistedProperties, reducedJSONChildren, this); 30065 var fileAttachmentValue = reducedJSONChildren.files; 30066 reducedJSONChildren.files = this._getFileAttachmentNames(fileAttachmentValue); 30067 return reducedJSONChildren; 30068 }, 30069 30070 _getContentType : function(fileUrl) { 30071 var contentType = null, 30072 self = this; 30073 if (self._fileAttachmentWrapper) { 30074 var element = self._fileAttachmentWrapper.find(function(x) { return x.data === fileUrl}); 30075 if (element) { 30076 contentType = element.contentType; 30077 } 30078 } 30079 return contentType 30080 }, 30081 30082 30083 _getFileAttachmentNames : function (fileAttachmentValue) { 30084 var value = fileAttachmentValue || this.value; 30085 if (value) { 30086 var self = this, 30087 fileNames = _.map(value.split("\n"), function (val) { 30088 if (self._fileAttachmentWrapper) { 30089 var element = self._fileAttachmentWrapper.find(function(x) { return x.data === val}); 30090 if (element) { 30091 return element.name; 30092 } 30093 } 30094 var fName = val; 30095 30096 if (fName.lastIndexOf("/") === fName.length - 1) { 30097 fName = fName.substring(0, fName.length - 1); 30098 } 30099 return fName.substring(fName.lastIndexOf("/") + 1); 30100 }).join("\n"); 30101 return fileNames; 30102 } 30103 }, 30104 30105 _triggerFileListChange : function () { 30106 var currValue = this._fileList; 30107 this.trigger(guidelib.event.GuideModelEvent.MODEL_CHANGED, 30108 guidelib.event.GuideModelEvent.createEvent( 30109 guidelib.event.GuideModelEvent.MODEL_CHANGED, 30110 this, 30111 "fileList", 30112 currValue, 30113 currValue 30114 ) 30115 ); 30116 }, 30117 30118 _getCurrentFileAttachmentWrapper : function(attachments) { 30119 var currentListOfAttachments = null, 30120 effectiveBindRef = this._getEffectiveBindRef(), 30121 self = this; 30122 if (_.isArray(attachments) && attachments.length > 0) { 30123 currentListOfAttachments = attachments.filter(function(x) { 30124 return x.bindRef === effectiveBindRef; 30125 }) 30126 } 30127 return currentListOfAttachments; 30128 }, 30129 30130 _playAttachmentWrappers : function(currentAttachmentWrappers) { 30131 var currValue = this.fileAttachment.value, 30132 _guide = this._guide(); 30133 if (_.isArray(currentAttachmentWrappers) && currentAttachmentWrappers.length > 0) { 30134 this._fileAttachmentWrapper = currentAttachmentWrappers; 30135 30136 if (this.valueCommitScript && _guide.version.isOn(_guide.version.Flags.RUN_VALUE_COMMMIT_ON_PREFILL) && currValue) { 30137 30138 _guide.queueExpressions(this, ["valueCommitScript"]); 30139 } 30140 var data = currentAttachmentWrappers.map(function(x) {return x.data}); 30141 30142 var fieldValue = data.join("\n"); 30143 this.fileAttachment._setGuideValue(fieldValue); 30144 if (!_.isEmpty(fieldValue)) { 30145 this._fileList = fieldValue.split("\n"); 30146 } 30147 } 30148 }, 30149 30150 playJson : function (pJsonModel, attachments) { 30151 if (attachments) { 30152 var currentListOfAttachments = this._getCurrentFileAttachmentWrapper(attachments); 30153 this._playAttachmentWrappers(currentListOfAttachments); 30154 } else { 30155 30156 GuideFileUpload._super.playJson.call(this, pJsonModel); 30157 } 30158 }, 30159 30160 _syncModelToAttachments : function () { 30161 var files = this.fileAttachment.value || "", 30162 filesArray = files.split('\n'), 30163 uniqueNames = guideBridge._makeFileNameUnique(); 30164 var isIOS = guidelib.util.GuideUtil._isIOS(); 30165 var files = this.fileAttachment.value || "", 30166 filesArray = files.split('\n'), 30167 areNamesUnique = (new Set(filesArray)).size === filesArray.length; 30168 this.jsonModel.files = 30169 _.map(files.split('\n'), function (file, index) { 30170 if (!_.isEmpty(file)) { 30171 if ((uniqueNames || (!areNamesUnique && isIOS)) && file[0] !== '/') { 30172 file = this.uuid + "-" + (index + 1) + "__afAttachment__" + file; 30173 } 30174 } 30175 return file; 30176 }, this).join('\n'); 30177 }, 30178 30179 _updateLiveData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar) { 30180 this._syncModelAndData(bound_indexedXpathSoFar, unBound_indexedXpathSoFar, "_updateLiveData"); 30181 }, 30182 30183 _playLiveData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar) { 30184 this._syncModelAndData(bound_indexedXpathSoFar, unBound_indexedXpathSoFar, "_playLiveData"); 30185 }, 30186 30187 _handleFileAttachmentItem : function (fileAttachmentModel, bound_indexedXpathSoFar, unBound_indexedXpathSoFar, recurse) { 30188 30189 var dataUtils = this._guide().internal.liveDataUtils, 30190 dataContext = dataUtils._getDataContext(fileAttachmentModel, bound_indexedXpathSoFar, unBound_indexedXpathSoFar); 30191 if (recurse == "_updateLiveData") { 30192 dataUtils._updateLazyAttachmentMapFromModel(this); 30193 dataUtils.setDataValue(dataContext.indexedXpath, dataContext.xmlSec, 30194 !fileAttachmentModel.isEmpty(), fileAttachmentModel.isEmpty() ? "" : this._getFileAttachmentValue()); 30195 } else { 30196 var data = dataUtils._getAttachmentDataForModel(this); 30197 if (!_.isArray(data) && !_.isEmpty(data)) { 30198 this.fileList = data.fileList; 30199 var fileAttachmentValue = []; 30200 var value = data.value.split("\n"); 30201 _.each(value, function (value, index) { 30202 if (value[0] != '/') { 30203 30204 30205 var name = value.substr(value.lastIndexOf("_") + 1); 30206 fileAttachmentValue.push(name); 30207 } else { 30208 30209 fileAttachmentValue.push(value); 30210 } 30211 }); 30212 fileAttachmentModel.value = fileAttachmentValue.join("\n"); 30213 } 30214 if (_.isArray(data) && data.length > 0) { 30215 this._playAttachmentWrappers(data); 30216 } 30217 this._syncModelToAttachments(); 30218 } 30219 }, 30220 30221 _syncModelAndData : func
30221tion (bound_indexedXpathSoFar, unBound_indexedXpathSoFar, recurse) { 30222 if (_.isString(recurse)) { 30223 var liveDataUtils = this._guide().internal.liveDataUtils; 30224 var dataContext = liveDataUtils._getDataContext(this, bound_indexedXpathSoFar, unBound_indexedXpathSoFar); 30225 if (dataContext.xmlSec === liveDataUtils.constants.BOUND_TAG) { 30226 bound_indexedXpathSoFar = dataContext.indexedXpath; 30227 } else { 30228 unBound_indexedXpathSoFar = dataContext.indexedXpath; 30229 } 30230 _.each(this.items, function (item) { 30231 if (_.isFunction(item[recurse])) { 30232 if (item.name == "fileAttachment") { 30233 30234 30235 this._handleFileAttachmentItem(item, bound_indexedXpathSoFar, unBound_indexedXpathSoFar, recurse); 30236 } else { 30237 item[recurse](bound_indexedXpathSoFar, unBound_indexedXpathSoFar); 30238 } 30239 } 30240 }, this); 30241 } 30242 }, 30243 30244 30245 _getIndexedXpath : function (model, bound_indexedXpathSoFar, unBound_indexedXpathSoFar) { 30246 var name = model.getAttribute("name").replace(/\s+/g, ''); 30247 return unBound_indexedXpathSoFar ? unBound_indexedXpathSoFar + '/' + name : bound_indexedXpathSoFar + '/' + name; 30248 }, 30249 30250 30251 _getFileAttachmentValue : function () { 30252 30253 30254 30255 this._syncModelToAttachments(); 30256 return this._getFileAttachmentNames(this.jsonModel.files); 30257 } 30258 30259 }); 30260 30261 GuideFileUpload.defineProps({ 30262 30263 multiSelection : { 30264 get : function () { 30265 return this.getAttribute("multiSelection"); 30266 } 30267 }, 30268 30269 buttonText : { 30270 get : function () { 30271 return this.getAttribute("buttonText"); 30272 } 30273 }, 30274 30275 showComment : { 30276 get : function () { 30277 return this.getAttribute("showComment"); 30278 } 30279 }, 30280 30281 30282 fileSizeLimit : { 30283 get : function () { 30284 return this.getAttribute("fileSizeLimit"); 30285 } 30286 }, 30287 30288 fileList : { 30289 get : function () { 30290 return this._fileList; 30291 }, 30292 30293 set : function (newValue) { 30294 var oldValue = this._fileList; 30295 var newTypedValue = newValue; 30296 if (newTypedValue != oldValue) { 30297 this._fileList = newTypedValue; 30298 } 30299 30300 30301 30302 var isIOS = guidelib.util.GuideUtil._isIOS(), 30303 fileList = this._fileList, 30304 that = this; 30305 if (isIOS && fileList) { 30306 30307 this._fileAttachmentWrapperIOS = []; 30308 30309 for (var i = 0; i < fileList.length; i++) { 30310 if (!_.isString(fileList[i])) { 30311 30312 var files = fileList[i].get(0).files, 30313 _readFile = function (file) { 30314 30315 that._fileAttachmentWrapperIOS.push( 30316 new Promise(function(resolve, reject){ 30317 var reader = new FileReader(); 30318 reader.onload = function() { 30319 var faWrapper = new guidelib.model.FileAttachmentWrapper({ 30320 name: file.name, 30321 data: this.result, 30322 formElementName : that.name, 30323 contentType: file.type, 30324 bindRef: that._getEffectiveBindRef() 30325 }); 30326 resolve(faWrapper); 30327 }; 30328 reader.onerror = reject;
30329 reader.readAsDataURL(file); 30330 }) 30331 ) 30332 }; 30333 if (files) { 30334 30335 [].forEach.call(files, _readFile); 30336 } 30337 } 30338 } 30339 } 30340 this._triggerFileListChange(); 30341 } 30342 }, 30343 value : { 30344 get : function () { 30345 this._syncModelToAttachments(); 30346 return this.jsonModel.files; 30347 } 30348 } 30349 }); 30350 30351})(_, guidelib); 30352 30353(function (_, guidelib) { 30354 var GuideAdModuleGroup = guidelib.model.GuideAdModuleGroup = guidelib.model.GuideItemsContainer.extend({ 30355 msClassName : "guideAdModuleGroup", 30356 30357 _getTypedValue : function (value) { 30358 30359 if (_.isUndefined(value) || value === null) { 30360 return null; 30361 } 30362 return value + ""; 30363 }, 30364 30365 playJson : function (pJsonModel) { 30366 var typedValue = this._getTypedValue(pJsonModel._value); 30367 30368 if (typedValue || typedValue === "") { 30369 30370 var olval = this.jsonModel._value; 30371 this.jsonModel._value = pJsonModel._value; 30372 this._triggerOnBridge("elementValueChanged", this, "value", olval, this.jsonModel._value); 30373 } else { 30374 30375 GuideAdModuleGroup._super.playJson.call(this, pJsonModel); 30376 } 30377 } 30378 }); 30379 30380 GuideAdModuleGroup.defineProps({ 30381 30382 value : { 30383 get : function () { 30384 return this._getTypedValue(this.jsonModel._value); 30385 }, 30386 set : function (newValue) { 30387 var oldValue = this._getTypedValue(this.jsonModel._value), 30388 newTypedValue = this._getTypedValue(newValue); 30389 30390 if (newTypedValue !== undefined && (newTypedValue !== oldValue)) { 30391 if (this.jsonModel._value !== newValue) { 30392 this.jsonModel._value = newTypedValue || ""; 30393 } 30394 this._triggerOnBridge("elementValueChanged", this, "value", oldValue, newTypedValue); 30395 } 30396 } 30397 } 30398 }); 30399 30400}(_, guidelib)); 30401(function (_, guidelib) { 30402 guidelib.model.mixin.AddDependencyMgmt = { 30403 normalProperties : { 30404 _addDependant : function (oNode, expressionType) { 30405 var dependantConf = this._findDependant(oNode); 30406 if (!dependantConf) { 30407 dependantConf = {dependant : oNode, events : []}; 30408 this.dependants.push(dependantConf); 30409 } 30410 30411 if (dependantConf.events.indexOf(expressionType) < 0) { 30412 dependantConf.events.push(expressionType); 30413 oNode.on(guidelib.event.GuideModelEvent.OBJECT_DESTROYED, this._handleDependentDestroyed, this); 30414 } 30415 }, 30416 30417 _notifyDependants : function () { 30418 _.each(this.dependants, function (dependantConf) { 30419 this._guide().queueExpressions(dependantConf.dependant, dependantConf.events); 30420 }, this); 30421 }, 30422 30423 _removeDependant : function (oNode) { 30424 oNode.off(guidelib.event.GuideModelEvent.OBJECT_DESTROYED, this._handleDependentDestroyed, this); 30425 var dependantConf = this._findDependant(oNode); 30426 this.dependants = _.without(this.dependants, dependantConf); 30427 }, 30428 30429 _findDependant : function (oNode) { 30430 return _.find(this.dependants, function (conf) { return (conf.dependant === oNode); }); 30431 }, 30432 30433 _handleDependentDestroyed : function (event) { 30434 this._removeDependant(event.target); 30435 } 30436 } 30437 }; 30438})(_, guidelib); 30439 30440(function (_, guidelib) { 30441 var GuideChart = guidelib.model.GuideChart = guidelib.model.Scriptable.extend({ 30442 msClassName : "guideChart", 30443 30444 _collectExpressions : function () { 30445 GuideChart._super._collectExpressions.apply(this); 30446 this._compiledExpressions["aggregateExp"] = this._compileExpression('guidelib.chartUtils.gatherAxisData(this);', "data"); 30447 } 30448 }); 30449 30450 GuideChart.defineProps({ 30451 30452 data : { 30453 get : function () { 30454 var context = this._guide()._currentContext; 30455 if (context && context.contextNode && context.expression 30456 && !(context.contextNode === this && context.expression === "aggregateExp")) { 30457 this._addDependant(context.contextNode, context.expression); 30458 } 30459 return this.jsonModel.data; 30460 }, 30461 30462 set : function (newValue) { 30463 var oldValue = this.jsonModel.data; 30464 this.jsonModel.data = newValue; 30465 30466 var valueHasChanged = !_.isEqual(oldValue, newValue); 30467 if (valueHasChanged) { 30468 30469 this._notifyDependants(); 30470 this._triggerEvent(guidelib.event.GuideModelEvent.MODEL_CHANGED, "data", oldValue, newValue); 30471 } 30472 } 30473 }, 30474 30475 30476 dataSourceType : { 30477 get : function () { 30478 return this.getAttribute("dataSourceType"); 30479 }, 30480 set : function (newValue) { 30481 var oldValue = this.jsonModel.dataSourceType; 30482 this.jsonModel.dataSourceType = newValue; 30483 this._triggerEvent(guidelib.event.GuideModelEvent.MODEL_CHANGED, "dataSourceType", oldValue, newValue); 30484 } 30485 }, 30486 30487 30488 width : { 30489 get : function () { 30490 return this.getAttribute("width"); 30491 }, 30492 30493 set : function (newValue) { 30494 this.jsonModel.width = newValue; 30495 } 30496 }, 30497 30498 height : { 30499 get : function () { 30500 return this.getAttribute("height"); 30501 }, 30502 30503 set : function (newValue) { 30504 this.jsonModel.height = newValue; 30505 } 30506 }, 30507 30508 xAxisTitle : { 30509 get : function () { 30510 return this.getAttribute("xAxisTitle"); 30511 }, 30512 set : function (newValue) { 30513 this.jsonModel.chartType = newValue; 30514 } 30515 }, 30516 30517 yAxisTitle : { 30518 get : function () { 30519 return this.getAttribute("yAxisTitle"); 30520 }, 30521 set : function (newValue) { 30522 this.jsonModel.chartType = newValue; 30523 } 30524 }, 30525 30526 chartType : { 30527 get : function () { 30528 return this.getAttribute("chartType"); 30529 }, 30530 set : function (newValue) { 30531 var oldValue = this.jsonModel.chartType; 30532 this.jsonModel.chartType = newValue; 30533 this._triggerEvent(guidelib.event.GuideModelEvent.MODEL_CHANGED, "chartType", oldValue, newValue); 30534 } 30535 }, 30536 30537 repeatableItem : { 30538 get : function () { 30539 return this.getAttribute("repeatableItem"); 30540 }, 30541 set : function (newValue) { 30542 this.jsonModel.repeatableItem = newValue; 30543 } 30544 }, 30545 30546 xExp : { 30547 get : function () { 30548 return this.getAttribute("xExp"); 30549 }, 30550 set : function (newValue) { 30551 this.jsonModel.xExp = newValue; 30552 } 30553 }, 30554 30555 reducerXFunction : { 30556 get : function () { 30557 return this.getAttribute("reducerXFunction"); 30558 }, 30559 set : function (newValue) { 30560 this.jsonModel.reducerXFunction = newValue; 30561 if (newValue !== 'none') {
30562 this.jsonModel.reducerYFunction = 'none'; 30563 } 30564 } 30565 }, 30566 30567 yExp : { 30568 get : function () { 30569 return this.getAttribute("yExp"); 30570 }, 30571 set : function (newValue) { 30572 this.jsonModel.yExp = newValue; 30573 } 30574 }, 30575 30576 reducerYFunction : { 30577 get : function () { 30578 return this.getAttribute("reducerYFunction"); 30579 }, 30580 set : function (newValue) { 30581 this.jsonModel.reducerYFunction = newValue; 30582 if (newValue !== 'none') { 30583 this.jsonModel.reducerXFunction = 'none'; 30584 } 30585 } 30586 }, 30587 30588 innerRadius : { 30589 get : function () { 30590 return this.getAttribute("innerRadius"); 30591 }, 30592 set : function (newValue) { 30593 this.jsonModel.innerRadius = newValue; 30594 } 30595 }, 30596 30597 lineColor : { 30598 get : function () { 30599 return this.getAttribute("lineColor"); 30600 }, 30601 set : function (newValue) { 30602 this.jsonModel.lineColor = newValue; 30603 } 30604 }, 30605 30606 pointColor : { 30607 get : function () { 30608 return this.getAttribute("pointColor"); 30609 }, 30610 set : function (newValue) { 30611 this.jsonModel.pointColor = newValue; 30612 } 30613 }, 30614 30615 areaColor : { 30616 get : function () { 30617 return this.getAttribute("areaColor"); 30618 }, 30619 set : function (newValue) { 30620 this.jsonModel.areaColor = newValue; 30621 } 30622 }, 30623 30624 tooltipHtml : { 30625 get : function () { 30626 return this.getAttribute("tooltipHtml"); 30627 }, 30628 set : function (newValue) { 30629 this.jsonModel.tooltipHtml = newValue; 30630 } 30631 }, 30632 30633 showLegends : { 30634 get : function () { 30635 return this.getAttribute("showLegends"); 30636 }, 30637 set : function (newValue) { 30638 this.jsonModel.showLegends = newValue; 30639 } 30640 }, 30641 30642 legendPosition : { 30643 get : function () { 30644 return this.getAttribute("legendPosition"); 30645 }, 30646 set : function (newValue) { 30647 this.jsonModel.legendPosition = newValue; 30648 } 30649 } 30650 }); 30651 30652 GuideChart.addMixins([ 30653 guidelib.model.mixin.AddDependencyMgmt 30654 ]); 30655}(_, guidelib)); 30656(function (_, guidelib) { 30657 30658 var GuideInstanceManager = guidelib.model.GuideInstanceManager = guidelib.model.GuideNode.extend({ 30659 msClassName : "guideInstanceManager", 30660 initialize : function () { 30661 GuideInstanceManager._super.initialize.call(this); 30662 this._instances = []; 30663 this.dependants = []; 30664 this.deafen = false; 30665 this._bindPending = true; 30666 }, 30667 30668 _postInitializeBinding : function () { 30669 30670 30671 30672 if (!this._bindPending) { 30673 return; 30674 } else { 30675 this._bindPending = false; 30676 } 30677 30678 30679 30680 30681 30682 30683 var instance = this._instances[this.instanceCount - 1]; 30684 if (!instance) { 30685 this.logger().log("There was no instance found for InstanceManager at postInitialize:" + this.somExpression); 30686 } 30687 if (instance.bindNode && instance.bindNode.instanceManager) { 30688 this.bindNode = instance.bindNode.instanceManager; 30689 this.bindNode.parent.on(xfalib.script.XfaModelEvent.CHILD_ADDED, this); 30690 this.bindNode.parent.on(xfalib.script.XfaModelEvent.CHILD_REMOVED, this); 30691 } 30692 }, 30693 30694 _unloadModel : function () { 30695 var instance = this._instances[this.instanceCount - 1]; 30696 30697 if (instance.bindNode && instance.bindNode.instanceManager) { 30698 this.bindNode.parent.off(xfalib.script.XfaModelEvent.CHILD_ADDED, this); 30699 this.bindNode.parent.off(xfalib.script.XfaModelEvent.CHILD_REMOVED, this); 30700 } 30701 30702 GuideInstanceManager._super._unloadModel.call(this); 30703 }, 30704 30705 30706 handleEvent : function (event) { 30707 if (!this.deafen && event instanceof xfalib.script.XfaModelEvent) { 30708 switch (event.name) { 30709 case xfalib.script.XfaModelEvent.CHILD_ADDED: 30710 var addedInstance = event.newText; 30711 if (addedInstance.instanceManager == this.bindNode) { 30712 this._insertInstance(addedInstance.instanceIndex, addedInstance); 30713 } 30714 break; 30715 case xfalib.script.XfaModelEvent.CHILD_REMOVED: 30716 var removedInstance = event.prevText; 30717 if (removedInstance.instanceManager == this.bindNode) { 30718 this._removeInstance(removedInstance.instanceIndex, false); 30719 } 30720 break; 30721 case xfalib.script.XfaModelEvent.CHILD_MOVED: 30722 this.logger().log("CHILD_REMOVED should never be dispatched. It's achieved via ad and remove child."); 30723 break; 30724 default: 30725 30726 break; 30727 } 30728 } 30729 }, 30730 30731 _instanceTemplate : function () { 30732 return this._guide()._modelTemplateCacheStore.cloneJsonTemplate(this.jsonModel.instanceTemplateId); 30733 }, 30734 30735 30736 addInstance : function (addedXfaInstance) { 30737 return this._insertInstance(undefined, addedXfaInstance); 30738 }, 30739 30740 30741 addInstances : function (instancesConfig, addedXfaInstances) { 30742 var instanceCount = instancesConfig.instanceCount, 30743 instancesToAdd, availableInstances; 30744 if (this.maxOccur == -1) { 30745 instancesToAdd = instanceCount; 30746 }else { 30747 availableInstances = this.maxOccur - this.instanceCount; 30748 30749 instancesToAdd = instanceCount > availableInstances ? availableInstances : instanceCount; 30750 } 30751 var oChildsAdded = []; 30752 for (var i = 0; i < instancesToAdd ; i++) { 30753 oChildsAdded.push(this._insertInstance(undefined, addedXfaInstances, true)); 30754 } 30755 var oParentContainer = this.parent; 30756 oParentContainer._triggerEvent(guidelib.event.GuideModelEvent.MULTIPLE_CHILD_ADDED, "multipleChildAdded", 30757 null, oChildsAdded); 30758 }, 30759 30760 _manageChild : function (oCreatedChild, nIndex) { 30761 oCreatedChild._instanceManager = this; 30762 if (nIndex === undefined) { 30763 this._instances.push(oCreatedChild); 30764 } else { 30765 this._instances.splice(nIndex, 0, oCreatedChild); 30766 } 30767 }, 30768 30769 30770 _insertInstance : function (nIndex, addedXfaInstance, muteEvent) { 30771 if ((+this.maxOccur >= 0) && (+this.maxOccur == this.instanceCount)) { 30772 return null; 30773 } 30774 30775 if (nIndex !== undefined && nIndex > +this.maxOccur && +this.maxOccur > -1) { 30776 return null; 30777 } 30778 30779 var addedBindNode = addedXfaInstance; 30780 if (addedXfaInstance && this.bindNode == null) { 30781 this.logger().error("AF", "Invalid argument addedXfaInstance."); 30782 } 30783 if (!addedXfaInstance && this.bindNode) { 30784 this.deafen = true; 30785 try { 30786 30787 addedBindNode = this.bindNode.insertInstance(nIndex); 30788 } 30789 finally { 30790 this.deafen = false;
30791 } 30792 } 30793 var template = this._instanceTemplate(); 30794 30795 30796 30797 var clonedJson = {}; 30798 var uniquePrefix = this.guideUtil.generateUID(), 30799 that = this; 30800 this.copyObject(template, clonedJson, 30801 { 30802 transformMaps : { 30803 "id" : function (srcValue, options, parentObj) { 30804 return uniquePrefix + "__" + parentObj.templateId; 30805 }, 30806 30807 30808 30809 "bindRef" : function (originalBindRef, options, src) { 30810 if (addedBindNode != null && that.bindNode != null) { 30811 if (template.bindRef === originalBindRef) { 30812 return addedBindNode.somExpression; 30813 } else if (originalBindRef.substring(0, template.bindRef.length) === template.bindRef) { 30814 return originalBindRef.replace(template.bindRef, addedBindNode.somExpression); 30815 } 30816 } 30817 30818 return originalBindRef; 30819 } 30820 } 30821 } 30822 ); 30823 30824 var options = ((addedBindNode && this.bindNode) ? {bindNode : addedBindNode} : null); 30825 if (this.options._guideContainer) { 30826 options = _.extend({}, options, {"_guideContainer" : this.options._guideContainer}); 30827 } 30828 var oChildAdded = guidelib.model.GuideModelRegistry.prototype.createModel(clonedJson, options); 30829 if (oChildAdded != null) { 30830 30831 30832 30833 this._manageChild(oChildAdded, nIndex); 30834 var oParentContainer = this.parent; 30835 if (oParentContainer != null) { 30836 if (this._instances.length > 0) { 30837 30838 30839 30840 30841 nIndex = nIndex !== undefined ? nIndex : this._instances.length - 1 ; 30842 if(nIndex === 0 ) { 30843 30844 30845 30846 oParentContainer._addChildAt(oChildAdded, oParentContainer._children.indexOf(this) + 1, muteEvent); 30847 } else { 30848 var lastInstanceIndex = oParentContainer._children.indexOf(this._instances[nIndex - 1]); 30849 oParentContainer._addChildAt(oChildAdded, lastInstanceIndex + 1, muteEvent); 30850 } 30851 } else { 30852 30853 30854 30855 30856 oParentContainer._addChildAt(oChildAdded, oParentContainer._children.indexOf(this) + 1, muteEvent); 30857 } 30858 var guideStateConstants = guidelib.model.GuideSchema.prototype.GuideStateConstants; 30859 var dataUtils = this._guide().internal.liveDataUtils; 30860 if (this._isDataNodeUpdateRequired(oChildAdded)) { 30861 var parentNode = dataUtils.getParentDataNode(this._getDataContext(oChildAdded), true, {}); 30862 var index = dataUtils._convertModelIndexToDataIndex(oChildAdded.instanceIndex); 30863 var node = dataUtils._getElement(parentNode, oChildAdded._getDataNodeName(), {index : index}); 30864 30865 30866 if (!node || (node && !(oChildAdded.instanceIndex == this._instances.length - 1))) { 30867 var dataNode = dataUtils.insertNode(parentNode, oChildAdded._getDataNodeName(), oChildAdded.instanceIndex); 30868 if (!dataNode) { 30869 this.logger().warn("AF", "Unable to store the data of the element"); 30870 } 30871 } 30872 } 30873 } 30874 this._execExpressions(nIndex); 30875 return oChildAdded; 30876 } else { 30877 this.logger().log("guide", "insertInstance could not create child" + this.jsonModel.instanceTemplateId); 30878 } 30879 return null; 30880 }, 30881 30882 30883 insertInstance : function (nIndex) { 30884 return this._insertInstance(nIndex); 30885 }, 30886 30887 30888 removeInstance : function (index) { 30889 this._removeInstance(index, true); 30890 }, 30891 30892 30893 _removeInstance : function (index, removeXfaInstance) { 30894 30895 if (this.instanceCount == 0 || this.minOccur >= this.instanceCount) { 30896 return; 30897 } 30898 30899 if (index >= +this.instanceCount) { 30900 return; 30901 } 30902 30903 if (removeXfaInstance && this.bindNode) { 30904 this.deafen = true; 30905 try { 30906 this.bindNode.removeInstance(index); 30907 } 30908 finally { 30909 this.deafen = false;
30910 } 30911 } 30912 30913 30914 30915 var oChild = this._instances[index]; 30916 var dataUtils = this._guide().internal.liveDataUtils; 30917 if (this._isDataNodeUpdateRequired(oChild)) { 30918 var parentNode = dataUtils.getParentDataNode(this._getDataContext(oChild)); 30919 dataUtils.removeChild(parentNode, oChild._getDataNodeName(), oChild.instanceIndex); 30920 } 30921 this._instances.splice(index, 1); 30922 var parent = oChild.parent; 30923 parent._removeChild(oChild); 30924 this._execExpressions(index); 30925 }, 30926 30927 _isDataNodeUpdateRequired : function (child) { 30928 var guideStateConstants = guidelib.model.GuideSchema.prototype.GuideStateConstants, 30929 guide = guideBridge._guide; 30930 return guide && guide.getGuideState() === guideStateConstants.GUIDE_STATE_MODEL_COMPLETE 30931 && child._hasLazyDescendant; 30932 }, 30933 30934 _getDataContext : function (model) { 30935 var dataUtils = this._guide().internal.liveDataUtils, 30936 elementContext = dataUtils._getXpathContext(model), 30937 xmlContext = dataUtils._getDataContext(model, elementContext.bound, 30938 elementContext.unBound), 30939 xpath = xmlContext.indexedXpath; 30940 xpath = dataUtils.addIndexToPath(xpath, model.instanceIndex); 30941 return { 30942 indexedXpath : xpath, 30943 xmlSec : xmlContext.xmlSec 30944 }; 30945 }, 30946 30947 _getInstanceName : function () { 30948 return this.jsonModel.instanceName; 30949 }, 30950 30951 _instanceIsTableRow : function () { 30952 30953 return this._instanceTemplate()["guideNodeClass"] === "guideTableRow"; 30954 }, 30955 30956 30957 _execExpressions : function (modifiedIndex) { 30958 try { 30959 30960 this._notifyDependants(); 30961 30962 30963 for (var i = modifiedIndex; i < this.instances.length; i++) { 30964 this.instances[i]._notifyDependants(); 30965 } 30966 30967 this._guide().runPendingExpressions(); 30968 } catch (ex) { 30969 this.logger().error("guide", ex.message); 30970 } 30971 } 30972 30973 }); 30974 GuideInstanceManager.defineProps({ 30975 30976 minOccur : { 30977 get : function () { 30978 var isTableRow = this._instanceIsTableRow(); 30979 30980 if (isTableRow) { 30981 return ((+this.jsonModel.minOccur) || 1); 30982 } else { 30983 return this.getOrElse(this.jsonModel.minOccur, 1); 30984 } 30985 } 30986 }, 30987 30988 30989 maxOccur : { 30990 get : function () { 30991 return this.getOrElse(this.jsonModel.maxOccur, 1); 30992 } 30993 }, 30994 30995 initialOccur : { 30996 get : function () { 30997 return this.getOrElse(this.jsonModel.initialOccur, 1); 30998 } 30999 }, 31000 31001 31002 instanceTemplateId : { 31003 get : function () { 31004 return this.jsonModel.instanceTemplateId; 31005 } 31006 }, 31007 31008 31009 instanceCount : { 31010 get : function () { 31011 var context = this._guide()._currentContext; 31012 if (context && context.managedExp) { 31013 31014 this._addDependant(context.contextNode, context.expression); 31015 } 31016 return this._instances.length ; 31017 } 31018 }, 31019 31020 31021 repeatable : { 31022 get : function () { 31023 return (this.minOccur != 1 || this.maxOccur != 1); 31024 } 31025 }, 31026 31027 instances : { 31028 31029 get : function () { 31030 var context = this._guide()._currentContext; 31031 if (context && context.managedExp) { 31032 31033 this._addDependant(context.contextNode, context.expression); 31034 } 31035 return (this._instances || []).slice(0); 31036 } 31037 } 31038 }); 31039 31040 GuideInstanceManager.addMixins([ 31041 guidelib.model.mixin.AddDependencyMgmt 31042 ]); 31043})(_, guidelib); 31044(function (_, guidelib) { 31045 31046 31047 var Field = guidelib.model.Field = guidelib.model.Scriptable.extend({ 31048 msClassName : "field", 31049 31050 _runValidation : true, 31051 initialize : function () { 31052 Field._super.initialize.call(this); 31053 this.jsonModel["{default}"] = this.getOrElse(this.jsonModel, "{default}", this.jsonModel._value); 31054 this.isValid = true; 31055 this.forceErrorShow = false;
31056 31057 this._bParentValidationsDisabled = false; 31058 31059 this._validationsDisabled = false; 31060 31061 this._failedTest = null; 31062 31063 31064 this._errorText = ""; 31065 31066 var effectiveBindRef = this._getEffectiveBindRef(); 31067 31068 if (this.isGlobal || (this._guide() && this._guide().internal.liveModel.isLive(effectiveBindRef))) { 31069 this._guide().internal.liveModel.add(effectiveBindRef, this); 31070 } 31071 }, 31072 _postInitialize: function() { 31073 Field._super._postInitialize.call(this); 31074 if (this.getAttribute("dorExclusion") !== null && this.jsonModel.visible === false) { 31075 if ((this._guide().getAttribute("excludeFromDoRIfHidden") === "true") 31076 || 31077 (this._guide().print && 31078 this._guide().print["excludeFromDoRIfHidden"] === "true")) { 31079 this.dorExclusion = true; 31080 } 31081 } 31082 }, 31083 _unloadModel : function () { 31084 var effectiveBindRef = this.bindRef || this.getAttribute("name"); 31085 if (this.isGlobal || this._guide().internal.liveModel.isLive(effectiveBindRef)) { 31086 this._guide().internal.liveModel.remove(effectiveBindRef, this); 31087 } 31088 Field._super._unloadModel.call(this); 31089 }, 31090 31091 _collectExpressions : function () { 31092 Field._super._collectExpressions.apply(this); 31093 if (this.calcExp) { 31094 this._compiledExpressions.calcExp = this._compileExpression(this.calcExp, "value"); 31095 } 31096 if (this.validateExp) { 31097 31098 this._compiledScripts.validateExp = this._compileExpression(this.validateExp, null); 31099 } 31100 if (this.valueCommitScript) { 31101 31102 31103 this._compiledScripts.valueCommitScript = this._compileExpression(this.valueCommitScript, null); 31104 } 31105 31106 this._compiledScripts.validateAllExp = this._compileExpression("this._runTests()", null); 31107 }, 31108 31109 _handleXfaModelChanged : function (event) { 31110 if (event._property === "rawValue") { 31111 this._triggerEvent(guidelib.event.GuideModelEvent.VALUE_CHANGED, "value", 31112 event.prevText, event.newText); 31113 } else if (event._property == "ClearError" || event._property == "ValidationState") { 31114 31115 this._guide().queueExpressions(this, ["validateAllExp"]); 31116 } else { 31117 Field._super._handleXfaModelChanged.call(this, event); 31118 } 31119 }, 31120 31121 31122 31123 validate : function (errorList) { 31124 31125 if (!this.visible) { 31126 return true; 31127 } 31128 if (_.isUndefined(errorList)) { 31129 errorList = []; 31130 } 31131 var status = true; 31132 this._runTests(true); 31133 if (this._errorText) { 31134 errorList.push({ 31135 som : this.somExpression, 31136 errorText : this._errorText 31137 }); 31138 status = false; 31139 } 31140 return status; 31141 }, 31142 31143 _getTypedValue : function (value) { 31144 if (this.checkIfNull(value)) { 31145 return null; 31146 } 31147 return value + ""; 31148 }, 31149 31150 _getFormattedValue : function (value) { 31151 if (_.isUndefined(value) || value === null || value === "") { 31152 return null; 31153 } 31154 31155 var picture = this.jsonModel.displayPictureClause; 31156 31157 if (picture) { 31158 try { 31159 31160 var formattedValue = xfalib.ut.PictureFmt.format(value + "", picture, null, true); 31161 31162 return formattedValue != null && formattedValue !== "" ? formattedValue : value; 31163 } catch (exception) { 31164 31165 } 31166 } 31167 return value; 31168 }, 31169 31170 _getValue : function () { 31171 if (this.bindNode) { 31172 return this.bindNode.rawValue; 31173 } 31174 return this._getTypedValue(this.jsonModel._value); 31175 }, 31176
31177 _triggerDisplayFormatChange : function () { 31178 var currValue = this._getValue(); 31179 this._triggerEvent(guidelib.event.GuideModelEvent.VALUE_CHANGED, "value", 31180 currValue, this._getFormattedValue(currValue)); 31181 }, 31182 31183 31184 checkIfNull : function (value) { 31185 return value == null || value === ""; 31186 }, 31187 31188 31189 isEmpty : function () { 31190 return this.checkIfNull(this.value); 31191 }, 31192 31193 _setXFAValue : function (value) { 31194 this.bindNode.rawValue = value; 31195 }, 31196 31197 31198 _setXFAMandatory : function (value) { 31199 31200 31201 var convertor = this._guide()._guideSchema.getConvertor("mandatory"); 31202 if (convertor) { 31203 31204 31205 this.bindNode.validate.nullTest = convertor.guideToXfa.apply(this, [!!value]); 31206 } 31207 }, 31208 31209 _setGuideValue : function (value) { 31210 this.jsonModel._value = (value === undefined || value === null) ? null : value; 31211 }, 31212 31213 _runMandatoryTest : function () { 31214 var currValue = this._getValue(), 31215 isNull = this.checkIfNull(currValue); 31216 return !isNull; 31217 }, 31218 31219 _runValidatePictureTest : function () { 31220 var value = this._getValue(), 31221 validateFlag = true, 31222 regex; 31223 if (!this.checkIfNull(value) && this.validatePictureClause) { 31224 31225 try { 31226 value = xfalib.ut.PictureFmt.format(value + "", this.validatePictureClause, null, false); 31227 } catch (exception) { 31228 31229 this.logger().log("AF", exception); 31230 31231 if (exception.indexOf("Invalid picture clause") !== -1) { 31232 value = undefined; 31233 } else { 31234 value = null; 31235 } 31236 } 31237 } 31238 if (_.isUndefined(value)) { 31239 try { 31240 31241 regex = new RegExp(this.validatePictureClause); 31242 if (regex) { 31243 validateFlag = regex.test(this._getValue()); 31244 } 31245 } catch (exception) { 31246 31247 this.logger().error("AF", "Invalid Regular Expression" + exception); 31248 validateFlag = false; 31249 } 31250 } else if (value === null) { 31251 validateFlag = false; 31252 } 31253 31254 return validateFlag; 31255 }, 31256 31257 31258 _runTests : function (forceRun) { 31259 31260 var validFlag = true, 31261 prevErrorText = this._errorText, 31262 prevValidationState = this.validationState, 31263 obj = { 31264 'validFlag' : validFlag, 31265 'forceRun' : forceRun 31266 }; 31267 31268 if (this.validationsDisabled === true) { 31269 31270 31271 return true; 31272 } 31273 31274 this._runValidations(obj); 31275 validFlag = obj.validFlag; 31276 31277 if (validFlag) { 31278 this._errorText = ""; 31279 this.validationState = true; 31280 31281 this._failedTest = null; 31282 } else { 31283 this.validationState = false; 31284 } 31285 31286 if ((prevErrorText !== this._errorText) || (prevValidationState !== this.validationState) || forceRun) { 31287 31288 if (forceRun) { 31289 this.forceErrorShow = true; 31290 } 31291 this._triggerEvent(guidelib.event.GuideModelEvent.ERROR_CHANGED, 31292 "validationStatus", this.validationState, this._errorText); 31293 } 31294 31295 return this.validationState; 31296 }, 31297 31298 playJson : function (pJsonModel) { 31299 var currValue = pJsonModel._value, 31300 _guide = this._guide(); 31301 31302 if (this.valueCommitScript && _guide.version.isOn(_guide.version.Flags.RUN_VALUE_COMMMIT_ON_PREFILL) && currValue) { 31303 31304 _guide.queueExpressions(this, ["valueCommitScript"]); 31305 } 31306 this._setGuideValue(pJsonModel._value); 31307 }, 31308 31309 31310 _runValidations : function (obj) { 31311 var isRegex = false, 31312 INVALID_PICTURE_CLAUSE_LIST = ["date.default{}", "date.short{}", "date.medium{}", 31313 "date.long{}", "date.full{}", "num.percent{}", "num.decimal{}", "num.currency{}"]; 31314 if (this.bindNode) { 31315 if (this.validatePictureClause && (this.value || this.value === 0)) { 31316 31317 31318 try { 31319 xfalib.ut.PictureFmt.format(this.value + "", this.validatePictureClause, null, false); 31320 } catch (exception) { 31321 if (INVALID_PICTURE_CLAUSE_LIST.indexOf(this.validatePictureClause) >= 0) { 31322 isRegex = false;
31323 } else if (exception.indexOf("Invalid picture clause") !== -1) { 31324 isRegex = true; 31325 } 31326 } 31327 } 31328 if (isRegex) { 31329 try { 31330 31331 var regex = new RegExp(this.validatePictureClause); 31332 if (regex) { 31333 obj.validFlag = regex.test(this._getValue()); 31334 } 31335 } catch (exception) { 31336 this.logger().error("AF", "Error in running regular expression" + exception); 31337 obj.validFlag = false; 31338 } 31339 if (!obj.validFlag) { 31340 this.bindNode._setErrorData("formatTest", this.getOrElse(this.bindNode.validate.formatTest, this.bindNode._defaults.validate.formatTest), this.bindNode.formatMessage); 31341 this._errorText = this.bindNode._errorText; 31342 xfalib.ut.XfaUtil.prototype._triggerOnBridge("elementValidationStatusChanged", this.bindNode, "validationStatus", false, true); 31343 this.bindNode.execEvent("validationState"); 31344 } 31345 } else { 31346 if (obj.forceRun) { 31347 this.bindNode.execValidate(); 31348 } 31349 this._errorText = this.bindNode._errorText; 31350 if (this._errorText) { 31351 obj.validFlag = false; 31352 } 31353 } 31354 31355 this._failedTest = this.bindNode._mFailedValTest; 31356 } else { 31357 31358 if (this.mandatory) { 31359 obj.validFlag = this._runMandatoryTest(); 31360 if (!obj.validFlag) { 31361 this._errorText = this.mandatoryMessage; 31362 this._failedTest = this.guideUtil.MANDATORY_TEST; 31363 } 31364 } 31365 if (obj.validFlag && this.validatePictureClause && !this.checkIfNull(this.value)) { 31366 obj.validFlag = this._runValidatePictureTest(); 31367 if (!obj.validFlag) { 31368 this._errorText = this.validatePictureClauseMessage; 31369 this._failedTest = this.guideUtil.FORMAT_TEST; 31370 } 31371 } 31372 } 31373 31374 if (obj.validFlag && this.validateExp) { 31375 obj.validFlag = this.executeExpression("validateExp"); 31376 if (!obj.validFlag) { 31377 this._errorText = this.validateExpMessage; 31378 this._failedTest = this.guideUtil.SCRIPT_TEST; 31379 } 31380 } 31381 }, 31382 31383 _collectValues : function (keyValue) { 31384 31385 keyValue[this.name] = this.value; 31386 }, 31387 31388 31389 resetData : function () { 31390 this._runValidation = false; 31391 this.value = this.jsonModel["{default}"]; 31392 this._runValidation = true; 31393 31394 this._errorText = ""; 31395 this.validationState = true; 31396 this._failedTest = null; 31397 this._triggerEvent(guidelib.event.GuideModelEvent.ERROR_RESET, 31398 "validationStatus", this.validationState, this._errorText); 31399 }, 31400 31401 _preserveLazyValue : function () { 31402 return !(_.contains(['guideButton', 'guideTextDraw', 'guideAdobeSignBlock'], this.className) || this._isXfaNode()); 31403 }, 31404 31405 31406 _updateLiveData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar) { 31407 if (this._preserveLazyValue()) { 31408 var dataUtils = this._guide().internal.liveDataUtils, 31409 dataContext = dataUtils._getDataContext(this, bound_indexedXpathSoFar, 31410 unBound_indexedXpathSoFar), 31411 isRichText = this instanceof guidelib.model.GuideTextBox && this.allowRichText, 31412 setValue = isRichText ? dataUtils.setRichTextValue : dataUtils.setDataValue; 31413 setValue.apply(dataUtils, [dataContext.indexedXpath, dataContext.xmlSec, 31414 !this.isEmpty(), this.isEmpty() ? "" : this.value]); 31415 } 31416 }, 31417 31418 31419 _playLiveData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar) { 31420 if (this._preserveLazyValue()) { 31421 var dataUtils = this._guide().internal.liveDataUtils, 31422 dataContext = dataUtils._getDataContext(this, bound_indexedXpathSoFar, 31423 unBound_indexedXpathSoFar), 31424 isRichText = this instanceof guidelib.model.GuideTextBox && this.allowRichText, 31425 getValue = isRichText ? dataUtils.getRichTextValue : dataUtils.getDataValue; 31426 var value = getValue.apply(dataUtils, [dataContext.indexedXpath, dataContext.xmlSec]); 31427 if (value != undefined) { 31428 this.value = value; 31429 } else if (this.jsonModel && this.jsonModel._value) { 31430 31431 var _guide = this._guide(); 31432 31433 if (this.valueCommitScript && _guide.version.isOn(_guide.version.Flags.RUN_VALUE_COMMMIT_ON_PREFILL)) { 31434 31435 _guide.queueExpressions(this, ["valueCommitScript"]); 31436 } 31437 } 31438 } 31439 }, 31440 31441 31442 _allowEmptyValueString : function () { 31443 return false;
31444 }, 31445 31446 markAsInvalid : function (errorText, shouldShowError) { 31447 shouldShowError = (typeof shouldShowError !== 'undefined') ? shouldShowError : false; 31448 this.validationState = false; 31449 if (!errorText) { 31450 errorText = this.validateExpMessage; 31451 } 31452 if(shouldShowError) { 31453 this._errorText = errorText; 31454 this.forceErrorShow = true; 31455 } 31456 this._triggerEvent(guidelib.event.GuideModelEvent.ERROR_CHANGED, 31457 "validationStatus", this.validationState, errorText); 31458 }, 31459 31460 31461 _isStateOverridden : function (property) { 31462 return this.getOrElse(this.jsonModel.stateOverrides, property, null) != null; 31463 } 31464 }); 31465 31466 Field.defineProps({ 31467 calcExp : { 31468 get : function () { 31469 return this.getAttribute("calcExp"); 31470 } 31471 }, 31472 31473 31474 isGlobal : { 31475 get : function () { 31476 return this.getAttribute('isGlobal') === "true"; 31477 } 31478 }, 31479 31480 31481 title : { 31482 get : function () { 31483 return this.getAttribute("jcr:title"); 31484 }, 31485 set : function (title) { 31486 this.setAttribute(title, "jcr:title"); 31487 } 31488 }, 31489 31490 valueCommitScript : { 31491 get : function () { 31492 return this.getAttribute("valueCommitScript"); 31493 } 31494 }, 31495 31496 validateExp : { 31497 get : function () { 31498 return this.getAttribute("validateExp"); 31499 } 31500 }, 31501 31502 31503 placeholderText : { 31504 get : function () { 31505 return this.getAttribute("placeholderText"); 31506 } 31507 }, 31508 31509 31510 value : { 31511 get : function () { 31512 var context = this.getOrElse(this._guide(), "_currentContext", null); 31513 if (context && context.managedExp 31514 31515 && !(context.contextNode === this 31516 && context.expression === "calcExp")) { 31517 31518 this._addDependant(context.contextNode, context.expression); 31519 } 31520 return this._getValue(); 31521 }, 31522 set : function (newValue) { 31523 var oldValue = this._getValue(), 31524 newTypedValue = this._getTypedValue(newValue), 31525 _guide = this._guide(); 31526 31527 if (this._allowEmptyValueString() && newValue === "") { 31528 newTypedValue = ""; 31529 } 31530 31531 31532 if (newTypedValue !== undefined && !(this.checkIfNull(newTypedValue) && this.checkIfNull(oldValue)) 31533 && (newTypedValue !== oldValue)) { 31534 if (this.bindNode) { 31535 this._setXFAValue(newTypedValue); 31536 } else if (this.jsonModel._value !== newValue) { 31537 this._setGuideValue(newTypedValue); 31538 } 31539 if (_guide && _guide.version.isOn(_guide.version.Flags.RUN_VALUE_COMMMIT_ON_SCRIPT_CHANGE)) { 31540 var context = _guide._currentContext, 31541 contextNode = this.getOrElse(context, "contextNode", null), 31542 contextExpression = this.getOrElse(context, "expression", null); 31543 if (!context || contextNode != this || contextExpression != "valueCommitScript") { 31544 31545 _guide.queueExpressions(this, ["valueCommitScript"]); 31546 } 31547 } 31548 31549 this._notifyDependants(); 31550 31551 if (this._runValidation && _guide) { 31552 _guide.queueExpressions(this, ["validateAllExp"]); 31553 } 31554 this._triggerOnBridge("elementValueChanged", this, "value", oldValue, newTypedValue); 31555 31556 31557 if (!this.bindNode || (this.bindNode && this.getAttribute("html5Type") !== undefined)) {
31558 this._triggerDisplayFormatChange(); 31559 } 31560 } 31561 } 31562 }, 31563 31564 31565 formattedValue : { 31566 get : function () { 31567 var value; 31568 if (this.bindNode) { 31569 value = this.bindNode.formattedValue; 31570 } else { 31571 value = this._getFormattedValue(this._getValue()); 31572 } 31573 return value; 31574 } 31575 }, 31576 31577 31578 displayPictureClause : { 31579 get : function () { 31580 return this.getAttribute("displayPictureClause"); 31581 } 31582 }, 31583 31584 31585 validatePictureClause : { 31586 get : function () { 31587 if (this.jsonModel.displayIsSameAsValidate) { 31588 return this.displayPictureClause; 31589 } 31590 return this.getAttribute("validatePictureClause"); 31591 } 31592 }, 31593 31594 31595 editPictureClause : { 31596 get : function () { 31597 if (this.jsonModel.isEditSameAsDisplayPattern) { 31598 return this.displayPictureClause; 31599 } 31600 return this.getAttribute("editPictureClause"); 31601 } 31602 }, 31603 31604 31605 isEditPictureClausePresent : { 31606 get : function () { 31607 return typeof this.editPictureClause !== 'undefined'; 31608 } 31609 }, 31610 31611 31612 mandatory : { 31613 get : function () { 31614 return this.getAttribute("mandatory"); 31615 }, 31616 31617 set : function (newValue) { 31618 var oldValue = this.getAttribute("mandatory"); 31619 if (newValue !== undefined && oldValue !== newValue) { 31620 if (this.bindNode) { 31621 this._setXFAMandatory(newValue); 31622 } else { 31623 31624 this.jsonModel.mandatory = !!newValue; 31625 } 31626 31627 this._triggerEvent(guidelib.event.GuideModelEvent.MODEL_CHANGED, "mandatory", oldValue, newValue); 31628 } 31629 } 31630 }, 31631 31632 31633 mandatoryMessage : { 31634 get : function () { 31635 return this.getAttribute("mandatoryMessage"); 31636 } 31637 }, 31638 31639 31640 validateExpMessage : { 31641 set : function (message) { 31642 31643 if (this.isValid) { 31644 this.jsonModel.validateExpMessage = message; 31645 } else { 31646 this.setAttribute(message, "validateExpMessage"); 31647 } 31648 }, 31649 get : function () { 31650 return this.getAttribute("validateExpMessage"); 31651 } 31652 }, 31653 31654 31655 validatePictureClauseMessage : { 31656 get : function () { 31657 return this.getAttribute("validatePictureClauseMessage"); 31658 } 31659 }, 31660 31661 31662 validationState : { 31663 get : function () { 31664 return this.isValid; 31665 }, 31666 set : function (newValue) { 31667 var oldVal = this.isValid; 31668 if (oldVal != newValue) { 31669 this.isValid = newValue; 31670 this._triggerOnBridge("elementValidationStatusChanged", this, 31671 "validationStatus", oldVal, newValue); 31672 } 31673 } 31674 }, 31675 31676 width : { 31677 get : function () { 31678 return this.getAttribute("width"); 31679 }, 31680 31681 set : function (newValue) { 31682 this.jsonModel.width = newValue; 31683 } 31684 }, 31685 31686 height : { 31687 get : function () { 31688 return this.getAttribute("height"); 31689 }, 31690 31691 set : function (newValue) { 31692 this.jsonModel.height = newValue; 31693 } 31694 } 31695 }); 31696 31697 Field.addMixins([ 31698 guidelib.model.mixin.AddDependencyMgmt, 31699 guidelib.model.mixin.ValidationsDisabled 31700 ]); 31701}(_, guidelib)); 31702 31703(function (_, guidelib) { 31704 31705 var GuideButton = guidelib.model.GuideButton = guidelib.model.Field.extend({ 31706 msClassName : "guideButton", 31707 defaultClickExpressions : { 31708 "moveNext" : "window.guideBridge.setFocus(this.panel.somExpression, 'nextItem', true)", 31709 "movePrev" : "window.guideBridge.setFocus(this.panel.somExpression, 'prevItem', true)" 31710 }, 31711 defaultNavigationExpressions : { 31712 "moveNext" : "this.visible=this.panel.navigationContext.hasNextItem", 31713 "movePrev" : "this.visible=this.panel.navigationContext.hasPrevItem" 31714 }, 31715 31716 _collectExpressions : function () { 31717 GuideButton._super._collectExpressions.apply(this); 31718 if (this.clickExp) { 31719 this._compiledScripts["clickExp"] = this._compileExpression(this.clickExp, null); 31720 } else if (this.targetVersion >= 1.1 && this.defaultClickExpressions[this.type]) { 31721 this.jsonModel.clickExp = this.defaultClickExpressions[this.type]; 31722 this._compiledScripts["clickExp"] = this._compileExpression(this.clickExp, null); 31723 } 31724 if (this.navigationChangeExp) { 31725 this._compiledScripts["navigationChangeExp"] = this._compileExpression(this.navigationChangeExp, null); 31726 } else if (this.targetVersion >= 1.1 && this.defaultNavigationExpressions[this.type]) { 31727 this.jsonModel.navigationChangeExp = this.defaultNavigationExpressions[this.type]; 31728 this._compiledScripts["navigationChangeExp"] = this._compileExpression(this.navigationChangeExp, null); 31729 } 31730 }, 31731 31732 }); 31733 31734 GuideButton.defineProps({ 31735 clickExp : { 31736 get : function () { 31737 return this.jsonModel.clickExp; 31738 } 31739 }, 31740 navigationChangeExp : { 31741 get : function () { 31742 return this.jsonModel.navigationChangeExp; 31743 } 31744 }, 31745 31746 type : { 31747 get : function () { 31748 return this.getAttribute("type"); 31749 } 31750 } 31751 }); 31752})(_, guidelib); 31753 31754(function (_, guidelib) { 31755 var GuideListFileAttachmentButton = guidelib.model.GuideListFileAttachmentButton = guidelib.model.GuideButton.extend({ 31756 msClassName : "guideListFileAttachmentButton", 31757 initialize : function () { 31758 31759 if (_.isUndefined(this.jsonModel.clickExp)) { 31760 this.jsonModel.clickExp = "guideBridge._updateFileListing.call(this,this)"; 31761 31762 } 31763 GuideListFileAttachmentButton._super.initialize.apply(this, arguments); 31764 } 31765 }); 31766 31767})(_, guidelib); 31768(function (_, guidelib) { 31769 var GuideCompositeFieldItem = guidelib.model.GuideCompositeFieldItem = guidelib.model.Field.extend({ 31770 msClassName : "GuideCompositeFieldItem" 31771 }); 31772 31773 GuideCompositeFieldItem.defineProps({ 31774 31775 bindRef : { 31776 get : function () { 31777 if (this.parent && !this.parent._isXfaNode() && !_.isEmpty(this.parent.bindRef)) { 31778 return this.parent.bindRef + '/' + this.getAttribute("name").replace(/\s+/g, ''); 31779 } else { 31780 return (this.getAttribute("bindRef") || "").replace(/\s+/g, ''); 31781 } 31782 } 31783 } 31784 }); 31785 31786})(_, guidelib); 31787(function (_, guidelib) { 31788 var GuideTextDraw = guidelib.model.GuideTextDraw = guidelib.model.Field.extend({ 31789 msClassName : "guideTextDraw", 31790 31791 _valueEscapeRegex : new RegExp('\\$', 'g'), 31792 31793 31794 _getValue : function () { 31795 if (this.bindNode) { 31796 return this.bindNode._getValue(null, true); 31797 } 31798 return this._getTypedValue(this.jsonModel._value); 31799 }, 31800 31801 31802 playJson : function (pJsonModel) { 31803 31804 this._setGuideValue(this._floatingFieldResolutionFunction(pJsonModel)); 31805 }, 31806 31807 _allowEmptyValueString : function () { 31808 return true; 31809 }, 31810 31811 _isFloatingField : function () { 31812 return this.documentFragmentVariables && this.documentFragmentVariables.length > 0; 31813 }, 31814 31815 _floatingFieldResolutionFunction : function (jsonModel) { 31816 var resolvedValue = this.value, 31817 variableRegexMap = this._variableRegexMap, 31818 valueEscapeRegex = this._valueEscapeRegex, 31819 somExpression = this.somExpression, 31820 self = this, 31821 31822 31823 variablesDefaultValue = [], 31824 documentFragmentVariables = this.documentFragmentVariables; 31825 if (jsonModel.documentFragmentVariables) { 31826 for (var index = 0 ; index < jsonModel.documentFragmentVariables.length ; index++) { 31827 variablesDefaultValue[index] = jsonModel.documentFragmentVariables[index]._value; 31828 } 31829 } 31830 this.jsonModel.defaultValue = variablesDefaultValue; 31831 _.each(variableRegexMap, function (regexPattern, variableId) { 31832 var textVariable, 31833 bindRef, 31834 floatingFieldValue; 31835 textVariable = documentFragmentVariables.filter(function (variable) { 31836 return variable.variableId === variableId; 31837 })[0]; 31838 bindRef = textVariable.bindRef; 31839 if (!bindRef) { 31840 bindRef = textVariable.name; 31841 } 31842 31843 if (jsonModel && jsonModel.documentFragmentVariables && jsonModel.documentFragmentVariables.length > 0) { 31844 var variableFromPlayJson = jsonModel.documentFragmentVariables.filter(function (variable) { 31845 return variable.variableId === variableId; 31846 })[0]; 31847 floatingFieldValue = variableFromPlayJson._value; 31848 } else { 31849 floatingFieldValue = guidelib.util.GuideUtil.getValueForBindRefField(bindRef, somExpression, this._guide()); 31850 } 31851 if (!floatingFieldValue) { 31852 31853 floatingFieldValue = ""; 31854 } else { 31855 31856 31857 floatingFieldValue = floatingFieldValue.replace(valueEscapeRegex, '$$$$'); 31858 } 31859 if (floatingFieldValue) { 31860 var dataType = textVariable.dataType, 31861 displayPattern = textVariable.displayPictureClause; 31862 if (dataType === 'number' || dataType === 'integer') { 31863 displayPattern = displayPattern ? displayPattern : 'num{zzz,zzz,zzz,zzz,zzz,zzz,zzz.zzzzzzzzzzzzzzz}'; 31864 } else if (dataType === 'date-time' || dataType === 'date') { 31865 displayPattern = displayPattern ? displayPattern : 'date{' + guidelib.i18n.datePatterns.med + '}'; 31866 } 31867 31868 if (displayPattern) { 31869 if (floatingFieldValue.indexOf(',') !== -1) { 31870 31871 var valArray = floatingFieldValue.split(','), 31872 tmpValue = ""; 31873 valArray.forEach(function (val) { 31874 tmpValue = tmpValue + guidelib.util.GuideUtil.formatValue(val, displayPattern, dataType) + ", " ; 31875 }); 31876 floatingFieldValue = tmpValue.substr(0, tmpValue.length - 2); 31877 } else { 31878 floatingFieldValue = guidelib.util.GuideUtil.formatValue(floatingFieldValue, displayPattern, dataType); 31879 } 31880 } 31881 } 31882 resolvedValue = resolvedValue.replace(regexPattern, floatingFieldValue); 31883 }); 31884 return resolvedValue; 31885 }, 31886 31887 initialize : function () { 31888 if (this._isFloatingField()) { 31889 var variableRegexMap = this._variableRegexMap = {}; 31890 _.each(this.documentFragmentVariables, function (documentFragmentVariable) { 31891 var variableId = documentFragmentVariable.variableId, 31892 regexPattern; 31893 if (!variableRegexMap[variableId]) { 31894 31895 regexPattern = '(?:<df-variable[^>]*variableid="' + variableId + '"[^>]*>)[^<]*(?:<\/df-variable>)'; 31896 variableRegexMap[variableId] = new RegExp(regexPattern, 'ig'); 31897 } 31898 }); 31899 } 31900 GuideTextDraw._super.initialize.apply(this, [arguments]); 31901 } 31902 }); 31903 31904 GuideTextDraw.defineProps({ 31905 calcExp : { 31906 get : function () { 31907 return this._calcExp; 31908 } 31909 }, 31910 31911 documentFragmentVariables : { 31912 get : function () { 31913 return this.jsonModel.documentFragmentVariables; 31914 } 31915 } 31916 }); 31917}(_, guidelib)); 31918 31919(function (_, guidelib) { 31920 var GuideAdobeSignBlock = guidelib.model.GuideAdobeSignBlock = guidelib.model.GuideTextDraw.extend({ 31921 msClassName : "guideAdobeSignBlock" 31922 }); 31923}(_, guidelib)); 31924 (function (_, guidelib) { 31925 var GuideFootnotePlaceHolder = guidelib.model.GuideFootnotePlaceHolder = guidelib.model.GuideTextDraw.extend({ 31926 msClassName : "guideFootnotePlaceHolder", 31927 31928 initialize : function () { 31929 GuideFootnotePlaceHolder._super.initialize.apply(this); 31930 } 31931 }); 31932 GuideFootnotePlaceHolder.defineProps({ 31933 footnoteMap : { 31934 get : function () { 31935 if (this.options._guideContainer.jsonModel.textReplacementMap) { 31936 var footnoteMap = {}; 31937 var footnoteArray = Object.entries(this.options._guideContainer.jsonModel.textReplacementMap) 31938 var parentDiv = document.createElement("p"); 31939 parentDiv.setAttribute("class", "footnoteClass"); 31940 for (var i = 0; i < footnoteArray.length; i++) { 31941 var pTag = $("p[id=\"" + footnoteArray[i][0] + "\"]")[0]; 31942 if (pTag != null && pTag.tagName == 'P') { 31943 var childTag = document.createElement("p"); 31944 31945 childTag.setAttribute("role", "footnote"); 31946 childTag.setAttribute("aria-live", "polite"); 31947 childTag.setAttribute("aria-atomic", "true"); 31948 var supTag = document.createElement('sup'); 31949 var anchorTag = document.createElement('a'); 31950 var parentTag = pTag.cloneNode(true); 31951 parentTag.removeAttribute("id"); 31952 anchorTag.setAttribute('id', footnoteArray[i][0]+ "_ftn"); 31953 anchorTag.innerHTML = footnoteArray[i][1]; 31954 supTag.appendChild(anchorTag); 31955 parentTag.insertBefore(supTag, parentTag.children[0]); 31956 parentTag.style.display = "block"; 31957 childTag.appendChild(parentTag); 31958 footnoteMap[footnoteArray[i][0]] = childTag.outerHTML; 31959 } 31960 } 31961 return footnoteMap; 31962 } 31963 return null; 31964 } 31965 } 31966 }); 31967 31968}(_, guidelib)); 31969 31970 31971(function (_, guidelib) { 31972 31973 var GuideTextBox = guidelib.model.GuideTextBox = guidelib.model.Field.extend({ 31974 msClassName : "guideTextBox", 31975 31976 31977 _runMinimumLengthTest : function () { 31978 return this.value && this.value.length >= this.minLength; 31979 }, 31980 31981 31982 _runTotalLengthTest : function () { 31983 return this.value && this.value.length === this.length; 31984 }, 31985 31986 31987 _runValidations : function (obj) { 31988 GuideTextBox._super._runValidations.call(this, obj); 31989 if (obj.validFlag) { 31990 31991 if (this.length != null) {
31992 obj.validFlag = this._runTotalLengthTest(); 31993 if (!obj.validFlag) { 31994 this._errorText = this.guideUtil.getLocalizedMessage("", guidelib.i18n.strings.totalLengthMessage, [this.length]); 31995 this._failedTest = this.guideUtil.LENGTH_TEST; 31996 } 31997 } else if (this.minLength != null) { 31998 obj.validFlag = this._runMinimumLengthTest(); 31999 if (!obj.validFlag) { 32000 this._errorText = this.guideUtil.getLocalizedMessage("", guidelib.i18n.strings.minimumLengthMessage, [this.minLength]); 32001 this._failedTest = this.guideUtil.MINIMUM_LENGTH_TEST; 32002 } 32003 } 32004 32005 } 32006 }, 32007 32008 32009 _runMandatoryTest : function () { 32010 if (this.allowRichText) { 32011 32012 32013 var getTextContent = function (htmlString) { 32014 var result = htmlString, 32015 regex = null; 32016 if (htmlString != null) { 32017 32018 32019 regex = /(<([^>]+)>)/ig; 32020 result = htmlString.replace(regex, ""); 32021 } 32022 return result; 32023 }, 32024 currValue = getTextContent(this._getValue()), 32025 isNull = this.checkIfNull(currValue); 32026 return !isNull; 32027 } else { 32028 return GuideTextBox._super._runMandatoryTest.apply(this, arguments); 32029 } 32030 }, 32031 32032 _allowEmptyValueString : function () { 32033 return true; 32034 } 32035 32036 }); 32037 32038 GuideTextBox.defineProps({ 32039 32040 "multiLine" : { 32041 get : function () { 32042 return this.getAttribute("multiLine"); 32043 } 32044 }, 32045 32046 32047 "maxChars" : { 32048 get : function () { 32049 return this.getAttribute("maxChars"); 32050 } 32051 }, 32052 32053 32054 "minLength" : { 32055 get : function () { 32056 return this.getAttribute("minLength"); 32057 } 32058 }, 32059 32060 32061 "length" : { 32062 get : function () { 32063 return this.getAttribute("length"); 32064 } 32065 }, 32066 32067 "allowRichText" : { 32068 get : function () { 32069 return this.getAttribute("allowRichText"); 32070 } 32071 } 32072 }); 32073 32074}(_, guidelib)); 32075 32076(function (_, guidelib) { 32077 32078 var countriesDialingCodesMap = { 32079 '441481' : 'Guernsey', 32080 '441624' : 'Isle of Man', 32081 '441534' : 'Jersey', 32082 '1868' : 'Trinidad and Tobago', 32083 '1473' : 'Grenada', 32084 '1670' : 'Northern Mariana Islands', 32085 '1869' : 'Saint Kitts and Nevis', 32086 '1758' : 'Saint Lucia', 32087 '1671' : 'Guam', 32088 "1684" : "American Samoa", 32089 "1268" : "Antigua and Barbuda", 32090 "1264" : "Anguilla", 32091 "1242" : "Bahamas", 32092 "1246" : "Barbados", 32093 '1441' : 'Bermuda', 32094 '1284' : 'British Virgin Islands', 32095 '1345' : 'Cayman Islands', 32096 '1787' : 'Puerto Rico', 32097 '1876' : 'Jamaica', 32098 '1939' : 'Puerto Rico', 32099 '1767' : 'Dominica', 32100 '1809' : 'Dominican Republic', 32101 '1829' : 'Dominican Republic', 32102 '1664' : 'Montserrat', 32103 '1849' : 'Dominican Republic', 32104 '1340' : 'U.S. Virgin Islands', 32105 '1784' : 'Saint Vincent and the Grenadines', 32106 '1649' : 'Turks and Caicos Islands', 32107 '1721' : 'Sint Maarten', 32108 "355" : "Albania", 32109 "213" : "Algeria", 32110 "376" : "Andorra", 32111 "244" : "Angola", 32112 "672" : "Antarctica", 32113 "374" : "Armenia", 32114 "297" : "Aruba", 32115 "994" : "Azerbaijan", 32116 "973" : "Bahrain", 32117 "880" : "Bangladesh", 32118 "375" : "Belarus", 32119 "501" : "Belize", 32120 "229" : "Benin", 32121 '975' : 'Bhutan', 32122 '591' : 'Bolivia', 32123 '387' : 'Bosnia and Herzegovina', 32124 '267' : 'Botswana', 32125 '246' : 'British Indian Ocean Territory', 32126 '673' : 'Brunei', 32127 '359' : 'Bulgaria', 32128 '226' : 'Burkina Faso', 32129 '257' : 'Burundi', 32130 '855' : 'Cambodia', 32131 '237' : 'Cameroon', 32132 '238' : 'Cape Verde', 32133 '236' : 'Central African Republic', 32134 '235' : 'Chad', 32135 '269' : 'Comoros', 32136 '682' : 'Cook Islands', 32137 '506' : 'Costa Rica', 32138 '385' : 'Croatia', 32139 32140 '357' : 'Cyprus', 32141 '420' : 'Czech Republic', 32142 '243' : 'Democratic Republic of the Congo', 32143 '253' : 'Djibouti', 32144 '670' : 'East Timor', 32145 '593' : 'Ecuador', 32146 '503' : 'El Salvador', 32147 '240' : 'Equatorial Guinea', 32148 '291' : 'Eritrea', 32149 '372' : 'Estonia', 32150 '251' : 'Ethiopia', 32151 '500' : 'Falkland Islands', 32152 '298' : 'Faroe Islands', 32153 '679' : 'Fiji', 32154 '358' : 'Finland', 32155 '689' : 'French Polynesia', 32156 '241' : 'Gabon', 32157 '220' : 'Gambia', 32158 '995' : 'Georgia', 32159 '233' : 'Ghana', 32160 '350' : 'Gibraltar', 32161 '299' : 'Greenland', 32162 '502' : 'Guatemala', 32163 '224' : 'Guinea', 32164 '245' : 'Guinea-Bissau', 32165 '592' : 'Guyana', 32166 '509' : 'Haiti', 32167 '504' : 'Honduras', 32168 '852' : 'Hong Kong', 32169 '354' : 'Iceland', 32170 '964' : 'Iraq', 32171 '353' : 'Ireland', 32172 '972' : 'Israel', 32173 '225' : 'Ivory Coast', 32174 '962' : 'Jordan', 32175 '254' : 'Kenya', 32176 '686' : 'Kiribati', 32177 '383' : 'Kosovo', 32178 '965' : 'Kuwait', 32179 '996' : 'Kyrgyzstan', 32180 '856' : 'Laos', 32181 '371' : 'Latvia', 32182 '961' : 'Lebanon', 32183 '266' : 'Lesotho', 32184 '231' : 'Liberia', 32185 '218' : 'Libya', 32186 '423' : 'Liechtenstein', 32187 '370' : 'Lithuania', 32188 '352' : 'Luxembourg', 32189 '853' : 'Macau', 32190 '389' : 'Macedonia', 32191 '261' : 'Madagascar', 32192 '265' : 'Malawi', 32193 '960' : 'Maldives', 32194 '223' : 'Mali', 32195 '356' : 'Malta', 32196 '692' : 'Marshall Islands', 32197 '222' : 'Mauritania', 32198 '230' : 'Mauritius', 32199 32200 '691' : 'Micronesia', 32201 '373' : 'Moldova', 32202 '377' : 'Monaco', 32203 '976' : 'Mongolia', 32204 '382' : 'Montenegro', 32205 32206 '258' : 'Mozambique', 32207 '264' : 'Namibia', 32208 '674' : 'Nauru', 32209 '977' : 'Nepal', 32210 '599' : 'Netherlands Antilles', 32211 '687' : 'New Caledonia', 32212 '505' : 'Nicaragua', 32213 '227' : 'Niger', 32214 '234' : 'Nigeria', 32215 '683' : 'Niue', 32216 '850' : 'North Korea', 32217 '968' : 'Oman', 32218 '680' : 'Palau', 32219 '970' : 'Palestine', 32220 '507' : 'Panama', 32221 '675' : 'Papua New Guinea', 32222 '595' : 'Paraguay', 32223 '351' : 'Portugal', 32224 '974' : 'Qatar', 32225 '242' : 'Republic of the Congo', 32226 '262' : 'Reunion', 32227 '250' : 'Rwanda', 32228 32229 '290' : 'Saint Helena', 32230 '590' : 'Saint Martin', 32231 '508' : 'Saint Pierre and Miquelon', 32232 '685' : 'Samoa', 32233 '378' : 'San Marino', 32234 '239' : 'Sao Tome and Principe', 32235 '966' : 'Saudi Arabia', 32236 '221' : 'Senegal', 32237 '381' : 'Serbia', 32238 '248' : 'Seychelles', 32239 '232' : 'Sierra Leone', 32240 '421' : 'Slovakia', 32241 '386' : 'Slovenia', 32242 '677' : 'Solomon Islands', 32243 '252' : 'Somalia', 32244 '211' : 'South Sudan', 32245 '249' : 'Sudan', 32246 '597' : 'Suriname', 32247 '268' : 'Swaziland', 32248 '963' : 'Syria', 32249 '886' : 'Taiwan', 32250 '992' : 'Tajikistan', 32251 '255' : 'Tanzania', 32252 '228' : 'Togo', 32253 '690' : 'Tokelau', 32254 '676' : 'Tonga', 32255 '216' : 'Tunisia', 32256 '993' : 'Turkmenistan', 32257 '688' : 'Tuvalu', 32258 '256' : 'Uganda', 32259 '380' : 'Ukraine', 32260 '971' : 'United Arab Emirates', 32261 '598' : 'Uruguay', 32262 '998' : 'Uzbekistan', 32263 '678' : 'Vanuatu', 32264 '379' : 'Vatican', 32265 '681' : 'Wallis and Futuna', 32266 '212' : 'Western Sahara', 32267 '967' : 'Yemen', 32268 '260' : 'Zambia', 32269 '263' : 'Zimbabwe', 32270 '60' : 'Malaysia', 32271 '58' : 'Venezuela', 32272 '30' : 'Greece', 32273 '84' : 'Vietnam', 32274 '44' : 'United Kingdom', 32275 '45' : 'Denmark', 32276 '53' : 'Cuba', 32277 '46' : 'Sweden', 32278 '52' : 'Mexico', 32279 '41' : 'Switzerland', 32280 '40' : 'Romania', 32281 32282 '36' : 'Hungary', 32283
32284 "43" : "Austria", 32285 '34' : 'Spain', 32286 '91' : 'India', 32287 '62' : 'Indonesia', 32288 '98' : 'Iran', 32289 '94' : 'Sri Lanka', 32290 '27' : 'South Africa', 32291 '95' : 'Myanmar', 32292 '65' : 'Singapore', 32293 '39' : 'Italy', 32294 '82' : 'South Korea', 32295 "32" : "Belgium", 32296 '81' : 'Japan', 32297 '31' : 'Netherlands', 32298 '20' : 'Egypt', 32299 "54" : "Argentina", 32300 "93" : "Afghanistan", 32301 32302 '56' : 'Chile', 32303 '86' : 'China', 32304 '51' : 'Peru', 32305 '63' : 'Philippines', 32306 '64' : 'Pitcairn', 32307 '48' : 'Poland', 32308 '47' : 'Norway', 32309 '33' : 'France', 32310 32311 '61' : 'Cocos Islands', 32312 '55' : 'Brazil', 32313 '92' : 'Pakistan', 32314 '49' : 'Germany', 32315 '57' : 'Colombia', 32316 '66' : 'Thailand', 32317 '90' : 'Turkey', 32318 32319 '1' : 'Canada', 32320 32321 '7' : 'Russia' 32322 }; 32323 32324 var GuideTelephone = guidelib.model.GuideTelephone = guidelib.model.GuideTextBox.extend({ 32325 msClassName : "guideTelephone", 32326 32327 _extractNumericDigits : function (telephoneNumber) { 32328 var digitArray, 32329 number = ""; 32330 if (telephoneNumber) { 32331 digitArray = telephoneNumber.match(/\d+/g); 32332 if (digitArray) { 32333 number = digitArray.join(""); 32334 } 32335 } 32336 return number; 32337 }, 32338 32339 _extractCountryCode : function (telephoneNumber) { 32340 var number = this._extractNumericDigits(telephoneNumber); 32341 if (!number || (telephoneNumber && number && telephoneNumber.lastIndexOf("+", 0) !== 0)) { 32342 return ""; 32343 } 32344 for (var countryCode in countriesDialingCodesMap) { 32345 if (number && number.lastIndexOf(countryCode, 0) === 0) { 32346 return countryCode; 32347 } 32348 } 32349 return ""; 32350 }, 32351 32352 _extractPhoneNumber : function (telephoneNumber) { 32353 var countryCode = this._extractCountryCode(telephoneNumber), 32354 number = this._extractNumericDigits(telephoneNumber), 32355 phoneNumber = ""; 32356 if (number) { 32357 phoneNumber = number.substr(countryCode.length); 32358 } 32359 return phoneNumber; 32360 } 32361 }); 32362 32363 GuideTelephone.defineProps({ 32364 32365 countryCode : { 32366 get : function () { 32367 var value = this._getValue(); 32368 return this._extractCountryCode(value); 32369 } 32370 }, 32371 32372 32373 phoneNumber : { 32374 get : function () { 32375 var value = this._getValue(); 32376 return this._extractPhoneNumber(value); 32377 } 32378 } 32379 }); 32380 32381}(_, guidelib)); 32382 32383(function (_, guidelib) { 32384 32385 var GuideCaptcha = guidelib.model.GuideCaptcha = guidelib.model.Field.extend({ 32386 msClassName : "guideCaptcha", 32387 32388 initialize : function () { 32389 GuideCaptcha._super.initialize.call(this); 32390 var invisibleMandatoryRecaptchaInitialization = "af.invisibleMandatoryRecaptchaInitialization"; 32391 if ((FD.isToggleEnabled(guidelib.util.FeatureToggleConstants.FT_TURNSTILE_HCAPTCHA) 32392 && (this.isWidgetHcaptcha || this.isWidgetTurnstile) && this.captchaInvisible) 32393 || (this.isWidgetRecaptcha && ((this.captchaEnterprise && !this.checkBoxkey) || (this.captchaInvisible && this.mandatory)))) { 32394 32395 this.captchaValidate = false; 32396 this._triggerOnBridge(invisibleMandatoryRecaptchaInitialization, this, null, null, null); 32397 } 32398 }, 32399 32400 showCaptchaError : function (serverErrorMessage) { 32401 if (this.captchaEnterprise) { 32402 if (this.checkBoxkey) { 32403 serverErrorMessage = this.errorMessage; 32404 } else { 32405 window.alert(this.errorMessage); 32406 return; 32407 } 32408 } 32409 if (this.captchaInvisible) { 32410 if (FD.isToggleEnabled(guidelib.util.FeatureToggleConstants.FT_TURNSTILE_HCAPTCHA)) { 32411 window.alert(this.errorMessage); 32412 } 32413 return; 32414 } 32415 if (FD.isToggleEnabled(guidelib.util.FeatureToggleConstants.FT_TURNSTILE_HCAPTCHA) && this.isWidgetRecaptcha) { 32416 serverErrorMessage = this.errorMessage; 32417 } else { 32418 if (_.isEmpty(serverErrorMessage)) { 32419 serverErrorMessage = guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.LogMessages["AEM-AF-901-006"]); 32420 } 32421 } 32422 32423 this._triggerEvent(guidelib.event.GuideModelEvent.ERROR_CHANGED, 32424 "validationStatus", false, serverErrorMessage); 32425 }, 32426 32427 validate : function (errorList) { 32428 if (_.isUndefined(errorList)) { 32429 errorList = []; 32430 } 32431 32432 if(!this.captchaValidate) { 32433 return; 32434 } 32435 if (window.guideBridge.hostName !== "server") { 32436 if ((this.visible && !this.value) || (this.mandatory && !this.visible)) { 32437 errorList.push({ 32438 som : this.somExpression, 32439 errorText : this.mandatoryMessage 32440 }); 32441 this._triggerEvent(guidelib.event.GuideModelEvent.ERROR_CHANGED, 32442 "validationStatus", false, this.mandatoryMessage); 32443 return false;
32444 } else { 32445 this._triggerEvent(guidelib.event.GuideModelEvent.ERROR_CHANGED, 32446 "validationStatus", true, null); 32447 } 32448 } 32449 }, 32450 32451 _updateLiveData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar) { 32452 if (!FD.isToggleEnabled("FT_FORMS-4185")) { 32453 GuideCaptcha._super._updateLiveData.call(this, bound_indexedXpathSoFar, unBound_indexedXpathSoFar); 32454 } 32455 }, 32456 32457 _playLiveData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar) { 32458 if (!FD.isToggleEnabled("FT_FORMS-4185")) { 32459 GuideCaptcha._super._playLiveData.call(this, bound_indexedXpathSoFar, unBound_indexedXpathSoFar); 32460 } 32461 } 32462 }); 32463 32464 GuideCaptcha.defineProps({ 32465 value : { 32466 get : function () { 32467 return this.jsonModel._value; 32468 }, 32469 set : function (value) { 32470 var oldValue = this.jsonModel._value, 32471 newTypedValue; 32472 32473 this.jsonModel._value = (value === undefined) ? oldValue : value; 32474 newTypedValue = this.jsonModel._value; 32475 this.validate(); 32476 this._triggerOnBridge("elementValueChanged", this, "value", oldValue, newTypedValue); 32477 } 32478 }, 32479 captchaWidget : { 32480 get : function () { 32481 return this.getAttribute("captchaService"); 32482 } 32483 }, 32484 captchaValidate : { 32485 get : function () { 32486 return this._captchaValidate == undefined ? true : this._captchaValidate; 32487 }, 32488 set : function (value) { 32489 this._captchaValidate = value; 32490 } 32491 }, 32492 captchaInvisible : { 32493 get : function () { 32494 if (FD.isToggleEnabled(guidelib.util.FeatureToggleConstants.FT_TURNSTILE_HCAPTCHA) && this.captchaWidget === "turnstile") { 32495 return this.getAttribute("widgetType") == "invisible" ? true : false; 32496 } else if (FD.isToggleEnabled(guidelib.util.FeatureToggleConstants.FT_TURNSTILE_HCAPTCHA) && this.captchaWidget === "hcaptcha") { 32497 return this.getAttribute("size") == "invisible" ? true : false; 32498 } else { 32499 return this.getAttribute("rcSize") == "invisible" ? true : false; 32500 } 32501 } 32502 }, 32503 captchaEnterprise : { 32504 get : function () { 32505 return (FD.isToggleEnabled("FT_FORMS-4185") && this.getAttribute("rcVersion") === "enterprise") ? true : false; 32506 } 32507 }, 32508 checkBoxkey : { 32509 get : function () { 32510 return this.getAttribute("rcKeyType") === "checkbox" ? true : false; 32511 } 32512 }, 32513 errorMessage : { 32514 get: function () { 32515 return this.getAttribute("errorMessage"); 32516 } 32517 }, 32518 isWidgetRecaptcha : { 32519 get: function () { 32520 return (this.captchaWidget === "recaptcha"); 32521 } 32522 }, 32523 isWidgetHcaptcha : { 32524 get: function () { 32525 return (FD.isToggleEnabled(guidelib.util.FeatureToggleConstants.FT_TURNSTILE_HCAPTCHA) && (this.captchaWidget === "hcaptcha")); 32526 } 32527 }, 32528 isWidgetTurnstile : { 32529 get: function () { 32530 return (FD.isToggleEnabled(guidelib.util.FeatureToggleConstants.FT_TURNSTILE_HCAPTCHA) && (this.captchaWidget === "turnstile")); 32531 } 32532 } 32533 32534 32535 }); 32536 32537}(_, guidelib)); 32538 32539(function (_, guidelib) { 32540 var GuidePasswordBox = guidelib.model.GuidePasswordBox = guidelib.model.Field.extend({ 32541 msClassName : "guidePasswordBox", 32542 32543 _getReducedJSON : function () { 32544 32545 32546 if (this.submitPassword) { 32547 return GuidePasswordBox._super._getReducedJSON.call(this); 32548 } 32549 32550 var whitelistedProperties = ["name", "templateId", "guideNodeClass"], 32551 reducedJsonObject = {}; 32552 guidelib.model.util.CommonUtils.returnMinimalJSON(whitelistedProperties, reducedJsonObject, this); 32553 return reducedJsonObject; 32554 }, 32555 32556 _preserveLazyValue : function () { 32557 return !!this.submitPassword && GuidePasswordBox._super._preserveLazyValue.call(this); 32558 }, 32559 32560 _allowEmptyValueString : function () { 32561 return true; 32562 } 32563 }); 32564 GuidePasswordBox.defineProps({ 32565 submitPassword : { 32566 get : function () { 32567 return this.getAttribute("submitPassword"); 32568 } 32569 } 32570 }); 32571 32572})(_, guidelib); 32573 32574(function (_, guidelib) { 32575 var GuideScribble = guidelib.model.GuideScribble = guidelib.model.Field.extend({ 32576 msClassName : "guideScribble" 32577 }); 32578})(_, guidelib); 32579 32580 32581(function (_, guidelib) { 32582 var AbstractField = guidelib.model.AbstractField = guidelib.model.GuideNode.extend({ 32583 msClassName : "abstractField", 32584 32585 initialize : function () { 32586 this._name = this.options.name || ""; 32587 this._className = this.options.className || ""; 32588 this._bindRef = this.options.bindRef || ""; 32589 this._afDataSom = this.options.afDataSom || ""; 32590 this._dataSom = this._isXfaNode() ? this.options.dataSom : ""; 32591 this.dependants = []; 32592 32593 this._depdendantIds = []; 32594 }, 32595 32596 _getValue : function () { 32597 return this.jsonModel._value; 32598 }, 32599 32600 _setValue : function (value) { 32601 this.jsonModel._value = value; 32602 }, 32603 32604 resetData : function () { 32605 return guidelib.model.Field.prototype.resetData.call(this); 32606 }, 32607 32608 _isXfaNode : function () { 32609 return this.bindRef.indexOf("xfa[0].form[0].") === 0; 32610 }, 32611 32612 getAttribute : function (attrName) { 32613 var attrValue; 32614 switch (attrName) { 32615 case "name": 32616 attrValue = this.name; 32617 break; 32618 case "bindRef": 32619 attrValue = this.bindRef; 32620 break; 32621 default: 32622 attrValue = null; 32623 break; 32624 } 32625 return attrValue; 32626 } 32627 }); 32628 32629 AbstractField.defineProps({ 32630 somExpression : { 32631 get : function () { 32632 return ""; 32633 } 32634 }, 32635 name : { 32636 get : function () { 32637 return (this._name || "").replace(/\s+/g, ''); 32638 } 32639 }, 32640 className : { 32641 get : function () { 32642 return (this._className || ""); 32643 } 32644 }, 32645 bindRef : { 32646 get : function () { 32647 return (this._bindRef || "").replace(/\s+/g, ''); 32648 } 32649 }, 32650 dataSom : { 32651 get : function () { 32652 return this._dataSom; 32653 } 32654 }, 32655 afDataSom : { 32656 get : function () { 32657 return this._afDataSom.replace(/\s+/g, ''); 32658 } 32659 }, 32660 32661 value : { 32662 get : function () { 32663 var context = this._guide()._currentContext; 32664 if (context && context.managedExp && context.contextNode && context.expression) { 32665 this._addDependant(context.contextNode, context.expression); 32666 32667 this._depdendantIds.push(context.contextNode.id); 32668 } 32669 return this.jsonModel._value; 32670 }, 32671 set : function (newValue) { 32672 if (this.jsonModel._value !== newValue) { 32673 this.jsonModel._value = newValue; 32674 32675 var guideDirtyMarkerAndVisitor = this._guide().internal.GuideDirtyMarkerAndVisitor, 32676 visitMap = guideDirtyMarkerAndVisitor.visitMap, 32677 listOfDependents = this._depdendantIds; 32678 guideDirtyMarkerAndVisitor._findAndMarkDirty(visitMap, listOfDependents); 32679 this._notifyDependants(); 32680 } 32681 } 32682 } 32683 }); 32684 32685 AbstractField.addMixins([ 32686 guidelib.model.mixin.AddDependencyMgmt 32687 ]); 32688}(_, guidelib)); 32689 32690(function ($, guidelib, _) { 32691 var ModelTemplateCacheStore = guidelib.model.util.ModelTemplateCacheStore = xfalib.ut.Class.extend({ 32692 initialize : function () { 32693 ModelTemplateCacheStore._super.initialize.apply(this); 32694 this._modelIdCache = {}; 32695 this._templateIdCache = {}; 32696 32697 32698 32699 32700 this._lazyTemplateIdCache = {}; 32701 var guideJson = JSON.parse(JSON.stringify(this.options.modelTemplateJson)); 32702 this._putTemplate(guideJson); 32703 }, 32704 32705 32706 putModel : function (model) { 32707 if (model.id) { 32708 var modelId = model.id; 32709 this._modelIdCache[modelId] = model; 32710 if (model.children) { 32711 _.each(model.children, function (child) { 32712 this.putModel(child); 32713 }, this); 32714 } 32715 } else { 32716 this.logger().log("no Id found for model" + model.getAttribute("name")); 32717 } 32718 }, 32719 32720 32721 removeModel : function (id) { 32722 if (this._modelIdCache.hasOwnProperty(id)) { 32723 delete this._modelIdCache[id]; 32724 } 32725 }, 32726 32727 getModel : function (id) { 32728 if (this._modelIdCache.hasOwnProperty(id)) { 32729 return this._modelIdCache[id]; 32730 } 32731 }, 32732 32733 32734 _putTemplate : function (jsonTemplate) { 32735 if (jsonTemplate.templateId && jsonTemplate.guideNodeClass) { 32736 this._templateIdCache[jsonTemplate.templateId] = jsonTemplate; 32737 } 32738 _.each(jsonTemplate, function (childTemplate, key) { 32739 if (_.isObject(childTemplate)) { 32740 this._putTemplate(childTemplate); 32741 } 32742 }, this); 32743 }, 32744 32745 32746 _putLazyTemplate : function (lazyTemplateJson) { 32747 if (lazyTemplateJson.templateId && lazyTemplateJson.guideNodeClass) { 32748 this._lazyTemplateIdCache[lazyTemplateJson.templateId] = lazyTemplateJson; 32749 } 32750 }, 32751 32752 cloneJsonTemplate : function (templateId) { 32753 if (this._templateIdCache[templateId]) { 32754 var template = this._templateIdCache[templateId]; 32755 return JSON.parse(JSON.stringify(template)); 32756 } 32757 }, 32758 32759 _getTemplate : function (templateId, lookupLazyStore) { 32760 var template = this._templateIdCache[templateId]; 32761 32762 32763 32764 if (lookupLazyStore && guidelib.util.GuideUtil.isLazyJson(template)) { 32765 template = this._lazyTemplateIdCache[templateId]; 32766 } 32767 32768 if (!_.isUndefined(template)) { 32769 return JSON.parse(JSON.stringify(template)); 32770 32771 } 32772 } 32773 }); 32774 32775 ModelTemplateCacheStore.defineProps({ 32776 }); 32777}($, guidelib, window._)); 32778(function ($, guidelib) { 32779 var DomTemplateCacheStore = guidelib.view.util.DomTemplateCacheStore = xfalib.ut.Class.extend({ 32780 cloneDomElement : function (htmlId) { 32781 return this.$htmlTemplateDom.find(htmlId).clone(); 32782 }, 32783 32784 putDomElement : function (parentIdSelector, $child) { 32785 32786 this.$htmlTemplateDom.find(parentIdSelector).eq(0).append($child); 32787 }, 32788 32789 removeDomElement : function (parentIdSelector) { 32790 32791 this.$htmlTemplateDom.find(parentIdSelector).children().remove(); 32792 } 32793 }); 32794 32795 DomTemplateCacheStore.defineProps({ 32796 $htmlTemplateDom : { 32797 get : function () { 32798 return this.options.$htmlTemplateDom;
32799 } 32800 } 32801 }); 32802}($, guidelib)); 32803(function (_, guidelib) { 32804 32805 var AddMinMaxValidation = guidelib.model.mixin.AddMinMaxValidation = { 32806 normalProperties : { 32807 32808 _runMaximumValueTest : function () { 32809 if (this.exclusiveMaximum) { 32810 return this.value < this.maximum; 32811 } else { 32812 return this.value <= this.maximum; 32813 } 32814 }, 32815 32816 _runMinimumValueTest : function () { 32817 if (this.exclusiveMinimum) { 32818 return this.value > this.minimum; 32819 } else { 32820 return this.value >= this.minimum; 32821 } 32822 }, 32823 32824 32825 _minMaxValidation : function (value, obj) { 32826 if (value != null && obj.validFlag) { 32827 32828 if (this.maximum) { 32829 obj.validFlag = this._runMaximumValueTest(); 32830 if (!obj.validFlag) { 32831 var maxFormattedValue = this._getFormattedValue(this.maximum); 32832 this._errorText = this.exclusiveMaximum ? this.guideUtil.getLocalizedMessage("", guidelib.i18n.strings.exclusiveMaxValErrorMessage, [maxFormattedValue]) : 32833 this.guideUtil.getLocalizedMessage("", guidelib.i18n.strings.maxValErrorMessage, [maxFormattedValue]); 32834 this._failedTest = this.guideUtil.MAXIMUM_VALUE_TEST; 32835 } 32836 } 32837 32838 if (obj.validFlag && this.minimum !== null) { 32839 obj.validFlag = this._runMinimumValueTest(); 32840 if (!obj.validFlag) { 32841 var minFormattedValue = this._getFormattedValue(this.minimum); 32842 this._errorText = this.exclusiveMinimum ? this.guideUtil.getLocalizedMessage("", guidelib.i18n.strings.exclusiveMinValErrorMessage, [minFormattedValue]) : 32843 this.guideUtil.getLocalizedMessage("", guidelib.i18n.strings.minValErrorMessage, [minFormattedValue]); 32844 this._failedTest = this.guideUtil.MINIMUM_VALUE_TEST; 32845 } 32846 } 32847 } 32848 } 32849 32850 }, 32851 propertyDescriptors : { 32852 32853 maximum : { 32854 get : function () { 32855 return this.getAttribute("maximum"); 32856 } 32857 }, 32858 32859 32860 minimum : { 32861 get : function () { 32862 return this.getAttribute("minimum"); 32863 } 32864 }, 32865 32866 32867 exclusiveMaximum : { 32868 get : function () { 32869 return this.getAttribute("exclusiveMaximum"); 32870 } 32871 }, 32872 32873 32874 exclusiveMinimum : { 32875 get : function () { 32876 return this.getAttribute("exclusiveMinimum"); 32877 } 32878 } 32879 32880 } 32881 }; 32882 32883}(_, guidelib)); 32884(function (_, guidelib) { 32885 32886 32887 var GuideNumericBox = guidelib.model.GuideNumericBox = guidelib.model.Field.extend({ 32888 msClassName : "guideNumericBox", 32889 32890 _getTypedValue : function (value) { 32891 var dataType = this.dataType, 32892 tmpValue, str, leadD, fracD; 32893 32894 if (this.checkIfNull(value)) { 32895 return null; 32896 } 32897 switch (dataType) { 32898 case "integer": 32899 tmpValue = parseInt(value); 32900 break; 32901 case "float": 32902 tmpValue = parseFloat(value); 32903 break; 32904 case "decimal": 32905 tmpValue = parseFloat(value); 32906 if (!isNaN(tmpValue)) { 32907 str = tmpValue.toString(); 32908 leadD = str.indexOf("."); 32909 leadD = leadD === -1 ? str.length : leadD; 32910 leadD = str.indexOf("-") === 0 ? leadD - 1 : leadD; 32911 fracD = str.length - leadD - 1; 32912 if (fracD > this.fracDigits && this.fracDigits !== -1) { 32913 tmpValue = parseFloat(tmpValue.toFixed(this.fracDigits)); 32914 } 32915 if (leadD > this.leadDigits && this.leadDigits !== -1) { 32916 return undefined; 32917 } 32918 } 32919 break; 32920 } 32921 if (isNaN(tmpValue)) { 32922 return undefined; 32923 } 32924 return tmpValue; 32925 }, 32926 _getFormattedValue : function (value) { 32927 if (_.isUndefined(value) || value === null || value === "") { 32928 return null; 32929 } 32930 32931 var picture = this.jsonModel.displayPictureClause, 32932 defaultPattern = "zzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzz"; 32933 32934 32935 try { 32936 if (picture && this.jsonModel.html5Type !== "number") { 32937 return xfalib.ut.PictureFmt.format(value + "", picture, guideBridge._readRuntimeLocale(), true); 32938 } else { 32939 var pattern = (this.jsonModel.html5Type === "number") ? defaultPattern : guidelib.i18n.numberPatterns.numeric; 32940 return xfalib.ut.PictureFmt.format(value + "", "num{" + pattern + "}", 32941 guideBridge._readRuntimeLocale(), true, true); 32942 } 32943 } catch (exception) { 32944 this.logger().error("Cannot format value " + value + " " + exception); 32945 32946 return value; 32947 } 32948 }, 32949 32950 32951 _totalDigitValidation : function (value, obj) {
32952 if (value && obj.validFlag && this.leadDigits > -1) { 32953 obj.validFlag = true; 32954 if (this.dataType === "integer") { 32955 obj.validFlag = this.value.toString().length <= this.leadDigits; 32956 } 32957 if (!obj.validFlag) { 32958 this._errorText = guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.totalDigitMessage, [this.leadDigits]); 32959 this._failedTest = this.guideUtil.TOTAL_DIGITS_TEST; 32960 } 32961 } 32962 }, 32963 32964 32965 _datatypeValidation : function (obj) { 32966 if (obj.validFlag) { 32967 var value = this.getAttribute("_value"); 32968 obj.validFlag = !isNaN(value); 32969 if (!obj.validFlag) { 32970 this._errorText = guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.datatypeMessage, ["numeric"]); 32971 this._failedTest = this.guideUtil.FORMAT_TEST; 32972 } 32973 } 32974 }, 32975 32976 32977 _runValidations : function (obj) { 32978 var value = this.value; 32979 GuideNumericBox._super._runValidations.call(this, obj); 32980 this._datatypeValidation(obj); 32981 this._minMaxValidation(value, obj); 32982 this._totalDigitValidation(value, obj); 32983 } 32984 }); 32985 GuideNumericBox.defineProps({ 32986 32987 dataType : { 32988 get : function () { 32989 return this.getAttribute("dataType"); 32990 } 32991 }, 32992 32993 32994 leadDigits : { 32995 get : function () { 32996 return this.getAttribute("leadDigits"); 32997 } 32998 }, 32999 33000 33001 fracDigits : { 33002 get : function () { 33003 return this.getAttribute("fracDigits"); 33004 } 33005 } 33006 }); 33007 33008 GuideNumericBox.addMixins([ 33009 guidelib.model.mixin.AddMinMaxValidation 33010 ]); 33011 33012})(_, guidelib); 33013 33014(function (_, guidelib) { 33015 33016 var GuideDatePicker = guidelib.model.GuideDatePicker = guidelib.model.Field.extend({ 33017 msClassName : "guideDatePicker", 33018 errorList : [], 33019 that : this, 33020 33021 initialize : function () { 33022 GuideDatePicker._super.initialize.call(this); 33023 if (_.isEmpty(this.jsonModel._value) && this.jsonModel.defaultToCurrentDate === "true") { 33024 this._setGuideValue(new Date().toISOString().slice(0, 10)); 33025 } 33026 }, 33027 33028 _setGuideValue : function (value) { 33029 var retVal = guidelib.util.GuideUtil._reformatDate(value, this.isEditPictureClausePresent); 33030 GuideDatePicker._super._setGuideValue.call(this, retVal); 33031 }, 33032 33033 _getTypedValue : function (value) { 33034 if (value) { 33035 return value; 33036 } 33037 return null; 33038 }, 33039 33040 33041 _datatypeValidation : function (obj) { 33042 if (obj.validFlag) { 33043 var value = this.getAttribute("_value"); 33044 obj.validFlag = true; 33045 if (value != null && xfalib.ut.DateInfo.Parse(value, undefined, this.isEditPictureClausePresent) == null) { 33046 obj.validFlag = false; 33047 } 33048 if (!obj.validFlag) { 33049 this._errorText = guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.datatypeMessage, ["date"]); 33050 this._failedTest = this.guideUtil.FORMAT_TEST; 33051 } 33052 } 33053 }, 33054 33055 _validateDatePart : function (field, datePart, errorList) { 33056 if (field === "D") { 33057 if (datePart > 31) { 33058 errorList.push(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.genericInvalidDatePart, [guidelib.i18n.calendarSymbols.month, guidelib.i18n.calendarSymbols.more, 31, guidelib.i18n.calendarSymbols.days])); 33059 } 33060 if (datePart < 1) { 33061 errorList.push(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.genericInvalidDatePart, [guidelib.i18n.calendarSymbols.month, guidelib.i18n.calendarSymbols.less, 1, guidelib.i18n.calendarSymbols.days])); 33062 } 33063 } 33064 if (field === "M") { 33065 if (datePart > 12) { 33066 errorList.push(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.genericInvalidDatePart, [guidelib.i18n.calendarSymbols.year, guidelib.i18n.calendarSymbols.more, 12, guidelib.i18n.calendarSymbols.months])); 33067 } 33068 if (datePart < 1) { 33069 errorList.push(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.genericInvalidDatePart, [guidelib.i18n.calendarSymbols.year, guidelib.i18n.calendarSymbols.less, 1, guidelib.i18n.calendarSymbols.months])); 33070 } 33071 } 33072 if (field === "Y") { 33073 if (datePart.length < 4) { 33074 errorList.push(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.genericInvalidYearPart)); 33075 } 33076 33077 } 33078 }, 33079 _getOrderedDateParts : function (value) { 33080 var dateFormat = this.jsonModel.dateDisplayFormat || "date{M/D/YYYY}"; 33081 var separator = dateFormat.match(/^date\{.*([^mdy]).*\}$/i)[1]; 33082 var fieldOrder = ['M', 'D', 'Y'] 33083 .map(function (val) { 33084 return { 33085 value : val, 33086 index : dateFormat.indexOf(val) 33087 }; 33088 }) 33089 .sort(function (a, b) { 33090 return a.index - b.index; 33091 }) 33092 .map(function (obj) { 33093 return obj.value; 33094 }); 33095 var dateParts = value.split(separator); 33096 return [dateParts, fieldOrder]; 33097 }, 33098 _checkIsolatedDateValidity : function (obj, value, errorList) { 33099 var orderedParts = this._getOrderedDateParts(value); 33100 var dateParts = orderedParts[0], fieldOrder = orderedParts[1]; 33101 for (var i = 0; i < fieldOrder.length; i++) { 33102 var field = fieldOrder[i]; 33103 var datePart = dateParts[i]; 33104 if (!_.isEmpty(datePart)) {
33105 this._validateDatePart(field, datePart, errorList); 33106 } 33107 } 33108 }, 33109 _validateDaysOfMonth : function (obj, value, errorList) { 33110 var orderedParts = this._getOrderedDateParts(value); 33111 var dateParts = orderedParts[0], fieldOrder = orderedParts[1]; 33112 month = dateParts[fieldOrder.indexOf('M')], 33113 day = dateParts[fieldOrder.indexOf('D')], 33114 year = dateParts[fieldOrder.indexOf('Y')]; 33115 if (month !== "" && day !== "") { 33116 month = Number(month) || 0; 33117 day = Number(day) || 0; 33118 var currentMonthName = guidelib.i18n.calendarSymbols.monthNames[month - 1]; 33119 if (31 === day && [4,6,9,11].includes(month)) { 33120 errorList.push(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.nonFebruaryMessage, [currentMonthName, day - 1])); 33121 } 33122 } 33123 }, 33124 _validateFieldCompleteness : function (obj, value, errorList) { 33125 var orderedParts = this._getOrderedDateParts(value); 33126 var dateParts = orderedParts[0], fieldOrder = orderedParts[1]; 33127 var localizedFieldMapping = { 33128 M : guidelib.i18n.calendarSymbols.month, 33129 D : guidelib.i18n.calendarSymbols.day, 33130 Y : guidelib.i18n.calendarSymbols.year 33131 }; 33132 var emptyFields = fieldOrder 33133 .map(function (fieldName) { 33134 return localizedFieldMapping[fieldName]; 33135 }) 33136 .filter(function (_, index) { 33137 return dateParts[index] === ""; 33138 }); 33139 if (emptyFields.length !== 3 && emptyFields.length > 0) { 33140 errorList.push("These fields still need to be filled: [" + emptyFields.join(", ") + "]"); 33141 } 33142 }, 33143 _validateFullDate : function (obj, value, errorList) { 33144 var orderedParts = this._getOrderedDateParts(value); 33145 var dateParts = orderedParts[0], fieldOrder = orderedParts[1]; 33146 month = dateParts[fieldOrder.indexOf('M')], 33147 day = dateParts[fieldOrder.indexOf('D')], 33148 year = dateParts[fieldOrder.indexOf('Y')]; 33149 if (month !== "" && day !== "" && year !== "") { 33150 month = Number(month) || 0; 33151 day = Number(day) || 0; 33152 year = Number(year) || 0; 33153 var isLeapYear = (year % 400 === 0 || (year % 4 === 0 && year % 100 !== 0)); 33154 if (month === 2) { 33155 var maxFebruary = isLeapYear ? 29 : 28; 33156 if (day === 29 && !isLeapYear) { 33157 errorList.push(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.februaryMessage, [maxFebruary, year])); 33158 } 33159 if (day >= 30) { 33160 errorList.push(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.februaryMessage, [maxFebruary, year])); 33161 } 33162 } 33163 } 33164 }, 33165 _computeErrors : function (obj, errorList) { 33166 var that = this; 33167 obj.validFlag = errorList.length === 0; 33168 if (!obj.validFlag) { 33169 that._errorText = errorList.join(" "); 33170 that._failedTest = that.guideUtil.FORMAT_TEST; 33171 } 33172 }, 33173 33174 33175 _runValidations : function (obj) { 33176 var value = this.value; 33177 if (this.jsonModel.titleDay || this.jsonModel.titleMonth || this.jsonModel.titleYear) { 33178 if (null === value) { 33179 value = "//"; 33180 } 33181 var errorList = []; 33182 33183 this._checkIsolatedDateValidity(obj, value, errorList); 33184 33185 if (errorList.length === 0) { 33186 this._validateDaysOfMonth(obj, value, errorList); 33187 } 33188 33189 if (errorList && errorList.length === 0 && window.FD && window.FD.isToggleEnabled(guidelib.util.FeatureToggleConstants.FT_DATE_PICKER_ERRORMESSAGE) ) { 33190
33191 this._validateFieldCompleteness(obj, value, errorList); 33192 } 33193 33194 if (errorList.length === 0) { 33195 this._validateFullDate(obj, value, errorList); 33196 } 33197 this._computeErrors(obj, errorList); 33198 33199 33200 if (errorList.length === 0) { 33201 this.value = value = this.value === "//" ? "" : this.value; 33202 GuideDatePicker._super._runValidations.call(this, obj); 33203 try { 33204 this.value = value = this.value !== null && this.value !== "" ? xfalib.ut.PictureFmt.parseDate(this.value, (this.jsonModel.dateDisplayFormat || "date{M/D/YYYY}")) : this.value; 33205 } catch (error) {} 33206 this._minMaxValidation(value, obj); 33207 } 33208 } else { 33209 GuideDatePicker._super._runValidations.call(this, obj); 33210 this._datatypeValidation(obj); 33211 this._minMaxValidation(value, obj); 33212 } 33213 } 33214 }); 33215 33216 GuideDatePicker.addMixins([ 33217 guidelib.model.mixin.AddMinMaxValidation 33218 ]); 33219 33220})(_, guidelib); 33221 33222(function (guidelib, $, _) { 33223 var ErrorConstants = guidelib.util.ErrorConstants = { 33224 DATA_ATTRIBUTE_ERROR_ITEM : "data-af-global-error-item", 33225 DATA_ATTRIBUTE_DISPLAY_ON : "data-af-global-errors-display-on", 33226 DATA_ATTRIBUTE_ERROR_TEXT_CONTAINER : "data-af-global-error-text", 33227 DATA_ATTRIBUTE_ERROR_CONTAINER : "data-af-global-errors", 33228 DATA_ATTRIBUTE_SOM : "data-af-som", 33229 CONTEXT_SUBMISSION : "form", 33230 CONTEXT_NAVIGATION : "panel", 33231 CONTEXT_FIELD : "field" 33232 33233 }; 33234 ErrorConstants[ErrorConstants.CONTEXT_SUBMISSION] = 4; 33235 ErrorConstants[ErrorConstants.CONTEXT_NAVIGATION] = 2; 33236 ErrorConstants[ErrorConstants.CONTEXT_FIELD] = 1; 33237 33238 var GlobalErrorContainer = function ($el, options) { 33239 this.$container = $el; 33240 var $items = $el.find("[" + ErrorConstants.DATA_ATTRIBUTE_ERROR_ITEM + "]").first(), 33241 displayOnAttribute = $el.attr(ErrorConstants.DATA_ATTRIBUTE_DISPLAY_ON) || ""; 33242 this.displayOn = 0; 33243 this.errorCount = 0; 33244 this.$container.addClass("no-validation-errors"); 33245 _.each(displayOnAttribute.split(","), function (displayOn) { 33246 var val = ErrorConstants[displayOn] || 0; 33247 this.displayOn += val; 33248 }, this); 33249 this.$item = $items.eq(0).clone(); 33250 $items.remove(); 33251 }; 33252 _.extend(GlobalErrorContainer.prototype, { 33253 33254 showError : function (msg, context, fieldSom) { 33255 var nContext, 33256 $el = this.$container.find('[' + ErrorConstants.DATA_ATTRIBUTE_SOM + '="' + fieldSom + '"]');; 33257 if ($el.length > 0) { 33258 $el.find("[" + ErrorConstants.DATA_ATTRIBUTE_ERROR_TEXT_CONTAINER + "]") 33259 .addBack("[" + ErrorConstants.DATA_ATTRIBUTE_ERROR_TEXT_CONTAINER + "]") 33260 .text(msg); 33261 } else { 33262 if (typeof ErrorConstants[context] !== "number") { 33263 return; 33264 } 33265 nContext = ErrorConstants[context]; 33266 if ((nContext & this.displayOn) === nContext) { 33267 if (this.errorCount === 0) { 33268 this.$container.removeClass("no-validation-errors"); 33269 } 33270 this.errorCount++; 33271 this.$item.clone() 33272 .find("[" + ErrorConstants.DATA_ATTRIBUTE_ERROR_TEXT_CONTAINER + "]") 33273 .addBack("[" + ErrorConstants.DATA_ATTRIBUTE_ERROR_TEXT_CONTAINER + "]") 33274 .text(msg) 33275 .click(function (evnt) { 33276 guideBridge.setFocus(fieldSom); 33277 }) 33278 .end() 33279 .end() 33280 .attr(ErrorConstants.DATA_ATTRIBUTE_SOM, fieldSom) 33281 .appendTo(this.$container); 33282 } 33283 } 33284 }, 33285 hideError : function (fieldSom) { 33286 var $err = this.$container.find('[' + ErrorConstants.DATA_ATTRIBUTE_SOM + '="' + fieldSom + '"]'); 33287 if ($err.length > 0) { 33288 $err.remove(); 33289 this.errorCount--; 33290 } 33291 if (this.errorCount === 0) { 33292 this.$container.addClass("no-validation-errors"); 33293 } 33294 } 33295 }); 33296 33297 $.fn.globalErrorContainer = function (options) { 33298 var args = arguments; 33299 return this.each(function () { 33300 var $this = $(this), 33301 obj = $this.data("global-error-container"); 33302 if (obj === undefined) { 33303 obj = new GlobalErrorContainer($this, $.extend({}, typeof options === "object" && options)); 33304 $this.data("global-error-container", obj); 33305 } 33306 if (typeof options === "string" && typeof obj[options] === "function") { 33307 obj[options].apply(obj, [].splice.apply(args, [1])); 33308 } 33309 }); 33310 }; 33311}(guidelib, $, _)); 33312 33313(function (guidelib, $, _) { 33314 33315 var ErrorConstants = guidelib.util.ErrorConstants, 33316 $GlobalErrorContainer; 33317 var GuideErrorManager = guidelib.util.GuideErrorManager = xfalib.ut.Class.extend({ 33318 33319 _defaultErrorMessage : "There is an error in this field !", 33320 33321 initialize : function () { 33322 GuideErrorManager._super.initialize.apply(arguments); 33323 $GlobalErrorContainer = $("[" + ErrorConstants.DATA_ATTRIBUTE_ERROR_CONTAINER + "]").globalErrorContainer(); 33324 }, 33325 33326 33327 33328 markError : function (msg, wrapper, fieldSom, context, type) { 33329 var errorDiv; 33330 33331 if (_.isUndefined(msg)) { 33332 msg = this._defaultErrorMessage; 33333 } 33334 33335 msg = msg.trim(); 33336 33337 $GlobalErrorContainer.globalErrorContainer("showError", msg, context, fieldSom); 33338 33339 33340 if (wrapper) { 33341 if (wrapper.length >= 1) { 33342 errorDiv = wrapper.find(".guideFieldError"); 33343 if (errorDiv.length < 1) { 33344 $("<div class='guideFieldError'></div>").appendTo(wrapper).text(msg); 33345 } else { 33346 errorDiv.text(msg); 33347 var roleAttr = errorDiv.attr('role'); 33348 if (roleAttr != undefined || roleAttr !== false) { 33349 errorDiv.attr('role', 'alert'); 33350 } 33351 errorDiv.show(); 33352 } 33353 33354 } 33355 } 33356 }, 33357 33358 unMarkError : function (wrapper, fieldSom) { 33359 33360 33361 wrapper.find(".guideFieldError").text(""); 33362 $GlobalErrorContainer.globalErrorContainer("hideError", fieldSom); 33363 } 33364 }); 33365})(guidelib, $, _); 33366(function (_, guidelib) { 33367 guidelib.model.mixin.ChoiceGroupOptionHandler = { 33368 normalProperties : { 33369 33370 _getOptionsArray : function (saveValueKey, displayValueKey) { 33371 var items = [], items1 = this.items; 33372 saveValueKey = saveValueKey || "saveValue"; 33373 displayValueKey = displayValueKey || "displayValue"; 33374 if (_.isArray(items1)) { 33375 _.each(items1, function (val) { 33376 33377 33378 var temp = val.split('='), 33379 obj = {}; 33380 obj[saveValueKey] = temp[0]; 33381 obj[displayValueKey] = temp[1] || temp[0]; 33382 items.push(obj); 33383 }); 33384 } 33385 return items; 33386 }, 33387 33388 33389 _getPossibleValueArray : function () { 33390 var values = [], items1 = this.items; 33391 if (_.isArray(items1)) { 33392 _.each(items1, function (val) { 33393 33394 var temp = val.split('='); 33395 values.push(temp[0]); 33396 }); 33397 } 33398 return values; 33399 }, 33400 33401 33402 _triggerItemsChange : function (oldValue, newValue) { 33403 this.trigger(guidelib.event.GuideModelEvent.ITEMS_CHANGED, 33404 guidelib.event.GuideModelEvent.createEvent( 33405 guidelib.event.GuideModelEvent.ITEMS_CHANGED, 33406 this, 33407 "items", 33408 oldValue, 33409 newValue 33410 ) 33411 ); 33412 }, 33413 33414 _resetModelValueForOptionChange : function () { 33415 if (!_.isUndefined(this.jsonModel._value) && this.jsonModel._value != null) { 33416 var valueArr = this.jsonModel._value.split(","); 33417 var possibleValues = this._getPossibleValueArray(); 33418 var modelValue = ""; 33419 _.each(valueArr, function (val) { 33420 if ($.inArray(val, possibleValues, 0) !== -1) { 33421 modelValue += val + ","; 33422 } 33423 }, this); 33424 if (modelValue.length > 0) { 33425 modelValue = modelValue.substring(0, modelValue.length - 1); 33426 } 33427 this.jsonModel._value = modelValue; 33428 } 33429 } 33430 } 33431 }; 33432 33433}(_, guidelib)); 33434(function (_, guidelib) { 33435 var GuideCheckBox = guidelib.model.GuideCheckBox = guidelib.model.Field.extend({ 33436 msClassName : "guideCheckBox", 33437 33438 _collectExpressions : function () { 33439 GuideCheckBox._super._collectExpressions.apply(this); 33440 if (this.optionsExp) { 33441 this._compiledExpressions.optionsExp = this._compileExpression(this.optionsExp, "items"); 33442 } 33443 }, 33444 33445 getOnOffValues : function (index) { 33446 var temp = this.jsonModel.options || [], items = [], on, off; 33447 if (this.bindNode) { 33448 on = this.bindNode.getSaveItem(0); 33449 off = this.bindNode.getSaveItem(1); 33450 } else { 33451 33452 if (temp.length == 0) { 33453 on = "0"; 33454 } else { 33455 on = temp[index].split('=')[0].trim(); 33456 } 33457 off = "-100"; 33458 } 33459 33460 items = [on, off]; 33461 return items; 33462 }, 33463 33464 _setXFAValue : function (value) { 33465 33466 if (value === "" || value === null) { 33467 this.bindNode.rawValue = this.bindNode.getSaveItem(1) || null; 33468 } else { 33469 this.bindNode.rawValue = value; 33470 } 33471 }, 33472 33473 _getCustomAssist : function (index) { 33474 var customAssist, item; 33475 33476 if (index == null) { 33477 33478 if (this.bindNode && this.bindNode.assist && this.bindNode.assist.speak && this.bindNode.assist.speak.value) { 33479 return this.bindNode.assist.speak.value; 33480 } 33481 return null; 33482 } 33483 33484 if (this.bindNode && this.bindNode.members && this.bindNode.members.item) { 33485 item = this.bindNode.members.item(index); 33486 if (item && item.assist && item.assist.speak && item.assist.speak.value) { 33487 customAssist = item.assist.speak.value; 33488 } 33489 } else if (this.jsonModel.custom) { 33490 33491 var custom; 33492 custom = this.jsonModel.custom || []; 33493 if (_.isString(custom) && index <= 0) { 33494 customAssist = custom; 33495 } else if (!custom.length === 0) { 33496 customAssist = custom[index]; 33497 } 33498 } 33499 return customAssist; 33500 }, 33501 _getToolTip : function (index) { 33502 var toolTip, item; 33503 if (this.bindNode && this.bindNode.members && this.bindNode.members.item) { 33504 item = this.bindNode.members.item(index); 33505 33506 if (item && item.assist && item.assist.speak && item.assist.speak.value) { 33507 toolTip = item.assist.toolTip.value; 33508 } 33509 33510 }
33510 else if (this.jsonModel.shortDescription) { 33511 toolTip = this.jsonModel.shortDescription; 33512 } 33513 return toolTip; 33514 }, 33515 _getCaption : function (index) { 33516 var item, caption, option; 33517 if (index == null) { 33518 33519 if (this.bindNode && this.bindNode.caption && this.bindNode.caption.value && this.bindNode.caption.value.oneOfChild && this.bindNode.caption.value.oneOfChild.value) { 33520 return this.bindNode.caption.value.oneOfChild.value; 33521 } 33522 return null; 33523 } 33524 if (this.bindNode && this.bindNode.members && this.bindNode.members.item) { 33525 item = this.bindNode.members.item(index); 33526 if (item.caption && item.caption.value && item.caption.value.oneOfChild && item.caption.value.oneOfChild.value) { 33527 caption = item.caption.value.oneOfChild.value; 33528 } 33529 33530 } else if (this.jsonModel.options) { 33531 var options; 33532 options = this.jsonModel.options || []; 33533 if (index < 0) { 33534 index = 0; 33535 } 33536 if (!options.length == 0) { 33537 option = options[index]; 33538 caption = guidelib.util.GuideUtil.getOptionsKeyValue(option).pop(); 33539 } 33540 33541 } 33542 return caption; 33543 }, 33544 _getName : function (index) { 33545 if (this.bindNode && this.bindNode.members && this.bindNode.members.item && this.bindNode.members.item(index)) { 33546 33547 return this.bindNode.members.item(index).name; 33548 } 33549 return null; 33550 }, 33551 33552 _getScreenReaderText : function (index) { 33553 var screenReaderText, assistPriority = this._getAssistPriority() || "caption"; 33554 33555 if (this.bindNode) { 33556 screenReaderText = GuideCheckBox._super._getScreenReaderText.apply(this, [index]); 33557 } else { 33558 if (assistPriority == "custom") { 33559 screenReaderText = this._getCustomAssist(index) || this._getCaption(index); 33560 } else if (assistPriority == "caption") { 33561 screenReaderText = this._getCaption(index); 33562 } 33563 } 33564 return screenReaderText; 33565 } 33566 }); 33567 33568 GuideCheckBox.defineProps({ 33569 33570 optionsExp : { 33571 get : function () { 33572 return this.getAttribute("optionsExp"); 33573 } 33574 }, 33575 33576 33577 items : { 33578 get : function () { 33579 var items = this.jsonModel.options; 33580 if (items && !_.isArray(items)) { 33581 items = items.split(","); 33582 } else if (items) { 33583 items = items.slice(0); 33584 } 33585 return items; 33586 }, 33587 set : function (newValue) { 33588 if (!this.bindNode) { 33589 var oldValue = this.jsonModel.options; 33590 if (JSON.stringify(newValue) !== JSON.stringify(oldValue)) { 33591 33592 this.jsonModel.options = newValue; 33593 this._resetModelValueForOptionChange(); 33594 this._addStateOverride("options", {"option" : this._getOptionsArray()}); 33595 this._triggerItemsChange(oldValue, newValue); 33596 } 33597 } 33598 } 33599 } 33600 }); 33601 33602 GuideCheckBox.addMixins([ 33603 guidelib.model.mixin.ChoiceGroupOptionHandler 33604 ]); 33605})(_, guidelib); 33606(function (_, guidelib) { 33607 var GuideSwitch = guidelib.model.GuideSwitch = guidelib.model.GuideCheckBox.extend({ 33608 msClassName : "guideSwitch", 33609 33610 initialize : function () { 33611 33612 var uncheckedValue = this.getOnOffValues()[1]; 33613 this.jsonModel["_value"] = this.getOrElse(this.jsonModel, "_value", uncheckedValue); 33614 GuideSwitch._super.initialize.call(this); 33615 }, 33616 33617 getOnOffValues : function (index) { 33618 var options, checkedLabel, uncheckedLabel, items; 33619 if (this.bindNode) { 33620 checkedLabel = this.bindNode.getSaveItem(0); 33621 uncheckedLabel = this.bindNode.getSaveItem(1); 33622 } else { 33623 items = this.jsonModel.options; 33624 33625 if (Array.isArray(items) && items.length > 0) { 33626 checkedLabel = items[0].split('=')[0].trim(); 33627 } else if (!_.isUndefined(items) && items.length > 0) { 33628 checkedLabel = items.split('=')[0].trim(); 33629 } else { 33630 checkedLabel = "1"; 33631 } 33632 if (Array.isArray(items) && items.length > 1) { 33633 uncheckedLabel = items[1].split('=')[0].trim(); 33634 } else { 33635 uncheckedLabel = "0"; 33636 } 33637 } 33638 options = [checkedLabel, uncheckedLabel]; 33639 return options; 33640 }, 33641 33642 resetData : function () { 33643 this.value = this.jsonModel["{default}"]; 33644 } 33645 }); 33646})(_, guidelib); 33647(function (_, guidelib) { 33648 var GuideRadioButton = guidelib.model.GuideRadioButton = guidelib.model.Field.extend({ 33649 msClassName : "guideRadioButton", 33650 prevOnItem : null, 33651 initialize : function () { 33652 33653 GuideRadioButton._super.initialize.call(this); 33654 }, 33655 33656 _postInitialize : function () { 33657 GuideRadioButton._super._postInitialize.call(this);
33658 this.prevOnItem = this.getSelectedIndex(this.value); 33659 if (this.bindNode && this.bindNode.members) { 33660 for (var i = 0; i < this.bindNode.members.length; i++) { 33661 var field = this.bindNode.members.item(i); 33662 field.on(xfalib.script.XfaModelEvent.FORM_MODEL_CHANGED, this); 33663 } 33664 } 33665 }, 33666 33667 _unloadModel : function () { 33668 if (this.bindNode && this.bindNode.members) { 33669 for (var i = 0; i < this.bindNode.members.length; i++) { 33670 var field = this.bindNode.members.item(i); 33671 field.off(xfalib.script.XfaModelEvent.FORM_MODEL_CHANGED, this); 33672 } 33673 } 33674 33675 GuideRadioButton._super._unloadModel.call(this); 33676 }, 33677 33678 33679 _collectExpressions : function () { 33680 GuideRadioButton._super._collectExpressions.apply(this); 33681 if (this.optionsExp) { 33682 this._compiledExpressions.optionsExp = this._compileExpression(this.optionsExp, "items"); 33683 } 33684 }, 33685 33686 33687 getItemIdentifier : function (index) { 33688 if (this.bindNode) { 33689 return this.bindNode.members.item(index).somExpression; 33690 } else { 33691 return index; 33692 } 33693 33694 }, 33695 33696 playJson : function (pJsonModel) { 33697 GuideRadioButton._super.playJson.call(this, pJsonModel); 33698 this.prevOnItem = this.getSelectedIndex(this.jsonModel._value); 33699 }, 33700 33701 getOnOffValues : function (index) { 33702 var temp = this.jsonModel.options || [], 33703 items = [], 33704 on, 33705 off; 33706 if (this.bindNode) { 33707 var item = this.bindNode.members.item(index); 33708 on = item.getSaveItem(0); 33709 off = item.getSaveItem(1) ? item.getSaveItem(1) : null; 33710 } else { 33711 33712 if (temp.length == 0) { 33713 on = "0"; 33714 } else { 33715 on = temp[index].split('=')[0].trim(); 33716 } 33717 off = null; 33718 } 33719 33720 items = [on, off]; 33721 return items; 33722 }, 33723 33724 _handleXfaModelChanged : function (event) { 33725 if (event._property == "rawValue") { 33726 this.trigger(guidelib.event.GuideModelEvent.VALUE_CHANGED, 33727 guidelib.event.GuideModelEvent.createEvent( 33728 guidelib.event.GuideModelEvent.VALUE_CHANGED, 33729 this, 33730 "value", 33731 event.target.somExpression, 33732 event.newText 33733 ) 33734 ); 33735 } else { 33736 GuideRadioButton._super._handleXfaModelChanged.call(this, event); 33737 } 33738 }, 33739 33740 getSelectedIndex : function (value) { 33741 var index = null; 33742 if (!_.isEmpty(this.jsonModel.options) && !_.isArray(this.jsonModel.options)) { 33743 this.jsonModel.options = [this.jsonModel.options]; 33744 } 33745 var currOption = _.find(this.jsonModel.options, function (opt, i) { 33746 var items = this.getOnOffValues(i); 33747 index = i; 33748 return (items[0] == value); 33749 }, this); 33750 33751 if (currOption) { 33752 return index; 33753 } else { 33754 return null; 33755 } 33756 33757 }, 33758 33759 33760 33761 _triggerDisplayFormatChange : function () { 33762 if (!this.bindNode) { 33763 var currValue = this._getValue(); 33764 var currSelected = this.getSelectedIndex(currValue); 33765 33766 if (this.prevOnItem !== null) { 33767 this._triggerEvent(guidelib.event.GuideModelEvent.VALUE_CHANGED, "value", this.prevOnItem, null); 33768 } 33769 if (currSelected !== null) { 33770 this._triggerEvent(guidelib.event.GuideModelEvent.VALUE_CHANGED, "value", currSelected, this._getFormattedValue(currValue)); 33771 } 33772 this.prevOnItem = currSelected; 33773 } 33774 }, 33775 _getCustomAssist : function (index) { 33776 var customAssist, item; 33777 33778 if (index == null) { 33779 33780 if (this.bindNode && this.bindNode.assist && this.bindNode.assist.speak && this.bindNode.assist.speak.value) { 33781 return this.bindNode.assist.speak.value; 33782 } 33783 return null; 33784 } 33785 33786 if (this.bindNode && this.bindNode.members && this.bindNode.members.item) { 33787 item = this.bindNode.members.item(index); 33788 if (item && item.assist && item.assist.speak && item.assist.speak.value) { 33789 customAssist = item.assist.speak.value; 33790 } 33791 } else if (this.jsonModel.custom) { 33792 33793 var custom; 33794 custom = this.jsonModel.custom || []; 33795 if (_.isString(custom) && index <= 0) { 33796 33797 customAssist = custom; 33798 } else { 33799 if (!custom.length == 0) { 33800 customAssist = custom[index]; 33801 } 33802 } 33803 } 33804 return customAssist; 33805 }, 33806 _getToolTip : function (index) { 33807 var toolTip, item; 33808 if (this.bindNode && this.bindNode.members && this.bindNode.members.item) { 33809 item = this.bindNode.members.item(index); 33810 33811 if (item && item.assist && item.assist.speak && item.assist.speak.value) { 33812 toolTip = item.assist.toolTip.value; 33813 } 33814 33815 }
33815 else if (this.jsonModel.shortDescription) { 33816 toolTip = this.jsonModel.shortDescription; 33817 } 33818 return toolTip; 33819 }, 33820 _getCaption : function (index) { 33821 var item, caption, option; 33822 if (index == null) { 33823 33824 if (this.bindNode && this.bindNode.caption && this.bindNode.caption.value && this.bindNode.caption.value.oneOfChild && this.bindNode.caption.value.oneOfChild.value) { 33825 return this.bindNode.caption.value.oneOfChild.value; 33826 } 33827 return null; 33828 } 33829 if (this.bindNode && this.bindNode.members && this.bindNode.members.item) { 33830 item = this.bindNode.members.item(index); 33831 if (item.caption && item.caption.value && item.caption.value.oneOfChild && item.caption.value.oneOfChild.value) { 33832 caption = item.caption.value.oneOfChild.value; 33833 } 33834 33835 } else if (this.jsonModel.options) { 33836 var options; 33837 options = this.jsonModel.options || []; 33838 if (index < 0) { 33839 index = 0; 33840 } 33841 if (!options.length == 0) { 33842 option = options[index]; 33843 caption = guidelib.util.GuideUtil.getOptionsKeyValue(option).pop(); 33844 } 33845 33846 } 33847 return caption; 33848 }, 33849 _getName : function (index) { 33850 if (this.bindNode && this.bindNode.members && this.bindNode.members.item && this.bindNode.members.item(index)) { 33851 33852 return this.bindNode.members.item(index).name; 33853 } 33854 return null; 33855 }, 33856 33857 _getScreenReaderText : function (index) { 33858 var screenReaderText, assistPriority = this._getAssistPriority() || "caption"; 33859 33860 if (this.bindNode) { 33861 screenReaderText = GuideRadioButton._super._getScreenReaderText.apply(this, [index]); 33862 } else { 33863 if (assistPriority == "custom") { 33864 screenReaderText = this._getCustomAssist(index) || this._getCaption(index); 33865 } else if (assistPriority == "caption") { 33866 screenReaderText = this._getCaption(index); 33867 } 33868 } 33869 return screenReaderText; 33870 } 33871 }); 33872 33873 GuideRadioButton.defineProps({ 33874 33875 optionsExp : { 33876 get : function () { 33877 return this.getAttribute("optionsExp"); 33878 } 33879 }, 33880 33881 33882 items : { 33883 get : function () { 33884 var items = this.jsonModel.options; 33885 if (items && !_.isArray(items)) { 33886 items = items.split(","); 33887 } else if (items) { 33888 items = items.slice(0); 33889 } 33890 return items; 33891 }, 33892 set : function (newValue) { 33893 if (!this.bindNode && newValue && newValue.length > 1) { 33894 var oldValue = this.jsonModel.options; 33895 if (JSON.stringify(newValue) !== JSON.stringify(oldValue)) { 33896 33897 this.jsonModel.options = newValue; 33898 this._resetModelValueForOptionChange(); 33899 this._addStateOverride("options", {"option" : this._getOptionsArray()}); 33900 this._triggerItemsChange(oldValue, newValue); 33901 } 33902 } 33903 } 33904 } 33905 }); 33906 33907 GuideRadioButton.addMixins([ 33908 guidelib.model.mixin.ChoiceGroupOptionHandler 33909 ]); 33910})(_, guidelib); 33911 33912(function (_, guidelib) { 33913 33914 33915 var GuideDropDownList = guidelib.model.GuideDropDownList = guidelib.model.Field.extend({ 33916 msClassName : "guideDropDownList" , 33917 33918 _collectExpressions : function () { 33919 GuideDropDownList._super._collectExpressions.apply(this); 33920 if (this.optionsExp) { 33921 this._compiledExpressions["optionsExp"] = this._compileExpression(this.optionsExp, "items"); 33922 } 33923 }, 33924 33925 _handleXfaModelChanged : function (event) { 33926 if (event._property === "addItem" || event._property === "clearItems" || event._property === "deleteItem") { 33927 this._triggerEvent(guidelib.event.GuideModelEvent.MODEL_CHANGED, event._property, event.prevText, event.newText); 33928 } else { 33929 GuideDropDownList._super._handleXfaModelChanged.call(this, event); 33930 } 33931 }, 33932 33933 _getDisplayValue : function (saveValue) { 33934 var items = this._getOptionsArray(), 33935 displayValue = null; 33936 _.each(items, function (val) { 33937 if (saveValue === val.saveValue) { 33938 displayValue = val.displayValue; 33939 } 33940 }, this);
33941 return displayValue; 33942 }, 33943 33944 _getItems : function () { 33945 return this.jsonModel.options; 33946 }, 33947 33948 _setXFAItems : function (options) { 33949 var optionsStr = this._getXFAOptionStringFromGuideItems(options); 33950 var SET_ITEMS_INSERT_MODE_PAIR = 2; 33951 if (optionsStr) { 33952 this.bindNode.setItems(optionsStr, SET_ITEMS_INSERT_MODE_PAIR); 33953 } else { 33954 this.bindNode.clearItems(); 33955 } 33956 }, 33957 33958 33959 _allowEmptyValueString : function () { 33960 return true; 33961 } 33962 33963 }); 33964 33965 GuideDropDownList.defineProps({ 33966 33967 33968 33969 multiSelect : { 33970 get : function () { 33971 return this.getAttribute("multiSelect"); 33972 }, 33973 set : function () { 33974 this.setAttribute("multiSelect"); 33975 } 33976 }, 33977 33978 optionsExp : { 33979 get : function () { 33980 return this.getAttribute("optionsExp"); 33981 } 33982 }, 33983 33984 33985 displayValue : { 33986 get : function () { 33987 return this._getDisplayValue(this.value); 33988 } 33989 }, 33990 33991 33992 33993 items : { 33994 get : function () { 33995 var items = []; 33996 if (this.bindNode) { 33997 var that = this.bindNode; 33998 for (var index = 0; index < that.length; index++) { 33999 var item = that.getSaveItem(index) + "=" + that.getDisplayItem(index); 34000 items.push(item); 34001 } 34002 return items; 34003 } else { 34004 items = this._getItems(); 34005 if (items && !_.isArray(items)) { 34006 items = items.split(","); 34007 } else if (items) { 34008 items = items.slice(0); 34009 } 34010 return items; 34011 } 34012 }, 34013 set : function (newValue) { 34014 var oldValue = this._getItems(); 34015 if (JSON.stringify(newValue) !== JSON.stringify(oldValue)) { 34016 if (this.bindNode) { 34017 this._setXFAItems(newValue); 34018 } else { 34019 this.jsonModel.options = newValue; 34020 } 34021 if (this.multiSelect) { 34022 this._resetModelValueForOptionChange(); 34023 } 34024 this._addStateOverride("options", {"option" : this._getOptionsArray()}); 34025 this._triggerItemsChange(oldValue, this.items); 34026 } 34027 } 34028 } 34029 }); 34030 GuideDropDownList.addMixins([ 34031 guidelib.model.mixin.ChoiceGroupOptionHandler 34032 ]); 34033})(_, guidelib); 34034 34035 34036(function (guidelib, $, _) { 34037 34038 var GuideLazyUtil = guidelib.util.GuideLazyUtil = xfalib.ut.Class.extend({ 34039 34040 34041 putDirtyToTemplateCacheIfMissing : function (guide) { 34042 var guideDirtyMarker = guide.internal.GuideDirtyMarkerAndVisitor || this._guide().internal.GuideDirtyMarkerAndVisitor, 34043 listOfDirtyChildren = guideDirtyMarker._flattenDirtyPanelToList(); 34044 this._getAllDirtyJsonTemplateInCache(listOfDirtyChildren); 34045 }, 34046 34047 34048 _getAllDirtyJsonTemplateInCache : function (listOfTemplateIds) { 34049 var modelTemplateCache = window.guideBridge._guide._modelTemplateCacheStore, 34050 toGetFromServer = this._generateListOfCacheMissFromTemplateJson(listOfTemplateIds); 34051 if (toGetFromServer.length > 0 && window.guideBridge.panelProvider) { 34052 var options = { 34053 path : window.guideBridge._getGuidePathUrl(".jsonhtmlemitter"), 34054 listOfTemplateIds : toGetFromServer, 34055 success : addToTemplateCache 34056 }; 34057 window.guideBridge.panelProvider.getMultipleTemplateJson(options); 34058 } 34059 34060 function addToTemplateCache(toInsertToTemplateCache) { 34061 _.each(toInsertToTemplateCache, function (jsonModelString) { 34062 var template = JSON.parse(jsonModelString); 34063 modelTemplateCache._putLazyTemplate(template); 34064 }); 34065 } 34066 }, 34067 34068 34069 _generateListOfCacheMissFromTemplateJson : function (listOfTemplateIds) { 34070 var templateCache = window.guideBridge._guide._modelTemplateCacheStore, 34071 cacheMiss = []; 34072 _.each(listOfTemplateIds, function (templateID) { 34073 var templateJson = templateCache._getTemplate(templateID, true); 34074 if (guidelib.util.GuideUtil.isLazyJson(templateJson)) { 34075 cacheMiss.push(templateID); 34076 } 34077 }); 34078 return cacheMiss; 34079 }, 34080 34081 _guide : function () { 34082 return this.options._guideContainer; 34083 } 34084 34085 }); 34086})(guidelib, $, _); 34087(function (_, guidelib) { 34088 var guideSchema = {}, 34089 convertor = { 34090 "visible" : { 34091 "xfaToGuide" : function (xfaValue) { 34092 return xfaValue === "visible"; 34093 }, 34094 "guideToXfa" : function (guideValue) { 34095 return guideValue === true ? "visible" : "hidden"; 34096 } 34097 }, 34098 "enabled" : { 34099 "xfaToGuide" : function (xfaValue) { 34100 return xfaValue === "open"; 34101 }, 34102 "guideToXfa" : function (guideValue) { 34103 return guideValue === true ? "open" : "readOnly"; 34104 } 34105 }, 34106 "assistPriority" : { 34107 "xfaToGuide" : function (xfaValue) { 34108 return { 34109 "custom" : "custom",
34110 "toolTip" : "shortDescription", 34111 "caption" : "label", 34112 "name" : "name" 34113 }[xfaValue]; 34114 }, 34115 "guideToXfa" : function (guideValue) { 34116 return { 34117 "custom" : "custom", 34118 "shortDescription" : "toolTip", 34119 "title" : "caption", 34120 "name" : "name" 34121 }[guideValue]; 34122 } 34123 }, 34124 "mandatory" : { 34125 "xfaToGuide" : function (xfaValue) { 34126 return xfaValue === "error"; 34127 }, 34128 "guideToXfa" : function (guideValue) { 34129 return guideValue === true ? "error" : "disabled"; 34130 } 34131 }, 34132 "multiLine" : { 34133 "xfaToGuide" : function (xfaValue) { 34134 return xfaValue == 1; 34135 }, 34136 "guideToXfa" : function (guideValue) { 34137 return guideValue === true ? 1 : 0; 34138 } 34139 }, 34140 34141 34142 "options" : { 34143 "xfaToGuide" : function (xfaValue) { 34144 var items = []; 34145 if (xfaValue) { 34146 var bndNode = this.bindNode; 34147 _.each(xfaValue, function (item, index, list) { 34148 items.push(bndNode.getSaveItem(index) + "=" + bndNode.getDisplayItem(index)); 34149 }); 34150 } 34151 return items; 34152 }, 34153 "guideToXfa" : function (guideValue) { 34154 return guideValue; 34155 } 34156 }, 34157 "multiSelect" : { 34158 "xfaToGuide" : function (xfaValue) { 34159 return xfaValue === "multiSelect"; 34160 }, 34161 "guideToXfa" : function (guideValue) { 34162 return guideValue === true ? "multiSelect" : "userControl"; 34163 } 34164 }, 34165 "calcExp" : { 34166 "xfaToGuide" : function (xfaValue) { 34167 return xfaValue !== null && xfaValue !== "" ? null : undefined; 34168 }, 34169 "guideToXfa" : function (guideValue) { 34170 return guideValue !== null && guideValue !== "" ? null : undefined; 34171 } 34172 }, 34173 "dataType" : { 34174 "xfaToGuide" : function (xfaValue) { 34175 return xfaValue; 34176 }, 34177 "guideToXfa" : function (guideValue) { 34178 return undefined; 34179 } 34180 } 34181 }; 34182 convertor.validateExp = convertor.visibleExp = 34183 convertor.enabledExp = 34184 convertor.clickExp = 34185 convertor.calcExp; 34186 34187 guidelib.model.GuideSchema = xfalib.ut.Class.extend({ 34188 34189 GuideStateConstants : { 34190 34191 GUIDE_STATE_MODEL_CREATION : 0, 34192 34193 GUIDE_STATE_MODEL_CREATED : 1, 34194 34195 GUIDE_STATE_MERGE_PROGRESS : 2, 34196 34197 GUIDE_STATE_MERGE_COMPLETE : 3, 34198 34199 GUIDE_STATE_MODEL_COMPLETE : 4 34200 }, 34201 34202 initialize : function () { 34203 34204 this.addSchema('guideNode', 34205 [ 34206 ["name", "string", null], 34207 ["id", "string", null], 34208 ["jcr:title", "string", null], 34209 ["jcr:description", "string", null], 34210 ["css", "string", ""], 34211 ["fd:targetVersion", "float", 1.0] 34212 ]); 34213 34214 this.addSchema("scriptable", 34215 [ 34216 ["visibleExp", "string", null], 34217 ["enabledExp", "string", null], 34218 ["visible", "boolean", true, "presence"], 34219 ["enabled", "boolean", true, "access"], 34220 ["assistPriority", "string", null, "assist.speak.priority"], 34221 ["custom", "string", null, "assist.speak.value"],
34222 ["shortDescription", "string", null, "assist.toolTip.value"], 34223 ["longDescription", "string", null] 34224 ], 34225 'guideNode'); 34226 34227 this.addSchema("guideInstanceManager", [], "guideNode"); 34228 34229 this.addSchema("esign", [], "guideNode"); 34230 34231 this.addSchema("verify", [], "guideNode"); 34232 34233 this.addSchema("guideItemsContainer", [], "scriptable"); 34234 34235 this.addSchema("guideImage", [], "scriptable"); 34236 34237 this.addSchema("guideContainerNode", 34238 [ 34239 ["disableSwipeGesture", "boolean", false] 34240 ], 34241 "guideItemsContainer"); 34242 34243 this.addSchema("guidePanel", 34244 [ 34245 ["validateOnStepCompletion","boolean",false] 34246 ], 34247 "guideItemsContainer"); 34248 34249 this.addSchema("rootPanelNode", [], "guidePanel"); 34250 34251 this.addSchema("guideTable", [], "guidePanel"); 34252 34253 this.addSchema("guideTableRow", [], "guidePanel"); 34254 34255 this.addSchema("guideToolbar", [], "guideItemsContainer"); 34256 34257 this.addSchema("guideCompositeField", [], "guideItemsContainer"); 34258 34259 this.addSchema("guideFileUpload", 34260 [ 34261 ["multiSelection", "boolean", false], 34262 ["buttonText", "string", null], 34263 ["fileSizeLimit", "integer", 2], 34264 ["showComment", "boolean", false] 34265 ], 34266 "guideCompositeField"); 34267 34268 34269 34270 this.addSchema("guideField", 34271 [ 34272 ["jcr:title", "string", null, "caption.value.oneOfChild.value","Guide"], 34273 ["calcExp", "string", null, "calculate.script.value", "Guide"], 34274 ["validateExp", "string", null, "validate.script.value", "Guide"], 34275 ["_value", "string", null, "rawValue"], 34276 ["displayPictureClause", "string", null, "format.picture.value"], 34277 ["validatePictureClause", "string", null, "validate.picture.value"], 34278 ["mandatory", "boolean", false, "validate.nullTest"], 34279 ["mandatoryMessage", "string", guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.LogMessages["AEM-AF-901-005"]), 34280 "mandatoryMessage"], 34281 ["validateExpMessage", "string", guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.LogMessages["AEM-AF-901-006"]), 34282 "validationMessage","Guide"], 34283 ["validatePictureClauseMessage", "string", guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.LogMessages["AEM-AF-901-007"]), 34284 "formatMessage"], 34285 ["validationState", "boolean", false], 34286 ["width", "string", null], 34287 ["height", "string", null] 34288 ], 34289 "scriptable"); 34290 34291 this.addSchema("guideTextBox", 34292 [ 34293 ["multiLine", "boolean", false, "ui.textEdit.multiLine"], 34294 ["maxChars", "integer", 0, "value.text.maxChars"], 34295 ["minLength", "integer", null], 34296 ["length", "integer", null] 34297 ], 34298 "guideField"); 34299 34300 this.addSchema("guideCaptcha", [], "guideField"); 34301 34302 this.addSchema("guideTelephone", [], "guideField"); 34303 34304 this.addSchema("guideNumericBox", 34305 [ 34306 ["dataType", "string", "decimal", "value.oneOfChild.className"], 34307 ["leadDigits", "integer", -1, "value.decimal.leadDigits"], 34308 ["fracDigits", "integer", 2, "value.decimal.fracDigits"], 34309 ["maximum", "integer", null], 34310 ["minimum", "integer", null], 34311 ["exclusiveMaximum", "boolean", null], 34312 ["exclusiveMinimum", "boolean", null] 34313 ], 34314 "guideField"); 34315 34316 this.addSchema("guidePasswordBox", [], "guideField"); 34317 34318 this.addSchema("guideRadioButton", [ 34319 ["optionsExp", "string", null], 34320 ["options", "object", null, "items"] 34321 ], "guideField"); 34322 34323 this.addSchema("guideCheckBox", [ 34324 ["optionsExp", "string", null], 34325 ["options", "object", null, "items"] 34326 ], "guideField"); 34327 34328 this.addSchema("guideSwitch", [], "guideCheckBox"); 34329 34330 this.addSchema("guideScribble", [], "guideField"); 34331 34332 this.addSchema("guideDatePicker", 34333 [ 34334 ["maximum", "string", null], 34335 ["minimum", "string", null], 34336 ["exclusiveMaximum", "boolean", null], 34337 ["exclusiveMinimum", "boolean", null] 34338 ], "guideField"); 34339 34340 this.addSchema("guideButton", [], "guideField"); 34341 34342 this.addSchema("guideListFileAttachmentButton", [], "guideButton"); 34343 34344 this.addSchema("guideTextDraw", 34345 [ 34346 ["documentFragmentVariables", "string", null] 34347 ], 34348 "guideField"); 34349 34350 this.addSchema("guideFootnotePlaceHolder",[], "guideTextDraw"); 34351 34352 this.addSchema("guideAdobeSignBlock", 34353 [ 34354 ["documentFragmentVariables", "string", null] 34355 ], 34356 "guideField"); 34357 34358 this.addSchema("guideCompositeFieldItem", [], "guideField"); 34359 34360 this.addSchema("guideDropDownList", 34361 [ 34362 ["title", "string", "DropDown"], 34363 ["multiSelect", "boolean", false, "ui.oneOfChild.open"], 34364 ["optionsExp", "string", null], 34365 ["options", "object", null, "items"] 34366 ], 34367 "guideField"); 34368 34369 this.addSchema("guideTermsAndConditions", 34370 [ 34371 ["showLink", "boolean", false], 34372 ["showAsPopUp", "boolean", false], 34373 ["clickStatus", "string", null] 34374 ], 34375 "guideCompositeField"); 34376 34377 this.addSchema("guideChart", [ 34378 ["height", "integer", 300], 34379 ["width", "integer", 100], 34380 ["data", "object", null], 34381 ["xAxisTitle", "string", null], 34382 ["yAxisTitle", "string", null], 34383 ["chartType", "string", "linepoint"], 34384 ["repeatableItem", "string", null], 34385 ["xExp", "string", null], 34386 ["reducerXFunction", "string", "none"], 34387 ["yExp", "string", null], 34388 ["reducerYFunction", "string", "none"], 34389 ["innerRadius", "integer", 0], 34390 ["lineColor", "string", "#000000"], 34391 ["pointColor", "string", "#000000"], 34392 ["areaColor", "string", "#000000"], 34393 ["tooltipHtml", "string", "<p>${x}(${y})</p>"], 34394 ["showLegends", "boolean", false], 34395 ["legendPosition", "string", "right"] 34396 ], "scriptable"); 34397 34398 this.addSchema("guideAdModule", [["_value", "string", null]], "scriptable"); 34399 this.addSchema("guideAdModuleGroup", [["_value", "string", null]], "scriptable"); 34400 }, 34401 34402 addSchema : function (elementName, attrArray, superElement) { 34403 var el = {}; 34404 if (typeof superElement === "object") { 34405 _.extend(el, superElement); 34406 } else if (typeof superElement === "string" && guideSchema[superElement]) { 34407 _.extend(el, guideSchema[superElement]); 34408 } 34409 this.addAttributes(el, attrArray); 34410 guideSchema[elementName] = el; 34411 }, 34412 34413 addAttributes : function (element, attrArray) { 34414 _.each(attrArray, function (elem) { 34415 element[elem[0]] = { 34416 "type" : elem[1], 34417 "default" : elem[2], 34418 "xfaProp" : elem[3], 34419 "priority" : elem[4] 34420 }; 34421 }); 34422 }, 34423 34424 getAttributeProps : function (element, attribute) { 34425 try { 34426 return guideSchema[element][attribute] || {}; 34427 } catch (e) { 34428 this.logger().error("AF", "schema has no element " + element); 34429 } 34430 }, 34431 getAttributes : function (element) { 34432 return guideSchema[element]; 34433 }, 34434 34435 getTypedValue : function (type, value) { 34436 if (value === null || value === undefined) { 34437 return value; 34438 } 34439 if (type instanceof Array) { 34440 return value; 34441 } 34442 switch (type) { 34443 case "string": 34444 return value + ""; 34445 case "integer": 34446 return parseInt(value); 34447 case "boolean": 34448 return value === true || value === "true" ? true : false;
34449 case "float": 34450 return parseFloat(value); 34451 default : 34452 return value; 34453 } 34454 }, 34455 34456 getConvertor : function (attr) { 34457 return convertor[attr]; 34458 } 34459 }); 34460 34461}(_, guidelib)); 34462 34463(function (_, guidelib) { 34464 34465 34466 34467 var GuideContainerNode = guidelib.model.GuideContainerNode = guidelib.model.GuideItemsContainer.extend({ 34468 msClassName : "guideContainerNode", 34469 34470 setGuideState : function (guideState) { 34471 var isStateValid = _.some(guidelib.model.GuideSchema.prototype.GuideStateConstants, function (val) { 34472 return val === guideState; 34473 }); 34474 if (isStateValid === true) { 34475 this._guideState = guideState; 34476 } 34477 }, 34478 34479 getGuideState : function () { 34480 return this._guideState; 34481 }, 34482 34483 initialize : function () { 34484 var configString = ""; 34485 34486 guidelib.__runtime__.guide = this; 34487 34488 34489 34490 this._guideState = guidelib.model.GuideSchema.prototype.GuideStateConstants.GUIDE_STATE_MODEL_CREATION; 34491 34492 34493 this.internal = this.internal || {}; 34494 34495 34496 this.internal.liveDataUtils = this.options.liveDataUtils || new guidelib.model.LiveXmlUtils(); 34497 this.internal.liveModel = this.options.liveModel || new guidelib.model.LiveModel(); 34498 this.internal.GuideDirtyMarkerAndVisitor = new guidelib.model.GuideDirtyMarkerAndVisitor(); 34499 34500 34501 this.runtime = { 34502 guideContext : {}, 34503 _private : {}, 34504 errorManager : {} 34505 }; 34506 34507 34508 this.runtime.errorManager = new guidelib.util.GuideErrorManager(); 34509 34510 this._modelTemplateCacheStore = 34511 new guidelib.model.util.ModelTemplateCacheStore({modelTemplateJson : this.jsonModel}); 34512 this._guideSchema = new guidelib.model.GuideSchema(); 34513 this.guideLazyUtil = new guidelib.util.GuideLazyUtil({"_guideContainer" : this}); 34514 this._pendingQueues = { 34515 calcExp : [], 34516 valueCommitScript : [], 34517 enabledExp : [], 34518 visibleExp : [], 34519 validateAllExp : [], 34520 optionsExp : [], 34521 navigationChangeExp : [], 34522 summaryExp : [], 34523 autoSaveStartExp : [], 34524 aggregateExp : [], 34525 submitSuccess : [], 34526 submitError : [], 34527 saveSuccess : [], 34528 saveError : [] 34529 }; 34530 this._resetExpressionCounters(); 34531 this._currentContext = null; 34532 GuideContainerNode._super.initialize.call(this); 34533 this.autoSaveStart = false;
34534 34535 34536 this._modelTemplateCacheStore.putModel(this); 34537 this._postInitialize(); 34538 var xfaHost = this.getOrElse(xfalib, "runtime.xfa.host", null); 34539 if (xfaHost !== null) { 34540 xfaHost.on(xfalib.script.XfaModelEvent.FORM_MODEL_REFRESH, 34541 function (evnt) { 34542 switch (evnt.name) { 34543 case xfalib.script.XfaModelEvent.FORM_MODEL_REFRESH: 34544 this._triggerEvent(guidelib.event.GuideModelEvent.MODEL_REFRESH, "jsonModel", null, null); 34545 break; 34546 default: 34547 34548 } 34549 }, 34550 this); 34551 } 34552 }, 34553 34554 _resetExpressionCounters : function () { 34555 this._runningExpressionCount = { 34556 calcExp : {}, 34557 valueCommitScript : {}, 34558 enabledExp : {}, 34559 visibleExp : {}, 34560 validateAllExp : {}, 34561 optionsExp : {}, 34562 navigationChangeExp : {}, 34563 summaryExp : {}, 34564 autoSaveStartExp : {}, 34565 aggregateExp : {}, 34566 submitSuccess : {}, 34567 submitError : {}, 34568 saveSuccess : {}, 34569 saveError : {} 34570 }; 34571 }, 34572 34573 _getReducedJSON : function () { 34574 34575 34576 var reducedJSONChildren = guidelib.model.GuideNode.prototype._getReducedJSON.call(this), 34577 addtionalWhitelistedProperties = ["xdpRef", "xsdRef", "id", "dorTemplateRef", "dorType", "excludeFromDoRIfHidden", "schemaRef", "schemaType"]; 34578 guidelib.model.util.CommonUtils.returnMinimalJSON(addtionalWhitelistedProperties, reducedJSONChildren, this); 34579 reducedJSONChildren["rootPanel"] = this["rootPanel"]._getReducedJSON(); 34580 if (this.jsonModel.toolbar) { 34581 reducedJSONChildren["toolbar"] = this["toolbar"]._getReducedJSON(); 34582 } 34583 return reducedJSONChildren; 34584 }, 34585 34586 _initChildren : function () { 34587 34588 var options = {"_guideContainer" : this}; 34589 this.rootPanel = guidelib.model.GuideModelRegistry.prototype.createModel(this.jsonModel.rootPanel, options); 34590 this._initializeChild(this.rootPanel); 34591 this._children.push(this.rootPanel); 34592 34593 var instanceManager = guidelib.model.GuideModelRegistry.prototype.createInstanceManager(this.rootPanel); 34594 this._initializeChild(instanceManager); 34595 this._children.splice(this._children.indexOf(this.rootPanel), 0, instanceManager); 34596 instanceManager._manageChild(this.rootPanel); 34597 34598 if (this.jsonModel.toolbar) { 34599 var options = {}; 34600 if (this._guide()) { 34601 options = _.extend({}, options, {"_guideContainer" : this._guide()}); 34602 } 34603 this.toolbar = guidelib.model.GuideModelRegistry.prototype.createModel(this.jsonModel.toolbar, options); 34604 this._initializeChild(this.toolbar); 34605 this._children.push(this.toolbar); 34606 } 34607 }, 34608 34609 34610 _addToExcludeFromDorMap : function (fieldTemplateId, bExcludeFromDor) { 34611 this._excludeFromDorMap = this._excludeFromDorMap || {}; 34612 this._excludeFromDorMap[fieldTemplateId] = bExcludeFromDor; 34613 }, 34614 34615 34616 _getExcludeFromDorMap : function () { 34617 var that = this; 34618 if (!_.isUndefined(that._excludeFromDorMap)) { 34619 return _.keys(that._excludeFromDorMap).map(function (key) { 34620 34621 return key + "=" + that._excludeFromDorMap[key]; 34622 }); 34623 } 34624 }, 34625 34626 34627 _addToStateOverrideMap : function (fieldName, fieldsOverrid
34627denMap) { 34628 this._stateOverrideMap = this._stateOverrideMap || {}; 34629 this._stateOverrideMap[fieldName] = fieldsOverriddenMap; 34630 }, 34631 34632 34633 _getStateOverrideMap : function () { 34634 var that = this; 34635 var retval = {}; 34636 if (!_.isUndefined(that._stateOverrideMap)) { 34637 var elementsArray = _.keys(that._stateOverrideMap).map(function (key) { 34638 return that._stateOverrideMap[key]; 34639 }); 34640 retval = {"element" : elementsArray}; 34641 } 34642 return retval; 34643 34644 }, 34645 34646 34647 _resolveAfDataSom : function (afDataSom) { 34648 var resolvedField = null; 34649 34650 34651 _.each(this.internal.liveModel.getCrossFragmentFields(), function (fields) { 34652 34653 var globalFieldModels = this.internal.liveModel.getAllAbstractFieldModels(_.keys(fields)); 34654 _.each(globalFieldModels, function (globalField) { 34655 if (globalField.afDataSom === afDataSom) { 34656 resolvedField = globalField; 34657 return false; 34658 } 34659 }); 34660 if (resolvedField) { 34661 return false; 34662 } 34663 }); 34664 return resolvedField; 34665 }, 34666 34667 34668 _getSigners : function () { 34669 var signers = {}; 34670 34671 if (this.enableAdobeSign && (_.isString(this.xdpRef) || _.isString(this.xsdRef) || (!_.isString(this.jsonModel.schemaRef)))) { 34672 var signer, 34673 that = this, 34674 email, 34675 number, 34676 countryCode, 34677 evalExp = function (fldSom, fldAfDataSom, type) { 34678 var val = null, 34679 resolvedField; 34680 try { 34681 resolvedField = guideBridge._guide.resolveNode(fldSom); 34682 if (!resolvedField) { 34683 resolvedField = guideBridge._guide._resolveAfDataSom(fldAfDataSom); 34684 } 34685 val = resolvedField.value; 34686 if (resolvedField.className === 'guideTelephone') { 34687 if (type === 'countryCode') { 34688 val = guidelib.model.GuideTelephone.prototype._extractCountryCode(val); 34689 } else if (type === 'phone') { 34690 val = guidelib.model.GuideTelephone.prototype._extractPhoneNumber(val); 34691 } 34692 } 34693 } catch (e) { 34694 34695 } 34696 34697 34698 return val ? val.toString() : val; 34699 }; 34700 if (this.signerInfo) { 34701 _.each(_.keys(this.signerInfo), function (name) { 34702 signer = that.signerInfo[name]; 34703 if (signer && typeof signer === "object") { 34704 email = null; 34705 number = null; 34706 countryCode = null; 34707 if (signer.emailSource === 'form' && signer.email) { 34708 email = evalExp(signer.email, signer.emailAfDataSom, 'email'); 34709 } 34710 signers[name] = {}; 34711 signers[name].email = email ? email : ""; 34712 if (signer.securityOption === 'PHONE') { 34713 if (signer.phoneSource === 'form' && signer.phone) { 34714 number = evalExp(signer.phone, signer.phoneAfDataSom, 'phone'); 34715 } 34716 if (signer.countryCodeSource === 'form' && signer.countryCode) { 34717 countryCode = evalExp(signer.countryCode, signer.countryCodeAfDataSom, 'countryCode'); 34718 } 34719 signers[name].phone = {}; 34720 signers[name].phone.countryCode = countryCode ? countryCode : ""; 34721 signers[name].phone.number = number ? number : ""; 34722 } 34723 } 34724 }); 34725 } 34726 } 34727 34728 return signers; 34729 }, 34730 34731 34732 defaultSubmitSuccess : "window.guideBridge._defaultSubmitSuccessHandler($event.data)", 34733 34734 34735 defaultSubmitError : "window.guideBridge._handleServerValidationError($event.data)", 34736 34737 34738 defaultSaveSuccess : "window.guideBridge._defaultSaveSuccessHandler($event.data)", 34739 defaultSaveError : "window.guideBridge._defaultSaveErrorHandler($event.data)", 34740 34741 34742 _collectExpressions : function () { 34743 if (this.autoSaveStartExpression) { 34744 this._compiledExpressions["autoSaveStartExp"] = this._compileExpression(this.autoSaveStartExpression, "autoSaveStart"); 34745 } 34746 34747 34748 if (!this.submitSuccess) { 34749 this.jsonModel.submitSuccess = this.defaultSubmitSuccess; 34750 } 34751 this._compiledScripts.submitSuccess = this._compileExpression(this.submitSuccess, null); 34752 34753 if (!this.submitError) { 34754 this.jsonModel.submitError = this.defaultSubmitError; 34755 } 34756 this._compiledScripts.submitError = this._compileExpression(this.submitError, null); 34757 34758 if (!this.saveSuccess) { 34759 this.jsonModel.saveSuccess = this.defaultSaveSuccess; 34760 } 34761 this._compiledScripts.saveSuccess = this._compileExpression(this.saveSuccess, null); 34762 34763 if (!this.saveError) { 34764 this.jsonModel.saveError = this.defaultSaveError; 34765 } 34766 this._compiledScripts.saveError = this._compileExpression(this.saveError, null); 34767 }, 34768 34769 prepare : function () { 34770 34771 34772 if ((this.getGuideState() !== guidelib.model.GuideSchema.prototype.GuideStateConstants.GUIDE_STATE_MERGE_PROGRESS) && (this.getGuideState() !== guidelib.model.GuideSchema.prototype.GuideStateConstants.GUIDE_STATE_MODEL_CREATION)) { 34773 _.each(this._children, function (childNode) { 34774 childNode.prepare(); 34775 }, this); 34776 this.queueExpressions(this, ["autoSaveStartExp"]); 34777 this.runPendingExpressions(); 34778 } 34779 }, 34780 34781 runPendingExpressions : function () { 34782 34783 this._runExpressionQueue("calcExp"); 34784 this._runExpressionQueue("enabledExp"); 34785 this._runExpressionQueue("visibleExp"); 34786 this._runExpressionQueue("valueCommitScript"); 34787 this._runExpressionQueue("validateAllExp"); 34788 this._runExpressionQueue("optionsExp"); 34789 this._runExpressionQueue("navigationChangeExp"); 34790 this._runExpressionQueue("summaryExp"); 34791 this._runExpressionQueue("aggregateExp"); 34792 this._runExpressionQueue("submitSuccess"); 34793 this._runExpressionQueue("submitError"); 34794 this._runExpressionQueue("saveSuccess"); 34795 this._runExpressionQueue("saveError"); 34796 34797 if (window.guideBridge.hostName !== "server") { 34798 this._runExpressionQueue("autoSaveStartExp"); 34799 } 34800 this._resetExpressionCounters(); 34801 }, 34802 34803 _runExpressionQueue : function (expName) { 34804 var expQueue = this._pendingQueues[expName], node; 34805 if (expQueue) { 34806 while (expQueue.length > 0) { 34807 node = this._pendingQueues[expName].shift(); 34808 if (node) { 34809 node.executeExpression(expName); 34810 } 34811 } 34812 } 34813 }, 34814 34815 queueExpressions : function (node, expressionArray) { 34816 if (!node || !expressionArray) { 34817 return; 34818 } 34819 if (_.isString(expressionArray)) { 34820 expressionArray = [expressionArray]; 34821 } 34822 _.each(expressionArray, function (expression) { 34823 var expQueue = this._pendingQueues[expression], 34824 som = node.somExpression, 34825 counters = this._runningExpressionCount[expression]; 34826 counters[som] = counters[som] || 0; 34827 if (expQueue && expQueue.indexOf(node) < 0 && counters[som] < 10) { 34828 expQueue.push(node); 34829 counters[som] += 1; 34830 } 34831 }, this); 34832 }, 34833 34834 playJson : function (pJsonModel, attachments) { 34835 this.rootPanel.playJson(pJsonModel.rootPanel, attachments); 34836 if (this.toolbar) { 34837 this.toolbar.playJson(pJsonModel.toolbar, attachments); 34838 } 34839 }, 34840 34841 _guide : function () { 34842 return this; 34843 }, 34844 34845 _collectValues : function (keyValue) { 34846 _.each(this._children, function (childNode) { 34847 childNode._collectValues(keyValue); 34848 }, this); 34849 }, 34850 34851 34852 _isFirstSignerFormFiller : function () { 34853 return this.signerInfo.firstSignerFormFiller === "true"; 34854 }, 34855 34856 34857 resolveNode : function (somExpression) { 34858 if (!somExpression || somExpression === "") { 34859 return; 34860 } 34861 var hierarchy = somExpression.split("."), 34862 componentInModel = null; 34863 if (hierarchy[0] === "guide[0]") { 34864 hierarchy.shift(); 34865 componentInModel = this; 34866 } 34867 if (hierarchy[0] === this._escapeQualifiedName()) { 34868 componentInModel = this; 34869 hierarchy.shift(); 34870 } else if (this.hasOwnProperty(hierarchy[0])) { 34871 componentInModel = this[hierarchy[0]]; 34872 hierarchy.shift(); 34873 } else if (!componentInModel) { 34874 componentInModel = this.rootPanel; 34875 } 34876 _.each(hierarchy, function (element) { 34877 if (componentInModel && componentInModel._findChildren) { 34878 componentInModel = componentInModel._findChildren(element, false)[0]; 34879 } else { 34880 componentInModel = null; 34881 } 34882 }, this); 34883 if (componentInModel == null) { 34884 34885 var relativeName = somExpression; 34886 componentInModel = this.getOrElse(this._guide().runtime, relativeName, null); 34887 } 34888 return componentInModel; 34889 } 34890 }); 34891 34892 GuideContainerNode.defineProps({ 34893 34894 submitSuccess : { 34895 get : function () { 34896 return this.jsonModel.submitSuccess; 34897 } 34898 }, 34899 34900 submitError : { 34901 get : function () { 34902 return this.jsonModel.submitError; 34903 } 34904 }, 34905 34906 saveSuccess : { 34907 get : function () { 34908 return this.jsonModel.saveSuccess; 34909 } 34910 }, 34911 34912 saveError : { 34913 get : function () { 34914 return this.jsonModel.saveError; 34915 } 34916 }, 34917 34918 34919 "autoSaveStart" : { 34920 get : function () { 34921 return this.jsonModel.autoSaveStart; 34922 }, 34923 34924 set : function (newValue) { 34925 this.jsonModel.autoSaveStart = newValue; 34926 if (newValue === true) { 34927 delete this._compiledExpressions.autoSaveStartExp; 34928 this._triggerOnBridge(window.guideBridge.GUIDE_AUTO_SAVE_START, this); 34929 } 34930 } 34931 }, 34932 34933 34934 "enableAutoSave" : { 34935 set : function (newValue) { 34936 this.jsonModel.enableAutoSave = newValue; 34937 }, 34938 34939 get : function () { 34940 return this.jsonModel.enableAutoSave || false; 34941 } 34942 }, 34943 34944 34945 "autoSaveStartExpression" : { 34946 get : function () { 34947 return this.jsonModel.autoSaveStartExpression; 34948 } 34949 }, 34950 34951 34952 "autoSaveInfo" : { 34953 get : function () { 34954 return this.jsonModel.autoSaveInfo; 34955 } 34956 }, 34957 34958 34959 "globalMetaInfo" : { 34960 get : function () { 34961 return this.jsonModel.globalMetaInfo; 34962 } 34963 }, 34964 34965 34966 "submissionMetaInfo" : { 34967 get : function () { 34968 return this.jsonModel.submissionMetaInfo; 34969 } 34970 }, 34971 34972 34973 "signerInfo" : { 34974 get : function () { 34975 return this.jsonModel.signerInfo; 34976 } 34977 }, 34978 34979 "xdpRef" : { 34980 get : function () { 34981 return this.jsonModel.xdpRef; 34982 } 34983 }, 34984 34985 "dorTemplateRef" : { 34986 get : function () { 34987 return this.jsonModel.dorTemplateRef; 34988 } 34989 }, 34990 34991 "dorType" : { 34992 get : function () { 34993 return this.jsonModel.dorType; 34994 } 34995 }, 34996 34997 "actionType" : { 34998 get : function () { 34999 return this.jsonModel.actionType; 35000 } 35001 }, 35002 35003 "xsdRef" : { 35004 get : function () { 35005 return this.jsonModel.xsdRef; 35006 } 35007 }, 35008 35009 35010 panel : { 35011 get : function () { 35012 return this.rootPanel; 35013 } 35014 }, 35015 35016 35017 print : { 35018 get : function () { 35019 if (this.dorType === "generate" && this.jsonModel.view) { 35020 return this.jsonModel.view.print; 35021 } 35022 35023 return null; 35024 } 35025 }, 35026 35027 35028 "allLazyChildren" : { 35029 get : function () { 35030 return this.jsonModel.allLazyChildren; 35031 } 35032 }, 35033 35034 35035 "enableAsyncSubmission" : { 35036 set : function (newValue) { 35037 this.jsonModel.enableAsyncSubmission = newValue; 35038 }, 35039 35040 get : function () { 35041 if (this.jsonModel.enableAsyncSubmission && (this.jsonModel.enableAsyncSubmission === "true" || this.jsonModel.enableAsyncSubmission === true)) { 35042 return true; 35043 } else { 35044 return false;
35045 } 35046 } 35047 }, 35048 35049 35050 "enableAdobeSign" : { 35051 get : function () { 35052 return this.jsonModel._useSignedPdf; 35053 } 35054 }, 35055 35056 35057 "enableFocusOnFirstField" : { 35058 set : function (newValue) { 35059 this.jsonModel.enableFocusOnFirstField = newValue; 35060 }, 35061 35062 get : function () { 35063 if (this.jsonModel.enableFocusOnFirstField === undefined) { 35064 return true; 35065 } 35066 return this.jsonModel.enableFocusOnFirstField; 35067 } 35068 } 35069 }); 35070}(_, guidelib)); 35071(function (_, guidelib) { 35072 guidelib.model.mixin.AddNavigationContext = { 35073 propertyDescriptors : { 35074 "navigationContext" : { 35075 get : function () { 35076 if (!this._navigationContext) { 35077 this._navigationContext = new guidelib.model.util.GuideNavigationContext({ 35078 currentItem : null, 35079 parentPanel : this.panel 35080 }); 35081 } 35082 return this._navigationContext; 35083 } 35084 } 35085 } 35086 }; 35087})(_, guidelib); 35088 35089(function (_, guidelib) { 35090 35091 35092 var GuidePanel = guidelib.model.GuidePanel = guidelib.model.GuideItemsContainer.extend({ 35093 msClassName : "guidePanel", 35094 defaultExpressions : { 35095 "summary" : "this.title + (this.instanceIndex > 0 ? ' ' + this.instanceIndex : '')" 35096 }, 35097 35098 initialize : function () { 35099 GuidePanel._super.initialize.call(this); 35100 this._currentItem = null; 35101 35102 this._navigationContext = null; 35103 }, 35104 35105 _collectExpressions : function () { 35106 GuidePanel._super._collectExpressions.call(this); 35107 if (this.completionExp) { 35108 this._compiledScripts.completionExp = this._compileExpression(this.completionExp, null); 35109 } 35110 if (this.jsonModel.summaryExp) { 35111 this._compiledExpressions.summaryExp = this._compileExpression(this.jsonModel.summaryExp, "summary"); 35112 } else { 35113 this._compiledExpressions.summaryExp = this._compileExpression(this.defaultExpressions["summary"], "summary"); 35114 } 35115 }, 35116 35117 _initializeInstanceManager : function (child, index, insertOffset) { 35118 var instanceManager = guidelib.model.GuideModelRegistry.prototype.createInstanceManager(child); 35119 this._initializeChild(instanceManager); 35120 35121 this._children.splice(index + insertOffset++, 0, instanceManager); 35122 instanceManager._manageChild(child); 35123 35124 var bindNode = child._getBindNode(), 35125 bindNodeInstCount = this.getOrElse(bindNode, "instanceManager.count", 0), 35126 35127 panelInstancesToAdd = Math.max(child.minOccur, bindNodeInstCount) - 1, 35128 bindNodeOffset = 1, 35129 addedXfaInstance; 35130 while (panelInstancesToAdd > 0) { 35131 35132 addedXfaInstance = null; 35133 if (bindNodeInstCount > 1) { 35134 35135 addedXfaInstance = bindNode.instanceManager.instances[bindNodeOffset++]; 35136 } 35137 instanceManager.addInstance(addedXfaInstance); 35138 panelInstancesToAdd -= 1; 35139 insertOffset += 1; 35140 } 35141 return insertOffset; 35142 }, 35143 35144 35145 _initChildren : function (bLazyInitialization) { 35146 GuidePanel._super._initChildren.call(this); 35147 if (!bLazyInitialization) { 35148 this._instanceManager = null; 35149 } 35150 this._childInitializeGoingOn = true; 35151 var currentChildren = this.children, 35152 insertOffset = 0; 35153 _.each(currentChildren, function (child, index) { 35154 if (child instanceof guidelib.model.GuidePanel) { 35155 insertOffset = this._initializeInstanceManager(child, index, insertOffset); 35156 } 35157 }, this); 35158 if (this.jsonModel.toolbar) { 35159 var options = {}; 35160 if (this.options._guideContainer) { 35161 options = _.extend({}, options, {"_guideContainer" : this.options._guideContainer}); 35162 } 35163 var toolbar = guidelib.model.GuideModelRegistry.prototype.createModel(this.jsonModel.toolbar, options); 35164 this._initializeChild(toolbar); 35165 this._children.push(toolbar); 35166 } 35167 this._summary = null; 35168 this._childInitializeGoingOn = false;
35169 }, 35170 35171 _postInitialize : function () { 35172 GuidePanel._super._postInitialize.call(this); 35173 35174 this.instanceManager._postInitializeBinding(); 35175 }, 35176 35177 _addChildAt : function (child, childIndex, muteEvent) { 35178 if (child) { 35179 this._initializeChild(child); 35180 this._guide()._modelTemplateCacheStore.putModel(child); 35181 var newItemIndex = this._getItemsInsertIndex(childIndex - 1); 35182 var newItems = {}; 35183 var newItemKey = child.id; 35184 var lastItemIndex = -1; 35185 _.each(this.jsonModel.items, function (value, key) { 35186 if (lastItemIndex == newItemIndex - 1) { 35187 newItems[newItemKey] = child.jsonModel; 35188 } 35189 newItems[key] = value; 35190 lastItemIndex++; 35191 }, this); 35192 if (lastItemIndex == newItemIndex - 1) { 35193 newItems[newItemKey] = child.jsonModel; 35194 } 35195 this.jsonModel.items = newItems; 35196 child._isItem = true; 35197 this._children.splice(childIndex, 0, child); 35198 this._normalizeChildren(); 35199 child._postInitialize(); 35200 if (this._guide().getGuideState() >= guidelib.model.GuideSchema.prototype.GuideStateConstants.GUIDE_STATE_MERGE_COMPLETE) { 35201 child.prepare(); 35202 } 35203 35204 35205 35206 if (!(this._lazyReference && this._childInitializeGoingOn)) { 35207 if (!muteEvent) { 35208 this._triggerEvent(guidelib.event.GuideModelEvent.CHILD_CHANGED, "childAdded", null, child); 35209 } 35210 } 35211 } 35212 }, 35213 35214 35215 validate : function (errorList) { 35216 var markInvalid = false; 35217 35218 35219 if (!this.visible) { 35220 return true; 35221 } 35222 var lazyModelUnloadPending = false; 35223 35224 if (this._lazyReference && this.guideUtil.isLazyJson(this.jsonModel)) { 35225 var guideDirtyMarker = this._guide().internal.GuideDirtyMarkerAndVisitor, 35226 visitMap = guideDirtyMarker.visitMap, 35227 modelTemplateCacheStore = this._guide()._modelTemplateCacheStore, 35228 guideUtil = guidelib.util.GuideUtil, 35229 templateJson, 35230 templateId = this.templateId, 35231 uniquePrefix; 35232 35233 if (visitMap[templateId] === 0) { 35234 if (this._ancestorRepeatable) { 35235 uniquePrefix = guideUtil.generateUID(); 35236 } 35237 35238 templateJson = modelTemplateCacheStore._getTemplate(templateId, true); 35239 35240 35241 if (!_.isEmpty(templateJson)) { 35242 this._embedJson(templateJson.items, uniquePrefix); 35243 this._guide().internal.liveDataUtils.playLiveData(this); 35244 35245 this.prepare(); 35246 this._guide().runPendingExpressions(); 35247 this._guide().internal.liveDataUtils.updateLiveData(); 35248 lazyModelUnloadPending = true; 35249 } else { 35250 35251 markInvalid = true; 35252 } 35253 35254 } 35255 35256 } 35257 var validationResult = GuidePanel._super.validate.call(this, errorList); 35258 if (lazyModelUnloadPending) { 35259 35260 35261 this._unloadLazyReferenceModel(true); 35262 } 35263 if (markInvalid === true) { 35264 validationResult = false;
35265 } 35266 return validationResult; 35267 }, 35268 35269 _loadLazyFragment : function (options) { 35270 options = options || {}; 35271 if (_.isUndefined(this._itemsLoaded)) { 35272 35273 var path = this.jsonModel["jcr:path"], 35274 externalizedPath; 35275 35276 externalizedPath = guideBridge._getGuidePathUrl(".jsonhtmlemitter"); 35277 this._fetchFromAjaxCall(externalizedPath, options); 35278 } else { 35279 if (_.isFunction(options.success)) { 35280 options.success.call(this); 35281 } 35282 } 35283 35284 35285 }, 35286 35287 _fetchFromAjaxCall : function (externalizedPath, options) { 35288 if (options && _.isFunction(options.preFetch)) { 35289 options.preFetch.call(this); 35290 } 35291 var that = this, 35292 urlSuffix = "", 35293 lazyOptions, 35294 commonCallbacks = { 35295 success: fetchCallback, 35296 error: (options && _.isFunction(options.error)) ? options.error : errorCallback, 35297 complete: completeCallback, 35298 async: options.async 35299 }; 35300 35301 if (FD.isToggleEnabled(guidelib.util.FeatureToggleConstants.FT_CACHE_LAZY_LOADED_FRAGMENTS)) { 35302 35303 urlSuffix = [ 35304 "/templateId-" + that.templateId, 35305 "/fetchJSON-true", 35306 "/fetchHTML-true", 35307 ".json" 35308 ].join(""); 35309 35310 lazyOptions = _.extend({ 35311 path: externalizedPath + urlSuffix 35312 }, commonCallbacks); 35313 } else { 35314 lazyOptions = _.extend({ 35315 path: externalizedPath, 35316 templateId: that.templateId, 35317 fetchJSON: true, 35318 fetchHTML: true 35319 }, commonCallbacks); 35320 } 35321 35322 window.guideBridge.panelProvider.getHtmlJson(lazyOptions); 35323 35324 function fetchCallback(jsonHtml) { 35325 var uniquePrefix; 35326 35327 35328 35329 if (that.repeatable || that._ancestorRepeatable) { 35330 uniquePrefix = that.guideUtil.generateUID(); 35331 } 35332 if (guidelib.util.GuideUtil._embedHtml(that, jsonHtml["html"], uniquePrefix)) { 35333 that._ajaxCallDone = true; 35334 35335 35336 35337 35338 var referredJson = JSON.parse(jsonHtml["json"])["items"]; 35339 that._embedJson(referredJson, uniquePrefix); 35340 35341 var guideDirtyMarkerAndVisitor = that._guide().internal.GuideDirtyMarkerAndVisitor; 35342 35343 if (!that.repeatable) { 35344 guideDirtyMarkerAndVisitor._updateCountOrInsert(guideDirtyMarkerAndVisitor.visitMap, that.templateId); 35345 } 35346 35347 that._guide().internal.liveDataUtils.playLiveData(that); 35348 35349 that.prepare(); 35350 that._itemsLoaded = true; 35351 that._guide().trigger(guidelib.event.GuideModelEvent.LAZY_LOADED); 35352 35353 that._triggerOnBridge("elementLazyLoaded", that); 35354 35355 35356 if (options && _.isFunction(options.success)) { 35357 options.success.call(this); 35358 } 35359 35360 35361 35362 } 35363 } 35364 35365 function errorCallback() { 35366 that.logger().error("AF", "Failed to fetch HTML and JSON for :" + externalizedPath); 35367 } 35368 35369 function completeCallback() { 35370 if (options && _.isFunction(options.postFetch)) { 35371 options.postFetch.call(this); 35372 } 35373 } 35374 35375 }, 35376 35377 35378 _unloadLazyReferenceModel : function (muteValidation) { 35379 try { 35380 if (this._lazyReference) { 35381 window.guideBridge._populateBindRefToSomMap(this); 35382 if (!muteValidation) {
35383 var validationStatus = this.validate(), 35384 visitMap = this._guide().internal.GuideDirtyMarkerAndVisitor.visitMap; 35385 if (validationStatus === false && visitMap[this.id] > 0) { 35386 visitMap[this.id] = 0; 35387 } 35388 } 35389 35390 35391 _.each(this.children, function (child) { 35392 child._unloadModel(muteValidation); 35393 var nIndex = this._children.indexOf(child); 35394 35395 this._children.splice(nIndex, 1); 35396 var childKey = null; 35397 35398 _.each(this.jsonModel.items, function (value, key) { 35399 if (value === child.jsonModel) { 35400 childKey = key; 35401 } 35402 }, this); 35403 if (childKey) { 35404 delete this.jsonModel.items[childKey]; 35405 } 35406 35407 this._normalizeChildren(); 35408 }, this); 35409 35410 this._navigationContext = null; 35411 this._currentItem = null; 35412 } 35413 } catch (exception) { 35414 this.logger().error(exception); 35415 } 35416 35417 }, 35418 35419 _unloadModel : function (muteValidation) { 35420 var visitMap = this._guide().internal.GuideDirtyMarkerAndVisitor.visitMap; 35421 _.each(this.children, function (child) { 35422 if (this._lazyReference && !muteValidation) { 35423 var validationStatus = child.validate(); 35424 if (validationStatus === false) { 35425 if (!_.isUndefined(visitMap[this.templateId])) { 35426 visitMap[this.templateId] = 0; 35427 } 35428 } 35429 } 35430 child._unloadModel(muteValidation); 35431 }, this); 35432 guidelib.model.Scriptable.prototype._unloadModel.call(this); 35433 }, 35434 35435 _removeChild : function (oChild) { 35436 oChild._unloadModel(); 35437 var nIndex = this._children.indexOf(oChild); 35438 this._children.splice(nIndex, 1); 35439 var childKey = null; 35440 _.each(this.jsonModel.items, function (value, key) { 35441 if (value === oChild.jsonModel) { 35442 childKey = key; 35443 } 35444 }, this); 35445 if (childKey) { 35446 delete this.jsonModel.items[childKey]; 35447 } 35448 this._normalizeChildren(); 35449 this._triggerEvent(guidelib.event.GuideModelEvent.CHILD_CHANGED, "childRemoved", oChild, null); 35450 }, 35451 35452 35453 _embedJson : function (referredJson, uniquePrefix) { 35454 35455 var bIsSuccess = false; 35456 var clonedJson = JSON.parse(JSON.stringify(referredJson)), 35457 currentPanelId = this.id, 35458 referredPanelRoot = null, 35459 referredPanelRootName = null, 35460 bindRefPrefix = this.jsonModel.bindRef; 35461 35462 currentPanelId = currentPanelId.slice(0, -2); 35463 if (referredJson) { 35464 35465 if (this.repeatable || this._ancestorRepeatable) { 35466 this.copyObject(referredJson, clonedJson, 35467 { 35468 transformMaps : { 35469 "id" : function (srcValue, options, parentObj) { 35470 return uniquePrefix + "__" + parentObj.templateId; 35471 } 35472 } 35473 } 35474 ); 35475 } 35476 35477 35478 _.each(clonedJson, function (panelJson, panelName) { 35479 if (_.isObject(panelJson)) { 35480 bIsSuccess = true; 35481 35482 this.jsonModel.items = this.jsonModel.items || {}; 35483 this.jsonModel.items[panelName] = panelJson; 35484 35485 this._guide()._modelTemplateCacheStore._putTemplate(JSON.parse(JSON.stringify(panelJson))); 35486 } 35487 }, this); 35488 35489 this._embedModel(); 35490 35491 } 35492 if (bIsSuccess === true) { 35493 35494 } 35495 return bIsSuccess; 35496 }, 35497 35498 35499 _embedModel : function () { 35500 35501 this._initChildren(true); 35502 35503 35504 this._guide()._modelTemplateCacheStore.putModel(this); 35505 35506 this._postInitialize(); 35507 35508 this._normalizeChildren(); 35509 }, 35510 35511 _getItemsInsertIndex : function (childIndex) { 35512 var itemIndex = 0; 35513 _.find(this._children, function (child, index) { 35514 if (child._isItem) { 35515 itemIndex++; 35516 } 35517 if (index >= childIndex) { 35518 return true; 35519 } 35520 }, this); 35521 return itemIndex; 35522 }, 35523 35524 playJson : function (pJsonModel, attachments) { 35525 var playNonPanelItems = {}; 35526 var playPanelItems = {}; 35527 _.each(pJsonModel.items, function (item) { 35528 if (_.isObject(item)) { 35529 35530 if (item.guideNodeClass === "guidePanel" || item.guideNodeClass === "guideTable" || item.guideNodeClass === "guideTableRow") { 35531 if (playPanelItems[item.name]) { 35532 playPanelItems[item.name].push(item); 35533 } else { 35534 playPanelItems[item.name] = [item]; 35535 } 35536 } else { 35537 if (playNonPanelItems[item.name]) { 35538 playNonPanelItems[item.name].push(item); 35539 } else { 35540 playNonPanelItems[item.name] = [item]; 35541 } 35542 } 35543 } 35544 }, this); 35545 35546 35547 var panelIMs = _.filter(this._children, function (child) { 35548 return child instanceof guidelib.model.GuideInstanceManager; 35549 }, this); 35550 35551 _.each(panelIMs, function (instanceManager) { 35552 var panelName = instanceManager._getInstanceName(); 35553 var newPanelItems = playPanelItems[panelName] || []; 35554 var panelInstances = instanceManager._instances.slice(0); 35555 _.each(panelInstances, function (panelInstance, index) { 35556 if (newPanelItems.length > 0) { 35557 var panelJson = newPanelItems.shift(); 35558 panelInstance.playJson(panelJson, attachments); 35559 } else { 35560 instanceManager.removeInstance(index); 35561 } 35562 }, this); 35563 if (newPanelItems.length > 0) { 35564 _.each(newPanelItems, function (paneljson) { 35565 var addedInstance = instanceManager.addInstance(); 35566 if (addedInstance) { 35567 addedInstance.playJson(paneljson, attachments); 35568 } 35569 }, this); 35570 } 35571 }, this); 35572 35573 35574 _.each(this.items, function (child) { 35575 if (!(child instanceof guidelib.model.GuidePanel)) { 35576 var nonPanelItemName = child.name; 35577 var nonPanelItem = playNonPanelItems[nonPanelItemName]; 35578 if (nonPanelItem && nonPanelItem.length > 0) { 35579 child.playJson(nonPanelItem.shift(), attachments); 35580 } 35581 } 35582 }, this); 35583 35584 35585 if (this.toolbar) { 35586 this.toolbar.playJson(pJsonModel.toolbar, attachments); 35587 } 35588 }, 35589 35590 _getReducedJSON : function (isParentRepeatable) { 35591 var reducedJSONChildren, 35592 isRepeatable; 35593 isRepeatable = isParentRepeatable || this.canBeRepeatable; 35594 reducedJSONChildren = GuidePanel._super._getReducedJSON.call(this, isRepeatable); 35595 35596 35597 if (this.jsonModel.toolbar) { 35598 reducedJSONChildren["toolbar"] = this.toolbar._getReducedJSON(); 35599 } 35600 return reducedJSONChildren; 35601 }, 35602 35603 _getRole : function () { 35604 var guideRole, xfaRole, roleMap; 35605 35606 roleMap = { 35607 "Table" : "grid", 35608 "Header Row" : "rowHeader", 35609 "Body Row" : "rowGroup", 35610 "Footer Row" : "rowGroup", 35611 "List" : "list" 35612 }; 35613 if (this.bindNode) { 35614 xfaRole = this.getOrElse(this.bindNode.assist && this.bindNode.assist.role, null); 35615 if (xfaRole) { 35616 guideRole = roleMap[xfaRole]; 35617 } 35618 } 35619 return guideRole; 35620 }, 35621 _getAssistPriority : function () { 35622 return (this.getAttribute("assistPriority") || "description"); 35623 }, 35624 35625 _getScreenReaderText : function () { 35626 var screenReaderText, assistPriority = this._getAssistPriority(); 35627 if (assistPriority !== "description") { 35628 screenReaderText = GuidePanel._super._getScreenReaderText.apply(this); 35629 } 35630 return screenReaderText; 35631 }, 35632 35633 execCompletion : function () { 35634 var complete = true; 35635 _.find(this.children, function (childModel) { 35636 35637 if (childModel instanceof guidelib.model.GuidePanel && !childModel.execCompletion()) { 35638 complete = false;
35639 return true; 35640 } 35641 }, this); 35642 if (complete && this.completionExp) { 35643 complete = this.executeExpression("completionExp"); 35644 } 35645 return complete; 35646 }, 35647 35648 _preserveLazyValue : function () { 35649 return !this._isXfaNode() && !(this instanceof guidelib.model.RootPanelNode) 35650 && (this.canBeRepeatable || this._guide().internal.liveDataUtils.isIndexedPath(this.bindRef)); 35651 }, 35652 35653 35654 _syncModelAndData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar, updateInstances, recurse) { 35655 var dataUtils = this._guide().internal.liveDataUtils; 35656 if (this._preserveLazyValue()) { 35657 35658 var dataContext = dataUtils._getDataContext(this, bound_indexedXpathSoFar, unBound_indexedXpathSoFar), 35659 indexedXpath = dataContext.indexedXpath; 35660 35661 if (this.canBeRepeatable) { 35662 35663 if (_.isFunction(updateInstances) && this.instanceIndex === 0) { 35664 updateInstances(dataUtils.getDataInstances(dataContext, this._getDataNodeName()), 35665 dataUtils.getParentDataNode(dataContext)); 35666 } 35667 indexedXpath = dataUtils.addIndexToPath(indexedXpath, this.instanceIndex); 35668 } 35669 35670 35671 if (dataContext.xmlSec === dataUtils.constants.UNBOUND_TAG) { 35672 unBound_indexedXpathSoFar = indexedXpath; 35673 } else if (dataContext.xmlSec === dataUtils.constants.BOUND_TAG) { 35674 bound_indexedXpathSoFar = indexedXpath; 35675 } 35676 } 35677 35678 if (_.isString(recurse)) { 35679 35680 _.each(this.items, function (item) { 35681 if (_.isFunction(item[recurse])) { 35682 item[recurse](bound_indexedXpathSoFar, unBound_indexedXpathSoFar); 35683 } 35684 }); 35685 } 35686 35687 return { 35688 'bound' : bound_indexedXpathSoFar, 35689 'unBound' : unBound_indexedXpathSoFar 35690 }; 35691 }, 35692 35693 _getDataNodeName : function () { 35694 var bindRef = this.bindRef, 35695 dataNodeName; 35696 if (bindRef) { 35697 dataNodeName = bindRef.substring(bindRef.lastIndexOf("/") + 1); 35698 } else { 35699 35700 dataNodeName = this.getAttribute("name"); 35701 } 35702 return dataNodeName; 35703 }, 35704 35705 _updateLiveData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar) { 35706 var dataUtils = this._guide().internal.liveDataUtils, 35707 that = this; 35708 35709 function updateDataInstances(dataNodes, parentNode) { 35710 var count = that.instanceManager.instanceCount; 35711 if (dataNodes && (dataNodes.length > count)) { 35712 35713 35714 for (var i = dataNodes.length -1; i >= count; --i) { 35715 dataUtils.removeChild(parentNode, that._getDataNodeName(), i); 35716 } 35717 } 35718 } 35719 35720 var contextSoFar = this._syncModelAndData(bound_indexedXpathSoFar, unBound_indexedXpathSoFar, updateDataInstances, '_updateLiveData'); 35721 }, 35722 35723 _playLiveData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar) { 35724 var parentArgs = arguments, 35725 that = this; 35726 35727 function updateModelInstances(dataNodes, parentNode) { 35728 var _dataNodes = dataNodes; 35729 if (_dataNodes == null) { 35730 _dataNodes = []; 35731 } 35732 35733 var i; 35734 if (_dataNodes && (_dataNodes.length < that.instanceManager.instanceCount)) { 35735 35736 for (i = Math.max(_dataNodes.length, Math.abs(that.minOccur)); i < that.instanceManager.instanceCount; ++i) { 35737 that.instanceManager.removeInstance(i); 35738 } 35739 } else if (_dataNodes && (_dataNodes.length > that.instanceManager.instanceCount)) { 35740 35741 var totalInstances = that.maxOccur < 0 ? _dataNodes.length : Math.min(_dataNodes.length, that.maxOccur); 35742 for (i = that.instanceManager.instanceCount; i < totalInstances; ++i) { 35743 var addedInstance = that.instanceManager.addInstance(); 35744 if (addedInstance) { 35745 that._playLiveData.apply(addedInstance, parentArgs); 35746 } 35747 } 35748 } 35749 } 35750 35751 this._syncModelAndData(bound_indexedXpathSoFar, unBound_indexedXpathSoFar, updateModelInstances, '_playLiveData'); 35752 } 35753 }); 35754 35755 GuidePanel.defineProps({ 35756 35757 completionExp : { 35758 get : function () { 35759 return this.getAttribute("completionExp"); 35760 } 35761 }, 35762 35763 completionExpReq : { 35764 get : function () { 35765 return this.getAttribute("completionExpReq"); 35766 } 35767 }, 35768 35769 35770 minOccur : { 35771 get : function () { 35772 return this.getOrElse(this.jsonModel.minOccur, 1); 35773 } 35774 }, 35775 35776 35777 maxOccur : { 35778 get : function () { 35779 return this.getOrElse(this.jsonModel.maxOccur, 1); 35780 } 35781 }, 35782 initialOccur : { 35783 get : function () { 35784 return this.getOrElse(this.jsonModel.initialOccur, 1); 35785 } 35786 }, 35787 35788 repeatable : { 35789 get : function () { 35790 return (this.minOccur != 1 || this.maxOccur != 1); 35791 } 35792 }, 35793 35794 35795 canBeRepeatable : { 35796 get : function () { 35797 return (this.maxOccur < 0 || this.maxOccur > 1); 35798 } 35799 }, 35800 35801 panel : { 35802 get : function () { 35803 return this; 35804 } 35805 }, 35806 toolbar : { 35807 get : function () { 35808 this.getElement("guideToolbar"); 35809 } 35810 }, 35811 35812 instanceManager : { 35813 get : function () { 35814 return this._instanceManager; 35815 } 35816 }, 35817 35818 35819 instanceIndex : { 35820 get : function () { 35821 var context = this._guide()._currentContext; 35822 if (context && context.managedExp) { 35823 this._addDependant(context.contextNode, context.expression); 35824 } 35825 return this.instanceManager._instances.indexOf(this); 35826 } 35827 }, 35828 35829 title : { 35830 get : function () { 35831 return this.jsonModel["jcr:title"]; 35832 }, 35833 set : function (value) { 35834 var oldTitle = this.title; 35835 if (oldTitle !== value) { 35836 this.jsonModel["jcr:title"] = value; 35837 this.trigger(guidelib.event.GuideModelEvent.MODEL_CHANGED, 35838 guidelib.event.GuideModelEvent.createEvent( 35839 guidelib.event.GuideModelEvent.MODEL_CHANGED, 35840 this, 35841 "title", 35842 oldTitle, 35843 value 35844 ) 35845 ); 35846 } 35847 } 35848 }, 35849 35850 summary : { 35851 get : function () { 35852 return this._summary; 35853 }, 35854 set : function (value) { 35855 var oldSummary = this._summary; 35856 if (oldSummary !== value) { 35857 this._summary = value; 35858 this.trigger(guidelib.event.GuideModelEvent.MODEL_CHANGED, 35859 guidelib.event.GuideModelEvent.createEvent( 35860 guidelib.event.GuideModelEvent.MODEL_CHANGED, 35861 this, 35862 "summary", 35863 oldSummary, 35864 this._summary 35865 ) 35866 ); 35867 } 35868 } 35869 }, 35870 enableLayoutOptimization : { 35871 get : function () { 35872 return this.getOrElse(this.jsonModel, "layout.enableLayoutOptimization", false); 35873 } 35874 }, 35875 35876 35877 isNavigable : { 35878 get : function () { 35879 var isNonNavigable = this.getOrElse(this.jsonModel, "layout.nonNavigable", false); 35880 35881 35882 if (typeof isNonNavigable === 'string') { 35883 return !(isNonNavigable === "true"); 35884 } else { 35885 return !isNonNavigable; 35886 } 35887 } 35888 }, 35889 35890 _hopsToRootPanel : { 35891 get : function () { 35892 return guidelib.util.GuideUtil._countHopsToRootPanel(this); 35893 } 35894 35895 }, 35896 35897 _ancestorRepeatable : { 35898 get : function () { 35899 var parentOrAncestor = this.parent; 35900 while (parentOrAncestor) { 35901 if (parentOrAncestor && parentOrAncestor.repeatable) { 35902 return true; 35903 } 35904 parentOrAncestor = parentOrAncestor.parent; 35905 } 35906 35907 return false;
35908 } 35909 }, 35910 35911 35912 enabled : { 35913 get : function () { 35914 return guidelib.model.Scriptable.prototype._getEnabled.call(this); 35915 }, 35916 35917 set : function (value) { 35918 var oldValue = this.enabled; 35919 guidelib.model.Scriptable.prototype._setEnabled.call(this, value); 35920 if (this._parentAccess && value != oldValue) { 35921 this._changeContainerAccess(value); 35922 } 35923 } 35924 }, 35925 35926 35927 _hasLazyDescendant : { 35928 get : function () { 35929 if (!_.isEmpty(guideBridge._guide.allLazyChildren)) { 35930 return true; 35931 } 35932 return false; 35933 } 35934 } 35935 }); 35936 35937 35938 GuidePanel.addMixins([ 35939 guidelib.model.mixin.AddNavigationContext, 35940 guidelib.model.mixin.AddDependencyMgmt 35941 ]); 35942 35943})(_, guidelib); 35944 35945(function (_, guidelib) { 35946 var GuideTableRow = guidelib.model.GuideTableRow = guidelib.model.GuidePanel.extend({ 35947 msClassName : "guideTableRow" 35948 }); 35949}(_, guidelib)); 35950(function (_, guidelib) { 35951 35952 35953 var GuideTable = guidelib.model.GuideTable = guidelib.model.GuidePanel.extend({ 35954 msClassName : "guideTable" 35955 }); 35956 35957 GuideTable.defineProps({ 35958 35959 mobileLayout : { 35960 get : function () { 35961 return this.jsonModel.layout.mobileLayout; 35962 } 35963 }, 35964 35965 columnWidth : { 35966 get : function () { 35967 return this.jsonModel.columnWidth; 35968 } 35969 } 35970 }); 35971})(_, guidelib); 35972 35973(function (_, guidelib) { 35974 var RootPanelNode = guidelib.model.RootPanelNode = guidelib.model.GuidePanel.extend({ 35975 msClassName : "rootPanelNode", 35976 35977 _clearInactiveLazyViews : function (panelView) { 35978 _.each(this.childViews, function (item) { 35979 item._clearInactiveLazyViews(panelView); 35980 }); 35981 } 35982 35983 }); 35984 RootPanelNode.defineProps({ 35985 toolbar : { 35986 get : function () { 35987 35988 return this.getElement("guideToolbar") || this.parent.toolbar; 35989 } 35990 } 35991 }); 35992})(_, guidelib); 35993(function ($, guidelib, _) { 35994 function negate(predicateFunc) { 35995 return function () { 35996 return !predicateFunc.apply(this, arguments); 35997 }; 35998 } 35999 36000 function getPredicate(condition) { 36001 return condition instanceof Array 36002 ? Array.prototype.includes.bind(condition) 36003 : condition; 36004 } 36005 36006 var CommonUtils = { 36007 36008 36009 returnMinimalJSON : function (whitelistedProperties, reducedJsonObject, that) { 36010 if (!_.isObject(reducedJsonObject)) { 36011 reducedJsonObject = {}; 36012 } 36013 _.each(whitelistedProperties, function (whitelistedProperty) { 36014 if (!_.isUndefined(that.jsonModel[whitelistedProperty])) { 36015 reducedJsonObject[whitelistedProperty] = that.jsonModel[whitelistedProperty] ; 36016 36017 } else if (!_.isUndefined(that[whitelistedProperty])) { 36018 reducedJsonObject[whitelistedProperty] = that[whitelistedProperty]; 36019 } 36020 }); 36021 }, 36022 36023 createMap : function (list, value) { 36024 return _.mapObject(_.object(list, []), function () { 36025 return value; 36026 }); 36027 }, 36028 36029 updatedMapIfNot : function (map, condition, value) { 36030 return _updateMap(map, negate(getPredicate(condition)), value); 36031 }, 36032 36033 updatedMap : function (map, condition, value) { 36034 return _updateMap(map, getPredicate(condition), value); 36035 }, 36036 36037 _updatedMap : function (map, condition, value) { 36038 var newMap = {}, 36039 prop; 36040 for (prop in map) { 36041 if (map.hasOwnProperty(prop)) { 36042 newMap[prop] = condition(prop) ? value : map[prop]; 36043 } 36044 } 36045 return newMap; 36046 }, 36047 36048 _getScope : function (context) { 36049 var mergedScope = Object.assign(guidelib.runtime, context._guide().runtime); 36050 return mergedScope; 36051 } 36052 }; 36053 36054 guidelib.model.util.CommonUtils = CommonUtils; 36055}($, guidelib, _)); 36056(function (_, $, guidelib) { 36057 var getOrElse = xfalib.ut.XfaUtil.prototype.getOrElse, 36058 commonUtils = guidelib.model.util.CommonUtils, 36059 logger, 36060 constants = guidelib.model.GuideSchema.prototype.GuideStateConstants; 36061 36062 var initializeLogger = function (isXfaForm) {
36063 var configString = window.AF_log_config === undefined ? "0-a9" 36064 : "1-" + window.AF_log_config; 36065 36066 xfalib.ut.XfaUtil.prototype.registerLocaleProperties(guidelib.i18n); 36067 if (isXfaForm && window.formBridge) { 36068 window.formBridge.registerConfig("contextPath", window.guideBridge.userConfig["contextPath"]); 36069 window.formBridge.registerConfig("LoggerConfig", { 36070 "logConfigString" : configString, 36071 "categoryAcronyms" : {"d" : "AF"} 36072 }); 36073 } else { 36074 xfalib.ut.XfaUtil.prototype.logger = new xfalib.ut.Logger({ 36075 "jsonModel" : { 36076 "logConfigString" : configString, 36077 "categoryAcronyms" : {"d" : "AF"} 36078 } 36079 }); 36080 logger = xfalib.ut.XfaUtil.prototype.logger; 36081 } 36082 }; 36083 36084 var utils = { 36085 triggerEventOnWindow : function (eventPayload) { 36086 $(window).trigger(eventPayload); 36087 }, 36088 36089 postExternalMessage : function (name) { 36090 window.guideBridge._postExternalMessage({name : name}); 36091 } 36092 }; 36093 36094 var viewOnlyUtils = { 36095 createView : function (guide, $element) { 36096 utils.postExternalMessage("_layoutstart"); 36097 36098 var guideContainerView = new guidelib.view.GuideContainerView({ 36099 element : $element, 36100 model : guide 36101 }); 36102 36103 36104 window.guideBridge._setGuideView(guideContainerView); 36105 guidelib.util.GuideUtil.initializeHelp(); 36106 36107 36108 guidelib.util.AdUtil.applyDescriptionPlugin(); 36109 36110 utils.postExternalMessage("_layoutend"); 36111 36112 $(window).on("mousedown.guidebridge", function () { 36113 window.guideBridge.clickedOnWindow = true; 36114 }); 36115 }, 36116 36117 getLastFocusItem : function (guide) { 36118 var lastFocusItem; 36119 if (guide.runtime.guideContext) { 36120 lastFocusItem = guidelib.util.GuideUtil.fetchXMLNodeValue(guide.runtime.guideContext.guidePrefillXml, "lastFocusItem"); 36121 } 36122 36123 if (_.isUndefined(lastFocusItem)) { 36124 lastFocusItem = guidelib.util.GuideUtil._fetchJSONNodeValue(guide.runtime.guideContext.guidePrefillJson, "afSubmissionInfo.lastFocusItem"); 36125 } 36126 36127 if (_.isUndefined(lastFocusItem)) { 36128 lastFocusItem = window.guideBridge.customContextProperty("lastFocusItem"); 36129 } 36130 return lastFocusItem; 36131 }, 36132 36133 setFocus : function (item) { 36134 if (item) { 36135 window.guideBridge.setFocus(item); 36136 } else { 36137 window.guideBridge.setFocus(); 36138 } 36139 }, 36140 36141 preventCheckBoxMovementOnClick : function () { 36142 36143 36144 36145 36146 if (xfalib.ut.XfaUtil.prototype.isSafari() && !xfalib.ut.TouchUtil.TOUCH_ENABLED) { 36147 $('#guideContainerForm').addClass('macSafariForm'); 36148 } 36149 }, 36150 36151 disableDefaultSubmit : function () { 36152 36153 36154 $("#guideContainerForm").submit(function (evnt) { 36155 evnt.preventDefault(); 36156 }); 36157 }, 36158 36159 preventFormSubmitOnEnter : function () { 36160 36161 36162 $("#guideContainerForm input").keypress(function (evnt) { 36163 if (evnt.keyCode == 13 || evnt.charCode == 13 || evnt.which == 13) { 36164 evnt.preventDefault(); 36165 } 36166 }); 36167 }, 36168 36169 renderView : function (guide, $guideElement) { 36170 viewOnlyUtils.createView(guide, $guideElement); 36171 36172 var lastFocusItem = viewOnlyUtils.getLastFocusItem(guide); 36173 viewOnlyUtils.setFocus(lastFocusItem); 36174 utils.triggerEventOnWindow({type : "guideInitialized", guide : guide}); 36175 36176 viewOnlyUtils.preventCheckBoxMovementOnClick(); 36177 viewOnlyUtils.disableDefaultSubmit(); 36178 viewOnlyUtils.preventFormSubmitOnEnter(); 36179 } 36180 36181 }; 36182 36183 36184 guidelib.model._createXfaAndGuideModel = function (guideJson, xfaJson, options) { 36185 if (xfaJson) { 36186 xfalib.script.XfaModelRegistry.prototype.createModel(xfaJson); 36187 36188 new xfalib.acrobat.Acrobat(); 36189 } 36190 var guide = {}; 36191 guide = guidelib.model.GuideModelRegistry.prototype.createModel(guideJson, options); 36192 36193 guide._bindRefMap = {}; 36194 return guide; 36195 36196 }; 36197 36198 36199 guidelib.model._getGuideJsonWithSyncXfaProps = function (guideJson, xfaJson) { 36200 36201 var guide = guidelib.model._createXfaAndGuideModel(guideJson, xfaJson); 36202 36203 guide.syncXFAProps(); 36204 36205 36206 return { 36207 "guidejson" : JSON.stringify(guideJson), 36208 "xfajson" : JSON.stringify(xfaJson) 36209 }; 36210 }; 36211 36212 guidelib.model._prepareGuide = function (prefillData, guide) { 36213 var liveDataUtils = guide.internal.liveDataUtils, 36214 liveModel = guide.internal.liveModel, 36215 _getFileAttachmentWrappers = function(prefillDataAttachments) { 36216 var fileAttachmentWrappers = []; 36217 try { 36218 var atts = JSON.parse(prefillDataAttachments); 36219 fileAttachmentWrappers = atts.map(function (x) { 36220 return new guidelib.model.FileAttachmentWrapper(JSON.parse(x)) 36221 }); 36222 } catch (e) { 36223 if (e.stack) { 36224 guide.logger().error(e.stack); 36225 } 36226 } 36227 return fileAttachmentWrappers; 36228 }; 36229 36230 if (prefillData.isMergedJson && prefillData.data) { 36231 36232 if (prefillData.data.guideState && prefillData.data.guideState.attachments) { 36233 prefillData.data["attachments"] = _getFileAttachmentWrappers(prefillData.data.guideState.attachments); 36234 } 36235 window.guideBridge.restoreGuideState(prefillData.data); 36236 } else if (prefillData.data) { 36237 guide.setGuideState(constants.GUIDE_STATE_MERGE_PROGRESS); 36238 liveDataUtils.initLiveData(prefillData.data, 36239 null, 36240 _.isString(guide.xdpRef), 36241 _.isString(guide.xsdRef), 36242 guide.getAttribute("xsdRootElement"), 36243 _getFileAttachmentWrappers(prefillData.attachments)); 36244 liveDataUtils.playLiveData(guide.rootPanel); 36245 liveModel.prefillCrossFragFields(guide); 36246 guide.setGuideState(constants.GUIDE_STATE_MERGE_COMPLETE); 36247 guide.prepare(); 36248 } else { 36249 guide.prepare(); 36250 liveDataUtils.initLiveData(null, null, 36251 _.isString(guide.xdpRef), _.isString(guide.xsdRef), 36252 guide.getAttribute("xsdRootElement")); 36253 } 36254 36255 var fileAttachmentMap, 36256 obj = guideBridge.customContextProperty("fileAttachmentMap"); 36257 if (!_.isUndefined(obj) && typeof(obj) === "string") { 36258 try { 36259 obj = JSON.parse(obj); 36260 } catch (e) { 36261 if (e.stack) { 36262 guide.logger().error(e.stack); 36263 } 36264 obj = undefined; 36265 } 36266 } 36267 fileAttachmentMap = obj; 36268 36269 var i, node, fieldValue, 36270 fileAttachmentsList = window.guideBridge._getFileAttachmentsList(); 36271 36272 36273 if (!_.isUndefined(fileAttachmentMap)) { 36274 for (i = 0; i < fileAttachmentsList.length; i++) { 36275 node = fileAttachmentsList[i]; 36276 fieldValue = fileAttachmentMap[node.somExpression]; 36277 node.fileAttachment.value = fieldValue; 36278 if (!_.isEmpty(fieldValue)) { 36279 node._fileList = fieldValue.split("\n"); 36280 } 36281 } 36282 } 36283 guide.setGuideState(constants.GUIDE_STATE_MODEL_COMPLETE); 36284 }; 36285 36286 guidelib.model.markDirtyPanels = function (lazyChildren, dataString, dirtyPanels, guide) {
36287 var lazyChildrenMap = commonUtils.createMap(lazyChildren, 0); 36288 36289 if (!_.isEmpty(dataString)) { 36290 if (dirtyPanels === null || dirtyPanels.length === 0) { 36291 dirtyPanels = guide.internal.liveDataUtils.getListOfDirtyPanels(dataString); 36292 } 36293 if (dirtyPanels && dirtyPanels.length > 0) { 36294 lazyChildrenMap = commonUtils.updatedMapIfNot(lazyChildrenMap, dirtyPanels, 1); 36295 guide.internal.GuideDirtyMarkerAndVisitor.visitMap = lazyChildrenMap; 36296 } 36297 } else { 36298 guide.internal.GuideDirtyMarkerAndVisitor.visitMap = lazyChildrenMap; 36299 } 36300 }; 36301 36302 guidelib.model.initializeLiveDataUtils = function (schemaType) { 36303 var liveDataUtils = null; 36304 if (schemaType === "formdatamodel" || schemaType === "jsonschema") { 36305 liveDataUtils = new guidelib.model.LiveJsonUtils(); 36306 } else { 36307 liveDataUtils = new guidelib.model.LiveXmlUtils(); 36308 } 36309 return liveDataUtils; 36310 }; 36311 36312 guidelib.model.prepareInput = function (guideJsonData) { 36313 return { 36314 guideJson : JSON.parse(guideJsonData.guidejson || "null"), 36315 guideContext : JSON.parse(guideJsonData.guidecontext || "null"), 36316 guidemergedjson : JSON.parse(guideJsonData.guidemergedjson || "null"), 36317 xfaJson : JSON.parse(guideJsonData.xfajson || "null"), 36318 xfaRenderContext : JSON.parse(guideJsonData.xfarendercontext || "null") 36319 }; 36320 }; 36321 36322 guidelib.model.mergeData = function (prefillData, guide, guideContext) { 36323 var rawData = prefillData.data, 36324 liveDataUtils = guide.internal.liveDataUtils, 36325 dirtyPanels = [], 36326 customPropertyMap = {}, 36327 mergedXfaRenderContext = null; 36328 36329 guide.runtime.guideContext = guide.runtime.guideContext || {}; 36330 36331 if (prefillData.isMergedJson) { 36332 if (typeof prefillData.data === "string") { 36333 try { 36334 prefillData.data = JSON.parse(prefillData.data); 36335 } catch (e) { 36336 prefillData.data = ""; 36337 } 36338 } 36339 rawData = getOrElse(prefillData.data, 36340 "guideState.guideLiveData", 36341 getOrElse(rawData, 36342 "guideState.guidePrefillXml", 36343 getOrElse(prefillData.data, 36344 "guideState.guidePrefillJson", undefined))); 36345 36346 var dirtyPanelsStr = getOrElse(prefillData.data, 36347 "guideState.guideContext.afSubmissionInfo.afDraft", "") 36348 .replace(/\"/g, ""); 36349 36350 if (dirtyPanelsStr) { 36351 dirtyPanels = dirtyPanelsStr.split(","); 36352 } 36353 customPropertyMap = getOrElse(prefillData.data, 36354 "guideState.guideContext.customPropertyMap", 36355 {}); 36356 36357 var ccpMapViaNewPrefillService = getOrElse(prefillData.data, "guideState.customContext", null); 36358 var ccpMapViaOldImplementation = getOrElse(guidelib, "__runtime__.guideContext.customPropertyMap", {}); 36359 var ccpMapViaOldAndNewImplementation = _.extend({}, ccpMapViaOldImplementation, getOrElse(guide, "runtime.guideContext.customPropertyMap", {})); 36360 if (!_.isEmpty(ccpMapViaNewPrefillService) && _.isEmpty(ccpMapViaOldAndNewImplementation)) { 36361 guideBridge.customContextProperty(ccpMapViaNewPrefillService); 36362 } 36363 36364 var fileMapViaNewPrefillService = getOrElse(prefillData.data, "guideState.fileAttachmentMap", null); 36365 var fileMapViaOldImplementation = guideBridge.customContextProperty("fileAttachmentMap"); 36366 if (!_.isEmpty(fileMapViaNewPrefillService) && _.isEmpty(fileMapViaOldImplementation)) { 36367 guideBridge.customContextProperty("fileAttachmentMap", fileMapViaNewPrefillService); 36368 } 36369 } else { 36370 customPropertyMap = prefillData.customContext || {}; 36371 guideBridge.customContextProperty("fileAttachmentMap", prefillData.fileAttachmentMap); 36372 guideBridge.customContextProperty("fileAttachmentWrappers", prefillData.fileAttachmentWrappers); 36373 } 36374 36375 if (guide.xdpRef) { 36376 mergedXfaRenderContext = getOrElse(prefillData.data, "guideState.xfaState.xfaRenderContext", null); 36377 36378 if (mergedXfaRenderContext != null) { 36379 36380 xfalib.runtime.renderContext = JSON.parse(mergedXfaRenderContext); 36381 } 36382 36383 xfalib.runtime.xfa.form._initialize(true);
36384 $(window).trigger("XfaInitialized"); 36385 } 36386 36387 if (rawData !== "") { 36388 if (guideContext.schemaType === "formdatamodel" || guideContext.schemaType === "jsonschema") { 36389 guideContext.guidePrefillJson = rawData; 36390 } else { 36391 guideContext.guidePrefillXml = rawData; 36392 } 36393 } 36394 36395 guideContext.customPropertyMap = $.extend({}, guideContext.customPropertyMap, customPropertyMap); 36396 36397 36398 $.extend(true, guide.runtime.guideContext, guideContext); 36399 36400 guidelib.model.markDirtyPanels(guide.allLazyChildren, rawData, dirtyPanels, guide); 36401 36402 guidelib.model._prepareGuide(prefillData, guide); 36403 36404 36405 36406 if (guide.allLazyChildren.length > 0 && guideBridge.customContextProperty("fileAttachmentMap")) { 36407 var fileAttachmentMap = guideBridge.customContextProperty("fileAttachmentMap"); 36408 if (typeof fileAttachmentMap === "string") { 36409 fileAttachmentMap = JSON.parse(fileAttachmentMap); 36410 } 36411 guide.internal.liveDataUtils._updateLazyAttachmentMap(fileAttachmentMap); 36412 } 36413 }; 36414 36415 guidelib.model.fireOnContainerDomElementReady = function (guideJsonData, fetchData, $htmlElement, localContextCustomPropertyMap) { 36416 36417 var inputData = this.prepareInput(guideJsonData), 36418 guideJson = inputData.guideJson, 36419 guideContext = inputData.guideContext, 36420 guidemergedjson = inputData.guidemergedjson, 36421 xfaJson = inputData.xfaJson, 36422 xfaRenderContext = inputData.xfaRenderContext, 36423 localStorage, 36424 guide, 36425 dataPromise; 36426 initializeLogger(xfaJson != null); 36427 if (guideJson === null || guideContext == null) { 36428 console.error("Unable to load Form. Adaptive Form Json is invalid."); 36429 return; 36430 } 36431 36432 if (window.guideBridge !== undefined) { 36433 localStorage = window.guideBridge._getStorage(); 36434 } 36435 try { 36436 36437 localContextCustomPropertyMap = _.isObject(localContextCustomPropertyMap) ? 36438 JSON.stringify(localContextCustomPropertyMap) : localContextCustomPropertyMap; 36439 localContextCustomPropertyMap = JSON.parse(localContextCustomPropertyMap); 36440 } catch(e) { 36441 localContextCustomPropertyMap = {}; 36442 } 36443 36444 if (fetchData && (guidemergedjson === null || guidemergedjson === "" || getOrElse(localStorage, "guideState", null) !== null)) { 36445 if (fetchData instanceof Function) { 36446 var result = fetchData(); 36447 if (result.then instanceof Function) { 36448 dataPromise = result; 36449 } else { 36450 dataPromise = _.extend({}, {isMergedJson : false}, fetchData()); 36451 } 36452 } else if ((!(window.FD && window.FD.isToggleEnabled("FT_FORMS-14840"))) || 36453 ((guideJson.prefillService !== undefined && guideJson.prefillService !== "none") || (new URLSearchParams(window.location.search)).get("dataRef") !== null)) { 36454 var formContainerPath = getOrElse(window.guideBridge, "userConfig.submitConfig.aemFormComponentPath", guideContext.guidePath); 36455 var guideUrl = window.guideBridge._getGuidePathUrl(".af.prefilldata.json", formContainerPath); 36456 dataPromise = this.fetchData(guideUrl + window.location.search); 36457 } else { 36458 dataPromise = {data: null, isMergedJson: false}; 36459 } 36460 } else { 36461 var _mergeData = guidemergedjson; 36462 if (getOrElse(localStorage, "guideState", null) !== null) { 36463 _mergeData = localStorage; 36464 } 36465 36466 36467 dataPromise = { 36468 data : _mergeData, 36469 isMergedJson : true 36470 }; 36471 } 36472 36473 36474 var liveDataUtils = this.initializeLiveDataUtils(guideContext.schemaType), 36475 liveModel = new guidelib.model.LiveModel(); 36476 36477 if (window.guideBridge.hostName == "server") { 36478 36479 if (!FD.isToggleEnabled(guidelib.util.FeatureToggleConstants.FT_BROWSERLESS_SUBMISSION)) { 36480 liveModel._disableFunctions(); 36481 liveDataUtils._disableFunctions(); 36482 } 36483 36484 _.each(_.functions(viewOnlyUtils), function (funcName) { 36485 viewOnlyUtils[funcName] = function () {}; 36486 }); 36487 36488 if (window.formBridge) { 36489 36490 36491 36492 window.formBridge.ajaxCallMode = "server"; 36493 } 36494 } 36495 36496 liveModel.createDataNodes(guideJson.repeatBindRef); 36497 var allLazyChildren = getOrElse(guideJson, "allLazyChildren", []); 36498 36499 var options = {}; 36500 options = _.extend({}, options, {"liveModel" : liveModel, "liveDataUtils" : liveDataUtils}); 36501 36502 utils.postExternalMessage("_formdomstart"); 36503 try { 36504 guide = guidelib.model._createXfaAndGuideModel(guideJson, xfaJson, options); 36505 36506 guide.runtime.guideContext.customPropertyMap = _.extend({}, guide.runtime.guideContext.customPropertyMap, localContextCustomPropertyMap); 36507 if (allLazyChildren.length > 0) { 36508 liveModel.createCrossFragFields(guideJson.guideGlobalLazyField, guide); 36509 } 36510 guide.version = new guidelib.util.Version({ 36511 scriptingBehaviourVersion: guideContext.scriptingBehaviourVersion 36512 }); 36513 guide.setGuideState(constants.GUIDE_STATE_MODEL_CREATED); 36514 if (xfaJson && xfaRenderContext) { 36515 xfalib.runtime.renderContext = xfaRenderContext; 36516 } 36517 utils.triggerEventOnWindow({type: "guideModelInitialized", guide: guide}); 36518 } catch (e) { 36519 36520 if (e.stack) { 36521 console.error(e.stack); 36522 } 36523 } 36524 36525 var $guideElement = $htmlElement || $("div.guideContainerWrapperNode"); 36526 36527 if (dataPromise.then instanceof Function) { 36528 return dataPromise.then(function (result) { 36529 guidelib.model.mergeData(result, guide, guideContext); 36530 viewOnlyUtils.renderView(guide, $guideElement); 36531 }); 36532 } else { 36533 36534 guidelib.model.mergeData(dataPromise, guide, guideContext); 36535 viewOnlyUtils.renderView(guide, $guideElement); 36536 return guide; 36537 } 36538 }; 36539 36540 guidelib.model.fetchData = function (path) { 36541 var deferred = $.Deferred(); 36542 if (window.guideBridge.hostName === "server") { 36543 deferred.resolve({ 36544 data : "", 36545 isMergedJson : false 36546 }); 36547 } else { 36548 $.ajax({ 36549 url : path, 36550 type : 'POST', 36551 dataType : 'json' 36552 }).done(function (data) { 36553 var obj = _.extend({}, data, {isMergedJson : false}); 36554 deferred.resolve(obj); 36555 }).fail(function (obj, textStatus, errorThrown) { 36556 console.error(textStatus + " " + errorThrown); 36557 deferred.resolve({ 36558 data : "", 36559 isMergedJson : false 36560 }); 36561 }); 36562 } 36563 return deferred.promise(); 36564 }; 36565})(_, $, window.guidelib); 36566 36567(function ($) { 36568 var xfaUtil = xfalib.ut.XfaUtil.prototype; 36569 $.widget("xfaWidget.imageCheckButtonWidget", $.xfaWidget.XfaCheckBox, { 36570 36571 _widgetName : "imageCheckButtonWidget", 36572 36573 getOptionsMap : function () { 36574 var parentOptionsMap = $.xfaWidget.XfaCheckBox.prototype.getOptionsMap.apply(this, arguments); 36575 return $.extend({}, parentOptionsMap, { 36576 "displayValue" : function (val) { 36577 parentOptionsMap.displayValue.apply(this, arguments); 36578 var rbParent = this.$userControl.parents('.guideRadioButtonItem, .guideCheckBoxItem'); 36579 if (rbParent) { 36580 rbParent.toggleClass('imageCheckButtonChecked', this.checkedState); 36581 } 36582 if (this.$userControl.attr('disabled') === 'disabled') { 36583 rbParent.addClass('imageCheckButtonDisabled'); 36584 } 36585 } 36586 }); 36587 } 36588 }); 36589})($); 36590(function (_, guidelib) { 36591 var GuideModelRegistry = guidelib.model.GuideModelRegistry = xfalib.ut.Class.extend({ 36592 36593 _nodeClassToFactoryMap : { 36594 36595 }, 36596 36597 createModel : function (jsonModel, options) { 36598 var model = null; 36599 var guideNodeClassTag = "GuideNode"; 36600 if (jsonModel.guideNodeClass && jsonModel.guideNodeClass.length > 0) {
36601 guideNodeClassTag = jsonModel.guideNodeClass.charAt(0).toUpperCase() + jsonModel.guideNodeClass.substr(1); 36602 } 36603 var factoryFnName = "create" + guideNodeClassTag ; 36604 if (jsonModel.guideNodeClass && this._nodeClassToFactoryMap[jsonModel.guideNodeClass]) { 36605 factoryFnName = this._nodeClassToFactoryMap[jsonModel.guideNodeClass]; 36606 } 36607 if (this[factoryFnName]) { 36608 model = this[factoryFnName].call(this, jsonModel, options); 36609 } 36610 36611 if (!model && guidelib.model[guideNodeClassTag]) { 36612 model = new guidelib.model[guideNodeClassTag](this._getOptions(jsonModel, options)); 36613 } 36614 36615 if (!model) { 36616 if (jsonModel.items) { 36617 model = new guidelib.model.GuideItemsContainer(this._getOptions(jsonModel, options)); 36618 } else { 36619 model = new guidelib.model.GuideNode(this._getOptions(jsonModel, options)); 36620 } 36621 } 36622 return model; 36623 }, 36624 36625 _getOptions : function (jsonModel, options) { 36626 return _.extend({}, options, {"jsonModel" : jsonModel}); 36627 }, 36628 36629 createInstanceManager : function (guidePanelModel) { 36630 var name = guidePanelModel.getAttribute("name"), 36631 imJson = { 36632 guideNodeClass : "guideInstanceManager", 36633 minOccur : guidePanelModel.minOccur, 36634 maxOccur : guidePanelModel.maxOccur, 36635 initialOccur : guidePanelModel.initialOccur, 36636 instanceTemplateId : guidePanelModel.templateId, 36637 name : "_" + name, 36638 instanceName : name, 36639 templateId : "im_" + guidePanelModel.templateId, 36640 id : "im_" + guidePanelModel.id 36641 }; 36642 var options = {}; 36643 if (guidePanelModel.options._guideContainer) { 36644 options = _.extend({}, options, {"_guideContainer" : guidePanelModel.options._guideContainer}); 36645 } 36646 return guidelib.model.GuideModelRegistry.prototype.createModel(imJson, options); 36647 } 36648 }); 36649})(_, guidelib); 36650 36651/************************************************************************* 36652 * 36653 * ADOBE CONFIDENTIAL 36654 * __________________ 36655 * 36656 * Copyright 2014 Adobe Systems Incorporated 36657 * All Rights Reserved. 36658 *
36659 * NOTICE: All information contained herein is, and remains 36660 * the property of Adobe Systems Incorporated and its suppliers, 36661 * if any. The intellectual and technical concepts contained 36662 * herein are proprietary to Adobe Systems Incorporated and its 36663 * suppliers and may be covered by U.S. and Foreign Patents, 36664 * patents in process, and are protected by trade secret or copyright law. 36665 * Dissemination of this information or reproduction of this material 36666 * is strictly forbidden unless prior written permission is obtained 36667 * from Adobe Systems Incorporated. 36668 **************************************************************************/ 36669 36670/** 36671 * Created with IntelliJ IDEA. 36672 * User: rismehta 36673 * Date: 1/15/14 36674 * Time: 5:49 PM 36675 * To change this template use File | Settings | File Templates. 36676 */ 36677 36678/*anonymous function to handle show of file list view */ 36679(function ($, guidelib) { 36680 36681 // Was causing problem in IE9 36682 // hence have added timeout to ensure that once button is rendered, event handler is registered 36683 // todo: may have to think of better namespace ? 36684 guidelib.intervals = guidelib.intervals || {}; 36685 guidelib.intervals.intId = setInterval(function () { 36686 var fileAttachmentListingBtn = $("div.fileattachmentlisting button[data-guide-fileListing]"); 36687 if (fileAttachmentListingBtn.length > 0) { 36688 clearInterval(guidelib.intervals.intId); 36689 var self; 36690 fileAttachmentListingBtn.click(function () { 36691 self = $(this); 36692 // added because in mobile devices it was causing problem of backdrop 36693 $("#fileAttachment").addClass("fileAttachmentDialog") 36694 $("#fileAttachment").appendTo('body'); 36695 $("#fileAttachment").modal("show"); 36696 }); 36697 // bring focus back to file attachment listing button on dialog hide 36698 $(".fileAttachmentDialog").on('hidden.bs.modal', function (e) { 36699 $(this).removeClass("fileAttachmentDialog"); 36700 self.focus(); 36701 }); 36702 } 36703 }, 1000); 36704}($, guidelib)); 36705 36706/************************************************************************* 36707 * 36708 * ADOBE CONFIDENTIAL 36709 * __________________ 36710 * 36711 * Copyright 2014 Adobe Systems Incorporated 36712 * All Rights Reserved. 36713 *
36714 * NOTICE: All information contained herein is, and remains 36715 * the property of Adobe Systems Incorporated and its suppliers, 36716 * if any. The intellectual and technical concepts contained 36717 * herein are proprietary to Adobe Systems Incorporated and its 36718 * suppliers and may be covered by U.S. and Foreign Patents, 36719 * patents in process, and are protected by trade secret or copyright law. 36720 * Dissemination of this information or reproduction of this material 36721 * is strictly forbidden unless prior written permission is obtained 36722 * from Adobe Systems Incorporated. 36723 **************************************************************************/ 36724 36725(function ($) { 36726 36727 // GUIDE ADD REMOVE CLASS DEFINITION 36728 // ==================== 36729 36730 var GuideAddRemove = function (element) { 36731 this.element = $(element); 36732 }; 36733 36734 GuideAddRemove.prototype.add = function () { 36735 $this = this.element; 36736 var id = $this.attr("data-guide-id"), 36737 nextPanel; 36738 36739 if (id) { 36740 if (window.guideBridge) { 36741 var guidePanel = window.guideBridge._resolveId(id); 36742 if (guidePanel) { 36743 nextPanel = guidePanel.instanceManager.insertInstance(guidePanel.instanceIndex + 1); 36744 if (nextPanel) { 36745 window.guideBridge.setFocus(nextPanel.somExpression, "firstItem"); 36746 } 36747 } 36748 } else { 36749 console.log("could not add new instance" + id); 36750 } 36751 } 36752 }; 36753 36754 GuideAddRemove.prototype.remove = function () { 36755 $this = this.element; 36756 var id = $this.attr("data-guide-id"); 36757 36758 if (id) { 36759 if (window.guideBridge) { 36760 var guidePanel = window.guideBridge._resolveId(id); 36761 if (guidePanel) { 36762 guidePanel.instanceManager.removeInstance(guidePanel.instanceIndex); 36763 } 36764 } else { 36765 console.log("could not remove instance"); 36766 } 36767 } 36768 }; 36769 36770 // GUIDE ADD REMOVE PLUGIN DEFINITION 36771 // ===================== 36772 36773 var old = $.fn.guideAddRemove; 36774 36775 $.fn.guideAddRemove = function (option) { 36776 return this.each(function () { 36777 var $this = $(this); 36778 var data = $this.data('guideAddRemove'); 36779 36780 if (!data) { 36781 $this.data('guideAddRemove', (data = new GuideAddRemove(this))); 36782 } 36783 if (typeof option == 'string') { 36784 data[option](); 36785 } 36786 }); 36787 }; 36788 36789 $.fn.guideAddRemove.Constructor = GuideAddRemove(); 36790 36791 // ADD REMOVE NO CONFLICT 36792 // =============== 36793 36794 $.fn.guideAddRemove.noConflict = function () { 36795 $.fn.guideAddRemove = old; 36796 return this; 36797 }; 36798 36799 // ADD REMOVE DATA-API 36800 // ============ 36801 36802 $(document).on('click.guideAddRemove.data-api keypress.guideAddRemove.data-api', '[data-guide-addremove="add"]', function (e) { 36803 if (e.type == "keypress" && !guidelib.util.GuideUtil.isEnterKeyPressed(e)) { 36804 return; 36805 } 36806 e.preventDefault(); 36807 //This is required for setting the focus on the new panel. Otherwise the focus remains on the previous panel. 36808 e.stopImmediatePropagation(); 36809 $(this).guideAddRemove('add'); 36810 }).on('click.guideAddRemove.data-api keypress.guideAddRemove.data-api', '[data-guide-addremove="remove"]', function (e) { 36811 if (e.type == "keypress" && !guidelib.util.GuideUtil.isEnterKeyPressed(e)) { 36812 return; 36813 } 36814 e.preventDefault(); 36815 $(this).guideAddRemove('remove'); 36816 }); 36817 36818}($)); 36819 36820/************************************************************************* 36821 * 36822 * ADOBE CONFIDENTIAL 36823 * __________________ 36824 * 36825 * Copyright <year> Adobe Systems Incorporated 36826 * All Rights Reserved. 36827 *
36828 * NOTICE: All information contained herein is, and remains 36829 * the property of Adobe Systems Incorporated and its suppliers, 36830 * if any. The intellectual and technical concepts contained 36831 * herein are proprietary to Adobe Systems Incorporated and its 36832 * suppliers and may be covered by U.S. and Foreign Patents, 36833 * patents in process, and are protected by trade secret or copyright law. 36834 * Dissemination of this information or reproduction of this material 36835 * is strictly forbidden unless prior written permission is obtained 36836 * from Adobe Systems Incorporated. 36837 **************************************************************************/ 36838 36839(function ($) { 36840 36841 // TABLE LAYOUT PLUGIN 36842 // ============ 36843 36844 $(document).on('panelRemoved.af', '.guideTableNode', function (e, $childRemoved, index) { 36845 // this plugin is specific to a layout 36846 // one can also check the layout based on CSS class set and perform things accordingly 36847 // prevent the bubbling up of the event 36848 e.stopPropagation(); 36849 // this would work only in runtime 36850 var $bodyRows = $(e.target).find("tr.guideTableRowNode:not(.guideTableHeader)"); 36851 // Set focus to first child 36852 if (index > 1) { 36853 // set focus on prev row since index is greater than 1 36854 var $prevRow = $bodyRows.eq(index - 1); 36855 guidelib.util.GuideUtil.setFocusOnFirstItemOfTableRow($prevRow); 36856 } else if (index == 1) { 36857 var $nextRow = $bodyRows.eq(1); 36858 // may there is only one row which has got deleted, hence check if next row actually exists 36859 if ($nextRow.length > 0) { 36860 guidelib.util.GuideUtil.setFocusOnFirstItemOfTableRow($nextRow); 36861 } 36862 } 36863 }); 36864 36865}($)); 36866 36867/************************************************************************* 36868 * 36869 * ADOBE CONFIDENTIAL 36870 * __________________ 36871 * 36872 * Copyright 2014 Adobe Systems Incorporated 36873 * All Rights Reserved. 36874 *
36875 * NOTICE: All information contained herein is, and remains 36876 * the property of Adobe Systems Incorporated and its suppliers, 36877 * if any. The intellectual and technical concepts contained 36878 * herein are proprietary to Adobe Systems Incorporated and its 36879 * suppliers and may be covered by U.S. and Foreign Patents, 36880 * patents in process, and are protected by trade secret or copyright law. 36881 * Dissemination of this information or reproduction of this material 36882 * is strictly forbidden unless prior written permission is obtained 36883 * from Adobe Systems Incorporated. 36884 **************************************************************************/ 36885 36886/*handle click of default next and previous navigator*/ 36887$(function ($) { 36888 var getPanelSom = function (panelId) { 36889 var panel = window.guideBridge._resolveId(panelId); 36890 if (panel === undefined || panel === null) { 36891 return ""; 36892 } 36893 return panel.somExpression; 36894 }, 36895 pointerup_evnt = xfalib.ut.TouchUtil.POINTER_UP; 36896 36897 if (pointerup_evnt === "touchend") { 36898 // touchend happens before blur, hence the value of the current 36899 // focused field is not committed and setFocus API receives the old 36900 // value. So as a hack we are using mouseup instead of touchend to 36901 // make sure that the value gets committed 36902 pointerup_evnt = "mouseup"; 36903 } 36904 $('body').on(pointerup_evnt + " keydown", '[data-guide-wizard-nav]', function (e) { 36905 var triggerKeyEvent = false; 36906 // check for event type and key press space/enter 36907 if (e.type === "keydown" && (e.keyCode === 32 || e.keyCode === 13)) { 36908 e.preventDefault(); 36909 triggerKeyEvent = true; // set to trigger key event 36910 } 36911 36912 // when event is pointerup(click) or space/enter key is pressed, trigger navigation 36913 if (e.type === "pointerup" || triggerKeyEvent) { 36914 var $this = $(this), 36915 options = $this.data("guide-wizard-nav"); 36916 if (_.isObject(options)) { //case of all the options, get som expression out of id 36917 options.somExpression = getPanelSom(options.panelId); 36918 } else { //case where its value of somId 36919 var somExpr = getPanelSom(options), 36920 navType = $(this).data("guide-wizard-nav-type"); 36921 options = { 36922 somExpression: somExpr, 36923 focusOption: navType, 36924 runCompletionScript: true 36925 }; 36926 } 36927 window.guideBridge.setFocus(options); 36928 } 36929 }); 36930 36931 window.guideBridge.on("elementNavigationChanged", 36932 function (evntName, evnt) { 36933 var activePanelSom = evnt.newText, 36934 activePanel = window.guideBridge._guideView.getView(activePanelSom), 36935 scrollDirection, 36936 scrollStep, 36937 scrollPos, 36938 list, 36939 $listElements; 36940 if (activePanel instanceof guidelib.view.GuidePanelView) { 36941 $listElements = activePanel.parentView.$element.find('[id*="' + guidelib.util.GuideUtil.GUIDE_ITEM_NAV_CONTAINER_SUFFIX + '"]'); 36942 if (!_.isUndefined($listElements) && !_.isNull($listElements) && $listElements.length > 0) { 36943 list = $listElements.eq(0); 36944 if (_.isUndefined(list.data("guideNavScrollPos"))) { 36945 list.data("guideNavScrollPos", 0); 36946 } 36947 scrollPos = list.data("guideNavScrollPos"); 36948 //Find index among the visible panels 36949 var parentChildViews = activePanel.parentView.childViews, 36950 iterator, 36951 navPos = 0; 36952 for (iterator = 0; iterator < parentChildViews.length; iterator++) { 36953 if (activePanel === parentChildViews[iterator]) { 36954 break; 36955 } 36956 if (parentChildViews[iterator]._model.visible) { 36957 navPos = navPos + 1; 36958 } 36959 } 36960 if (navPos > scrollPos) { 36961 scrollDirection = "right"; 36962 } else { 36963 scrollDirection = "left"; 36964 } 36965 scrollStep = Math.abs(navPos - scrollPos); 36966 guidelib.util.GuideUtil.navScroll(list, scrollDirection, scrollStep, '[id*="' + guidelib.util.GuideUtil.GUIDE_ITEM_
36966NAV_SUFFIX + '"]:not(.hidden)'); 36967 } 36968 } 36969 }); 36970}); 36971 36972/************************************************************************* 36973 * 36974 * ADOBE CONFIDENTIAL 36975 * __________________ 36976 * 36977 * Copyright 2014 Adobe Systems Incorporated 36978 * All Rights Reserved. 36979 * 36980 * NOTICE: All information contained herein is, and remains 36981 * the property of Adobe Systems Incorporated and its suppliers, 36982 * if any. The intellectual and technical concepts contained 36983 * herein are proprietary to Adobe Systems Incorporated and its 36984 * suppliers and may be covered by U.S. and Foreign Patents, 36985 * patents in process, and are protected by trade secret or copyright law. 36986 * Dissemination of this information or reproduction of this material 36987 * is strictly forbidden unless prior written permission is obtained 36988 * from Adobe Systems Incorporated. 36989 **************************************************************************/ 36990 36991$(function ($) { 36992 36993 /* handle swipe*/ 36994 var setSwipeGestureState = function () { 36995 var swipeEnabled = !window.guideBridge._guide.getAttribute("disableSwipeGesture"); 36996 window.guideBridge.enableSwipeGesture(swipeEnabled, swipeEnabled); 36997 }; 36998 window.guideBridge.connect(setSwipeGestureState, this); 36999 37000 /*show scroll indication on mobile devices*/ 37001 var scrollIndicator = function () { 37002 if ($(window).scrollTop() == $(document).height() - $(window).height()) { 37003 $('[data-guide-scroll-indicator]').removeClass('mobileScrollIndicator'); 37004 } else if ($(window).scrollTop() < $(document).height() - $(window).height()) { 37005 $('[data-guide-scroll-indicator]').addClass('mobileScrollIndicator'); 37006 } 37007 }; 37008 37009 //this should be changed back to $(document).ready(scrollIndicator) instead of windows onload, 37010 //once jquery version is bumped 37011 $(window).on('load scroll resize', scrollIndicator); 37012 window.guideBridge.on('elementNavigationChanged', scrollIndicator); 37013}); 37014 37015/************************************************************************* 37016 * 37017 * ADOBE CONFIDENTIAL 37018 * __________________ 37019 * 37020 * Copyright 2014 Adobe Systems Incorporated 37021 * All Rights Reserved. 37022 *
37023 * NOTICE: All information contained herein is, and remains 37024 * the property of Adobe Systems Incorporated and its suppliers, 37025 * if any. The intellectual and technical concepts contained 37026 * herein are proprietary to Adobe Systems Incorporated and its 37027 * suppliers and may be covered by U.S. and Foreign Patents, 37028 * patents in process, and are protected by trade secret or copyright law. 37029 * Dissemination of this information or reproduction of this material 37030 * is strictly forbidden unless prior written permission is obtained 37031 * from Adobe Systems Incorporated. 37032 **************************************************************************/ 37033/*anonymous function to handle click of default next and previous navigator*/ 37034(function ($) { 37035 window.guideBridge.on("elementNavigationChanged", 37036 function (evntName, evnt) { 37037 var activePanelSom = evnt.newText, 37038 activePanel = window.guideBridge.resolveNode(activePanelSom); 37039 if (activePanel) { 37040 var dynamicContentSelector = "[data-target-guide-content]", 37041 text = $(dynamicContentSelector).text(); 37042 // if there is an active panel already set and active panel is not an instance of root panel node 37043 // only then set the active panel title to the content 37044 if (text != null && text.length > 0 37045 && (!(activePanel instanceof guidelib.model.RootPanelNode) 37046 && !(activePanel instanceof guidelib.model.GuideToolbar))) { 37047 $(dynamicContentSelector).text(activePanel.title ? activePanel.title : ""); 37048 } 37049 } 37050 }); 37051}($)); 37052 37053// jscs:disable requireDotNotation 37054/* 37055 * *********************************************************************** 37056 * ADOBE CONFIDENTIAL 37057 * __________________ 37058 * 37059 * Copyright 2015 Adobe Systems Incorporated 37060 * All Rights Reserved. 37061 *
37062 * NOTICE: All information contained herein is, and remains 37063 * the property of Adobe Systems Incorporated and its suppliers, 37064 * if any. The intellectual and technical concepts contained 37065 * herein are proprietary to Adobe Systems Incorporated and its 37066 * suppliers and may be covered by U.S. and Foreign Patents, 37067 * patents in process, and are protected by trade secret or copyright law. 37068 * Dissemination of this information or reproduction of this material 37069 * is strictly forbidden unless prior written permission is obtained 37070 * from Adobe Systems Incorporated. 37071 * *********************************************************************** 37072 */ 37073 37074(function ($, guidelib, _) { 37075 var GuideUtil = guidelib.util.GuideUtil, 37076 CHART_TYPE = GuideUtil.chartType, 37077 37078 ChartUtils = guidelib.chartUtils = { 37079 37080 reducerOptions : window.chartReducer.reducerOptions, 37081 37082 /** 37083 * Returns the display format of axis data 37084 * @param dataType {string} representing data type of axis 37085 * @returns {string} 37086 */ 37087 getDisplayFormat : function (dataType) { 37088 var displayFormat = ""; 37089 if (dataType === 'date' || dataType === 'date-time') { 37090 displayFormat = 'date{' + guidelib.i18n.datePatterns.med + '}'; 37091 } 37092 return displayFormat; 37093 }, 37094 37095 /** 37096 * Reads chart model for chart configuration and computes the data for chart 37097 * @param chartModel 37098 * @returns {{}} 37099 */ 37100 gatherAxisData : function (chartModel) { 37101 var categoryExp, 37102 valueExp, 37103 reducerFunction, 37104 repeatableInstances, 37105 repeatableItem, 37106 seriesRepeatableItem, 37107 series, 37108 relativeSeriesNameExp, 37109 currentSeries, 37110 repeatablePath, 37111 seriesLength = 0, 37112 seriesRepeatableInstances, 37113 relativeSeriesRefExp, 37114 data = new Map(), 37115 chartBuildOptions = {}, 37116 isWebChannelChart = chartModel.jsonModel["sling:resourceType"] === 'fd/ccm/web-channel/components/chart/v1/chart', 37117 dataToFill = {}; 37118 chartBuildOptions.isFDMDataSource = chartModel.dataSourceType === "fdm" ? true : false; 37119 chartBuildOptions.chartModel = chartModel; 37120 dataToFill.valueDisplayFormat = ""; 37121 dataToFill.labelDisplayFormat = ""; 37122 dataToFill.categoryDataType = ""; 37123 dataToFill.valueDataType = ""; 37124 37125 repeatableItem = chartModel.getOrElse(chartModel._guide().runtime, chartModel.repeatableItem, undefined); 37126 37127 //Do not support reducer functions on x-axis for Web channel charts 37128 if (chartModel.reducerXFunction && chartModel.reducerXFunction !== 'none' && !isWebChannelChart) { 37129 chartBuildOptions.categoryExp = chartModel.yExp; 37130 chartBuildOptions.valueExp = chartModel.xExp; 37131 chartBuildOptions.reducerFunction = chartModel.reducerXFunction; 37132 dataToFill = ChartUtils._setProp(dataToFill, "categoryDataType", chartModel.jsonModel.yDataType); 37133 dataToFill = ChartUtils._setProp(dataToFill, "valueDataType", chartModel.jsonModel.xDataType); 37134 } else { 37135 chartBuildOptions.categoryExp = chartModel.xExp; 37136 chartBuildOptions.valueExp = chartModel.yExp; 37137 dataToFill = ChartUtils._setProp(dataToFill, "categoryDataType", chartModel.jsonModel.yDataType); 37138 dataToFill = ChartUtils._setProp(dataToFill, "valueDataType", chartModel.jsonModel.xDataType); 37139 if (chartModel.reducerYFunction && chartModel.reducerYFunction !== 'none') { 37140 chartBuildOptions.reducerFunction = chartModel.reducerYFunction; 37141 } 37142 } 37143 37144 if (chartBuildOptions.isFDMDataSource) { 37145 dataToFill.valueDisplayFormat = ChartUtils.getDisplayFormat(dataToFill.valueDataType); 37146 dataToFill.labelDisplayFormat = ChartUtils.getDisplayFormat(dataToFill.categoryDataType); 37147 repeatableItem = chartModel.repeatableItem; 37148 chartBuildOptions.categoryExp = chartBuildOptions.categoryExp.substring(repeatableItem.length + 1, chartBuildOptions.categoryExp.length).split("/"); 37149 chartBuildOptions.valueExp = chartBuildOptions.valueExp.substring(repeatableItem.length + 1, chartBuildOptions.valueExp.length).split("/"); 37150 if (isWebChannelChart) { 37151 dataToFill.series = series = []; 37152 if (chartModel.jsonModel.chartType === 'quadrant') { 37153 chartBuildOptions.isXYReferencePointSet = false;
37154 if (chartModel.jsonModel.referencePointType === 'staticReferencePoint') { 37155 if (chartModel.jsonModel.xDataType === 'date' || chartModel.jsonModel.xDataType === 'date-time') { 37156 //Whenx-axis is of Date type we need to compute reference value in milliseconds. 37157 chartModel.jsonModel.xAxisReferencePoint = new Date(chartModel.jsonModel.xAxisReferencePoint).getTime(); 37158 } 37159 chartBuildOptions.isXYReferencePointSet = true; 37160 } 37161 } 37162 } 37163 if ("true" == chartModel.jsonModel.multiSeries) { 37164 seriesRepeatableItem = chartModel.jsonModel.seriesRepeatableItem; 37165 relativeSeriesNameExp = chartModel.jsonModel.seriesName.substring(seriesRepeatableItem.length + 1, chartModel.jsonModel.seriesName.length); 37166 seriesRepeatableInstances = this._getRepeatableInstances(seriesRepeatableItem, null, chartModel); 37167 seriesLength = seriesRepeatableInstances ? seriesRepeatableInstances.length : seriesLength; 37168 repeatablePath = repeatableItem.substring(seriesRepeatableItem.length, repeatableItem.length); 37169 if (chartModel.jsonModel.chartType === 'quadrant' && chartModel.jsonModel.referencePointType === 'fdmReferencePoint') { 37170 relativeSeriesRefExp = chartModel.jsonModel.seriesReferenceExp.substring(seriesRepeatableItem.length + 1, chartModel.jsonModel.seriesReferenceExp.length); 37171 } 37172 for (var i = 0; i < seriesLength; i++) { 37173 chartBuildOptions.repeatableInstances = this._getRepeatableInstances(repeatablePath, seriesRepeatableInstances[i], chartModel); 37174 chartBuildOptions.repeatableItemForReferencePoint; 37175 if (relativeSeriesRefExp && !chartBuildOptions.isXYReferencePointSet) { 37176 chartBuildOptions.repeatableItemForReferencePoint = undefined; 37177 if (this.matchUserInputWithFDM(chartModel.jsonModel.seriesReferenceDataType, seriesRepeatableInstances[i][relativeSeriesRefExp], chartModel.jsonModel.seriesReferenceValue)) { 37178 chartBuildOptions.repeatableItemForReferencePoint = repeatableItem; 37179 } 37180 } 37181 currentSeries = this.buildChartData(chartBuildOptions); 37182 currentSeries.name = seriesRepeatableInstances[i][relativeSeriesNameExp]; 37183 series.push(currentSeries); 37184 } 37185 } else { 37186 chartBuildOptions.repeatableInstances = this._getRepeatableInstances(repeatableItem, null, chartModel); 37187 chartBuildOptions.repeatableItemForReferencePoint = repeatableItem; 37188 currentSeries = this.buildChartData(chartBuildOptions); 37189 series.push(currentSeries); 37190 } 37191 if (isWebChannelChart && chartModel.jsonModel.chartType === 'quadrant' && chartModel.jsonModel.referencePointType === 'fdmReferencePoint' && !chartBuildOptions.isXYReferencePointSet) { 37192 chartModel.jsonModel.xAxisReferencePoint = undefined; 37193 chartModel.jsonModel.yAxisReferencePoint = undefined; 37194 } 37195 chartBuildOptions.repeatableInstances = null; 37196 } else if (repeatableItem) { 37197 chartBuildOptions.repeatableInstances = repeatableItem.instanceManager.instances; 37198 } 37199 if (chartBuildOptions.repeatableInstances) { 37200 var chartData = this.buildChartData(chartBuildOptions); 37201 dataToFill.label = chartData.label; 37202 dataToFill.value = chartData.value; 37203 } 37204 return dataToFill; 37205 }, 37206 37207 buildChartData : function (chartBuildOptions) { 37208 var dataToFill = {}, 37209 data = new Map(), 37210 referencePointExp, 37211 isFDMReferencePointSet = false;
37212 dataToFill.value = []; 37213 dataToFill.label = []; 37214 37215 if (chartBuildOptions.chartModel.jsonModel.chartType === 'quadrant' && chartBuildOptions.chartModel.jsonModel.referencePointType === 'fdmReferencePoint' && chartBuildOptions.repeatableItemForReferencePoint) { 37216 referencePointExp = chartBuildOptions.chartModel.jsonModel.xyReferencePointExp.substring(chartBuildOptions.repeatableItemForReferencePoint.length + 1, chartBuildOptions.chartModel.jsonModel.xyReferencePointExp.length).split("/"); 37217 } 37218 var that = this; 37219 _.each(chartBuildOptions.repeatableInstances, function (repeatableInstance, index) { 37220 var categoryPropVal, 37221 valuePropVal, 37222 xyReferenceVal; 37223 if (chartBuildOptions.isFDMDataSource) { 37224 if (_.isArray(chartBuildOptions.categoryExp) && _.isArray(chartBuildOptions.valueExp)) { 37225 //Handling composite key case. 37226 var temp = repeatableInstance; 37227 _.each(chartBuildOptions.categoryExp, function (obj) { 37228 temp = temp[obj]; 37229 }); 37230 categoryPropVal = temp; 37231 37232 temp = repeatableInstance; 37233 _.each(chartBuildOptions.valueExp, function (obj) { 37234 temp = temp[obj]; 37235 }); 37236 valuePropVal = temp; 37237 37238 if (chartBuildOptions.chartModel.jsonModel.chartType === 'quadrant' && !chartBuildOptions.isXYReferencePointSet) { 37239 if (chartBuildOptions.repeatableItemForReferencePoint && chartBuildOptions.chartModel.jsonModel.referencePointType === 'fdmReferencePoint') { 37240 temp = repeatableInstance; 37241 _.each(referencePointExp, function (obj) { 37242 temp = temp[obj]; 37243 }); 37244 xyReferenceVal = temp; 37245 if (that.matchUserInputWithFDM(chartBuildOptions.chartModel.jsonModel.xyReferencePointDataType, xyReferenceVal, chartBuildOptions.chartModel.jsonModel.xyReferencePointValue)) { 37246 //For date type x-axis FDM value we need to get time in milliseconds to send to Highcharts 37247 chartBuildOptions.chartModel.jsonModel.xAxisReferencePoint = (chartBuildOptions.chartModel.jsonModel.xDataType === 'date' || chartBuildOptions.chartModel.jsonModel.xDataType === 'date-time') ? new Date(categoryPropVal).getTime() : categoryPropVal; 37248 chartBuildOptions.chartModel.jsonModel.yAxisReferencePoint = valuePropVal; 37249 chartBuildOptions.isXYReferencePointSet = true; 37250 } 37251 } 37252 } 37253 } 37254 } else { 37255 categoryPropVal = repeatableInstance[chartBuildOptions.categoryExp].value; 37256 valuePropVal = repeatableInstance[chartBuildOptions.valueExp].value; 37257 } 37258 37259 categoryPropVal = _.isUndefined(categoryPropVal) ? '' : categoryPropVal; 37260 valuePropVal = _.isUndefined(valuePropVal) ? '' : valuePropVal; 37261 if (chartBuildOptions.reducerFunction) { 37262 if (!data.has(categoryPropVal)) { 37263 data.set(categoryPropVal, []); 37264 } 37265 data.get(categoryPropVal).push(valuePropVal); 37266 } else { 37267 dataToFill.label.push(categoryPropVal); 37268 dataToFill.value.push(valuePropVal); 37269 } 37270 }); 37271 37272 if (chartBuildOptions.reducerFunction) { 37273 var reducer = ChartUtils.reducerOptions[chartBuildOptions.reducerFunction] || window[chartBuildOptions.reducerFunction]; 37274 data.forEach(function (value, key) { 37275 dataToFill.label.push(key); 37276 dataToFill.value.push(reducer(data.get(key))); 37277 }); 37278 } 37279 return dataToFill; 37280 }, 37281 37282 matchUserInputWithFDM : function (fdmObjectDataType, fdmObjectValue, userInputValue) { 37283 return (((fdmObjectDataType == 'date-time' || fdmObjectDataType == 'date') && new Date(userInputValue).getTime() == new Date(fdmObjectValue).getTime()) 37284 || (fdmObjectDataType == 'boolean' && JSON.parse(userInputValue) == fdmObjectValue) 37285 || (userInputValue == fdmObjectValue)); 37286 }, 37287 37288 /** 37289 * Returns dv.chart object created from chart model. 37290 * @param chartModel 37291 * @param $chartElement 37292 * @returns {dv.chart} 37293 */ 37294 constructChart : function (chartModel, $chartElement) { 37295 var chartType = chartModel.chartType, 37296 showLegends = chartModel.showLegends, 37297 legendPosition = chartModel.legendPosition, 37298 tooltipHtml = chartModel.tooltipHtml, 37299 innerRadius = chartModel.innerRadius, 37300 lineColor = chartModel.lineColor, 37301 pointColor = chartModel.pointColor, 37302 areaColor = chartModel.areaColor, 37303 dataToFill = chartModel.data, 37304 chartBehavior = [], 37305 axisMap = {}, 37306 axisScale = {}, 37307 chartLayers, 37308 chart, 37309 categoryAxis, 37310 valueAxis; 37311 if (chartModel.reducerXFunction && chartModel.reducerXFunction !== 'none') { 37312 categoryAxis = 'y'; 37313 valueAxis = 'x'; 37314 } else { 37315 categoryAxis = 'x'; 37316 valueAxis = 'y'; 37317 } 37318 37319 if (dataToFill.labelDisplayFormat) { 37320 dataToFill.label = dataToFill.label.map(function (value) { 37321 return guidelib.util.GuideUtil.formatValue(value, 37322 dataToFill.labelDisplayFormat, 37323 dataToFill.categoryDataType); 37324 }); 37325 } 37326 37327 if (dataToFill.valueDisplayFormat) { 37328 dataToFill.value = dataToFill.value.map(function (value) { 37329 return guidelib.util.GuideUtil.formatValue(value, 37330 dataToFill.valueDisplayFormat, 37331 dataToFill.valueDataType); 37332 }); 37333 } 37334 37335 axisMap[categoryAxis] = 'label'; 37336 axisMap[valueAxis] = 'value'; 37337 axisScale[valueAxis] = dv.scale.linear().lowerLimit(0); 37338 37339 try { 37340 if (GuideUtil.isChartTooltipApplicable(chartType)) { 37341 if (tooltipHtml && tooltipHtml !== '') { 37342 var xValMap = axisMap['x'], 37343 yValMap = axisMap['y']; 37344 chartBehavior = [dv.behavior.rollover().content(function (d) { 37345 var tooltip = tooltipHtml.replace(/\${x}/g, d.data[xValMap]); 37346 tooltip = tooltip.replace(/\${y}/g, d.data[yValMap]); 37347 return tooltip; 37348 })]; 37349 } 37350 } 37351 axisScale[categoryAxis] = dv.scale.ordinal(); 37352 chart = dv.chart(); 37353 chart.map('fill', 'label') 37354 .map('x', axisMap['x'], axisScale['x']) 37355 .map('y', axisMap['y'], axisScale['y']); 37356 37357 var chartPoint = dv.geom.point().set('fill', pointColor).behaviors(chartBehavior), 37358 chartLine = dv.geom.line().set('fill', lineColor), 37359 chartArea = dv.geom.area().set('alpha', 0.1).set('fill', areaColor), 37360 flippedCaretesianCoord = dv.coord.cartesian().flip(true),
37361 lineCommon = function () { 37362 chart.set('stroke', lineColor); 37363 chartLayers = [dv.geom.line()]; 37364 }, 37365 barTypeCommon = function () { 37366 chartLayers = [dv.geom.bar().behaviors(chartBehavior)]; 37367 chart.map('x', 'label', axisScale[categoryAxis]) 37368 .map('y', 'value'); 37369 }, 37370 barCommon = function () { 37371 barTypeCommon(); 37372 if (categoryAxis === 'x') { 37373 chart.coord(flippedCaretesianCoord); 37374 } 37375 }, 37376 columnCommon = function () { 37377 barTypeCommon(); 37378 if (categoryAxis === 'y') { 37379 chart.coord(flippedCaretesianCoord); 37380 } 37381 }, 37382 pieCommon = function (radius) { 37383 columnCommon(); 37384 dataToFill[categoryAxis] = Array.apply(null, Array(dataToFill["label"].length)).map(function () { 37385 return 1; 37386 }); 37387 axisMap[categoryAxis] = categoryAxis; 37388 if (radius > 0) { 37389 axisScale[categoryAxis] = axisScale[categoryAxis].padding(.3); 37390 } 37391 37392 chart.map('x', axisMap[categoryAxis], axisScale[categoryAxis]); 37393 37394 chart.coord(dv.coord.polar().flip(true).innerRadius(radius)) 37395 .guide(['x', 'y'], 'none') 37396 .position('fill'); 37397 }; 37398 37399 switch (chartType) { 37400 case CHART_TYPE.LINE: 37401 lineCommon(); 37402 chartLayers.push(chartLine); 37403 break; 37404 case CHART_TYPE.POINT: 37405 lineCommon(); 37406 chartLayers.push(chartPoint); 37407 break; 37408 case CHART_TYPE.AREA: 37409 lineCommon(); 37410 chartLayers.push(chartLine); 37411 chartLayers.push(chartArea); 37412 break; 37413 case CHART_TYPE.LINE_POINT: 37414 lineCommon(); 37415 chartLayers.push(chartPoint); 37416 chartLayers.push(chartLine); 37417 break; 37418 case CHART_TYPE.BAR: 37419 barCommon(); 37420 break; 37421 case CHART_TYPE.COLUMN: 37422 columnCommon(); 37423 break; 37424 case CHART_TYPE.PIE: 37425 pieCommon(0); 37426 break; 37427 case CHART_TYPE.DONUT: 37428 pieCommon(innerRadius); 37429 break; 37430 } 37431 37432 chart.layers(chartLayers); 37433 chart.data(dataToFill) 37434 .width(chartModel.width + '%') 37435 .height(chartModel.height) 37436 .parent("#" + $chartElement.attr('id')) 37437 .padding({"left" : 10, "top" : 10, "right" : 10, "bottom" : 10}); 37438 37439 if (GuideUtil.isChartAxisTitleApplicable(chartType)) { 37440 chart.guide('x', dv.guide.axis().title(chartModel.xAxisTitle)) 37441 .guide('y', dv.guide.axis().title(chartModel.yAxisTitle)); 37442 } 37443 37444 if (GuideUtil.isChartLegendApplicable(chartType) && showLegends) { 37445 chart.guide('fill', dv.guide.legend().orientation(legendPosition)); 37446 } 37447 } catch (exception) { 37448 window.guideBridge._guide.logger().log("Error while constructing chart " + exception); 37449 } 37450 return chart; 37451 }, 37452 37453 _setProp : function (object, prop, value) { 37454 if (object.constructor == {}.constructor && !_.isEmpty(value)) { 37455 object[prop] = value; 37456 } 37457 return object; 37458 }, 37459 37460 /** 37461 * Retrieves Repeatable Instances using liveDataUtils API for the given 37462 * repeatablePath. This API internally handles naked/non-naked case. 37463 * 37464 * @param repeatablePath 37465 * @param data 37466 * @return Repeatable Instances for the given repeatablePath using liveDataUtils. 37467 * 37468 * TODO Move this API to data utils. 37469 */ 37470 _getRepeatableInstances : function (repeatablePath, data, chartModel) { 37471 var liveDataUtils = chartModel._guide().internal.liveDataUtils, 37472 liveData = data ? data : liveDataUtils._liveDataDoc, 37473 xpath = ""; 37474 37475 if (_.isEmpty(liveData) || _.isEmpty(repeatablePath)) { 37476 return; 37477 } 37478 37479 if (!_.isEmpty(liveData.afData)) {//Non-Naked data case 37480 liveData = liveData.afData; 37481 xpath = liveDataUtils.constants.BOUND_DATA_XPATH; 37482 } else {//Naked data case or multiple series case 37483 repeatablePath = repeatablePath.substring(1, repeatablePath.length); 37484 } 37485 37486 //Find the repeatable instances. 37487 repeatableInstances = liveDataUtils._getElement(liveData, xpath + repeatablePath); 37488 37489 return repeatableInstances; 37490 } 37491 }; 37492}($, guidelib, _)); 37493 37494//Poly-filling request animation frame function for IE 9 37495(function () { 37496 var lastFramePaintTime = 0; 37497 if (!window.requestAnimationFrame) { 37498 window.requestAnimationFrame = function (callback, element) { 37499 var currTime = new Date().getTime(), 37500 timeToCall = Math.max(0, 16 - (currTime - lastFramePaintTime)), //16-16 frames per second 37501 id = window.setTimeout(function () { 37502 callback(currTime + timeToCall); 37503 }, timeToCall); 37504 lastFramePaintTime = currTime + timeToCall; 37505 return id; 37506 }; 37507 } 37508 37509 if (!window.cancelAnimationFrame) { 37510 window.cancelAnimationFrame = function (id) { 37511 clearTimeout(id); 37512 }; 37513 } 37514}()); 37515 37516/* 37517 * *********************************************************************** 37518 * ADOBE CONFIDENTIAL 37519 * __________________ 37520 * 37521 * Copyright 2015 Adobe Systems Incorporated 37522 * All Rights Reserved. 37523 *
37524 * NOTICE: All information contained herein is, and remains 37525 * the property of Adobe Systems Incorporated and its suppliers, 37526 * if any. The intellectual and technical concepts contained 37527 * herein are proprietary to Adobe Systems Incorporated and its 37528 * suppliers and may be covered by U.S. and Foreign Patents, 37529 * patents in process, and are protected by trade secret or copyright law. 37530 * Dissemination of this information or reproduction of this material 37531 * is strictly forbidden unless prior written permission is obtained 37532 * from Adobe Systems Incorporated. 37533 * *********************************************************************** 37534 */ 37535 37536(function ($, guidelib, xfalib, _) { 37537 var errorHandler = function (jqXHR) { 37538 var errorPayload; 37539 37540 // Actually we need clean-up old data but its not even happening in case of success with empty data 37541 // Running output mapping with empty result set to ensure old data is cleared 37542 37543 if (jqXHR.responseText) { 37544 var inputMapping = this.inputMapping; 37545 try { 37546 errorPayload = JSON.parse(jqXHR.responseText); 37547 } catch (error) { 37548 // result should be json if its not wel formed json or empty then ignoring it 37549 } 37550 if(errorPayload && errorPayload.errors) { 37551 37552 // Iterating over violations received and set it at field level using input mapping provided. 37553 var violations = errorPayload.errors; 37554 $.each(violations, function (i, violation) { 37555 if(violation && violation.bindRef && violation.errorMessages) { 37556 var key = violation.bindRef.slice(1).split("/").join("."); 37557 var field = inputMapping[key]; 37558 if (field) { 37559 field.markAsInvalid(violation.errorMessages.join("\n")); 37560 } 37561 } 37562 }); 37563 } 37564 } 37565 // Invoke author register error handler (if any) 37566 if(this.customErrorHandler) { 37567 this.customErrorHandler.call(this, jqXHR, errorPayload); 37568 } 37569 }; 37570 37571 var defaultErrorHandler = function (responseJson, headerMap) { 37572 if (responseJson) { 37573 if (responseJson && responseJson.validationErrors) { 37574 var violations = responseJson.validationErrors; 37575 $.each(violations, function (key, violation) { 37576 if (violation && violation.details && (violation.fieldName || violation.dataRef)) { 37577 if (!window.guideBridge._guide._bindRefMap || Object.keys(window.guideBridge._guide._bindRefMap).length === 0) { 37578 window.guideBridge._populateBindRefToSomMap(); 37579 } 37580 var som = (violation.fieldName) ? violation.fieldName : window.guideBridge._guide._bindRefMap[violation.dataRef]; 37581 var field = window.guideBridge.resolveNode(som); 37582 if (field) { 37583 field.markAsInvalid(violation.details.join("\n")); 37584 } 37585 } 37586 }); 37587 } 37588 } 37589 }; 37590 37591 var defaultErrorHandlerWrapper = function(jqXHR) { 37592 if (jqXHR.responseText) { 37593 try { 37594 responseJson = JSON.parse(jqXHR.responseText); 37595 } catch (error) { 37596 // result should be json if its not well formed json or empty then ignoring it 37597 } 37598 } 37599 37600 var headers = jqXHR.getAllResponseHeaders(); 37601 37602 // Convert the header string into an array 37603 // of individual headers 37604 var arr = headers.trim().split(/[\r\n]+/); 37605 37606 // Create a map of header names to values 37607 var headerMap = {}; 37608 arr.forEach(function (line) { 37609 var parts = line.split(': '); 37610 var header = parts.shift(); 37611 var value = parts.join(': '); 37612 headerMap[header] = value; 37613 }); 37614 37615 if (this.customErrorHandler === "guidelib.dataIntegrationUtils.defaultErrorHandler") { 37616 defaultErrorHandler(responseJson, headerMap); 37617 } else { 37618 if(this.customErrorHandler) { 37619 this.customErrorHandler.call(this, responseJson, headerMap); 37620 } 37621 } 37622 } 37623 37624 // Counts the number of Array(repeatable) in the output JSON of the WSDL. 37625 var outputJsonRepeatCount = function (wsdlOutputId, outputJSONObj) { 37626 var count = 0, 37627 wsdlOutputHierarchy = wsdlOutputId.split("."); 37628 if (Array.isArray(outputJSONObj)) { 37629 count++; 37630 outputJSONObj = outputJSONObj[0]; 37631 } 37632 $.each(wsdlOutputHierarchy, function (depth) { 37633 if (outputJSONObj) { 37634 outputJSONObj = outputJSONObj[wsdlOutputHierarchy[depth]]; 37635 if (Array.isArray(outputJSONObj)) { 37636 count++; 37637 outputJSONObj = outputJSONObj[0]; 37638 } 37639 } 37640 }); 37641 return count; 37642 }; 37643 37644 //Traversing to the highest repeatable field in hierarchy as a starting point. 37645 var outputRepeatAncestor = function (targetNode, repeatCount, targetNameHierarchy) { 37646 while (repeatCount > 0) { 37647 if (_.isNull(targetNode.parent)) { 37648 return targetNode;
37649 } 37650 targetNameHierarchy.push(targetNode.name); 37651 targetNode = targetNode.parent; 37652 if (targetNode.repeatable) { 37653 repeatCount--; 37654 } 37655 } 37656 return targetNode; 37657 }; 37658 37659 /** 37660 * Extract value of a hierarchy of properties 37661 * from a nested javascript object. 37662 * @param {Object} obj Nested javascript object 37663 * @param {Array|String} props list of properties 37664 * or dot separated string from root to leaf object 37665 * @return {Array} return list of values found 37666 */ 37667 function extractValues(obj, props) { 37668 // handle easy cases 37669 if (obj === null || typeof(obj) === "undefined") { 37670 return []; 37671 } 37672 if (typeof(props) == "string") { 37673 props = props.split("."); 37674 } 37675 if (props.length == 0) { 37676 return [obj]; 37677 } 37678 var ret = []; 37679 if (obj instanceof Array) { 37680 for (var i = 0; i < obj.length; i++) { 37681 ret = ret.concat(extractValues(obj[i], props)); 37682 } 37683 return ret; 37684 } 37685 if (!obj.hasOwnProperty(props[0])) { 37686 return []; 37687 } 37688 // handle actual case now 37689 37690 var key = props[0]; 37691 var remainingKeys = props.slice(1); 37692 var values = obj[key]; 37693 if (!(values instanceof Array)) { 37694 values = [values]; 37695 } 37696 for (var x = 0; x < values.length; x++) { 37697 ret = ret.concat(extractValues(values[x], remainingKeys)); 37698 } 37699 return ret; 37700 } 37701 //Maps the output JSON(outputJSONObj) to the Model(targetNode) 37702 var outputJsonMapping = function (wsdlOutputId, targetNode, targetNameHierarchy, outputJSONObj) { 37703 if (targetNameHierarchy.length === 0) { 37704 targetNode.value = xfalib.ut.XfaUtil.prototype.getOrElse(outputJSONObj, wsdlOutputId, ""); 37705 return; 37706 } 37707 var targetName = targetNameHierarchy.pop(); 37708 if (targetNode.repeatable) { 37709 //Gets respective array for this repeatable field. 37710 while (typeof outputJSONObj === "object" && !Array.isArray(outputJSONObj)) { 37711 var argsIndex = wsdlOutputId.indexOf('.'); 37712 outputJSONObj = outputJSONObj[wsdlOutputId.substring(0, argsIndex)] || ""; 37713 wsdlOutputId = wsdlOutputId.substring(argsIndex + 1); 37714 } 37715 //Adjust the number of instances to the number of array elements. 37716 var jsonLength = outputJSONObj.length, 37717 instanceCount = targetNode.instanceManager.instanceCount; 37718 if (instanceCount < jsonLength) { 37719 targetNode.instanceManager.addInstances({ 37720 instanceCount : jsonLength 37721 }); 37722 } 37723 //Check as "" might occur too for incorrect mappings. 37724 if (Array.isArray(outputJSONObj)) { 37725 //Recursive call for every instance with corresponding value. 37726 $.each(outputJSONObj, function (index) { 37727 // if the output from external API call contains more records, than the number 37728 // of instances present, return 37729 if (index >= targetNode.instanceManager.instanceCount) { 37730 return false; 37731 } 37732 targetNode = targetNode.instanceManager.instances[index]; 37733 outputJsonMapping(wsdlOutputId, targetNode[targetName], targetNameHierarchy, outputJSONObj[index]); 37734 }); 37735 } 37736 } else { 37737 //Recursive call down the hierarchy. 37738 outputJsonMapping(wsdlOutputId, targetNode[targetName], targetNameHierarchy, outputJSONObj); 37739 } 37740 //Pushing back the hierarchy for next instance if any. 37741 targetNameHierarchy.push(targetName); 37742 }; 37743 37744 var populateWsdlOutput = function (wsdlOutput, textStatus, jqXHR) { 37745 if (wsdlOutput == null || wsdlOutput.length == 0) { 37746 return; 37747 } 37748 37749 var origOutputJSONObj, 37750 outputMappingObj = this.callbackData; 37751 try { 37752 origOutputJSONObj = JSON.parse(wsdlOutput); 37753 } catch (e) { 37754 //Handling primitive output 37755 origOutputJSONObj = {"response" : wsdlOutput}; 37756 } 37757 37758 /* For each entry in outputMappingObj, we need to find the corresponding value in responseObj. 37759 * wsdlOutputId - wsdlOutput hierarchy, targetNode - field in the form whose value is to be set. 37760 * e.g. {ipinfo.ip, txtfield} */ 37761 $.each(outputMappingObj, function (wsdlOutputId, targetNode) { 37762 /* Gets value in outputJSONObj corresponding to targetNode. 37763 * First, It counts the number of Array in hierarchy as repeatCount. 37764 * Next, targetNode is taken to the starting point for traversal. 37765 * It's the topmost repeatable node in hierarchy. 37766 * Lastly, The outputJson is mapped to the TargetNode.*/ 37767 var repeatCount = outputJsonRepeatCount(wsdlOutputId, origOutputJSONObj), 37768 targetNameHierarchy = [], 37769 targetNode = outputRepeatAncestor(targetNode, repeatCount, targetNameHierarchy); 37770 outputJsonMapping(wsdlOutputId, targetNode, targetNameHierarchy, origOutputJSONObj); 37771 }); 37772 window.guideBridge._guide.runPendingExpressions(); 37773 }; 37774 37775 /** 37776 * Create and set items to dropdown field from wsdl response. 37777 * @this {Object} is of form {callbackData:data} 37778 */ 37779 function setOptionsCallback(wsdlOutput) { 37780 var cbData = this.callbackData; 37781 var options = []; 37782 if (!_.isEmpty(wsdlOutput)) { 37783 var wsdlOutputObj = JSON.parse(wsdlOutput); 37784 var savedValues = extractValues(wsdlOutputObj, cbData.savedValue); 37785 var displayedValues = extractValues(wsdlOutputObj, cbData.displayedValue); 37786 for (var i = 0; i < savedValues.length; i++) {
37787 options.push(savedValues[i] + "=" + displayedValues[i]); 37788 } 37789 } 37790 cbData.field.items = options; 37791 } 37792 37793 function setValueCallback(wsdlOutput) { 37794 var cbData = this.callbackData; 37795 var wsdlOutputObj = JSON.parse(wsdlOutput); 37796 cbData.field.value = extractValues(wsdlOutputObj, cbData.value); 37797 } 37798 37799 function appendLoadingIcon() { 37800 $("#loadingPage").addClass("guideServiceLoading"); 37801 } 37802 37803 function removeLoadingIcon() { 37804 $("#loadingPage").removeClass("guideServiceLoading"); 37805 } 37806 37807 function executeOperationInternal (wsdlInfoObj, jsonInputMappingObj, jsonOutputMappingObj, processOutputCallback, customErrorHandler, model, defaultErrorHandler, apiVersion) { 37808 // populate operationDetails object 37809 var successHandler = processOutputCallback || populateWsdlOutput; 37810 var wsdlInputObj = {}; 37811 37812 /* Iterate through the jsonInputMapping and create the input object. 37813 * wsdlInputId - wsdlInput hierarchy, targetNode - field in the form whose value is to be retrieved.*/ 37814 $.each(jsonInputMappingObj, function (wsdlInputId, targetNode) { 37815 var argsHierarchy = wsdlInputId.split("."), 37816 wsdlArgObj = wsdlInputObj, 37817 argDepth, 37818 valueToBeAssigned; 37819 37820 for (argDepth = 0; argDepth < argsHierarchy.length - 1; argDepth++) { 37821 wsdlArgObj[argsHierarchy[argDepth]] = wsdlArgObj[argsHierarchy[argDepth]] || {}; 37822 wsdlArgObj = wsdlArgObj[argsHierarchy[argDepth]]; 37823 } 37824 // assign the value of targetNode 37825 if (typeof targetNode === "object") { 37826 valueToBeAssigned = targetNode.value; 37827 } else { 37828 valueToBeAssigned = targetNode; 37829 } 37830 wsdlArgObj[argsHierarchy[argDepth]] = valueToBeAssigned; 37831 }); 37832 37833 var wsdlEndPoint = wsdlInfoObj.wsdlEndPoint, 37834 operationDetails = {}; 37835 operationDetails.operationName = wsdlInfoObj.operationName; 37836 operationDetails.input = JSON.stringify(wsdlInputObj); 37837 operationDetails.port = wsdlInfoObj.port; 37838 operationDetails.soapActionURI = wsdlInfoObj.soapActionURI; 37839 operationDetails.namespace = wsdlInfoObj.namespace; 37840 operationDetails.inputRoot = wsdlInfoObj.inputRoot; 37841 operationDetails.inputAttr = JSON.stringify(wsdlInfoObj.inputAttr); 37842 operationDetails.serviceEndPoint = wsdlInfoObj.serviceEndPoint; 37843 if (!model) { 37844 console.log("No model parameter passed to this API, this may fail during server side re-validation. Please correct your scripts."); 37845 } 37846 // TODO: this needs to be fixed, this API does not have access to guideContext but would execute in context of AF always 37847 var guide = model && model._guide && model._guide(); 37848 var wsdlServletURL = ((guide ? guide.jcrPath : guidelib.__runtime__.guide.jcrPath) + ".af.dermis"); 37849 var externalizedWSDLServletURL; 37850 if (guideBridge != null) { 37851 externalizedWSDLServletURL = guideBridge._getUrl(wsdlServletURL); 37852 } else { 37853 externalizedWSDLServletURL = Granite.HTTP.externalize(wsdlServletURL); 37854 } 37855 37856 var invokeData = {}; 37857 if (wsdlInfoObj.wsdlEndPoint) { 37858 invokeData.functionToExecute = 'invokeWsdlOperation'; 37859 invokeData.wsdlEndPoint = wsdlEndPoint; 37860 invokeData.operationName = operationDetails.operationName; 37861 invokeData.input = operationDetails.input; 37862 37863 if (operationDetails.port) { 37864 invokeData.port = operationDetails.port; 37865 } 37866 if (operationDetails.soapActionURI) { 37867 invokeData.soapActionURI = operationDetails.soapActionURI; 37868 } 37869 if (operationDetails.namespace) { 37870 invokeData.namespace = operationDetails.namespace; 37871 } 37872 if (operationDetails.inputRoot) { 37873 invokeData.inputRoot = operationDetails.inputRoot; 37874 } 37875 if (operationDetails.inputAttr) {
37876 invokeData.inputAttr = operationDetails.inputAttr; 37877 } 37878 if (operationDetails.serviceEndPoint) { 37879 invokeData.serviceEndPoint = operationDetails.serviceEndPoint; 37880 } 37881 } else if (wsdlInfoObj.formDataModelId) { 37882 invokeData.functionToExecute = 'invokeFDMOperation'; 37883 invokeData.formDataModelId = wsdlInfoObj.formDataModelId; 37884 invokeData.input = JSON.stringify(wsdlInputObj); 37885 invokeData.operationName = wsdlInfoObj.operationName; 37886 invokeData.runValidation = wsdlInfoObj.runValidation; 37887 invokeData.apiVersion = apiVersion; 37888 if (wsdlInfoObj.schemaRef) { 37889 invokeData.schemaRef = wsdlInfoObj.schemaRef; 37890 } 37891 if (wsdlInfoObj.schemaType) { 37892 invokeData.schemaType = wsdlInfoObj.schemaType; 37893 } 37894 } 37895 invokeData.guideNodePath = guide ? guide._currentContext.contextNode.jcrPath : guidelib.__runtime__.guide._currentContext.contextNode.jcrPath; 37896 37897 $.ajax({ 37898 type : 'POST', 37899 url : externalizedWSDLServletURL, 37900 data : invokeData, 37901 beforeSend : appendLoadingIcon, 37902 complete : removeLoadingIcon, 37903 dataType : 'text', 37904 success : successHandler, 37905 error : defaultErrorHandler, 37906 context : {callbackData : jsonOutputMappingObj, inputMapping: jsonInputMappingObj, customErrorHandler: customErrorHandler} 37907 }); 37908 } 37909 37910 var DataIntegrationUtils = guidelib.dataIntegrationUtils = { 37911 37912 setOptionsFromService : function (wsdlInfoObj, jsonInputMapping, jsonOutputMapping) { 37913 this.executeOperation(wsdlInfoObj, jsonInputMapping, jsonOutputMapping, setOptionsCallback); 37914 return jsonOutputMapping.field.items; 37915 }, 37916 37917 setValueFromService : function (wsdlInfoObj, jsonInputMapping, jsonOutputMapping) { 37918 this.executeOperation(wsdlInfoObj, jsonInputMapping, jsonOutputMapping, setValueCallback); 37919 return jsonOutputMapping.field.items; 37920 }, 37921 37922 /** 37923 * @deprecated 37924 */ 37925 executeOperation : function (wsdlInfoObj, jsonInputMappingObj, jsonOutputMappingObj, processOutputCallback, customErrorHandler, model) { 37926 var defaultErrorHandler = errorHandler; 37927 executeOperationInternal(wsdlInfoObj, jsonInputMappingObj, jsonOutputMappingObj, processOutputCallback, customErrorHandler, model, defaultErrorHandler); 37928 }, 37929 37930 executeOperationV2 : function (wsdlInfoObj, jsonInputMappingObj, jsonOutputMappingObj, processOutputCallback, customErrorHandler, model) { 37931 var defaultErrorHandler = defaultErrorHandlerWrapper; 37932 var apiVersion = "2"; 37933 executeOperationInternal(wsdlInfoObj, jsonInputMappingObj, jsonOutputMappingObj, processOutputCallback, customErrorHandler, model, defaultErrorHandler, apiVersion); 37934 }, 37935 37936 defaultErrorHandler : defaultErrorHandler 37937 }; 37938 37939 var WsdlUtils = guidelib.wsdlUtils = { 37940 /** 37941 * Internal API, called for invoking webservice and setting items in a drop down 37942 */ 37943 setOptionsFromWSDL : function (wsdlInfoObj, jsonInputMapping, jsonOutputMapping) { 37944 DataIntegrationUtils.executeOperation(wsdlInfoObj, jsonInputMapping, jsonOutputMapping, setOptionsCallback); 37945 return jsonOutputMapping.field.items; 37946 }, 37947 37948 setValueFromWSDL : function (wsdlInfoObj, jsonInputMapping, jsonOutputMapping) { 37949 DataIntegrationUtils.executeOperation(wsdlInfoObj, jsonInputMapping, jsonOutputMapping, setValueCallback); 37950 return jsonOutputMapping.field.items; 37951 }, 37952 37953 executeWSDLFunction : function (wsdlInfoObj, jsonInputMappingObj, jsonOutputMappingObj) { 37954 // populate operationDetails object 37955 DataIntegrationUtils.executeOperation(wsdlInfoObj, jsonInputMappingObj, jsonOutputMappingObj); 37956 } 37957 }; 37958}($, guidelib, xfalib, _)); 37959 37960/* 37961 * *********************************************************************** 37962 * ADOBE CONFIDENTIAL 37963 * __________________ 37964 * 37965 * Copyright 2015 Adobe Systems Incorporated 37966 * All Rights Reserved. 37967 *
37968 * NOTICE: All information contained herein is, and remains 37969 * the property of Adobe Systems Incorporated and its suppliers, 37970 * if any. The intellectual and technical concepts contained 37971 * herein are proprietary to Adobe Systems Incorporated and its 37972 * suppliers and may be covered by U.S. and Foreign Patents, 37973 * patents in process, and are protected by trade secret or copyright law. 37974 * Dissemination of this information or reproduction of this material 37975 * is strictly forbidden unless prior written permission is obtained 37976 * from Adobe Systems Incorporated. 37977 * *********************************************************************** 37978 */ 37979 37980/** 37981 * @package guidelib.model.GuideDirtyMarkerAndVisitor 37982 * @version 0.0.1 37983 */ 37984 37985(function ($, _, guidelib) { 37986 var GuideDirtyMarkerAndVisitor = guidelib.model.GuideDirtyMarkerAndVisitor = xfalib.ut.EventClass.extend({ 37987 37988 initialize : function() { 37989 // need to save the map while save and restore - will do it in getGuideState 37990 this.visitMap = {}; 37991 }, 37992 /** 37993 * Return a list of dirty children 37994 * @returns {Array} 37995 * @private 37996 */ 37997 _flattenDirtyPanelToList : function () { 37998 var csv = this.flattenDirtyPanelMapToCSV(); 37999 if (csv.length > 0) { 38000 return csv.split(","); 38001 } 38002 }, 38003 /** 38004 * If any dirty element then save it to CSV 38005 */ 38006 flattenDirtyPanelMapToCSV : function () { 38007 var listOfDirtyPanels = ""; 38008 _.each(_.keys(this.visitMap), function (key, index) { 38009 if (this.visitMap[key] === 0) { 38010 listOfDirtyPanels += key + ","; 38011 } 38012 }, this); 38013 if (listOfDirtyPanels.length > 0) { 38014 // strip last , 38015 listOfDirtyPanels = listOfDirtyPanels.substring(0, listOfDirtyPanels.length - 1); 38016 } 38017 return listOfDirtyPanels; 38018 }, 38019 /** 38020 * This method finds and marks dirty all the lazy children that were dependant of global field's value 38021 * @param mapOfLazyChildren 38022 * @param listOfIdsOfDependents 38023 * @private 38024 */ 38025 _findAndMarkDirty : function (mapOfLazyChildren, listOfIdsOfDependents) { 38026 var listOfLazyChildren = _.keys(mapOfLazyChildren); 38027 38028 _.each(listOfIdsOfDependents, function (depenId, index) { 38029 var longestPrefixLenSoFar = 0, 38030 currentPrefixLen = 0, 38031 nearestLazyId = null, 38032 i; 38033 // find hierarchically closest field by matching longest som prefix 38034 for (i = 0; i < listOfLazyChildren.length; ++i) { 38035 currentPrefixLen = guidelib.util.GuideUtil.commonPrefixLen(depenId, listOfLazyChildren[i]); 38036 if (longestPrefixLenSoFar < currentPrefixLen) { 38037 longestPrefixLenSoFar = currentPrefixLen; 38038 nearestLazyId = listOfLazyChildren[i]; 38039 } 38040 } 38041 // Mark dirty 38042 if (longestPrefixLenSoFar > 0) { 38043 mapOfLazyChildren[nearestLazyId] = 0; 38044 } 38045 }); 38046 }, 38047 /** 38048 * Iterates a map and finds the first occurrence of value found in any key 38049 * @param map 38050 * @param value 38051 */ 38052 _iterateMapAndReturnKeyOnValueFound : function (map, value) { 38053 var keyToReturn; 38054 _.each(_.keys(map), function (key, index) { 38055 if (map[key] === value) { 38056 keyToReturn = key; 38057 } 38058 }); 38059 return keyToReturn; 38060 }, 38061 /** 38062 * Updates the value of the key in map by one if present otherwise puts the key with value zero 38063 * @param map 38064 * @param key 38065 * @returns {*} 38066 */ 38067 _updateCountOrInsert : function (map, key) { 38068 if (_.isUndefined(map[key])) { 38069 map[key] = 0; 38070 } else { 38071 map[key]++; 38072 } 38073 38074 return map; 38075 } 38076 }); 38077 38078}($, _, window.guidelib)); 38079 38080/* 38081 * *********************************************************************** 38082 * ADOBE CONFIDENTIAL 38083 * __________________ 38084 * 38085 * Copyright 2016 Adobe Systems Incorporated 38086 * All Rights Reserved. 38087 *
38088 * NOTICE: All information contained herein is, and remains 38089 * the property of Adobe Systems Incorporated and its suppliers, 38090 * if any. The intellectual and technical concepts contained 38091 * herein are proprietary to Adobe Systems Incorporated and its 38092 * suppliers and may be covered by U.S. and Foreign Patents, 38093 * patents in process, and are protected by trade secret or copyright law. 38094 * Dissemination of this information or reproduction of this material 38095 * is strictly forbidden unless prior written permission is obtained 38096 * from Adobe Systems Incorporated. 38097 * *********************************************************************** 38098 */ 38099 38100(function ($) { 38101 //Firing resize as, CSS is loaded after table mobile layout, cell width is adjusted for repeatable row, to accommodate +, - controls 38102 $(function () { 38103 $(window).trigger('resize'); 38104 }); 38105}($));
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.