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 if (options["maxWidth"] > measuredWidth || (measuredWidth > options["minWidth"] > 0 && (options["maxWidth"] || -1) < 0)) { 4881 //complicated, please simplify if below hurts you: Add error margin if there is scope of further extension of extent 4882 measuredWidth = measuredWidth; 4883 } 4884 4885 if(measuredHeight == Math.ceil(options["height"]) || measuredHeight == Math.floor(options["height"])){ 4886 measuredHeight = options["height"]; 4887 } 4888 else if( $refEl.is("textarea") && (options["maxHeight"] > measuredHeight || (measuredHeight > options["minHeight"] > 0 && (options["maxHeight"] || -1) < 0))){ 4889 measuredHeight = measuredHeight +1; 4890 } 4891 this.$measureEl.empty(); 4892 return {width : measuredWidth, height : measuredHeight}; 4893 }, 4894 4895 _elWidth : function(refEl, options){ 4896 if(options["minWidth"] && options["minWidth"] > -1) 4897 return "auto"; 4898 else if(options["maxWidth"] && options["maxWidth"] > -1) 4899 return "auto"; 4900 else 4901 return options["width"] || "auto"; 4902 }, 4903 4904 _elHeight : function(refEl, options){ 4905 // TODO: check for calculations here for floating field and other cases. 4906 if(options["contentType"] === "text/html") 4907 return "auto"; 4908 if(options.isDraw) { // for handling the case of draw having floating fields 4909 return "auto"; 4910 } 4911 if(!$(refEl).is("textarea")) 4912 return options["height"] || "auto"; 4913 if(options["minHeight"] && options["minHeight"] > -1) 4914 return "auto"; 4915 else if(options["maxHeight"] && options["maxHeight"] > -1) 4916 return "auto"; 4917 else 4918 return options["height"] || "auto"; 4919 }, 4920 4921 _elMinWidth : function(refEl, options){ 4922 if(options["minWidth"] && options["minWidth"] > -1) 4923 return options["minWidth"]; 4924 else 4925 return "0"; //default css value 4926 }, 4927 4928 _elMinHeight : function(refEl, options){ 4929 if(options["minHeight"] && options["minHeight"] > -1) 4930 return options["minHeight"]; 4931 else 4932 return "0"; //default css value 4933 }, 4934 4935 _elMaxWidth : function(refEl, options){ 4936 if(options["maxWidth"] && options["maxWidth"] > -1) 4937 return options["maxWidth"]; 4938 else 4939 return "none"; //default css value 4940 }, 4941 4942 _elMaxHeight : function(refEl, options){ 4943 if(options["maxHeight"] && options["maxHeight"] > -1) 4944 return options["maxHeight"]; 4945 else 4946 return "none"; //default css value 4947 }, 4948 4949 _destroy : function() { 4950 $("#textMetrics").remove(); 4951 this.$measureEl = null; 4952 } 4953 } 4954})(_, $, xfalib); 4955(function($, _) { 4956 4957 $.alertBox = { 4958 4959 verticalOffset: -75, 4960 horizontalOffset: 0, 4961 repositionOnResize: true, 4962 overlayOpacity: 0.01,
4963 overlayColor: '#FFF', 4964 draggable: false, 4965 dialogClass: null, 4966 imageDirectory: "..", 4967 images: ["A_Warning_Lg_N.png", "A_Alert2_Lg_N.png", "C_QuestionBubble_Xl_N.png", "A_InfoBlue_32x32_N.png"], 4968 4969 alert: function(img, message, title, callback) { 4970 this._show(img, title, message, null, 'OK', function(result) { 4971 if( callback ) callback(result); 4972 }); 4973 }, 4974 4975 okCancel: function(img, message, title, callback) { 4976 this._show(img, title, message, null, 'OK-Cancel', function(result) { 4977 if( callback ) callback(result); 4978 }); 4979 }, 4980 yesNo: function(img, message, title, callback) { 4981 this._show(img, title, message, null, 'Yes-No', function(result) { 4982 if( callback ) callback(result); 4983 }); 4984 }, 4985 4986 yesNoCancel: function(img, message, title, callback) { 4987 this._show(img, title, message, null, 'Yes-No-Cancel', function(result) { 4988 if( callback ) callback(result); 4989 }); 4990 }, 4991 4992 _createBox: function(msgBox_message,buttons,callback) { 4993 var that = this; 4994 $("#"+msgBox_message).after("<div id='msgBox_panel'></div>"); 4995 _.each(buttons.split("-"),function(val,i) { 4996 var dispval = (xfalib.locale.Strings && xfalib.locale.Strings[val.toLowerCase()]) ? xfalib.locale.Strings[val.toLowerCase()] : val; 4997 var idSuffix = val; 4998 var $button = $("<input>", { 4999 type: "button", 5000 value: dispval, 5001 id: "msgBox_" + idSuffix, 5002 "class": "msgbox_input" 5003 }); 5004 $("#msgBox_panel").append($button); 5005 $button.click(function() { 5006 that._hide(); 5007 callback(!i); 5008 }); 5009 }); 5010 }, 5011 5012 _show: function(img, title, msg, value, type, callback) { 5013 5014 this._hide(); 5015 // Remember where focus was so we can restore it when the dialog closes 5016 this._previousFocus = document.activeElement; 5017 this._overlay('show'); 5018 5019 $("BODY").append( 5020 '<div id="msgBox_container" role="dialog" aria-modal="true" aria-labelledby="msgBox_title" aria-describedby="msgBox_message">' + 5021 '<h1 id="msgBox_title"></h1>' + 5022 '<div id="msgBox_content">' + 5023 '<div id="msgBox_message"></div>' + 5024 '</div>' + 5025 '</div>'); 5026 5027 if( this.dialogClass ) $("#msgBox_container").addClass($.alertBox.dialogClass); 5028 5029 $("#msgBox_container").css({ 5030 position: 'absolute', 5031 zIndex: 99999, 5032 padding: 0, 5033 margin: 0 5034 }); 5035 5036 $("#msgBox_title").text(title); 5037 $("#msgBox_content").addClass("msgBoxType"+img); 5038 msg = xfalib.ut.XfaUtil.prototype.encodeScriptableTags(msg.replace(/\n/g, '<br />')); 5039 $("#msgBox_message").html(msg); 5040 5041 $("#msgBox_container").css({ 5042 minWidth: $("#msgBox_container").outerWidth(), 5043 maxWidth: $("#msgBox_container").outerWidth() 5044 }); 5045 5046 this._reposition(); 5047 this._maintainPosition(true); 5048 5049 this._createBox("msgBox_message",type,callback); 5050 5051 // Keyboard: Escape dismisses (last button = No/Cancel), Tab/Shift+Tab traps focus within dialog 5052 $("#msgBox_container").on("keydown", function(e) { 5053 var $buttons = $("#msgBox_panel input"); 5054 var $focused = $(document.activeElement); 5055 if (e.keyCode === 27) { 5056 e.preventDefault(); 5057 $buttons.last().trigger("click"); 5058 } else if (e.keyCode === 9) { 5059 e.preventDefault(); 5060 var idx = $buttons.index($focused); 5061 if (e.shiftKey) { 5062 idx = (idx <= 0) ? $buttons.length - 1 : idx - 1; 5063 } else { 5064 idx = (idx >= $buttons.length - 1) ? 0 : idx + 1; 5065 } 5066 $buttons.eq(idx).focus(); 5067 } 5068 }); 5069 5070 // Defer focus so the browser paints the dialog before screen readers announce it 5071 setTimeout(function() { 5072 $("#msgBox_panel input:first").focus(); 5073 }, 0); 5074 5075 }, 5076 5077 _hide: function() { 5078 $("#msgBox_container").remove(); 5079 this._overlay('hide'); 5080 this._maintainPosition(false); 5081 // Restore focus to the element that was focused before the dialog opened 5082 if (this._previousFocus && this._previousFocus.focus) { 5083 this._previousFocus.focus(); 5084 this._previousFocus = null; 5085 } 5086 }, 5087 5088 _overlay: function(status) { 5089 switch( status ) { 5090 case 'show': 5091 this._overlay('hide'); 5092 $("BODY").append('<div id="msgBox_overlay"></div>'); 5093 $("#msgBox_overlay").css({ 5094 position: 'absolute', 5095 zIndex: 99998, 5096 top: '0px', 5097 left: '0px', 5098 width: '100%', 5099 height: $(document).height(), 5100 background: this.overlayColor, 5101 opacity: this.overlayOpacity 5102 }); 5103 break; 5104 case 'hide': 5105 $("#msgBox_overlay").remove(); 5106 break; 5107 } 5108 }, 5109 5110 _reposition: function() { 5111 var windowHeight = $(window).height() / xfalib.ut.XfaUtil.prototype.formScaleFactor, 5112 windowWidth = $(window).width() / xfalib.ut.XfaUtil.prototype.formScaleFactor, 5113 windowScrollTop = $(window).scrollTop() / xfalib.ut.XfaUtil.prototype.formScaleFactor, 5114 windowScrollLeft = $(window).scrollLeft() / xfalib.ut.XfaUtil.prototype.formScaleFactor, 5115 top = ((windowHeight / 2) - ($("#msgBox_container").outerHeight() / 2)) + this.verticalOffset, 5116 left = ((windowWidth / 2) - ($("#msgBox_container").outerWidth() / 2)) + this.horizontalOffset; 5117 if( top < 0 ) top = 0; 5118 if( left < 0 ) left = 0; 5119 5120 // IE6 fix 5121 if( $.browser.msie && parseInt($.browser.version) <= 6 ) top = top + windowScrollTop; 5122 5123 $("#msgBox_container").css({ 5124 top: top + windowScrollTop + 'px', 5125 left: left + windowScrollLeft + 'px' 5126 }); 5127 $("#msgBox_overlay").height( $(document).height() ); 5128 }, 5129 5130 _maintainPosition: function(status) { 5131 if( this.repositionOnResize ) { 5132 switch(status) { 5133 case true: 5134 $(window).on('resize', this._reposition); 5135 break; 5136 case false: 5137 $(window).off('resize', this._reposition); 5138 break; 5139 } 5140 } 5141 } 5142 5143 }; 5144})($, window._);/************************************************************************* 5145 * ADOBE CONFIDENTIAL 5146 * ___________________ 5147 * 5148 * Copyright 2016 Adobe Systems Incorporated 5149 * All Rights Reserved. 5150 *
5151 * NOTICE: All information contained herein is, and remains 5152 * the property of Adobe Systems Incorporated and its suppliers, 5153 * if any. The intellectual and technical concepts contained 5154 * herein are proprietary to Adobe Systems Incorporated and its 5155 * suppliers and are protected by all applicable intellectual property 5156 * laws, including trade secret and copyright laws. 5157 * Dissemination of this information or reproduction of this material 5158 * is strictly forbidden unless prior written permission is obtained 5159 * from Adobe Systems Incorporated. 5160 **************************************************************************/ 5161 5162 5163(function(_, $, xfalib){ 5164 xfalib.view.util.HtmlUtil = { 5165 /* 5166 * Most of the time it returns undefined while accessing an undefined attribute of a dom element. 5167 * But some browsers can throw specific exceptions while accessing an attribute which is un-supported for a specific case. 5168 * This API is to make this behaviour consistent across browsers and return undefined for un-supported attributes. 5169 * */ 5170 getHTMLSupportedAttr : function($domElement, attr){ 5171 try{ 5172 return $domElement[attr]; 5173 } 5174 catch (err){ 5175 return undefined; 5176 } 5177 }, 5178 5179 /** 5180 * Checks if the attribute is supported for the given HTML element. 5181 * This is primarily useful to support HTML5 features in widgets 5182 * @param element name of HTML element 5183 * @param attribute attribute to check on the element 5184 * @returns {boolean} 5185 */ 5186 elementSupportsAttribute : function (element, attribute) { 5187 var test = document.createElement(element); 5188 if (attribute in test) { 5189 $(test).remove(); 5190 test = null; 5191 return true; 5192 } else { 5193 $(test).remove(); 5194 test = null; 5195 return false; 5196 } 5197 } 5198 } 5199})(_, $, xfalib); 5200/************************************************************************* 5201* 5202* ADOBE CONFIDENTIAL 5203* ___________________ 5204* 5205* Copyright 2013 Adobe Systems Incorporated 5206* All Rights Reserved. 5207*
5208* NOTICE: All information contained herein is, and remains 5209* the property of Adobe Systems Incorporated and its suppliers, 5210* if any. The intellectual and technical concepts contained 5211* herein are proprietary to Adobe Systems Incorporated and its 5212* suppliers and are protected by trade secret or copyright law. 5213* Dissemination of this information or reproduction of this material 5214* is strictly forbidden unless prior written permission is obtained 5215* from Adobe Systems Incorporated. 5216**************************************************************************/ 5217 5218 5219 5220(function(_, $, xfalib){ 5221 xfalib.view.util.Styles = { 5222 xfaUtil : xfalib.ut.XfaUtil.prototype, 5223 _deviceResolution : 144.0, //DPI 5224 _in2mmFactor : 25.4, 5225 _pdfResolution : 72.0 , 5226 getStyleForEdge : function (edgeElement, str, cssStyleObj){ 5227 var style = { "raised" : "outset" , 5228 "dashDot" : "dashed" , 5229 "dashDotDot" : "dashed" , 5230 "dashed" : "dashed" , 5231 "dotted" : "dotted" , 5232 "embossed" : "groove" , 5233 "etched" : "inset" , 5234 "lowered" : "ridge", 5235 "solid" : "solid"}; 5236 if(edgeElement && edgeElement.jsonModel.presence != "hidden" && edgeElement.jsonModel.presence !="invisible") { 5237 cssStyleObj['border'+str+'width'] = this._subPixelValue(this._convertToPx(edgeElement.getAttribute('thickness'))) || "1px"; 5238 if(edgeElement.getElement("color") && edgeElement.getElement("color").getAttribute("value") !="") { 5239 var color = edgeElement.getElement("color").getAttribute("value"); 5240 color = "rgb(" + color + ")"; 5241 cssStyleObj['border'+str+'color'] = color ; 5242 } 5243 else { 5244 cssStyleObj['border'+str+'color'] = "rgb(0,0,0)" ; 5245 } 5246 cssStyleObj['border'+str+'style'] = style[edgeElement.getAttribute('stroke')] || "solid" ; 5247 } else { 5248 cssStyleObj['border'+str+'width'] = "0px"; 5249 return 1; 5250 } 5251 5252 }, 5253 5254 getStyleForBorder : function (border) { 5255 if(border) { 5256 var edge = border.getElement('edge', 0, true), 5257 edge1 = border.getElement('edge', 1, true), 5258 edge2 = border.getElement('edge', 2, true), 5259 edge3 = border.getElement('edge', 3, true); 5260 if(edge || edge1 || edge2 || edge3) { 5261 var cssStyleObj = {} ; 5262 var e0 = this.getStyleForEdge(edge, "-top-",cssStyleObj); 5263 var e1 = this.getStyleForEdge(edge1 || edge,"-right-",cssStyleObj); 5264 var e2 = this.getStyleForEdge(edge2|| edge,"-bottom-",cssStyleObj); 5265 var e3 = this.getStyleForEdge(edge3 || edge,"-left-",cssStyleObj); 5266 if(e0 !=1|| e1 !=1|| e2 !=1|| e3!=1) 5267 return cssStyleObj ; 5268 } 5269 } 5270 return null; 5271 }, 5272 5273 _convertToPx : function(size){ 5274 if(!size) 5275 return 0; 5276 size = "" + size; 5277 var pxSize = size; 5278 if(size.indexOf("in") >=0){ 5279 pxSize = this._mm2px(parseFloat(size) * this._in2mmFactor); 5280 } 5281 else if(size.indexOf("mm") >=0){ 5282 pxSize = this._mm2px(size); 5283 } 5284 else if(size.indexOf("cm") >=0){ 5285 pxSize = this._mm2px(parseFloat(size) * 10); 5286 } 5287 else if(size.indexOf("pt") >=0){ 5288 pxSize = parseFloat(size) * (this._deviceResolution/this._pdfResolution); 5289 } 5290 else if(size.indexOf("px") >=0){ 5291 pxSize = parseFloat(size); 5292 } 5293 return pxSize; 5294 }, 5295 5296 _mm2px : function(mmSize){ 5297 var mmSizeNum = 0; 5298 if(_.isNumber(mmSize)) 5299 mmSizeNum = mmSize; 5300 else{ 5301 mmSizeNum = parseFloat(mmSize) 5302 } 5303 var mm2in = 1/25.4 ; 5304 var pxSize = mmSizeNum*mm2in*this._deviceResolution; 5305 return pxSize; 5306 }, 5307 5308 _subPixelValue : function(value){ 5309 if(value > 0.01) 5310 return Math.max(value, 1.0); 5311 else 5312 return value; 5313 } 5314 } 5315})(_, $, xfalib); 5316/************************************************************************* 5317 * ADOBE CONFIDENTIAL 5318 * ___________________ 5319 * 5320 * Copyright 2017 Adobe Systems Incorporated 5321 * All Rights Reserved. 5322 *
5323 * NOTICE: All information contained herein is, and remains 5324 * the property of Adobe Systems Incorporated and its suppliers, 5325 * if any. The intellectual and technical concepts contained 5326 * herein are proprietary to Adobe Systems Incorporated and its 5327 * suppliers and are protected by all applicable intellectual property 5328 * laws, including trade secret and copyright laws. 5329 * Dissemination of this information or reproduction of this material 5330 * is strictly forbidden unless prior written permission is obtained 5331 * from Adobe Systems Incorporated. 5332 **************************************************************************/ 5333 5334 5335 5336 5337(function(_, $, xfalib){ 5338 xfalib.view.util.traversalManager = { 5339 5340 // compute tabIndex for the provided page 5341 _computTabIndex : function (pageView) { 5342 var pageNum = pageView._pageNumber(), 5343 tabIndex = this._tabIndexBasedOnRange(pageNum); 5344 this.geographicalOrder = []; 5345 this._createGeographicalOrder(pageView); 5346 this._createFinalTraversalOrder(tabIndex); // assign tab index using traversal element and geographicalOrder 5347 // 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 5348 this._lastFieldTabbed = null; 5349 }, 5350 5351 _tabIndexBasedOnRange : function (pageNum) { 5352 var behaviorConfig = new xfalib.ut.Version(formBridge.userConfig["behaviorConfig"]), 5353 tabIndexConfig = (behaviorConfig.isOn('mfRangeTabIndex')|| behaviorConfig.isOn('rangeTabIndex')), 5354 /*assuming single page can not have more than 1000 fields.[index -> 0 to 999] 5355 this is also configurable by passing the maximum number of fields allowable in the page 5356 in the config parameter */ 5357 maxFieldInPageForTabIndex = tabIndexConfig? parseInt(tabIndexConfig):1000; 5358 5359 return pageNum * maxFieldInPageForTabIndex; 5360 }, 5361 5362 // to create geographical order array which will be containing all the views in the geographical order 5363 _createGeographicalOrder : function (currentView) { 5364 var sortedChildViewWrapper = this._sortViewGeographically(currentView.childViews); 5365 _.each(sortedChildViewWrapper, function (wrapper) { 5366 var currentView = wrapper.view, 5367 instanceCheckMap = this._getMapOfInstanceCheck(currentView), 5368 isViewEligibleForTabbing = this._isViewEligibleForTabbing(currentView); 5369 // If the child view is fieldView, drawView, exclGroupView or subformView then we will push these views in this.geographicalOrder array, 5370 // as we need their traverse object during final traversing 5371 if (((instanceCheckMap.isField && !instanceCheckMap.isChildOfExclGroup) || instanceCheckMap.isSubform || instanceCheckMap.isDraw 5372 || instanceCheckMap.isExclGroup) && isViewEligibleForTabbing) { 5373 this.geographicalOrder.push({ 5374 view : currentView, 5375 visited : false 5376 }); 5377 } 5378 if (instanceCheckMap.isContainer && isViewEligibleForTabbing) { 5379 this._createGeographicalOrder(currentView); 5380 } 5381 }, this); 5382 }, 5383 5384 // to sort provided views in geographical order 5385 _sortViewGeographically : function (views) { 5386 var viewsWrapper = []; // wrapper of view and their geographical reference 5387 _.each(views, function(view) { 5388 var position = view.$el.offset(), 5389 paddedX = xfalib.ut.XfaUtil.prototype.padString(parseInt(position.left), 5, '0'), 5390 marginTop = view._marginTop(), 5391 paddedY = position.top - parseFloat(marginTop), 5392 positionalReference = parseInt("" + parseInt(paddedY) + paddedX); 5393 viewsWrapper.push({ 5394 positionalReference: positionalReference, 5395 view: view 5396 }); 5397 }); 5398 return _.sortBy(viewsWrapper, function(viewWrapper){ return viewWrapper.positionalReference; }); 5399 }, 5400 5401 // Walk through views in geographical order and assign tab index honouring traversal object if present 5402 _createFinalTraversalOrder : function (tabIndex) { 5403 var geographicalOrderLength = this.geographicalOrder.length, 5404 currentWrappedObj = null, 5405 index = -1, 5406 traversalIndex = 0, // index of the element to be traversed 5407 viewTraversed = 0; // counter of view traversed 5408 5409 while (1) { 5410 if (traversalIndex >= geographicalOrderLength) { 5411 traversalIndex = 0; 5412 } 5413 currentWrappedObj = this.geographicalOrder[traversalIndex]; 5414 5415 if (!currentWrappedObj || currentWrappedObj.visited) { // if the wrapped object does not exist or it has been visited move to the next one 5416 traversalIndex++; 5417 } else { 5418 currentWrappedObj.visited = true; 5419 viewTraversed++; 5420 var currentView = currentWrappedObj.view, 5421 instanceCheckMap = this._getMapOfInstanceCheck(currentView), 5422 currentModel = currentView.model, 5423 nextView = null, 5424 nextViewSom = null; 5425 5426 // get the first traversal of the subform if traversal object is present, else move to the next geographical element 5427 // next of the subform will be taken care when we will be finding the next view to be traversed, 5428 // as we will be checking if the ancestor contain next before moving to geographically next view 5429 if (instanceCheckMap.isSubform) { 5430 if (currentModel && currentModel.getTraversalObject()) { 5431 // get the first element to be traversed and update traversalIndex 5432 nextViewSom = currentModel.getNextTraversalSom(xfalib.template.Constants.firstTraversal); 5433 index = this._findViewInGeographicalOrderArray(nextViewSom); 5434 traversalIndex = index != -1 ? index : traversalIndex + 1; 5435 } else { 5436 traversalIndex++; 5437 } 5438 // get the next traversal for the field/draw if traversal object is present, else move to the next geographical element 5439 // update the tabindex for the field 5440 } else if (instanceCheckMap.isField || instanceCheckMap.isDraw) { 5441 if (instanceCheckMap.isField) { 5442 currentView.updateTabIndex(tabIndex); 5443 this._lastFieldTabbed = currentView; 5444 tabIndex++; 5445 } 5446 if (currentModel && currentModel.getTraversalObject()) { 5447 //get next element to be traversed and update traversalIndex 5448 nextViewSom = currentModel.getNextTraversalSom(xfalib.template.Constants.nextTraversal); 5449 index = this._findViewInGeographicalOrderArray(nextViewSom); 5450 traversalIndex = index != -1 ? index : traversalIndex + 1; 5451 } else { 5452 traversalIndex = this._findNextViewToBeTraversed(traversalIndex); 5453 } 5454 // if traversal object present get the next element to be traversed, if first is also present then update tab index of the first element 5455 // else look for the traversal element in the children 5456 } else if (instanceCheckMap.isExclGroup) { 5457 if (currentModel && currentModel.getTraversalObject()) { 5458 // get next element to be traversed and update traversalIndex 5459 nextViewSom = currentModel.getNextTraversalSom(xfalib.template.Constants.nextTraversal); 5460 index = this._findViewInGeographicalOrderArray(nextViewSom); 5461 traversalIndex = index != -1 ? index : traversalIndex + 1; 5462 // if first is also present assign tab index to that referred child else assign same tab index to all child 5463 nextViewSom = currentModel.getNextTraversalSom(xfalib.template.Constants.firstTraversal); 5464 tabIndex = this._updateTabIndexOfExclGroupChildren(currentView, tabIndex, nextViewSom); 5465 } else { 5466 tabIndex = this._updateTabIndexOfExclGroupChildren(currentView, tabIndex); 5467 traversalIndex = this._findTraversalInExclGroupChildren(currentView, traversalIndex); 5468 } 5469 } else { 5470 traversalIndex++; 5471 } 5472 } 5473 5474 // if all the view are traversed, we have assigned tab index to all the views 5475 if (viewTraversed >= geographicalOrderLength) { 5476 this._renderNextPageFuture(); 5477 break; 5478 } 5479 } 5480 }, 5481 5482 // Check if the nextView is a sibling of the currentView (shares the same parent) 5483 // if it is not a sibling, check if the parent has a NEXT traversal. 5484 // if so get the node traversed to else recurse to see if nextView is a sibling of our parent 5485 // return -1 if the provided next node is sibling of current node or if no ancestor contain next traversal 5486 // else return index of the next traversal object of parent 5487 _getParentNextTraversal : function (currentView, nextView, traversalIndex) { 5488 var parentView = currentView.parentView, 5489 parentModel = parentView.model, 5490 nextViewParentModel = nextView.parentView.model, 5491 traversalObj = null, 5492 nextIndex = -1; 5493 5494 if (parentModel && nextViewParentModel && parentModel.somExpression != nextViewParentModel.somExpression) { 5495 if(parentView && parentView instanceof xfalib.view.SubformView) { 5496 if (parentModel.getTraversalObject()) { 5497 var nextViewSom = parentModel.getNextTraversalSom(xfalib.template.Constants.nextTraversal); 5498 nextIndex = this._findViewInGeographicalOrderArray(nextViewSom); 5499 if (nextIndex != -1 && !this.geographicalOrder[
5499nextIndex].visited) { 5500 return nextIndex; 5501 } else { 5502 return traversalIndex++; 5503 } 5504 } else { 5505 this._getParentNextTraversal(parentView, nextView, traversalIndex); 5506 } 5507 } else { // parentView is not a subform so skip up a level and re-check sibling 5508 this._getParentNextTraversal(parentView, nextView, traversalIndex); 5509 } 5510 } else { 5511 return -1; //provided currentView and nextView are sibling 5512 } 5513 return traversalIndex++; 5514 }, 5515 5516 // return the index of the view having provided somExpression in the geographicalOrder array 5517 _findViewInGeographicalOrderArray : function (somExpression) { 5518 return _.findIndex(this.geographicalOrder, function (viewWrapper) { 5519 var currentViewModel = viewWrapper.view.model; 5520 return (currentViewModel && currentViewModel.somExpression == somExpression); 5521 }); 5522 }, 5523 5524 // find the next element to be traversed based on the provided traversalIndex 5525 _findNextViewToBeTraversed : function (traversalIndex) { 5526 var currentView = this.geographicalOrder[traversalIndex].view, 5527 index = this._getNextUnvisited(traversalIndex), //get next unvisited based on geographical location 5528 nextView = null, 5529 nextIndex = -1; 5530 5531 if (index != -1) { 5532 nextView = this.geographicalOrder[index].view; 5533 //check if both are sibling and if not find the next of the parent and update traversalIndex 5534 nextIndex = this._getParentNextTraversal(currentView, nextView, traversalIndex); 5535 return nextIndex != -1 ? nextIndex : index; 5536 } 5537 return traversalIndex++; 5538 }, 5539 5540 // return the next unvisited node based on geographical location 5541 // starting from the traversalIndex and wraps around to check all the views 5542 _getNextUnvisited : function (traversalIndex) { 5543 var geographicalOrderLength = this.geographicalOrder.length, 5544 index = 0, 5545 actualIndex = 0; 5546 while(index < geographicalOrderLength) { 5547 actualIndex = (index + traversalIndex) % geographicalOrderLength; 5548 if(!this.geographicalOrder[actualIndex].visited) { 5549 return actualIndex; 5550 } 5551 index++; 5552 } 5553 return -1; 5554 }, 5555 5556 // assign same tab index to all the child of exclude group 5557 // if exclude group contain first traverse object, then the child being referred as first should have less tabindex 5558 // compared to other child 5559 _updateTabIndexOfExclGroupChildren : function (exclGroupView, tabIndex, firstChildSom) { 5560 _.each(exclGroupView.childViews, function(child){ 5561 if (this._isViewEligibleForTabbing(child)) { 5562 if(firstChildSom && child.model.somExpression == firstChildSom) { 5563 tabIndex++; 5564 child.updateTabIndex(tabIndex-1); 5565 this._lastFieldTabbed = child; 5566 } else { 5567 child.updateTabIndex(tabIndex); 5568 } 5569 } 5570 }, this); 5571 if (!firstChildSom) { 5572 this._lastFieldTabbed = exclGroupView.childViews[0]; 5573 } 5574 return ++tabIndex; 5575 }, 5576 5577 // find if any child contains next pointer and update traversal index 5578 // start with the last in the geographical order of the children and find child which have next traversal 5579 _findTraversalInExclGroupChildren : function (exclGroupView, traversalIndex) { 5580 var sortedChildView = this._sortViewGeographically(exclGroupView.childViews), 5581 tempObj = null, 5582 childView = null, 5583 childModel = null, 5584 traversalObj = null, 5585 nextViewSom = null, 5586 index = -1; 5587 5588 sortedChildView.reverse(); 5589 tempObj = _.find(sortedChildView, function(child) { 5590 childView = child.view; 5591 childModel = childView.model; 5592 if(childModel && (traversalObj = childModel.getTraversalObject())) { 5593 return traversalObj.length > 0; 5594 } 5595 }); 5596 5597 if (tempObj) { 5598 nextViewSom = tempObj.model.getNextTraversalSom(xfalib.template.Constants.nextTraversal); 5599 index = this._findViewInGeographicalOrderArray(nextViewSom); 5600 traversalIndex = index != -1 ? index : traversalIndex + 1; 5601 } else { // else get next unvisited based on geographical location 5602 traversalIndex = this._findNextViewToBeTraversed(traversalIndex); 5603 } 5604 return traversalIndex; 5605 }, 5606 5607 // check if the view is initialized and visible 5608 _isViewEligibleForTabbing : function (view) { 5609 if (view._initialized && view.$el.css("visibility") != "hidden") { 5610 return true; 5611 } 5612 return false;
5613 }, 5614 5615 // return map of whethter provided view is instance of the various views 5616 _getMapOfInstanceCheck : function (view) { 5617 var instanceCheckMap = {}; 5618 instanceCheckMap.isSubform = view instanceof xfalib.view.SubformView; 5619 instanceCheckMap.isField = view instanceof xfalib.view.FieldView; 5620 instanceCheckMap.isDraw = view instanceof xfalib.view.XfaDrawView; 5621 instanceCheckMap.isExclGroup = view instanceof xfalib.view.ExclGroupView; 5622 instanceCheckMap.isChildOfExclGroup = view.parentView instanceof xfalib.view.ExclGroupView; 5623 instanceCheckMap.isContainer = view instanceof xfalib.view.ContainerView; 5624 5625 return instanceCheckMap; 5626 }, 5627 5628 // add event handler for rendering next page on tabbing on last field of the page 5629 _renderNextPageFuture : function () { 5630 if (this._lastFieldTabbed) { 5631 this._lastFieldTabbed.$el.one('focusin.traversalManager', function() { 5632 var pagingManager = window.formBridge ? window.formBridge.pagingManager() : null; 5633 $(window).on( "keyup.traversalManager", function (e) { 5634 var code = (e.keyCode ? e.keyCode : e.which); 5635 if (code == 9 && pagingManager && pagingManager.hasMorePages()) { 5636 pagingManager.renderNextPage(); 5637 $(window).off("keyup.traversalManager"); 5638 } 5639 }); 5640 }); 5641 } 5642 }, 5643 _destroy : function() { 5644 this.geographicalOrder = null; 5645 } 5646 } 5647})(_, $, xfalib); 5648/************************************************************************* 5649* 5650* ADOBE CONFIDENTIAL 5651* ___________________ 5652* 5653* Copyright 2013 Adobe Systems Incorporated 5654* All Rights Reserved. 5655*
5656* NOTICE: All information contained herein is, and remains 5657* the property of Adobe Systems Incorporated and its suppliers, 5658* if any. The intellectual and technical concepts contained 5659* herein are proprietary to Adobe Systems Incorporated and its 5660* suppliers and are protected by trade secret or copyright law. 5661* Dissemination of this information or reproduction of this material 5662* is strictly forbidden unless prior written permission is obtained 5663* from Adobe Systems Incorporated. 5664**************************************************************************/ 5665 5666 5667 5668(function(_, $, xfalib){ 5669 5670 var ErrorManager = xfalib.view.util.ErrorManager = xfalib.ut.Class.extend({ 5671 5672 options: { 5673 warningMessageVisible:false, 5674 errorMessageVisible: false 5675 }, 5676 5677 initialize: function () { 5678 $(window).on("destroy.xfa", function () { 5679 $("#error-msg").hide(); 5680 $("#warning-msg").hide(); 5681 }); 5682 }, 5683 5684 onFieldEnter: function (jqWidget) { 5685 var element = jqWidget.element; 5686 if (jqWidget.option("errorMessage")|| jqWidget.option("warningMessage")) { 5687 var pos = $(element).offset(), 5688 styles = {}; 5689 styles.left = (pos.left * (1 / xfalib.ut.XfaUtil.prototype.formScaleFactor) + element.width() + 5) + "px"; 5690 styles.top = pos.top * (1 / xfalib.ut.XfaUtil.prototype.formScaleFactor) + "px"; 5691 if (jqWidget.option("errorMessage")) { 5692 jqWidget.$css($("#error-msg").get(0), styles); 5693 $("#error-msg").text(jqWidget.option("errorMessage")).show(); 5694 jqWidget.option("errorMessageVisible",true); 5695 } 5696 else if (jqWidget.option("warningMessage")) { 5697 jqWidget.$css($("#warning-msg").get(0), styles); 5698 $("#warning-msg").text(jqWidget.option("warningMessage")).show(); 5699 jqWidget.option("warningMessageVisible",true); 5700 } 5701 } 5702 }, 5703 5704 onFieldExit: function (jqWidget) { 5705 if (jqWidget.option("errorMessageVisible")) { 5706 $("#error-msg").hide(); 5707 jqWidget.option("errorMessageVisible",false); 5708 } else if (jqWidget.option("warningMessageVisible")) { 5709 $("#warning-msg").hide(); 5710 jqWidget.option("warningMessageVisible",false); 5711 } 5712 }, 5713 5714 markError: function (jqWidget, msg, type) { 5715 // assigning role="alert" so that JAWS reads-out the validation message 5716 if (type != "warning") { 5717 if ($("#error-msg").length < 1) 5718 $("<div id='error-msg' role='alert'></div>").appendTo('body'); 5719 jqWidget.option("errorMessage",msg); 5720 jqWidget.element.addClass("dataInvalid"); 5721 } else { 5722 if ($("#warning-msg").length < 1) 5723 $("<div id='warning-msg' role='alert'></div>").appendTo('body'); 5724 jqWidget.option("warningMessage",msg); 5725 } 5726 5727 }, 5728 5729 clearError: function (jqWidget) { 5730 this.onFieldExit(jqWidget); 5731 jqWidget.element.removeClass("dataInvalid"); 5732 jqWidget.option("errorMessage",null); 5733 jqWidget.option("warningMessage",null); 5734 } 5735 }); 5736})(_, $, xfalib); 5737(function(_,$, xfalib) { 5738 var xfaUtil = xfalib.ut.XfaUtil.prototype, 5739 BUFFER_SPC = 20; 5740 5741 /* template for the clear Button */ 5742 var clearButtonTemplate = '<div class="dp-clear">' + 5743 '<a></a>' + 5744 '</div>'; 5745 5746 /* template for the calendar 5747 * header contains the navigation icons (left and right arrows) 5748 * and the current caption (which can be date, year or month) 5749 * 5750 * monthview displays the grid for showing the dates for a particular 5751 * month 5752 * 5753 * yearview displays all the months of that year 5754 * 5755 * yearsetview displays a grid of 16 years. This can be configured 5756 * through the option: yearsPerView 5757 * 5758 */ 5759 var calendarTemplate = '<div class="dp-header">' + 5760 '<div class="dp-leftnav"></div>' + 5761 '<div class="dp-caption"></div>' + 5762 '<div class="dp-rightnav"></div>' + 5763 '</div>' + 5764 '<div role="table" class="view dp-monthview"></div>' + 5765 '<div role="table" class="view dp-yearview"></div>' + 5766 '<div role="table" class="view dp-yearsetview"></div>'; 5767 5768 /*template for the timer: not implemented yet */ 5769 var watchTemplate = '<div class="dp-header">' + 5770 '<div class="dp-leftnav"></div>' + 5771 '<div class="dp-caption"></div>' + 5772 '<div class="dp-rightnav"></div>' + 5773 '</div>' + 5774 '<div class="view dp-monthview"></div>' + 5775 '<div class="view dp-yearview"></div>' + 5776 '<div class="view dp-yearsetview"></div>'; 5777 5778 /** default configuration options 5779 * 5780 * container: the html element where the datepicker template will be added 5781 *
5782 * yearsPerView: number of years to show in the yearset view 5783 * 5784 * width: with of the widget 5785 * 5786 * viewHeight: Height of the month,year and yearset view. This doesn't include 5787 * the height of the header 5788 * 5789 * locale: locale information for the locale in which to show the datepicker which comprises of 5790 * days: day names to display in the monthview 5791 * months: month names to display in the yearview 5792 * zero: string representation of zero in the locale. Numbers will be 5793 * displayed in that locale only 5794 * clearText: Text to display for the reset button 5795 * name: name of the locale 5796 * 5797 * format: input format for the datepicker (not implemented) 5798 * 5799 * pickerType: type of the datetimepicker (date, datetime and time) 5800 * 5801 * positioning: element around which datepicker will be displayed. if null then it 5802 * will be displayed around the input element 5803 * 5804 * showCalendarIcon: to show the Calendar on the right of the text field or not 5805 */ 5806 5807 var defaults = { 5808 container: "body", 5809 yearsPerView: 16, 5810 width: 340, 5811 viewHeight: 248, 5812 locale: { 5813 days:["S","M","T","W","T","F","S"], 5814 months: ["January","February","March","April","May","June","July","August","September","October","November","December"], 5815 zero: "0", 5816 clearText: "Clear", 5817 name:"en_US" 5818 }, 5819 format:"YYYY-MM-DD", 5820 pickerType:"date", 5821 positioning: null, 5822 showCalendarIcon: false 5823 }, 5824 dates = [31,28,31,30,31,30,31,31,30,31,30,31], 5825 /* 5826 * Actions to perform when clicked on the datepicker buttons 5827 * for different views 5828 * caption: view to show when clicked on caption 5829 * (Year/YearSet/Month/null) null means don't change the view 5830 * li: view to show when clicked on date, month or year element 5831 * upDown: add(up key) or subtract(down key) current date (for monthview), 5832 * month(Year View) or year(YearSetView) with the number provided 5833 * key: identifies the key that needs to be changed for that view 5834 */ 5835 viewAction = { 5836 Month: { 5837 caption: 'Year', 5838 li: null, 5839 key:"day", 5840 upDown:7 5841 }, 5842 Year: { 5843 caption: "Yearset", 5844 li: "Month", 5845 key:"month", 5846 upDown:3 5847 }, 5848 Yearset: { 5849 caption: null, 5850 li: "Year", 5851 key:"year", 5852 upDown:4 5853 } 5854 }, 5855 headerClass = "header", 5856 5857 DateTimePicker = function() { 5858 this.initialized = false; 5859 } 5860 5861 $.extend(DateTimePicker.prototype, { 5862 /* 5863 * create the widget using the provided options 5864 */ 5865 create: function(options) { 5866 var $dp,self = this,html="",prevNavWidth,nextNavWidth; 5867 this.options = $.extend({},defaults,options); 5868 // prevent memory leak since options.positioning holds reference to HTML DOM 5869 this.options.positioning = null; 5870 // If width of date-picker exceeds screen width then it'll take up the entire screen width in AF 5871 if(window.guideBridge && this.options.width > window.innerWidth && window.innerWidth > 0) { 5872 this.options.width=window.innerWidth - BUFFER_SPC; // buffer 5873 } 5874 if(this.options.pickerType.match(/date/)) { 5875 html += calendarTemplate; 5876 } 5877 5878 if(this.options.pickerType.match(/time/)) { 5879 html += watchTemplate; 5880 } 5881 5882 html += clearButtonTemplate; 5883 5884 $.extend(this, { 5885 selectedDay:0, 5886 selectedMonth:0, 5887 selectedYear:0, 5888 currentDay:0, 5889 currentMonth:0, 5890 currentYear:0, 5891 touchSupported : xfalib.ut.TouchUtil.TOUCH_ENABLED, 5892 _visible:false, 5893 _defaultView:"Month", 5894 _keysEnabled:false, 5895 focusedOnDatepickerItem : false, 5896 keyboardAccessibility : true, 5897 $dp:$("<div></div>").addClass("datetimepicker") 5898 .width(this.options.width) 5899 .append(html) 5900 .addClass("datePickerTarget") 5901 .appendTo(this.options.container) 5902 .toggleClass("datetimepicker-notouch",this.touchSupported), 5903 $month: $(".dp-monthview",this.$dp).height(this.options.viewHeight),
5904 $year: $(".dp-yearview",this.$dp).height(this.options.viewHeight), 5905 $yearset : $(".dp-yearsetview",this.$dp).height(this.options.viewHeight) 5906 }); 5907 this.actualWidth = Math.floor(this.$dp.width()); 5908 this.$clear = $('.dp-clear a', this.$dp).on("click", $.proxy(this._clearDate, this)); 5909 this.$prevNavWidthBtn = $(".dp-leftnav", this.$dp).on("click", 5910 function(evnt) { 5911 self._adjustDate(-1, self.view, false) 5912 }); 5913 this.$nextNavWidthBtn = $(".dp-rightnav", this.$dp).on("click", 5914 function(evnt) { 5915 self._adjustDate(1, self.view, false) 5916 }); 5917 prevNavWidth = this.$prevNavWidthBtn.outerWidth(true); 5918 nextNavWidth = this.$nextNavWidthBtn.outerWidth(true); 5919 this.$caption = $(".dp-caption", this.$dp).width(this.actualWidth - prevNavWidth - nextNavWidth) 5920 .on("click", 5921 function(evnt) { 5922 if(!self.$caption.hasClass("disabled")) { 5923 self._layout(viewAction[self.view].caption); 5924 } 5925 }); 5926 if (this.keyboardAccessibility) { 5927 _.each([this.$prevNavWidthBtn, this.$caption, this.$nextNavWidthBtn, this.$clear], function (elem, i) { 5928 elem.attr("tabIndex", i + 1); 5929 }); 5930 } 5931 // attach click event on entire datePicker popup 5932 $(this.$dp).on("click", 5933 function(evnt) { 5934 //focus only if the device doesn't support touch 5935 // input otherwise on screen keyboard will popup 5936 if(!self.touchSupported) 5937 self._curInstance.$field.focus(); 5938 }); 5939 5940 $(window).on("touchstart.datetimepicker mousedown.datetimepicker",self._checkWindowClicked); 5941 this._curInstance = null; 5942 }, 5943 5944 /* 5945 * attaches the date picker to the field. This is a one time operation 5946 * First creates a configuration object and stores it in the field data attributes 5947 * then attaches event handlers on click, focus (to show the picker) and blur (to hide) events 5948 */ 5949 _attachField: function($field,options, value) { 5950 var inst = this._newInst($field,options, value), 5951 self = this, 5952 activateField = function(evnt) { 5953 var data = xfaUtil.$data(evnt.target,"datetimepicker"); 5954 if(self._isFieldDisabled(data)) { 5955 return; 5956 } 5957 if(!self._curInstance) 5958 self._activateField(evnt); 5959 5960 if(self.options.showCalendarIcon) { 5961 if (evnt.type === self.getEvent()) { 5962 if (self._iconClicked) { 5963 self._iconClicked = false; 5964 if (self._visible) { 5965 self._hide(); // hide the calendar popup if visible when calendar icon is clicked 5966 self._curInstance.$field.focus(); // bring back focus in field 5967 } else { 5968 self._show(); //// show the calendar popup if not visible when calendar icon is clicked 5969 } 5970 } 5971 } 5972 } else { 5973 /*show the popup only if 5974 1. click/touch event 5975 2. focus event in case of non-touch devices and focus is not done using script 5976 */ 5977 if (evnt.type === self.getEvent() || (evnt.type === "focus" && !self.touchSupported && !self.scriptFocus)) { 5978 self._show(evnt); 5979 } 5980 } 5981 5982 self._clickedWindow = true; 5983 self.scriptFocus = false;
5984 }, 5985 deactivateField = function(evnt) { 5986 //deactivate only if clicked outside window 5987 // on touch devices only keyboard or calander should be active at once, touching keyboard should deactivate calendar 5988 if ((self._clickedWindow && !self.focusedOnDatepickerItem) && (self.options.showCalendarIcon || !self.touchSupported)) { 5989 self._hide(); 5990 self._deactivateField(); 5991 self._clickedWindow = true; 5992 } 5993 }; 5994 5995 xfaUtil.$data($field[0],"datetimepicker",inst); 5996 5997 $field.on(this.getEvent(),activateField) 5998 .focus(activateField) 5999 .blur(deactivateField); 6000 if(options.showCalendarIcon) { 6001 var calendarIcon = $("<div></div>") 6002 .addClass("datepicker-calendar-icon") 6003 .css({ 6004 "width": options.iconWidth + "px", 6005 "height": options.iconHeight + "px" 6006 }); 6007 calendarIcon.insertAfter($field); 6008 6009 if (this.keyboardAccessibility) { 6010 calendarIcon.attr("tabindex", 0); 6011 } 6012 6013 calendarIcon.on(this.getEvent(), function (evnt) { 6014 self._iconClicked = true; 6015 $field.click(); 6016 }) 6017 .on("keydown", function (event) { 6018 if (event.keyCode === 32 || event.keyCode === 13) { 6019 // Check if field is disabled before triggering click 6020 var data = xfaUtil.$data($field[0], "datetimepicker"); 6021 if (data && !self._isFieldDisabled(data)) { 6022 $field.click(); 6023 } 6024 } 6025 }); 6026 } 6027 }, 6028 6029 _newInst: function($f,options, value) { 6030 return { 6031 $field:$f, 6032 locale: options.locale, 6033 positioning: options.positioning || $f, 6034 access:options.access, 6035 selectedDate:options.value, 6036 editValue :options.editValue, 6037 minValidDate : options.minValidDate, 6038 maxValidDate : options.maxValidDate, 6039 exclMinDate : options.exclMinDate, 6040 exclMaxDate : options.exclMaxDate 6041 } 6042 }, 6043 6044 /* 6045 * To check where the click happened, if happened outside the datepicker 6046 * then hide the picker. This is checked whether any ancestor of clicked target 6047 * has a class datePickerTarget. This class is added to the attached element as well 6048 */ 6049 _checkWindowClicked : function(evnt) { 6050 var self = adobeDateTimePicker; 6051 if(self._curInstance) { 6052 // datepickerTarget class depicts that the component is a part of the Date Field 6053 // and on click of that class, we should not hide the datepicker or fire exit events. 6054 if(!$(evnt.target).closest(".datePickerTarget").length) { 6055 //non-touch devices do not deactivate on blur. Hence needs to be done here 6056 if(self.touchSupported) { 6057 self._hide() 6058 //clicking outside a field doesn't blur the field in IPad. Doing it by script 6059 self._curInstance.$field[0].blur() 6060 self._deactivateField() 6061 } else{ 6062 self._clickedWindow = true; 6063 // set focusedOnDatepickerItem to false, it hides the datepicker see method deactivateField. 6064 self.focusedOnDatepickerItem = false; 6065 self._curInstance.$field.blur() 6066 } 6067 } 6068 else { 6069 self._clickedWindow = false;
6070 } 6071 } 6072 }, 6073 6074 /** 6075 * Checks if the current datepicker field is disabled. 6076 * 6077 * Fields marked as "readOnly" or with access set to false are considered 6078 * disabled and should not allow datepicker interaction. 6079 * 6080 * @param {Object} [data] - Optional data object to check. If not provided, uses current instance. 6081 * @returns {boolean} True if the field is disabled (access is "readOnly" or false), false otherwise. 6082 * Returns false if no current instance exists. 6083 */ 6084 _isFieldDisabled: function(data) { 6085 if (data) { 6086 return data.access === false || data.access === "readOnly"; 6087 } 6088 return this._curInstance && (this._curInstance.access === false || this._curInstance.access === "readOnly"); 6089 }, 6090 6091 /* 6092 * handling of key strokes. All the key strokes prevent the default browser action 6093 * unless specified otherwise 6094 * tab: set focus on calendar icon when dateinput field is active, navigates through date picker buttons when datepicker is open, 6095 * otherwise perform default browser action 6096 * escape: hides the datepicker 6097 * down arrow key: navigate the picker downwards by the number specified in actionView.upDown of the current View 6098 * up arrow key: navigate the picker upwards by the number specified in actionView.upDown of the current View 6099 * left arrow key: navigate the picker one unit of that view backward 6100 * right arrow key: navigate the picker one unit of that view forward 6101 * shift + up: perform the action that happens on clicking the caption (as specified in actionView.caption) 6102 * shift + left: perform the action that happens on clicking the left navigation button 6103 * shift + right: perform the action that happens on clicking the right navigation button 6104 * space/enter: triggers the click event for the current focused element from datepicker/ opens datepicker when calendar icon is focused. 6105 */ 6106 _hotKeys: function(evnt) { 6107 var handled = false, date; 6108 switch(evnt.keyCode) { 6109 case 9: //tab 6110 // CQ-4239352 : Setting clickedWindow property to true on tabbing so that deactivateField logic gets executed 6111 // When clicking on "x" on input field in in IE and when selecting the content and releasing the mouse select outside the field 6112 // the click event is not trigerred on the field and hence activateField is not executed, so clickedWindow remains as false 6113 adobeDateTimePicker._clickedWindow = true; 6114 handled = false; 6115 break; 6116 case 27://escape 6117 if(this._visible) { 6118 adobeDateTimePicker._hide(); 6119 this._curInstance.$field.focus(); 6120 handled = true; 6121 } 6122 break; 6123 case 32: //space 6124 case 13: // enter 6125 if($(evnt.target).hasClass("datepicker-calendar-icon")){ 6126 // Check if field is disabled before showing datepicker 6127 // disabled fields are marked as readOnly in the form 6128 if(this._isFieldDisabled()) { 6129 return; 6130 } 6131 if(!this._visible) { 6132 this._show(); 6133 return; 6134 } 6135 this.$focusedDate.addClass("dp-focus"); 6136 } 6137 break; 6138 case 40: //down arrow key 6139 if(!this._visible) { 6140 // Check if field is disabled before showing datepicker 6141 if(this._isFieldDisabled()) { 6142 return; 6143 } 6144 this._show(); 6145 return; 6146 } 6147 this.$focusedDate.addClass("dp-focus"); 6148 break; 6149 } 6150 6151 if(adobeDateTimePicker._visible && this._keysEnabled) { 6152 var v = viewAction[this.view].key, 6153 updown=viewAction[this.view].upDown; 6154 switch(evnt.keyCode) { 6155 case 9: // tab
6156 if (evnt.shiftKey) { 6157 if ($(evnt.target).hasClass("dp-leftnav") || $(evnt.target).hasClass("dp-focus")) { 6158 this._hide(); 6159 this._curInstance.$field.focus(); 6160 handled = true; 6161 } else { 6162 handled = false; 6163 } 6164 } else { 6165 var buttonTabindex = $(evnt.target).attr("tabindex"); 6166 if (buttonTabindex === '0') { 6167 if (evnt.target.tagName.toLocaleLowerCase() === "input") { 6168 this._hide(); 6169 handled = false; 6170 } else { 6171 this.$prevNavWidthBtn.focus(); 6172 handled = true; 6173 } 6174 } else if (buttonTabindex === '4') { 6175 this._hide(); 6176 this._curInstance.$field.focus(); 6177 handled = true; 6178 } else { 6179 handled = false; 6180 } 6181 } 6182 break; 6183 case 32: //select on space 6184 case 13: // select on enter 6185 this.hotKeyPressed = true; 6186 this.focusedOnDatepickerItem = false; 6187 if (!this.focusedOnDatepickerItem) { 6188 $(evnt.target, this.$dp).triggerHandler("click"); 6189 } else { 6190 if (this.$focusedDate) { 6191 this.$focusedDate.trigger("click"); 6192 } 6193 } 6194 this.hotKeyPressed = false; 6195 handled = true; 6196 break; 6197 case 37: //left arrow key 6198 if (evnt.shiftKey) { 6199 $(".dp-leftnav", this.$dp).triggerHandler("click"); 6200 } else { 6201 this._adjustDate(-1, v, true); 6202 } 6203 handled = true; 6204 break; 6205 case 38: //up arrow key 6206 if (evnt.shiftKey) { 6207 this.$caption.triggerHandler("click"); 6208 } else { 6209 this._adjustDate(-updown, v, true); 6210 } 6211 handled = true; 6212 break; 6213 case 39: //right arrow key 6214 if (evnt.shiftKey) { 6215 $(".dp-rightnav", this.$dp).triggerHandler("click"); 6216 } else { 6217 this._adjustDate(+1, v, true); 6218 } 6219 handled = true; 6220 break; 6221 case 40: //down arrow key 6222 this._adjustDate(updown, v, true); 6223 handled = true; 6224 break; 6225 default: 6226 } 6227 } 6228 if(handled) { 6229 evnt.preventDefault(); 6230 } 6231 }, 6232 6233 /* 6234 * show the datepicker. 6235 */ 6236 _show: function() { 6237 if(this._isFieldDisabled()) 6238 return; 6239 this.options.locale = this._curInstance.locale; 6240 if(!this._visible) { 6241 var self = this, 6242 date = new Date(), 6243 val, 6244 maxDateInfo, 6245 minDateInfo, 6246 validDate; 6247 //Bug#3607735: 6248 // Date constructor in ipad 5.1 doesn't support "YYYY-MM-DD", hence parsing the date on our own 6249 validDate = xfalib.ut.DateInfo.ParseIsoString(this._curInstance.selectedDate); 6250 date = (validDate != null)? validDate.getDate(): new Date(); 6251 this.selectedDay = this.currentDay = date.getDate(); 6252 this.selectedMonth = this.currentMonth = date.getMonth(); 6253 this.selectedYear = this.currentYear = date.getFullYear(); 6254 maxDateInfo = this.options.maxValidDate ? xfalib.ut.DateInfo.ParseIsoString(this._curInstance.maxValidDate) : null; 6255 this.maxValidDate = maxDateInfo ? maxDateInfo.getDate() : null; 6256 minDateInfo = this.options.minValidDate ? xfalib.ut.DateInfo.ParseIsoString(this._curInstance.minValidDate) : null; 6257 this.minValidDate = minDateInfo ? minDateInfo.getDate() : null; 6258 this.exclMaxDate = this._curInstance.exclMaxDate; 6259 this.exclMinDate = this._curInstance.exclMinDate; 6260 $('.dp-clear a',this.$dp).text(this.options.locale.clearText); 6261 this._layout('Month'); 6262 this._position(); 6263 this.$dp.show(); 6264 // if li element of datepicker is focused then set focusedOnDatepickerItem to true, it manages the visibility of the datepicker. 6265 this.focusedOnDatepickerItem = false;
6266 this._visible = true; 6267 if (this.options.showCalendarIcon) { 6268 this._curInstance.$field.attr('readonly', true); // when the datepicker is active, deactivate the field 6269 } 6270 } 6271 6272 // Disabling the focus on ipad due to a bug where value of 6273 // date picker is not being set 6274 // Removing this code will only hamper one use case 6275 // where on ipad if you click on the calander then 6276 // the field becomes read only so 6277 // there is no indication where the current focus is 6278 // And if you remove this foucs code all together 6279 // then what happens is that on desktop MF in iframe the exit event 6280 // is not getting called hence calander getting remained open even 6281 // when you click somewhere on window or focus into some other field 6282 if (this.options.showCalendarIcon && !this.touchSupported) { 6283 if(this.$focusedDate && this.$focusedDate.length > 0) { 6284 this.$focusedDate.focus(); // shift focus on current date or selected date. 6285 } else { 6286 this._curInstance.$field.focus(); // field loses focus after being marked readonly, causing blur event not to be fired later 6287 } 6288 } 6289 }, 6290 6291 /* 6292 * position the datepicker around the positioning element 6293 * provided in the options 6294 */ 6295 _position: function() { 6296 var $elem = this._curInstance.positioning, 6297 windowScrollX = window.scrollX/ xfalib.ut.XfaUtil.prototype.formScaleFactor, 6298 windowScrollY = window.scrollY/ xfalib.ut.XfaUtil.prototype.formScaleFactor, 6299 windowInnerHeight = window.innerHeight/ xfalib.ut.XfaUtil.prototype.formScaleFactor, 6300 windowInnerWidth = window.innerWidth/ xfalib.ut.XfaUtil.prototype.formScaleFactor, 6301 height = $elem.outerHeight(true), 6302 width = $elem.outerWidth(true), 6303 top = $elem.offset().top / xfalib.ut.XfaUtil.prototype.formScaleFactor + height, 6304 left = $elem.offset().left / xfalib.ut.XfaUtil.prototype.formScaleFactor, 6305 styles = {"top": (top+"px"), "left": (left+"px")}, 6306 diffBottom = top + this.$dp.outerHeight(true) - windowInnerHeight - windowScrollY, 6307 newLeft, 6308 newTop; 6309 if(diffBottom > 0) { 6310 //can't appear at the bottom 6311 //check top 6312 newTop = top - height - this.$dp.outerHeight(true) - BUFFER_SPC; 6313 if(newTop < windowScrollY) { 6314 //can't appear at the top as well ... the datePicker pop up overlaps the date field 6315 newTop = top - diffBottom; 6316 // Fix for BUG #3626974 6317 if(xfaUtil.isWebkit() && !this.options.showCalendarIcon) { 6318 this._curInstance.$field.trigger("onoverlap.datetimepicker"); 6319 } 6320 } 6321 styles.top = newTop + "px"; 6322 } 6323 if(left + this.$dp.outerWidth(true) > windowScrollX + windowInnerWidth ) { 6324 //align with the right edge 6325 newLeft = windowScrollX + windowInnerWidth - this.$dp.outerWidth(true) - BUFFER_SPC; 6326 styles.left = newLeft + "px"; 6327 } 6328 xfaUtil.$css(this.$dp.get(0), styles); 6329 return this; 6330 }, 6331 6332 /* 6333 * layout the nextView. if nextView is null return 6334 * 6335 */ 6336 _layout: function(nextView) { 6337 if(nextView == null) { 6338 this._hide(); 6339 } else { 6340 if(this.view) 6341 this['$'+this.view.toLowerCase()].hide(); 6342 this.view = nextView; 6343 this.$caption.toggleClass("disabled",!viewAction[this.view].caption); 6344 this['$'+this.view.toLowerCase()].show(); 6345 this["show"+this.view](); 6346 } 6347 return this; 6348 }, 6349 6350 /* 6351 * show the month view 6352 */ 6353 showMonth: function() { 6354 var self = this, 6355 curDate = new Date(this.currentYear, this.currentMonth), 6356 maxDay = this._maxDate(this.currentMonth), 6357 prevMaxDay = this._maxDate((this.currentMonth + 11)%12), 6358 day1 = new Date(this.currentYear,this.currentMonth,1).getDay(), 6359 data,display; 6360 6361 this.tabulateView( 6362 { 6363 caption: this.options.locale.months[this.currentMonth] + ", "+ this._convertNumberToLocale(this.currentYear), 6364 header:this.options.locale.days, 6365 numRows:7, 6366 numColumns:7, 6367 elementAt: function(row,col) { 6368 var day = (row-1)*7 + col - day1 + 1; 6369 var monthVal = self.currentMonth + 1; 6370 display = self._convertNumberToLocale(day); 6371 data = day; 6372 if(day < 1) { 6373 display = self._convertNumberToLocale(prevMaxDay + day); 6374 data = -1; 6375 monthVal = self.currentMonth; 6376 } 6377 else if(day > maxDay) { 6378 display = self._convertNumberToLocale(day-maxDay); 6379 data = -1; 6380 monthVal = self.currentMonth + 2; 6381 } 6382 else { 6383 curDate.setDate(day); 6384 var compareFn = xfalib.ut.XfaUtil.prototype._compareVal; 6385 // check if the currentdate is valid based on max and min valid date 6386 if(compareFn(curDate, self.maxValidDate, self.exclMaxDate) || compareFn(self.minValidDate, curDate, self.exclMinDate)) { 6387 data = -1; 6388 } 6389 } 6390 return { 6391 data : data, 6392 display : display, 6393 ariaLabel : self.options.editValue(self.currentYear+"-"+self._pad2(monthVal)+"-"+self._pad2(display)) 6394 }; 6395 } 6396 }); 6397 }, 6398 6399 6400 6401 /* 6402 * show the year view 6403 */ 6404 showYear: function() { 6405 var self = this, 6406 minDate = this.minValidDate ? new Date(this.minValidDate.getFullYear(), this.minValidDate.getMonth()) : null, 6407 maxDate = this.maxValidDate ? new Date(this.maxValidDate.getFullYear(), this.maxValidDate.getMonth()) : null, 6408 curDate = new Date(this.currentYear, 0), //can't omit month, if only one param present it is treated as millisecond 6409 data, 6410 month; 6411 this.tabulateView( 6412 { 6413 caption : this._convertNumberToLocale(this.currentYear), 6414 numRows : 4, 6415 numColumns : 3, 6416 elementAt : function(row,col) { 6417 data = month = row*3 + col; 6418 curDate.setMonth(month); 6419 if ((minDate && curDate < minDate) || (maxDate && curDate > maxDate)) { 6420 data = -1; 6421 } 6422 return { 6423 data : data, 6424 display : self.options.locale.months[month], 6425 ariaLabel : self.options.locale.months[month] + " " +self.currentYear 6426 }; 6427 } 6428 }); 6429 }, 6430 6431 /* 6432 * show the year set view 6433 */ 6434 showYearset: function() { 6435 var year, 6436 minDate = this.minValidDate ? new Date(this.minValidDate.getFullYear(), 0
6436) : null , 6437 maxDate = this.maxValidDate ? new Date(this.maxValidDate.getFullYear() + 1, 0) : null, 6438 curDate = new Date(), 6439 data, 6440 self = this; 6441 this.tabulateView( 6442 { 6443 caption: this._convertNumberToLocale(this.currentYear - this.options.yearsPerView/2) +"-"+this._convertNumberToLocale(this.currentYear - this.options.yearsPerView/2 + this.options.yearsPerView - 1), 6444 numRows:4, 6445 numColumns:4, 6446 elementAt: function(row,col) { 6447 data = year = self.currentYear - 8 + (row*4 + col); 6448 curDate.setFullYear(year); 6449 if ((minDate && curDate < minDate) || (maxDate && curDate > maxDate)) { 6450 data = -1; 6451 } 6452 return { 6453 "data" : data, 6454 "display" : self._convertNumberToLocale(year), 6455 ariaLabel : year 6456 }; 6457 } 6458 }); 6459 }, 6460 6461 insertRow : function(rowNum,rowArray,isHeader,height) { 6462 var $view = this["$"+this.view.toLowerCase()], 6463 width = (this.actualWidth)/rowArray.length, 6464 $row = $("ul",$view).eq(rowNum), 6465 items,$li,element,$tmp, 6466 self= this; 6467 if(!$row.length) 6468 $row = $("<ul></ul>").attr("aria-label", "").attr("role", "row").appendTo($view).toggleClass(headerClass,isHeader); 6469 $row.height(height); 6470 items = $("li",$row).length; 6471 while(items++ < rowArray.length) { 6472 $tmp = $("<li></li>").attr("role", "cell").appendTo($row); 6473 if(!isHeader) 6474 $tmp.on("click", $.proxy(this._selectDate,this)); 6475 } 6476 6477 _.each(rowArray, function(el,index) { 6478 $li = $("li",$row).eq(index); 6479 if(isHeader) 6480 $li.text(rowArray[index]); 6481 else { 6482 element = rowArray[index]; 6483 xfaUtil.$data($li.get(0), "value", element.data); 6484 if(self._checkDateIsFocussed(element.data)) { 6485 if(self.$focusedDate) { 6486 self.$focusedDate.removeClass("dp-focus"); 6487 self.$focusedDate.attr("tabindex", "-1"); 6488 } 6489 self.$focusedDate = $li; 6490 if(self._keysEnabled) 6491 self.$focusedDate.addClass("dp-focus") 6492 } 6493 $li.toggleClass("dp-selected",self._checkDateIsSelected(element.data)) 6494 .toggleClass("disabled", element.data == -1).text(element.display) 6495 .attr("title", element.ariaLabel) 6496 .attr("aria-label", element.ariaLabel) 6497 .attr("tabindex", -1); 6498 } 6499 $li.css( {"height":height+"px","width":width+"px","line-height":height+"px"}); 6500 }); 6501 return $row; 6502 }, 6503 6504 /* 6505 * creates a tabular view based on the options provided. The options that can be passed are 6506 * numRows: number of rows that needs rendering 6507 * numCols: number of columns that needs rendering 6508 * caption: text for the datepickers caption element 6509 * header: an array of elements that identifies the header row 6510 * elementAt: a function(row, column) that returns an object (data: <data>, display: <display>) where 6511 * <data> is the value to set for that view when the element at (row,column) is clicked and 6512 * <display> is the value that will be visible to the user 6513 */ 6514 tabulateView : function(options) { 6515 var r = 0,rows = 0, 6516 row = [], 6517 ht = this.options.viewHeight/options.numRows, 6518 c; 6519 this.$caption.text(options.caption); 6520 if(options.header) { 6521 this.insertRow(r++,options.header,true,ht); 6522 } 6523 while(r < options.numRows) { 6524 c = 0; 6525 while(c < options.numColumns) { 6526 row[c] = options.elementAt(r,c); 6527 c++; 6528 } 6529 this.insertRow(r++,row,false,ht); 6530 } 6531 }, 6532 6533 _activateField : function(evnt) { 6534 this._curInstance = xfaUtil.$data(evnt.target,"datetimepicker"); 6535 this._curInstance.$field.trigger("onfocus1.datetimepicker").addClass("datePickerTarget"); 6536 // Issue LC-7049: 6537 // datepickerTarget should be added when activate the field and should be removed 6538 // after the fields gets deactivated. 6539 if (this.options.showCalendarIcon) { 6540 this._curInstance.$field.parent().addClass("datePickerTarget"); 6541 } 6542 //enable hot keys only for non touch devices 6543 if(!this.touchSupported && !this._keysEnabled) { 6544 $(window).on("keydown.datetimepicker", $.proxy(this._hotKeys,this)); 6545 this._keysEnabled = true; 6546 } 6547 }, 6548 6549 _deactivateField: function() { 6550 if(this._curInstance) { 6551 if(this._keysEnabled) { 6552 $(window).off("keydown.datetimepicker") 6553 this._keysEnabled = false;
6554 } 6555 //Bug#3607499: on deactivate check the value in the input box, if that is 6556 // different than the selected Date, change the selectedDate 6557 //if (this._curInstance.selectedDate != this._curInstance.$field.val()) { 6558 // this._curInstance.selectedDate = this._curInstance.$field.val(); 6559 //} 6560 this._curInstance.$field.trigger("onfocusout.datetimepicker").removeClass("datePickerTarget"); 6561 // Issue LC-7049: 6562 // datepickerTarget should be added when activate the field and should be removed 6563 // after the fields gets deactivated. Otherwise clicking on any other datefield 6564 // will not hide the existing datepicker 6565 if (this.options.showCalendarIcon) { 6566 this._curInstance.$field.parent().removeClass("datePickerTarget"); 6567 } 6568 this._curInstance = null; 6569 } 6570 }, 6571 6572 _hide: function() { 6573 if(this._visible) { 6574 this.$dp.hide(); 6575 this._curInstance.$field.trigger("onclose.datetimepicker"); 6576 this._visible = false; 6577 if (this.options.showCalendarIcon) { 6578 this._curInstance.$field.attr('readonly', false); // when the datepicker is deactivated, activate the field 6579 } 6580 } 6581 }, 6582 6583 _adjustDate: function(step, view, focus) { 6584 var maxDate,prevMaxDate; 6585 var _focus = focus || false; 6586 switch(view.toLowerCase()) { 6587 case "day": 6588 this.currentDay += step; 6589 maxDate = this._maxDate(this.currentMonth) 6590 if(this.currentDay < 1) { 6591 prevMaxDate = this._maxDate((this.currentMonth - 1 + 12)%12); 6592 this.currentDay = prevMaxDate + this.currentDay; 6593 return this._adjustDate(-1, "month", _focus); 6594 } 6595 if(this.currentDay > maxDate) { 6596 this.currentDay -= maxDate; 6597 return this._adjustDate(+1, "month", _focus); 6598 } 6599 break; 6600 case "month": 6601 this.currentMonth += step; 6602 if(this.currentMonth > 11) { 6603 this.currentYear++; 6604 this.currentMonth = 0; 6605 } 6606 if(this.currentMonth < 0) { 6607 this.currentYear--; 6608 this.currentMonth = 11; 6609 } 6610 break; 6611 case "year": 6612 this.currentYear += step; 6613 break;
6614 case "yearset": 6615 this.currentYear += step*this.options.yearsPerView; 6616 break; 6617 } 6618 this._layout(this.view); 6619 if (_focus) { 6620 this.focusedOnDatepickerItem = true; 6621 this.$focusedDate.attr("tabindex", 0)[0].focus(); 6622 } 6623 }, 6624 6625 _checkDateIsSelected: function(data) { 6626 switch(this.view.toLowerCase()) { 6627 case "month": 6628 return this.currentYear == this.selectedYear && this.currentMonth == this.selectedMonth && data == this.selectedDay; 6629 case "year": 6630 return this.currentYear == this.selectedYear && this.selectedMonth == data; 6631 case "yearset": 6632 return this.selectedYear == data; 6633 } 6634 }, 6635 6636 _checkDateIsFocussed: function(data) { 6637 switch(this.view.toLowerCase()) { 6638 case "month": 6639 return data == this.currentDay; 6640 case "year": 6641 return this.currentMonth == data;
6642 case "yearset": 6643 return this.currentYear == data; 6644 } 6645 }, 6646 6647 _convertNumberToLocale : function(number) { 6648 var zeroCode = this.options.locale.zero.charCodeAt(0); 6649 number += ""; 6650 var newNumber = []; 6651 for(var i = 0;i < number.length;i++) { 6652 newNumber.push(String.fromCharCode(zeroCode + parseInt(number.charAt(i)))); 6653 } 6654 return newNumber.join(""); 6655 }, 6656 6657 _clearDate: function() { 6658 var isDateEmpty = this._curInstance.$field.val() ? false : true; 6659 this.selectedYear 6660 = this.selectedMonth 6661 = this.selectedYear 6662 = -1; 6663 this._curInstance.selectedDate = ""; 6664 this._curInstance.$field.val(""); 6665 if (!isDateEmpty) { 6666 this._curInstance.$field.trigger("onvaluechange.datetimepicker", [ 6667 {selectedDate: ""} 6668 ]); 6669 } 6670 $(".dp-selected",this['$'+this.view.toLowerCase()]).removeClass("dp-selected"); 6671 }, 6672 6673 getEvent : function() { 6674 return "click";//this.touchSupported ? "touchstart" : "click"; 6675 }, 6676 6677 _pad2: function(m) { 6678 return m = m < 10 ?"0"+m:m; 6679 }, 6680 6681 toString : function() { 6682 return this.selectedYear +"-"+this._pad2(this.selectedMonth + 1)+"-"+this._pad2(this.selectedDay); 6683 }, 6684 6685 _selectDate : function(evnt) { 6686 var val = xfaUtil.$data(evnt.target, "value"), 6687 nextView = viewAction[this.view].li, 6688 editVal; 6689 //disabled dates have a value of -1. Do nothing in that case 6690 if(val == -1) 6691 return; 6692 switch(this.view.toLowerCase()) { 6693 case "month": 6694 this.selectedMonth = this.currentMonth; 6695 this.selectedYear = this.currentYear; 6696 this.selectedDay = val; 6697 this._curInstance.selectedDate = this.toString(); 6698 editVal = this._curInstance.editValue(this.toString()); 6699 this._curInstance.$field.val(editVal).focus(); 6700 this._curInstance.$field.trigger("onvaluechange.datetimepicker", [ 6701 {selectedDate: editVal} 6702 ]); 6703 $(".dp-selected",this['$'+this.view.toLowerCase()]).removeClass("dp-selected"); 6704 $(evnt.target).addClass("dp-selected"); 6705 break; 6706 case "year": 6707 this.currentMonth = val; 6708 break;
6709 case "yearset": 6710 this.currentYear = val; 6711 break; 6712 } 6713 this._layout(nextView); 6714 //manually focus on the field if clicked on the popup buttons for non-touch device 6715 if(!this.touchSupported) { 6716 //No need to focus if selection is made by pressing space. 6717 if(!this.hotKeyPressed) { 6718 this.scriptFocus = true; 6719 if(nextView == null) { 6720 this.focusedOnDatepickerItem = false; 6721 } 6722 } 6723 } else if(nextView == null){ 6724 //For touch devices, deactivate the field if a selection is made 6725 this.focusedOnDatepickerItem = false; 6726 this._deactivateField() 6727 } 6728 }, 6729 6730 _leapYear : function() { 6731 return this.currentYear % 400 == 0 || (this.currentYear % 100 != 0 && this.currentYear % 4 == 0); 6732 }, 6733 6734 _maxDate : function(m) { 6735 if(this._leapYear() && m == 1) 6736 return 29; 6737 else return dates[m]; 6738 }, 6739 6740 _access: function(val) { 6741 if(typeof val == "undefined") 6742 return this.access 6743 this.access = val; 6744 }, 6745 6746 _value:function(val) { 6747 if(typeof val == "undefined") 6748 return this.$field.val() 6749 else { 6750 this.selectedDate = val; 6751 var editValue = this.editValue(val); 6752 // update the field val with provided value instead of null 6753 if (!editValue) { 6754 editValue = val; 6755 } 6756 this.$field.val(editValue); 6757 } 6758 } 6759 }); 6760 6761 var adobeDateTimePicker = new DateTimePicker(); 6762 6763 $.fn.adobeDateTimePicker = function(options, value) { 6764 if(!adobeDateTimePicker.initialized) { 6765 adobeDateTimePicker.create(options); 6766 adobeDateTimePicker.initialized = true; 6767 } 6768 if(typeof options === "object") { 6769 adobeDateTimePicker._attachField(this, options); 6770 } 6771 else if(typeof options === "string") { 6772 if(arguments.length == 2) 6773 adobeDateTimePicker["_"+options].apply(xfaUtil.$data(this[0],"datetimepicker"),[value]) 6774 else 6775 return adobeDateTimePicker["_"+options].apply(xfaUtil.$data(this[0],"datetimepicker")) 6776 } 6777 return this; 6778 } 6779})(_, $, xfalib); 6780(function (xfalib) { 6781 xfalib.ut.TouchUtil = (function () { 6782 var touchAvailable = !!("ontouchstart" in window || window.DocumentTouch && document instanceof DocumentTouch) , 6783 pointerEnabled = !!(window.MSPointerEvent || window.PointerEvent) , 6784 POINTER_DOWN_EVENT = "mousedown", 6785 POINTER_MOVE_EVENT = "mousemove", 6786 POINTER_UP_EVENT = "mouseup", 6787 EVENT_TYPE = "MouseEvent"; 6788 6789 if (window.PointerEvent) { //> IE11 6790 POINTER_DOWN_EVENT = "pointerdown"; 6791 POINTER_MOVE_EVENT = "pointermove"; 6792 POINTER_UP_EVENT = "pointerup"; 6793 EVENT_TYPE = "PointerEvent"; 6794 6795 } else if (window.MSPointerEvent) { // IE10 6796 POINTER_DOWN_EVENT = "MSPointerDown"; 6797 POINTER_MOVE_EVENT = "MSPointerMove"; 6798 POINTER_UP_EVENT = "MSPointerUp"; 6799 EVENT_TYPE = "MSPointerEvent" ; 6800 6801 } else if (touchAvailable) { // other touch devices 6802 POINTER_DOWN_EVENT = "touchstart"; 6803 POINTER_MOVE_EVENT = "touchmove"; 6804 POINTER_UP_EVENT = "touchend"; 6805 EVENT_TYPE = "TouchEvent"; 6806 } 6807 return { 6808 TOUCH_ENABLED: touchAvailable, 6809 // new MS Pointer Events 6810 POINTER_EVENT: EVENT_TYPE, 6811 POINTER_ENABLED: pointerEnabled, 6812 POINTER_DOWN: POINTER_DOWN_EVENT, 6813 POINTER_MOVE: POINTER_MOVE_EVENT, 6814 POINTER_UP: POINTER_UP_EVENT, 6815 getTouchEvent: function (evt) { 6816 var target; 6817 if (pointerEnabled) { 6818 target = evt.originalEvent; 6819 } else if (touchAvailable) { 6820 target = evt.originalEvent || evt; 6821 target = target.touches[0]; 6822 //if (evt.originalEvent && evt.originalEvent.changedTouches && evt.originalEvent.changedTouches[0]) { 6823 // te = evt.originalEvent.changedTouches[0]; 6824 //} 6825 } 6826 6827 return target || evt; 6828 }, 6829 getPointerEvent: function (eventType) { 6830 var event = null; 6831 if ((typeof PointerEvent) === "function") { 6832 event = new PointerEvent(eventType, { 6833 bubbles: true, 6834 cancelable: true 6835 }); 6836 } else { 6837 event = document.createEvent(EVENT_TYPE); 6838 event.initEvent(eventType, true, true); 6839 } 6840 return event; 6841 }, 6842 getTouches:function(evt){ 6843 var touches = []; 6844 if(touchAvailable && evt.originalEvent && evt.originalEvent.touches ){ 6845 touches = evt.originalEvent.touches; 6846 } 6847 return touches; 6848 } 6849 }; 6850 })(); 6851})(xfalib); 6852(function ($, _) { 6853 $.widget("xfaWidget.abstractWidget", { 6854 6855 $userControl: null, 6856 6857 $data: xfalib.ut.XfaUtil.prototype.$data, 6858 6859 $css: xfalib.ut.XfaUtil.prototype.$css, 6860 6861 getOrElse: xfalib.ut.Class.prototype.getOrElse, 6862 6863 dIndexOf: xfalib.ut.XfaUtil.prototype.dIndexOf, 6864 6865 btwn: xfalib.ut.XfaUtil.prototype.btwn, 6866 6867 logger: xfalib.ut.XfaUtil.prototype.getLogger, 6868
6869 localeStrings: xfalib.ut.XfaUtil.prototype.getLocaleStrings, 6870 6871 logMsgs: xfalib.ut.XfaUtil.prototype.getLogMessages, 6872 6873 errorManager: xfalib.ut.XfaUtil.prototype.getErrorManager, 6874 6875 _widgetName: "abstractWidget", 6876 6877 // if there are any specific black listed attributes, each widget should define their own 6878 _blackListedAttributes : ["type"], 6879 6880 options: { 6881 name: "", 6882 value: null, 6883 commitProperty: "value", 6884 displayValue: null, 6885 screenReaderText: null, 6886 tabIndex: 0, 6887 role: null, 6888 paraStyles: null, 6889 dir: null, 6890 errorMessage: null, 6891 warningMessage: null, 6892 hScrollDisabled: false, 6893 placeholder:"", 6894 isValid:true, 6895 mandatory: false 6896 }, 6897 6898 getOptionsMap: function () { 6899 return { 6900 "tabIndex": function (val) { 6901 this.$userControl.attr("tabindex", val); 6902 }, 6903 "role": function (val) { 6904 if (val) 6905 this.$userControl.attr("role", val); 6906 }, 6907 "screenReaderText": function (val) { 6908 if (val) 6909 this.$userControl.attr("aria-label", val) 6910 }, 6911 "paraStyles": function (val) { 6912 if (val) 6913 this.$css(this.$userControl.get(0), val); 6914 }, 6915 "dir": function (val) { 6916 if (val) 6917 this.$userControl.attr("dir", this.options.dir); 6918 }, 6919 "height": function (val) { 6920 if (val) { 6921 this.$css(this.$userControl[0], {"height": val}) 6922 } 6923 }, 6924 "width": function (val) { 6925 if (val) 6926 this.$css(this.$userControl[0], {"width": val}) 6927 }, 6928 "isValid": function (val) { 6929 if(val){ 6930 this.$userControl.removeAttr("aria-invalid"); 6931 } else { 6932 this.$userControl.attr("aria-invalid",true); 6933 } 6934 }, 6935 "color" : function(value) { 6936 if(!_.isEmpty(value)) { 6937 var color = "rgb(" + value + ")"; 6938 this.$css(this.$userControl[0], {"color": color}); 6939 } 6940 }, 6941 "font-style" : function (value) { 6942 if (!_.isEmpty(value)) { 6943 this.$css(this.$userControl[0], {"font-style": value}); 6944 } 6945 }, 6946 "mandatory" : function (value) { 6947 if(value){ 6948 this.$userControl.attr("aria-required", true); 6949 } else { 6950 this.$userControl.removeAttr("aria-required"); 6951 } 6952 } 6953 }; 6954 }, 6955 6956 getEventMap: function () { 6957 return { 6958 "focus": xfalib.ut.XfaUtil.prototype.XFA_ENTER_EVENT, 6959 "blur": xfalib.ut.XfaUtil.prototype.XFA_EXIT_EVENT, 6960 "click": xfalib.ut.XfaUtil.prototype.XFA_CLICK_EVENT 6961 }; 6962 }, 6963 6964 /** 6965 * Copies all the attributes from source jquery object to destination jquery object 6966 * @param $src source jquery object 6967 * @param $dest destination jquery object 6968 */ 6969 copyAttributesFromSrcToDest : function($src, $dest){ 6970 var that = this; 6971 // let's get all the attribute from the src element and copy it to dest jquery object 6972 if($src != null && $src[0] && $src[0].attributes && $dest != null){ 6973 $.each($src[0].attributes, function() { 6974 // we don't add the black listed set of attributes 6975 if(this.specified && this.value != null && _.isString(this.value) && this.value.length > 0 && that._blackListedAttributes.indexOf(this.name) === -1) { 6976 $dest.attr(this.name, this.value); 6977 } 6978 }); 6979 } 6980 }, 6981 6982 _create: function () { 6983 this.widgetEventPrefix = ""; 6984 this.element.addClass(this._widgetName); 6985 this.$userControl = this.render(); 6986 this.optionsHandler = this.getOptionsMap(); 6987 this.eventMap = this.getEventMap(); 6988 this._initializeOptions(); 6989 this._initializeEventHandlers(); 6990 this.errObj = this.errorManager(); 6991 //call it only after render 6992 // Dirty hack to prevent this being called in Guide 6993 if (typeof guidelib === "undefined") { 6994 this.$css(this.$userControl.get(0), { 6995 "box-sizing": "border-box", 6996 "position": "absolute" 6997 }); 6998 } 6999 }, 7000 7001 _initializeEventHandlers: function () { 7002 xfalib.ut.XfaUtil.prototype.getLogger().debug("xfa", "initialize event handlers for " + this._widgetName); 7003 _.each(this.eventMap, function (xfaevent, htmlevent) { 7004 var self = this; 7005 if (xfaevent) { 7006 if (!(xfaevent instanceof Array)) { 7007 xfaevent = [xfaevent]; 7008 } 7009 for (var i = 0; i < xfaevent.length; i++) { 7010 xfalib.ut.XfaUtil.prototype.getLogger().debug("xfa", "binding " + htmlevent + " with " + xfaevent[i]); 7011 this.$userControl.on(htmlevent, 7012 (function (xfevnt) { 7013 return function (evnt) { 7014 xfalib.ut.XfaUtil.prototype.getLogger().debug("xfa", "trigger " + evnt.type + 7015 " xfa-event " + xfevnt); 7016 self._preProcessEvent.apply(self, [xfevnt, evnt]); 7017 //since the fix https://github.com/jquery/jquery/pull/972, Fix for keeping namespace when triggering an event using an Event #972 7018 //we need to clear the namespace and its regular expression of triggering event, as the listeners are registered on un-namespaced events 7019 evnt.namespace = ""; 7020 evnt.namespace_re = ""; 7021 self._trigger(xfevnt, evnt); 7022 self._postProcessEvent.apply(self, [xfevnt, evnt]); 7023 } 7024 })(xfaevent[i]) 7025 ) 7026 7027 } 7028 } 7029 }, this) 7030 }, 7031 7032 _preProcessEvent: function (xfaevent, htmlevent) { 7033 if (xfaevent == this.options.commitEvent) { 7034 this.preProcessCommit(htmlevent); 7035 } 7036 switch (xfaevent) { 7037 case xfalib.ut.XfaUtil.prototype.XFA_ENTER_EVENT: 7038 this.preProcessEnter(htmlevent); 7039 break; 7040 case xfalib.ut.XfaUtil.prototype.XFA_EXIT_EVENT: 7041 this.preProcessExit(htmlevent); 7042 break; 7043 case xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT: 7044 this.preProcessChange(htmlevent); 7045 break; 7046 case xfalib.ut.XfaUtil.prototype.XFA_CLICK_EVENT: 7047 this.preProcessClick(htmlevent); 7048 break; 7049 } 7050 7051 }, 7052 7053 _postProcessEvent: function (xfaevent, htmlevent) { 7054 if (xfaevent == this.options.commitEvent) { 7055 this.postProcessCommit(htmlevent); 7056 } 7057 switch (xfaevent) { 7058 case xfalib.ut.XfaUtil.prototype.XFA_ENTER_EVENT: 7059 this.postProcessEnter(htmlevent); 7060 break; 7061 case xfalib.ut.XfaUtil.prototype.XFA_EXIT_EVENT: 7062 this.postProcessExit(htmlevent); 7063 break; 7064 case xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT: 7065 this.postProcessChange(htmlevent); 7066 break; 7067 case xfalib.ut.XfaUtil.prototype.XFA_CLICK_EVENT: 7068 this.postProcessClick(htmlevent); 7069 break; 7070 } 7071 }, 7072 7073 _initializeOptions: function () { 7074 _.each(this.optionsHandler, function (value, key) { 7075 if (typeof value === "function") 7076 value.apply(this, [this.options[key]]); // TODO: check whether it is needed for initialization or not 7077 }, this) 7078 }, 7079 7080 _setOption: function (key, value) { 7081 if (this.options[key] != value) { 7082 this.options[ key ] = value; 7083 if (typeof this.optionsHandler[key] === "function") { 7084 this.optionsHandler[key].apply(this, [this.options[key]]) 7085 } 7086 } 7087 }, 7088 7089 /** 7090 * @override 7091 */ 7092 option: function (key, value) { 7093 if (arguments.length === 1 && 7094 typeof key === "string" && 7095 this.options.hasOwnProperty(key) && 7096 this.options[key] === undefined) { 7097 return undefined; 7098 } 7099 return $.Widget.prototype.option.apply(this, arguments) 7100 }, 7101 7102 destroy: function () { 7103 this.$userControl.removeClass(this._widgetName); 7104 }, 7105 7106 7107 render: function () { 7108 var control; 7109 if (this.element.children().length > 0) { 7110 control = $(this.element.children().get(0)); 7111 } 7112 else 7113 control = this.element; 7114 control.attr("name", this.options.name) 7115 return control; 7116 }, 7117 7118 7119 preProcessCommit: function (evnt) { 7120 this.options.value = this.getCommitValue(); 7121 xfalib.ut.XfaUtil.prototype.getLogger().debug("xfa", "passing commit value " + this.options.value + 7122 "to model "); 7123 }, 7124 7125 getCommitValue: function () { 7126 7127 }, 7128 7129 preProcessExit: function (evnt) { 7130 7131 }, 7132 7133 preProcessEnter: function (evnt) { 7134 //Only focus the enabled widgets 7135 if (this.options.access === "open") { 7136 this._showError(); 7137 this.showValue(); 7138 } 7139 }, 7140 7141 preProcessChange: function (evnt) { 7142 7143 }, 7144 7145 preProcessClick: function (evnt) { 7146 7147 }, 7148 7149 postProcessCommit: function (evnt) { 7150 this.showDisplayValue(); 7151 }, 7152 7153 postProcessExit: function (evnt) { 7154 //Only for the enabled widgets 7155 if (this.options.access === "open") { 7156 this.showDisplayValue(); 7157 this._hideError(); 7158 } 7159 }, 7160 7161 postProcessEnter: function (evnt) { 7162 }, 7163 7164 postProcessChange: function (evnt) { 7165 7166 }, 7167 7168 postProcessClick: function (evnt) { 7169 7170 }, 7171 7172 showDisplayValue: function () { 7173 this.$userControl.val(this.options.displayValue) 7174 }, 7175 7176 /** 7177 * Checks if the edit value is same as value present in the user control(html form element) 7178 * @returns {boolean} 7179 */ 7180 _isValueSame : function(){ 7181 return (((this.options.value === null) && (this.$userControl.val() === "")) || (this.options.value === this.$userControl.val())); 7182 }, 7183 7184 showValue: function () { 7185 // May be $userControl doesn't have val(), using it as of now 7186 // If the value of the field is not same as edit value, only then set the value, this also solves IE bug of cursor 7187 // moving to the end of field on click 7188 if(!this._isValueSame()) { 7189 this.$userControl.val(this.options.value) 7190 } 7191 }, 7192 7193 focus: function () { 7194 var that = this; 7195 // setTimeout added to fix CQ-51141 7196 // While using setFocus API in adaptive form, the focus was not being set in TextBox on chrome 7197 // and also on click of caption of RadioButton/Checkbox, due to fast event execution, he
7197nce adding delay during focus. 7198 setTimeout(function(){ 7199 that.$userControl[0].focus(); 7200 }, 1); 7201 }, 7202 7203 click: function () { 7204 this.focus(); 7205 this.$userControl.triggerHandler("click"); // we do not want the exact click as might bubble up to the field. 7206 }, 7207 7208 /* widget specific code */ 7209 7210 _showError: function () { 7211 if(this.errObj && _.isFunction(this.errObj.onFieldEnter)) { 7212 this.errObj.onFieldEnter(this); 7213 } 7214 }, 7215 7216 _calculatePaddingForVAlign:function(diff){ 7217 var flagForMoz = $.browser.mozilla && !xfalib.ut.Utilities.isIE11() && 7218 this.options.multiLine, 7219 vAlignBottomOrTop = this.options.paraStyles && 7220 (this.options.paraStyles["vertical-align"] == "bottom" || 7221 this.options.paraStyles["vertical-align"] == "top"); 7222 7223 if(flagForMoz && vAlignBottomOrTop || $.browser.msie && this.options.multiLine) { 7224 return; 7225 } 7226 // to handle the edge cases, if the diff is like -0.01 the whole operation is getting aborted 7227 // this diff comes mainly due to scroll height getting rounded off when widgetHeight is like x.999999 7228 diff = (diff > -0.01) ? Math.abs(diff) : diff; 7229 if (this.options.paraStyles && diff > 0) { 7230 var vAlign = this.options.paraStyles["vertical-align"]; 7231 if (vAlign == "bottom") { 7232 diff = diff - this.options.paraStyles["padding-bottom"]; 7233 this.$userControl.css("padding-top", diff); 7234 this.padding = this.$userControl.css("padding-top"); 7235 } 7236 else if (vAlign == "top" || (vAlign != "middle" && vAlign == undefined)) { 7237 if (this.options.paraStyles["padding-top"]) 7238 diff = diff - this.options.paraStyles["padding-top"]; 7239 this.$userControl.css("padding-bottom", diff); 7240 this.padding = this.$userControl.css("padding-bottom"); 7241 } 7242 else if (this.options.multiLine && vAlign == "middle") { 7243 var newDiff = diff / 2; 7244 newDiff = newDiff - this.options.paraStyles["padding-bottom"]; 7245 if (this.options.paraStyles["padding-top"]) 7246 newDiff = newDiff + this.options.paraStyles["padding-top"]; 7247 this.$userControl.css("padding-top", newDiff); 7248 } 7249 } 7250 }, 7251 7252 _handleVAlignOnExit: function (evnt) { 7253 7254 if (!this.options.paraStyles) { 7255 //vAlign has to be handled only if there is paraStyles 7256 return; 7257 } 7258 var value = this.options.displayValue, 7259 lineHeight = xfalib.view.util.TextMetrics.measureExtent(value, {refEl: this.$userControl.get(0), maxHeight: -1}).height, 7260 widgetHeight = this.options.height, 7261 diff = widgetHeight - lineHeight; 7262 this._calculatePaddingForVAlign(diff); 7263 7264 }, 7265 7266 _handleVAlignOnEnter: function (evnt) { 7267 //Only align the enabled widgets 7268 var flagForIE = $.browser.msie && this.options.multiLine; 7269 if (this.options.paraStyles && !flagForIE) { 7270 var vAlign = this.options.paraStyles["vertical-align"]; 7271 if (vAlign == "bottom" && this.padding) 7272 this.$userControl.css("padding-top", this.padding); 7273 else if (vAlign == "top" && this.padding) 7274 this.$userControl.css("padding-bottom", this.padding); 7275 } 7276 }, 7277 7278 _hideError: function () { 7279 if(this.errObj && _.isFunction(this.errObj.onFieldExit)) { 7280 this.errObj.onFieldExit(this); 7281 } 7282 }, 7283 7284 markError: function (msg, type) { 7285 if(this.errObj && _.isFunction(this.errObj.markError)) { 7286 this.errObj.markError(this, msg, type); 7287 } 7288 }, 7289 7290 clearError: function () { 7291 if(this.errObj && _.isFunction(this.errObj.clearError)) { 7292 this.errObj.clearError(this); 7293 } 7294 }, 7295 7296 getEditValue: function(value) { 7297 if(this.options.editPattern == null) { 7298 return value; 7299 } 7300 try { 7301 return xfalib.ut.PictureFmt.format(value, this.options.editPattern); 7302 } catch(e) { 7303 return null; 7304 } 7305 }, 7306 7307 parseEditValue: function(value) { 7308 if(this.options.editPattern == null) { 7309 return value; 7310 } 7311 try { 7312 return xfalib.ut.PictureFmt.parse(value, this.options.editPattern); 7313 } catch(e) { 7314 return value; 7315 } 7316 } 7317 }); 7318})($, window._); 7319(function($) { 7320 $.widget( "xfaWidget.defaultWidget", $.xfaWidget.abstractWidget, { 7321 7322 _widgetName: "defaultWidget", 7323 7324 getOptionsMap: function() { 7325 var parentOptionsMap = $.xfaWidget.abstractWidget.prototype.getOptionsMap.apply(this,arguments); 7326 return $.extend({},parentOptionsMap,{ 7327 "access": function(val) { 7328 switch(val) { 7329 case "open" : 7330 this.$userControl.removeAttr("readOnly"); 7331 this.$userControl.removeAttr("aria-readonly"); 7332 this.$userControl.removeAttr("disabled"); 7333 this.$userControl.removeAttr("aria-disabled"); 7334 break; 7335 case "nonInteractive" : 7336 case "protected" : 7337 this.$userControl.attr("disabled", "disabled"); 7338 this.$userControl.attr("aria-disabled", "true"); 7339 break; 7340 case "readOnly" : 7341 this.$userControl.attr("readOnly", "readOnly"); 7342 this.$userControl.attr("aria-readonly", "true"); 7343 break; 7344 default : 7345 this.$userControl.removeAttr("disabled"); 7346 this.$userControl.removeAttr("aria-disabled"); 7347 break; 7348 } 7349 }, 7350 7351 "displayValue": function(val) { 7352 if(this.options.commitProperty) { 7353 if($.browser.mozilla && this.options.commitProperty == "value") { 7354 // on submitting form firefox does not remember autocomplete values, if updated through attr() 7355 this.$userControl.val(this._displayEmptyStringForIE(this.options.displayValue)); 7356 } else { 7357 this.$userControl.prop(this.options.commitProperty, this._displayEmptyStringForIE(this.options.displayValue)); 7358 this.$userControl.attr(this.options.commitProperty, this._displayEmptyStringForIE(this.options.displayValue)); 7359 } 7360 } else { 7361 this.logger().debug("xfaView", "[DefaultWidget._update], User Control or Commit Property is null"); 7362 } 7363 }, 7364 7365 "placeholder": function(value){ 7366 this.$userControl.attr("placeholder", value); 7367 } 7368 }); 7369 }, 7370 7371 _displayEmptyStringForIE: function(value){ 7372 /*CQ-69417: By default "null" is displayed in the comments text box 7373 "null" values shown in IE */ 7374 // CQ-69107 included check for edge as well 7375 return (value == null && xfalib.ut.XfaUtil.prototype.detectIE()) ? '' : value; 7376 }, 7377 7378 render : function() { 7379 var control = $.xfaWidget.abstractWidget.prototype.render.apply(this,arguments) 7380 this._attachEventHandlers(control) 7381 return control 7382 }, 7383 7384 getCommitValue: function() { 7385 var value = this.$userControl.val(); 7386 if(this.options.hScrollDisabled && !this.options.multiLine) 7387 var value = xfalib.ut.XfaUtil.prototype.splitStringByWidth(this.$userControl.val(),this.$userControl.width(),this.$userControl.get(0)) ; 7388 return value; 7389 }, 7390 7391 _attachEventHandlers: function($control) {
7392 $control.keydown($.proxy(this._handleKeyDown,this)); 7393 $control.keypress($.proxy(this._handleKeyPress,this)); 7394 $control.on('paste',$.proxy(this._handlePaste,this)); 7395 $control.on('cut',$.proxy(this._handleCut,this)); 7396 }, 7397 7398 _compositionUpdateCallback : function (event) { 7399 return false; 7400 }, 7401 7402 _attachCompositionEventHandlers : function($control) { 7403 var isComposing = false; // IME Composing going on 7404 var hasCompositionJustEnded = false; // Used to swallow keyup event related to compositionend 7405 // IME specific handling, to handle japanese languages max limit 7406 // since enter can also be invoked during composing, a special handling is done here 7407 var that = this, 7408 changeCaratPosition = function() { 7409 // change the carat selection position to further limit input of characters 7410 var range = window.getSelection(); 7411 range.selectAllChildren(that.$userControl[0]); 7412 range.collapseToEnd(); 7413 }; 7414 $control.keyup(function(event) { 7415 if (/*isComposing || */hasCompositionJustEnded) { 7416 if (that._compositionUpdateCallback(event)) { 7417 changeCaratPosition(); 7418 } 7419 // IME composing fires keydown/keyup events 7420 hasCompositionJustEnded = false; 7421 } 7422 }); 7423 $control.on("compositionstart", 7424 function(event) { 7425 isComposing = true; 7426 }) 7427 .on("compositionupdate", 7428 function(event) { 7429 // event.originalEvent.data refers to the actual content 7430 if (that._compositionUpdateCallback(event)) { 7431 changeCaratPosition(); 7432 } 7433 }) 7434 .on("compositionend", 7435 function(event) { 7436 isComposing = false; 7437 // some browsers (IE, Firefox, Safari) send a keyup event after 7438 // compositionend, some (Chrome, Edge) don't. This is to swallow 7439 // the next keyup event, unless a keydown event happens first 7440 hasCompositionJustEnded = true; 7441 }) 7442 .on("keydown", 7443 function(event) { 7444 // Safari on OS X may send a keydown of 229 after compositionend 7445 if (event.which !== 229) { 7446 hasCompositionJustEnded = false; 7447 } 7448 }); 7449 }, 7450 7451 _handleKeyDown : function(event){ 7452 if(event.keyCode == 13 || event.charCode == 13 || event.which == 13) // touch devices may return charCode 7453 event.preventDefault(); 7454 }, 7455 7456 _handleKeyPress : function(event){ 7457 if(event.keyCode == 13 || event.charCode == 13 || event.which == 13) // touch devices may return charCode 7458 event.preventDefault(); 7459 } 7460 }); 7461})($); 7462(function($, _) { 7463 var xfaUtil = xfalib.ut.XfaUtil.prototype; 7464 $.widget( "xfaWidget.dateTimeEdit", $.xfaWidget.defaultWidget, { 7465 7466 _widgetName : "dateTimeEdit", 7467 7468 getEventMap: function() { 7469 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getEventMap.apply(this,arguments); 7470 if(this._nativeWidget === false) { 7471 return $.extend({}, parentOptionsMap, { 7472 "onfocus1.datetimepicker": xfalib.ut.XfaUtil.prototype.XFA_ENTER_EVENT, 7473 "onvaluechange.datetimepicker": xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT, 7474 "onfocusout.datetimepicker": xfalib.ut.XfaUtil.prototype.XFA_EXIT_EVENT, 7475 "onoverlap.datetimepicker": xfalib.ut.XfaUtil.prototype.XFA_CLICK_EVENT, // Custom Event to fix BUG #3626974 7476 "input": xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT, // TODO : add handler for xfa.event.change 7477 "focus": null, 7478 "blur": null 7479 }) 7480 } else { 7481 return $.extend({}, parentOptionsMap, { 7482 "change": xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT 7483 }) 7484 } 7485 }, 7486 7487 _getAdobeDatePickerOptionsMap : function(parentOptionsMap) { 7488 return { 7489 "access" : function (val) { 7490 switch (val) { 7491 case "open" : 7492 this.$userControl.adobeDateTimePicker("access", true); 7493 break; 7494 case "nonInteractive" : 7495 case "protected" : 7496 case "readOnly" : 7497 this.$userControl.adobeDateTimePicker("access", false); 7498 break; 7499 } 7500 parentOptionsMap.access.apply(this, arguments); 7501 }, 7502 "displayValue" : function (val) { 7503 // set the value in the datepicker plugin 7504 this.$userControl.adobeDateTimePicker("value", this.options.value); 7505 // show the display value 7506 this.showDisplayValue(); 7507 } 7508 } 7509 }, 7510 7511 _getNativeDatePickerOptionsMap: function (parentOptionsMap) { 7512 return { 7513 "displayValue": function (val) { 7514 this.showDisplayValue(); 7515 } 7516 } 7517 }, 7518 7519 7520 getOptionsMap: function() { 7521 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this,arguments), 7522 datePickerOptions = this._nativeWidget === false ? this._getAdobeDatePickerOptionsMap(parentOptionsMap) 7523 : this._getNativeDatePickerOptionsMap(parentOptionsMap), 7524 commonOptions = { 7525 "paraStyles": function (paraStyles) { 7526 parentOptionsMap.paraStyles.apply(this, arguments); 7527 this._handleVAlignOnExit(); 7528 }, 7529 7530 "access": function(val) { 7531 // update width on change of access (as width of widget is dependent on access) 7532 // The calender icon should be hidden, and widget should take full space when readOnly 7533 parentOptionsMap.access.apply(this, arguments); 7534 this.getOptionsMap().width.apply(this,[this.options.width]); 7535 }, 7536 "width": function (val) { 7537 parentOptionsMap.width.apply(this, arguments); 7538 if (this.options.showCalendarIcon && val && this.options.access == "open") { 7539 var effectiveWidth = val > this.options.calendarIconWidth ? val - this.options.calendarIconWidth : val; 7540 this.$userControl.width(effectiveWidth); // leave space for the cal icon 7541 } 7542 }, 7543 7544 "height": function(val) { 7545 parentOptionsMap.height.apply(this, arguments); 7546 this._handleVAlignOnExit(); 7547 }, 7548 "screenReaderText": function (val) { 7549 var editPattern = this.options.editPattern; 7550 var defaultEditPattern = this._nativeWidget ? "mm/dd/yyyy" : "YYYY-MM-DD"; 7551 var regex = /(?:date){0,1}{(.*)}/;
7551 // date{<pattern>} or {<pattern>} both are valid as per xfa spec 7552 editPattern = typeof editPattern === "string" ? editPattern.match(regex)[1] : defaultEditPattern; 7553 var defaultLabel = "Please Enter date in {0} format only"; 7554 if (editPattern) { 7555 var ariaLabel = xfalib.ut.LocalizationUtil.prototype.getLocalizedMessage("", 7556 xfalib.locale.Strings.datePickerAriaLabel || defaultLabel, [editPattern]) 7557 } 7558 var finalVal = val !== undefined ? val + " " + ariaLabel : val; 7559 this.$userControl.attr("aria-label", finalVal); 7560 } 7561 }; 7562 return $.extend({},parentOptionsMap,datePickerOptions, commonOptions); 7563 }, 7564 7565 postProcessExit: function(evnt) { 7566 $.xfaWidget.defaultWidget.prototype.postProcessExit.apply(this,arguments); 7567 this._handleVAlignOnExit (); 7568 }, 7569 7570 preProcessEnter: function(evnt) { 7571 $.xfaWidget.defaultWidget.prototype.preProcessEnter.apply(this,arguments); 7572 this._handleVAlignOnEnter(); 7573 }, 7574 7575 preProcessChange: function(evnt) { 7576 //CQ-46332:loss of date value in date-picker , setting the value here or else 7577 //it gets lost during focus 7578 if(this._nativeWidget === true){ 7579 this.options.value = this.$userControl.val(); 7580 } 7581 }, 7582 7583 showDisplayValue: function() { 7584 if(this._nativeWidget === false) { 7585 $.xfaWidget.defaultWidget.prototype.showDisplayValue.apply(this, arguments); 7586 } else { 7587 this.showValue(); 7588 } 7589 }, 7590 7591 7592 showValue: function () { 7593 if (this._nativeWidget == false) { 7594 this.$userControl.adobeDateTimePicker("value", this.options.value); 7595 } else { 7596 $.xfaWidget.defaultWidget.prototype.showValue.apply(this, arguments); 7597 } 7598 $.xfaWidget.textField.prototype._selectOnFocusInIE.apply(this, arguments); 7599 }, 7600 7601 getCommitValue: function() { 7602 if (this._nativeWidget === false) { 7603 var value = this.$userControl.adobeDateTimePicker("value"), 7604 parsedValue = this.parseEditValue(value); 7605 return parsedValue; 7606 } 7607 return $.xfaWidget.defaultWidget.prototype.getCommitValue.apply(this, arguments); 7608 }, 7609 7610 render: function() { 7611 var self = this, 7612 textStyle = this.getOrElse(this.$data(this.element.get(0), "xfamodel"), "textstyle", ""), 7613 $control = $.xfaWidget.abstractWidget.prototype.render.apply(this, arguments), 7614 $source = $control, 7615 id, 7616 existingInlineStyleAttributeValues, 7617 newInlineStyleAttributeValues, 7618 combinedInlineStyleAttributeValues; 7619 existingInlineStyleAttributeValues = this.element.find("input").attr("style") || ''; 7620 this._nativeWidget = true; 7621 if(this.options.useNativeWidget === false || $control[0].type !== "date") { 7622 this._nativeWidget = false; 7623 id = this.element.find("input")[0].id; 7624 this.element.children().remove(); 7625 $("<div></div>").css({position: "relative", width: "100%", height: "100%"}) // want to fill entire width of containing table cell 7626 .append($("<input type='text'/>")) 7627 .appendTo(this.element); 7628 $control = $("input", this.element). 7629 attr("style", textStyle). 7630 attr("name", this.options.name). 7631 attr("id", id). 7632 adobeDateTimePicker({ 7633 positioning: this.element, 7634 locale: { 7635 months: this.options.months, 7636 days: this.options.days, 7637 zero: this.options.zero, 7638 clearText: this.options.clearText 7639 }, 7640 access: this.options.access, 7641 value: this.options.value, 7642 showCalendarIcon: this.options.showCalendarIcon, 7643 iconWidth: this.options.calendarIconWidth, 7644 minValidDate : this.options.minValidDate, 7645 maxValidDate : this.options.maxValidDate, 7646 exclMinDate : this.options.exclMinDate, 7647 exclMaxDate : this.options.exclMaxDate, 7648 editValue: function (value) { 7649 return self.getEditValue(value); 7650 } 7651 }); 7652 } 7653 this._attachEventHandlers($control); 7654 newInlineStyleAttributeValues = this.element.find("input").attr("style") || ''; 7655 //append the previous inlineStyleAttributeValues to newInlineStyleAttributeValues so that the inline styles 7656 //added from the dialog are applied. 7657 combinedInlineStyleAttributeValues = newInlineStyleAttributeValues + existingInlineStyleAttributeValues; 7658 this.element.find("input").attr("style", combinedInlineStyleAttributeValues); 7659 // only in case of adaptive form, we would copy the attributes back 7660 if(window.guideBridge) { 7661 // restore the original attribute back to destination object 7662 this.copyAttributesFromSrcToDest($source, this.element.find("input")); 7663 } 7664 return $control; 7665 } 7666 }) ; 7667 7668})($, _); 7669(function($, _) { 7670$.widget("xfaWidget.numericInput", $.xfaWidget.defaultWidget, { 7671 7672 _widgetName: "numericInput", 7673 7674 options : { 7675 value : null, 7676 curValue: null, 7677 pos: 0, 7678 lengthLimitVisible: true, 7679 zero:"0",
7680 decimal:".", 7681 minus:"-" 7682 }, 7683 7684 //TODO: to support writing in different locales \d should be replaced by [0-9] for different locales 7685 _matchArray : { 7686 "integer":"^[+-]?{digits}*$", 7687 "decimal":"^[+-]?{digits}{leading}({decimal}{digits}{fraction})?$", 7688 "float":"^[+-]?{digits}*({decimal}{digits}*)?$" 7689 }, 7690 7691 _regex : null, 7692 7693 _engRegex : null, 7694 7695 _writtenInLocale : false, 7696 7697 _previousCompositionVal : "", 7698 7699 7700 _toLatinForm : function (halfOrFullWidthStr) { 7701 // refer http://www.fileformat.info/info/unicode/block/halfwidth_and_fullwidth_forms/utf8test.htm 7702 return halfOrFullWidthStr.replace( 7703 /[\uff00-\uffef]/g, 7704 function(ch) { return String.fromCharCode(ch.charCodeAt(0) - 0xfee0); } 7705 ); 7706 }, 7707 7708 getOptionsMap: function() { 7709 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this,arguments); 7710 return $.extend({},parentOptionsMap,{ 7711 "paraStyles": function(paraStyles){ 7712 parentOptionsMap.paraStyles.apply(this,arguments); 7713 this._handleVAlignOnExit (); 7714 } , 7715 7716 "height": function(val) { 7717 if(val) { 7718 this.$css(this.$userControl[0],{"height" :val}); 7719 this._handleVAlignOnExit(); // To Handle the case of expandable Fields 7720 } 7721 } 7722 7723 }) 7724 }, 7725 7726 getEventMap: function() { 7727 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getEventMap.apply(this,arguments); 7728 return $.extend({},parentOptionsMap,{ 7729 "onKeyInput.numericInput" : xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT 7730 }) 7731 }, 7732 7733 _getDigits: function() { 7734 var zeroCode = this.options.zero.charCodeAt(0), 7735 digits = ""; 7736 for(var i = 0;i < 10;i++) { 7737 digits += String.fromCharCode(zeroCode + i); 7738 } 7739 return "["+digits+"]" 7740 }, 7741 7742 _escape: function(str) { 7743 return str.replace(".","\\.") 7744 }, 7745 7746 postProcessExit: function(evnt) { 7747 $.xfaWidget.defaultWidget.prototype.postProcessExit.apply(this,arguments); 7748 this._handleVAlignOnExit (); 7749 }, 7750 7751 preProcessEnter: function(evnt) { 7752 $.xfaWidget.defaultWidget.prototype.preProcessEnter.apply(this,arguments); 7753 this._handleVAlignOnEnter(); 7754 }, 7755 7756 render : function() { 7757 var matchStr = this._matchArray[this.options.dataType]; 7758 if(matchStr) { 7759 var ld = this.options.leadDigits, 7760 fd = this.options.fracDigits, 7761 ldstr = ld && ld != -1 ? "{0,"+ld+"}" 7762 : "*", 7763 fdstr = fd && fd != -1 ? "{0,"+fd+"}" 7764 : "*", 7765 matchStr = matchStr.replace("{leading}",ldstr) 7766 .replace("{fraction}",fdstr), 7767 localeStr = matchStr.replace(/{digits}/g,this._getDigits()) 7768 .replace("{decimal}",this._escape(this.options.decimal)), 7769 engStr = matchStr.replace(/{digits}/g,"[0-9]") 7770 .replace("{decimal}","\\.") 7771 this._processValue = !(this._getDigits() == "[0123456789]" && this.options.decimal == ".") 7772 this._regex = new RegExp(localeStr, "g"); 7773 this._engRegex = new RegExp(engStr, "g"); 7774 } 7775 return $.xfaWidget.defaultWidget.prototype.render.apply(this, arguments); 7776 }, 7777 7778 getCommitValue: function() { 7779 var value = $.xfaWidget.defaultWidget.prototype.getCommitValue.apply(this, arguments); 7780 // we support full width, half width and locale specific numbers 7781 value = this._toLatinForm(value); 7782 if(value.length > 0 && this._processValue && !value.match(this._engRegex)) { 7783 this._writtenInLocale = true; 7784 value = this._convertValueFromLocale(value); 7785 } else { 7786 this._writtenInLocale = false 7787 } 7788 if(value && value.length >= this.options.combCells ) 7789 value = value.slice(0,this.options.combCells); 7790 this._previousCompositionVal = value; 7791 return value; 7792 }, 7793 7794 _compositionUpdateCallback : function (event) { 7795 var that = this; 7796 var flag = false;
7797 var leadDigits = that.options.leadDigits; 7798 var fracDigits = that.options.fracDigits; 7799 // we don't check use-case where just fracDigits is set since in case of composition update, the value to update is not known 7800 if (leadDigits !== -1) { 7801 var val = that.$userControl.val(); 7802 if (event.type === "compositionupdate" && event.originalEvent.data) { 7803 val = val + event.originalEvent.data.substr(event.originalEvent.data.length - 1); 7804 } 7805 // can't use the existing regex (since current regex checks for english digits), rather doing leadDigit compare 7806 var totalLength = leadDigits + (fracDigits !== -1 ? (fracDigits + that.options.decimal.length) : 0); 7807 if (val.indexOf(that.options.decimal) === -1) { 7808 totalLength = leadDigits; 7809 } 7810 var latinVal = this._toLatinForm(val); 7811 // match both since we support full width, half width and locale specific input 7812 var match = latinVal.match(that._regex)|| latinVal.match(this._engRegex); 7813 flag = !match; 7814 if (match === null) { 7815 // entered invalid character, revert to previous value 7816 that.$userControl.val(that._previousCompositionVal); 7817 flag = true; 7818 } else if (flag) { 7819 // if max reached 7820 var newVal = val.substr(0, totalLength); 7821 that.$userControl.val(newVal); 7822 that._previousCompositionVal = newVal; 7823 flag = true; 7824 } else { 7825 that._previousCompositionVal = val; 7826 } 7827 } 7828 return flag; 7829 }, 7830 7831 _attachEventHandlers : function($control) { 7832 $.xfaWidget.defaultWidget.prototype._attachEventHandlers.apply(this, arguments); 7833 // IME specific handling, to handle japanese languages max limit 7834 $.xfaWidget.defaultWidget.prototype._attachCompositionEventHandlers.apply(this, arguments); 7835 }, 7836 7837 _handleKeyInput : function(event, character, code){ 7838 if(event.ctrlKey && !_.contains(['paste', 'cut'], event.type)) { 7839 return true; 7840 } 7841 7842 $.xfaWidget.defaultWidget.prototype._handleKeyDown.apply(this,arguments); 7843 this.options.lengthLimitVisible = true; 7844 7845 var val = this.$userControl.prop(this.options.commitProperty) || '', 7846 // if selectionStart attribute isn't supported then its value will be undefined 7847 selectionStart = xfalib.view.util.HtmlUtil.getHTMLSupportedAttr(this.$userControl[0], "selectionStart"), 7848 isSelectionAttrSupported = !(selectionStart === undefined || selectionStart === null), 7849 selectionStart = selectionStart || 0, 7850 selectionEnd = xfalib.view.util.HtmlUtil.getHTMLSupportedAttr(this.$userControl[0], "selectionEnd") || 0, 7851 combCells = parseInt(this.options.combCells) || 0, 7852 current, 7853 change = character; 7854 7855 if (combCells > 0 ) { 7856 change = character.substr(0, combCells - val.length + selectionEnd - selectionStart); 7857 } 7858 7859 current = val.substr(0, selectionStart) + change + val.substr(selectionEnd); 7860 // done to handle support for both full width, half width or mixed input in number field 7861 var latinCurrentValue = this._toLatinForm(current); 7862 7863 // we want to check regex first and then see whether it was numeric or not. 7864 if (!(this._regex == null || latinCurrentValue.match(this._regex) || latinCurrentValue.match(this._engRegex))) { 7865 event.preventDefault(); 7866 return false; 7867 } 7868 7869 // CQ-4245407 : selectionStart and selectionEnd attributes aren't supported in case of input type = number 7870 // it is used for providing native HTML5 implementation for numeric field, so no further processing is required 7871 // As it is specific to AF and AF doesn't support change event on each keypress, so this change should be fine 7872 if (!isSelectionAttrSupported) { 7873 return true; 7874 } 7875 7876 if (!_.contains(['keydown', 'cut'], event.type) && combCells && (val.length >= combCells || current.length > combCells) && selectionStart === selectionEnd) { 7877 event.preventDefault(); 7878 return false;
7879 } 7880 7881 this.options.curValue = val; 7882 this._previousCompositionVal = val; 7883 this.options.pos = selectionStart; 7884 7885 if(this.options.hScrollDisabled && !_.contains(['keydown', 'cut'], event.type)) { 7886 var expectedWidth = xfalib.view.util.TextMetrics.measureExtent(current, {refEl: this.$userControl[0], maxWidth:-1}).width; 7887 if(!event.ctrlKey && expectedWidth > this.$userControl.width() - 5){ 7888 event.preventDefault(); 7889 this.options.lengthLimitVisible = false; 7890 } 7891 } 7892 7893 this.$userControl.trigger({ 7894 type : "onKeyInput.numericInput", 7895 originalType : event.type, 7896 character : character, // contains the pasted string or pressed key 7897 keyCode : event.keyCode || 0, 7898 charCode : event.charCode || 0, 7899 which : event.which || 0, 7900 ctrlKey : event.ctrlKey || event.metaKey || false, 7901 shiftKey : event.shiftKey || false, 7902 keyDown : false, // This property is available only for list boxes and drop-down lists 7903 selectionStart: selectionStart, 7904 selectionEnd: selectionEnd 7905 }); 7906 }, 7907 7908 _handleKeyDown : function(event){ 7909 if (event) { 7910 var code = event.charCode || event.which || event.keyCode || 0; 7911 if(code == 8 || code == 46) // backspace and del 7912 this._handleKeyInput(event, "", code); 7913 else if(code == 32) { // suppress space 7914 event.preventDefault(); 7915 return false; 7916 } 7917 } 7918 }, 7919 7920 _isValidChar: function (character) { 7921 character = this._toLatinForm(character); 7922 var lastSingleDigitChar = String.fromCharCode(this.options.zero.charCodeAt(0) + 9); 7923 // we only full width, half width and also locale specific if customer has overlayed the i18n file 7924 return (character >= "0" && character <= "9") || (character>=this.options.zero && character<=lastSingleDigitChar) || character===this.options.decimal || character===this.options.minus; 7925 }, 7926 7927 _handleKeyPress : function(event){ 7928 if (event) { 7929 var code = event.charCode || event.which || event.keyCode || 0, 7930 character = String.fromCharCode(code); 7931 7932 if(xfalib.ut.XfaUtil.prototype.isNonPrintableKey(event.key)) { // mozilla also generates a keypress, along with keydown 7933 return true; // for all keys, so only handling printable keys in keypress 7934 } 7935 7936 if (this._isValidChar(character)) 7937 this._handleKeyInput(event, character, code); 7938 else if (!event.ctrlKey){ 7939 event.preventDefault(); 7940 return false; 7941 } 7942 } 7943 }, 7944 7945 _handlePaste : function(event){ 7946 if (event) { 7947 var pastedChar = undefined; 7948 if (window.clipboardData && window.clipboardData.getData) { // IE 7949 pastedChar = window.clipboardData.getData('Text'); 7950 } else if (event.originalEvent.clipboardData && event.originalEvent.clipboardData.getData) { 7951 pastedChar = event.originalEvent.clipboardData.getData('text/plain'); 7952 } 7953 7954 if(pastedChar) { 7955 var allPastedCharsValid = _.every(pastedChar.split(''), function (character) { 7956 return this._isValidChar(character); 7957 }, this); 7958 if (allPastedCharsValid) { 7959 // during paste we support both half width, full width and locale specific numbers 7960 pastedChar = this._toLatinForm(pastedChar); 7961 this._handleKeyInput(event, pastedChar, 0); 7962 } 7963 else if (!event.ctrlKey) { 7964 event.preventDefault(); 7965 return false; 7966 } 7967 } 7968 } 7969 }, 7970 7971 _handleCut : function(event) { 7972 if (event) { 7973 this._handleKeyInput(event, "", 0); 7974 } 7975 }, 7976 // CQ-107886 : added handling for negative values, as for '-', '-3' was getting returned 7977 _convertValueToLocale: function(val) { 7978 var zeroCode = this.options.zero.charCodeAt(0); 7979 return _.map(val,function(c) { 7980 if(c == ".") { 7981 return this.options.decimal; 7982 } else if(c == "-") { 7983 return this.options.minus; 7984 } else { 7985 return String.fromCharCode(parseInt(c) + zeroCode); 7986 } 7987 },this).join(""); 7988 }, 7989 7990 _convertValueFromLocale: function(val) { 7991 val = this._toLatinForm(val); 7992 var zeroCode = this.options.zero.charCodeAt(0); 7993 return _.map(val,function(c) { 7994 if(c == this.options.decimal) { 7995 return "."; 7996 } else if(c == this.options.minus) { 7997 return "-"; 7998 } else { 7999 return (c.charCodeAt(0) - zeroCode).toString(); 8000 } 8001 },this).join(""); 8002 }, 8003 8004 showValue : function() { 8005 // if the value is same, don't do anything 8006 if(!this._isValueSame()){ 8007 if(this.options.value && this._writtenInLocale) { 8008 this.$userControl.val(this._convertValueToLocale(this.options.value)) 8009 } else { 8010 this.$userControl.val(this.options.value) 8011 } 8012 } 8013 //IE doesn't show selected text if we focus and set its value all the time so force selection 8014 $.xfaWidget.textField.prototype._selectOnFocusInIE.apply(this, arguments); 8015 } 8016}); 8017})($, window._);(function ($, _) { 8018 $.widget("xfaWidget.dropDownList", $.xfaWidget.defaultWidget, { //commitEvent: change; commitProperty: value<Array> 8019 8020 _widgetName: "dropDownList", 8021 8022 options: { 8023 value: [], 8024 items: [], 8025 editable: false, 8026 placeholder: "", 8027 displayValue: [] 8028 }, 8029 8030 widgetSkeleton: '<select name="" style="" size = "1"></select>', 8031 optionSkeleton: '<option data-user-option></option>', 8032 optGroupSkeleton: '<optgroup label=""></optgroup>', 8033 AF_OPTGROUP_NAME: "afOptGroupName", 8034 PLACE_HOLDER_STYLE_CLASS : "placeHolder", 8035 8036 getOptionsMap: function () { 8037 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this, arguments); 8038 return $.extend({}, parentOptionsMap, { 8039 "value": function (val) { 8040 if (!_.isArray(val)) { 8041 val = [val]; 8042 } 8043 var selectedOptionFound = false, 8044 that = this; 8045 //sync option selection as per new values 8046 $("option", this.$userControl).each(function (index) { 8047 var selectValue = $(this).val(); 8048 //Check if this value is present in options value array 8049 if (_.contains(val, selectValue)) { 8050 $(this).prop("selected", true); 8051 selectedOptionFound = true; 8052 } else { 8053 $(this).prop("selected", false); 8054 if (this.id === "emptyValue") { 8055 $(this).val("").html(that.options.placeholder); 8056 //Hiding emptyValue with no placeholder text configured. 8057 if(that.options.placeholder.length == 0) { 8058 $(this).hide(); 8059 } 8060 } 8061 } 8062 }); 8063 8064 /* Add default option if : 8065 / 1. If placeholder add an extra option 8066 / 2. If the value is set anything other than the options (and null/"") create a new option 8067 */ 8068 if ((!selectedOptionFound && val.length != 0 && val[0] != null) || that.options.placeholder.length != 0) { 8069 if (this.$userControl.children('[data-empty-option]').length == 0) { 8070 var extraOption = document.createElement("option"); 8071 extraOption.setAttribute("data-empty-option", ""); 8072 extraOption.setAttribute("role", "none"); 8073 extraOption.setAttribute("value", "") 8074 this.$userControl[0].insertBefore(extraOption, this.$userControl[0].firstChild); 8075 } 8076 // If placeholder is present the set value of empty option to placeholder 8077 if (that.options.placeholder.length != 0) { 8078 this.$userControl.children('[data-empty-option]').text(that.options.placeholder); 8079 } 8080 // If placeholder is present and value is not present then select placeholder 8081 if (val.length == 0 || val[0] == null) { 8082 this.$userControl.children('[data-empty-option]').prop("selected", true); 8083 } // If value is set anything other than option then set empty option to value 8084 else if (!selectedOptionFound && val.length != 0 && val[0] != null) { 8085 this.$userControl.children('[data-empty-option]').text(val[0]). 8086 prop("selected", true). 8087 val(_.escape(val[0])). 8088 show(); 8089 } 8090 8091 } 8092 else if (that.options.placeholder.length == 0) { 8093 // Delete default option if value is found in options while adding options 8094 if (selectedOptionFound && this.$userControl.children('[data-empty-option]').val() != that.options.displayValue) { 8095 if (this.$userControl.children('[data-empty-option]').length > 0) { 8096 this.$userControl[0].removeChild(this.$userControl.children('[data-empty-option]')[0]); 8097 } 8098 } 8099 // Reset the value of dropdown based on rule 8100 else if (!selectedOptionFound && (val.length == 0 || val == null || val[0] == null)) { 8101 this.$userControl[0].value = ""; 8102 } 8103 } 8104 this.$userControl.toggleClass(this.PLACE_HOLDER_STYLE_CLASS, val.length == 0 || val == null); 8105 }, 8106 8107 "items": function (val) { 8108 if (!_.isArray(val)) { 8109 val = [val]; 8110 } 8111 8112 var AF_OPTGROUP_NAME = "afOptGroupName"; 8113 var i, j, optgroupOptions = [], element, $viewOptgroup, $preOptgroup; 8114 var viewOptgroups = $("optgroup", this.$userControl); 8115 // Removes all options which earlier didn't belong to any optgroup. 8116 if (viewOptgroups.length == 0) { 8117 // save selected value because when value is set before items in setWidgetOptions 8118 // the selected value would get lost in html 8119 var selectedOption = this.$userControl.find('[selected]'); 8120 this.$userControl.children("option[data-user-option]").remove(); 8121 } 8122 for (i = 0, j = 0; j < val.length; j++) { 8123 element = val[j]; 8124 if (element.save != AF_OPTGROUP_NAME) { 8125 // Add options to String[] which will be later synced to the optgroup. 8126 optgroupOptions.push(element); 8127 } else { 8128 $viewOptgroup = viewOptgroups[i++]; 8129 // When optgroup is less than the required optgroups. 8130 if (i > viewOptgroups.length) { 8131 $viewOptgroup = this.addGroup(element.display); 8132 } 8133 // Undefined as it may not occur even once when list is purely of options. 8134 if (!_.isUndefined($viewOptgroup) && $viewOptgroup.label != element.display) { 8135 $viewOptgroup.label = element.display || ''; 8136 } 8137 // Check to skip the first optgroup. 8138 if (j != 0) { 8139 // Syncs options to the prev optgroup. 8140 // Prev optgroup because current optgroup marks the end of options of prev. 8141 this.handleOptions($preOptgroup, optgroupOptions); 8142 // Clear options of the optgroup for next optgroup. 8143 optgroupOptions = []; 8144 } 8145 $preOptgroup = $viewOptgroup; 8146 } 8147 } 8148 // Removes all extra optgroups. 8149 while (i < viewOptgroups.length) { 8150 $viewOptgroup = viewOptgroups[i++]; 8151 this.deleteGroup($viewOptgroup.label); 8152 } 8153 //Add remaining options to respective optgroup. 8154 if (optgroupOptions.length != 0) { 8155 this.handleOptions($preOptgroup, optgroupOptions, selectedOption); 8156 } 8157 8158 //Intentionally left the selection check -> I am relying on the fact that "value" sync event is called after "items" sync. 8159 }, 8160 8161 "displayValue": function () { 8162 }, 8163 "placeholder": function(value){ 8164 // overriding the default handling of place holder options setter 8165 }, 8166 "access": function (val) { 8167 switch (val) { 8168 case "open" : 8169 this.$userControl.removeAttr("disabled"); 8170 this.$userControl.removeAttr("aria-disabled"); 8171 this.$userControl.removeAttr("aria-readonly"); 8172 var options = this.$userControl[0]; 8173 if(options && options.length > 0) { 8174 _.each(this.$userControl[0], function (element) { 8175 element.removeAttribute("disabled"); 8176 }); 8177 } 8178 break; 8179 case "nonInteractive" : 8180 case "protected" : 8181 // In case of nonInteractive and protected, field should be disabled and cannot be tabbed. 8182 this.$userControl.attr("disabled", "disabled"); 8183 case "readOnly" : 8184 this.$userControl.attr("aria-disabled", "true"); 8185 this.$userControl.attr("aria-readonly", "true"); 8186 var options = this.$userControl[0]; 8187 if(options && options.length > 0) { 8188 _.each(this.$userControl[0], function (element) { 8189 element.disabled = true; 8190 }); 8191 } 8192 break; 8193 default : 8194 this.$userControl.removeAttr("disabled"); 8195 this.$userControl.removeAttr("aria-disabled"); 8196 this.$userControl.removeAttr("aria-readonly"); 8197 break; 8198 } 8199 } 8200 }) 8201 }, 8202 8203 getEventMap: function () { 8204 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getEventMap.apply(this, arguments); 8205 return $.extend({}, parentOptionsMap, { 8206 "focus": [xfalib.ut.XfaUtil.prototype.XFA_ENTER_EVENT, xfalib.ut.XfaUtil.prototype.XFA_PREOPEN_EVENT], 8207 "change": xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT 8208 }) 8209 }, 8210 8211 render: func
8211tion () { 8212 var existingInlineStyleAttributeValues = this.element.find("select").attr("style"), 8213 newInlineStyleAttributeValues, 8214 combinedInlineStyleAttributeValues, 8215 size = 1; 8216 8217 this.element.addClass(this._widgetName); 8218 this.element.children().remove(); 8219 8220 var inputName = _.uniqueId("select"), //Unique Id 8221 textStyle = this.getOrElse(this.$data(this.element.get(0), "xfamodel"), "textstyle", ""), 8222 $widgetSkeleton = $(this.widgetSkeleton) 8223 .attr('style', textStyle) 8224 .attr('name', inputName); 8225 if(this.options.editable) { 8226 $widgetSkeleton.addClass('combobox'); 8227 } 8228 8229 if(this.options.items && this.options.items.length>0){ 8230 size = this.options.items.length 8231 } 8232 if(this.options.multiSelect) { 8233 $widgetSkeleton.addClass('multiDropdown'); 8234 $widgetSkeleton.attr('multiple','multiple'); 8235 $widgetSkeleton.attr('size',size); 8236 $widgetSkeleton.attr('data-multiple-selection',"true"); 8237 } 8238 8239 var $parEl = $widgetSkeleton; 8240 _.each(this.options.items, function(item){ 8241 var saveItem = _.isString(item.save) ? item.save.replace(/\"/g, """) : ""; 8242 if (saveItem === this.AF_OPTGROUP_NAME){ // assuming optgroups appear before options 8243 $parEl = $(this.optGroupSkeleton).attr('label', item.display).appendTo($widgetSkeleton); 8244 } else { 8245 $(this.optionSkeleton).val(saveItem).text(item.display).appendTo($parEl); 8246 } 8247 },this); 8248 8249 this.element.append($widgetSkeleton); 8250 8251 var control = this.element.children().eq(0).attr("name", this.options.name); 8252 this._attachEventHandlers(control); 8253 newInlineStyleAttributeValues = this.element.find("select").attr("style"); 8254 //append the previous inlineStyleAttributeValues to newInlineStyleAttributeValues so that the inline styles 8255 //added from the dialog are applied. 8256 combinedInlineStyleAttributeValues = newInlineStyleAttributeValues + existingInlineStyleAttributeValues; 8257 this.element.find("select").attr("style", combinedInlineStyleAttributeValues); 8258 return control; 8259 }, 8260 8261 //syncs the options to the optgroup dynamically. 8262 handleOptions : function ($viewOptgroup, val, selectedOption) { 8263 //When the list so far consists purely of options. 8264 if (_.isUndefined($viewOptgroup)) { 8265 $viewOptgroup = this.$userControl[0]; 8266 } 8267 var viewOptions = $("option[data-user-option]", $viewOptgroup); 8268 //Syncs the value of options. 8269 for (var i = 0, j = 0; i < viewOptions.length && j < val.length; i++, j++) { 8270 var $viewOption = viewOptions[i]; 8271 var element = val[j]; 8272 if ($viewOption.text != element.display) { 8273 $viewOption.text = element.display || ''; 8274 } 8275 if ($viewOption.value != element.save) { 8276 $viewOption.value = element.save || ''; 8277 } 8278 } 8279 //Deletes options if count is more than required. 8280 while (i < viewOptions.length) { 8281 this.deleteOption(viewOptions[i++]) 8282 } 8283 //Add options if count is less than required. 8284 while (j < val.length) { 8285 this.addOption($viewOptgroup, val[j++], selectedOption); 8286 } 8287 // Set empty value to dropdown if placeholder and default value is not present 8288 if (this.options.placeholder.length == 0) { 8289 if (this.checkForEmptyValue(this.options.value)) { 8290 this.$userControl[0].value = ""; 8291 } 8292 } 8293 // since options are removed and added again during items we need to set the access again options. 8294 this.optionsHandler["access"].apply(this, [this.options["access"]]); 8295 }, 8296 8297 addOption : function ($viewOptgroup, element, selectedOption) { 8298 var $newOption = $(this.optionSkeleton).val(element.save).text(element.display); 8299 $newOption.appendTo($viewOptgroup); 8300 if(selectedOption) { 8301 if(element.save === selectedOption.val() && element.display === selectedOption.text()) { 8302 $newOption.prop("selected", true); 8303 } 8304 } 8305 // Since the displayValue is a '\n' separated string of selected values in case of multiSelect, 8306 // we convert it to an array and check whether that array contains the save value of the element 8307 var values; 8308 if (this.options.value && _.isString(this.options.value)) { 8309 values = this.options.value.split('\n'); 8310 } else if (_.isArray(this.options.value)) { 8311 // In the case of AF we have value/displayValue as an array 8312 values = this.options.value 8313 } 8314 if (values && values.indexOf(element.save) >= 0) { 8315 //Delete emptyValue with no placeholder text configured and value is found in options 8316 if (this.options.placeholder.length == 0 && this.$userControl.children('[data-empty-option]').length > 0) { 8317 this.$userControl[0].removeChild(this.$userControl.children('[data-empty-option]')[0]); 8318 } 8319 this.$userControl.children().filter(function() { 8320 return this.value == element.save; 8321 }).prop("selected", true); 8322 } 8323 }, 8324 8325 deleteOption: function ($viewOption) { 8326 this.$userControl.find('option[value='+$viewOption.value+']').remove(); 8327 }, 8328 8329 checkForEmptyValue: function(value) { 8330 if ((value && _.isArray(value) && value[0] == null) || (this.options.value == null)) 8331 return true; 8332 else 8333 return false;
8334 }, 8335 8336 addGroup: function(label) { 8337 //Creates a optgroup Node. 8338 var optionGroup = document.createElement("OPTGROUP"); 8339 optionGroup.label = label; 8340 this.$userControl[0].appendChild(optionGroup); 8341 return optionGroup; 8342 }, 8343 8344 deleteGroup: function(label) { 8345 this.$userControl.children().remove('optgroup[label='+label+']'); 8346 }, 8347 8348 addItem: function(itemValues) { 8349 var newOption = new Option(itemValues.sDisplayVal || '', itemValues.sSaveVal || ''), 8350 val = this.options.value; 8351 8352 this.$userControl[0].add(newOption, null); 8353 8354 // if item has same value as present in options then mark it as selected 8355 if (_.contains(val, itemValues.sSaveVal)) { 8356 this.$userControl.find("option[value=" + itemValues.sSaveVal + "]").prop("selected", true); 8357 var emptyValue = this.$userControl.children('[data-empty-option]'); 8358 if (emptyValue.length > 0 && emptyValue.val() === itemValues.sSaveVal) { 8359 this.$userControl[0].removeChild(emptyValue[0]); 8360 } 8361 } else if ((val == null || val.length == 0 || val[0] == null) && this.options.placeholder.length == 0) { 8362 // Value should remain empty if option is not already selected & placeholder is empty 8363 this.$userControl[0].value = ""; 8364 } 8365 }, 8366 8367 clearItems: function () { 8368 //Deleting all the options including optGroup except the empty value. 8369 this.$userControl.children().not('[data-empty-option]').remove(); 8370 }, 8371 8372 deleteItem: function (nIndex) { 8373 //check for emptyValue instead of blindly doing + 1 8374 if (this.$userControl[0].item(0) && this.$userControl[0].item(0).id == "emptyValue") 8375 nIndex = nIndex + 1; 8376 //if there is emptyValue element then just delete one index higher 8377 //this check is must instead of blindly increasing the index by 1 because NWKListBox extends this class and that doesn't maintain emptyValue 8378 this.$userControl[0].remove(nIndex); 8379 }, 8380 8381 getCommitValue: function (event) { 8382 var value = $("option:selected", this.$userControl).map(function () { 8383 return $(this).val(); 8384 }).get(); 8385 return value; 8386 }, 8387 8388 showDisplayValue: function () { 8389 }, 8390 8391 destroy: function () { 8392 this.element. 8393 removeClass(this._widgetName). 8394 children().remove(). 8395 text(""); 8396 8397 // call the base destroy function 8398 $.xfaWidget.defaultWidget.prototype.destroy.apply(this, arguments); 8399 }, 8400 8401 _handleKeyDown: function (event) { 8402 8403 if (event.keyCode == 13) { 8404 //do nothing 8405 //just override the return key behaviour and over to defaultWidget for rest of the stuff. 8406 //return key is intercepted to avoid submission of form which is default behavior of html form element 8407 //but as a side effect it also stops the closing of drop down only in IE -> probably I should use IE condition but 8408 // this code works fine in chrome as well so keeping it that way. 8409 //watson bug#3675141 8410 } 8411 else 8412 $.xfaWidget.defaultWidget.prototype._handleKeyDown.apply(this, arguments); 8413 }, 8414 8415 // CQ-51462 : focus and commit event (change) happen together hence first selection was modifying the value 8416 // we do not want focus to modify the value that is about to be committed 8417 showValue : function() { 8418 8419 } 8420 }); 8421})($, _); 8422(function($, _){ 8423 $.widget( "xfaWidget.listBox", $.xfaWidget.defaultWidget, { 8424 8425 _widgetName: "listBoxWidget", 8426 8427 options : { 8428 value : [], 8429 items : [], 8430 multiSelect : false 8431 }, 8432 8433 getOptionsMap: function() { 8434 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this,arguments); 8435 return $.extend({},parentOptionsMap,{ 8436 "width" : function(val) { 8437 //Bug#3597771. setting the height more than 0.95 brings scrollbar 8438 this.options.width = val*0.95 8439 parentOptionsMap.width.apply(this,[this.options.width]) 8440 }, 8441 "access" : function() {}, 8442 "value": function(val) { 8443 var newValues = this.options.value, 8444 self = this, 8445 tabSet = false;
8446 if(!_.isArray(newValues)) 8447 newValues = [newValues]; 8448 var tabSet 8449 this.$userControl.children().each(function(){ 8450 var saveVal = $(this).attr("data-save"); 8451 8452 // Check if this value is present in options value array 8453 if(newValues && _.contains(newValues, saveVal)){ 8454 self._selectListItem($(this)); 8455 tabSet = true; 8456 8457 // Set the selected data attribute to true. 8458 if (!$.data(this, "_xfaInitialized")) { 8459 //Initialized data- attributes parse for once using this call. 8460 // Next onward don't use this. Instead use $.data which is cheap/ 8461 $(this).data(); 8462 $.data(this, "_xfaInitialized", true); //Mark the element to say that data has been initialized. 8463 } 8464 $.data(this, "selected", true); 8465 8466 } 8467 else{ 8468 $(this).removeClass("item-selected"); 8469 $(this).addClass("item-selectable"); 8470 $(this).attr("tabIndex", "-1"); 8471 } 8472 }); 8473 if(!tabSet) { 8474 $(this.$userControl.children().get(0)).attr("tabIndex", this.options.tabIndex); 8475 } 8476 }, 8477 8478 "items" : function(val) { 8479 if(!_.isArray(val)) 8480 val = [val]; 8481 var viewItems = this.$userControl.children(); 8482 8483 //if number of items are not same in model and view then balance it 8484 if((viewItems.length) > val.length){ 8485 for(var i=viewItems.length; i > val.length; i--){ 8486 this.deleteItem(i-1); 8487 } 8488 } 8489 else if((viewItems.length) < val.length){ 8490 for(var i=viewItems.length; i < (val.length); i++){ 8491 this.addItem({sDisplayVal: val[i].display, sSaveVal: val[i].save}); 8492 } 8493 } 8494 8495 _.each(val, function(element, index){ 8496 var $viewItem = $(viewItems[index]); 8497 if( $viewItem.text() != element.display){ 8498 $viewItem.text(element.display || ''); 8499 } 8500 8501 if( $viewItem.attr("data-save") != element.save){ 8502 $viewItem.attr("data-save", element.save || ''); 8503 } 8504 }); 8505 8506 //Intentionally left the selection check -> I am relying on the fact that "value" sync event is called after "items" sync. 8507 }, 8508 8509 "displayValue" : function(){;}, 8510 8511 "tabIndex": function() { 8512 var selectedItem = this.$userControl.children(".item-selected"), 8513 children =this.$userControl.children() 8514 if(selectedItem.length) { 8515 selectedItem.eq(0).attr("tabIndex", this.options.tabIndex); 8516 } 8517 else if(children.length > 0) { 8518 children.eq(0).attr("tabIndex", this.options.tabIndex); 8519 } 8520 } 8521 }) 8522 }, 8523 8524 getEventMap: function() { 8525 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getEventMap.apply(this,arguments); 8526 return $.extend({},parentOptionsMap,{ 8527 "listboxenter":xfalib.ut.XfaUtil.prototype.XFA_ENTER_EVENT, 8528 "listboxexit":xfalib.ut.XfaUtil.prototype.XFA_EXIT_EVENT, 8529 "listboxchange":xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT, 8530 "focus":null, 8531 "blur":null 8532 }) 8533 }, 8534 8535 showDisplayValue : function() { 8536 }, 8537 8538 render : function() { 8539 this.element.addClass( this._widgetName); 8540 this.element.children().remove(); 8541 8542 //TODO: add a function for geting textStyle 8543 var textStyle = this.getOrElse(this.$data(this.element.get(0), "xfamodel"), "textstyle", ""), 8544 that = this, 8545 //Bug#3597771 width and height are provided by the view itself. 8546 listElTemplate = 8547 '<ol style="position:absolute;<%=textStyle%>" role="listbox">' + 8548 '<% _.each(items, function(item){ %>' + 8549 '<% var saveItem = item.save ? item.save.replace(/\"/g,"""):null %>'+ 8550 '<li role="option" data-save="<% print(saveItem) %>" data-selected="false"><% print(item.display) %></li>'+ 8551 '<%})%>'+ 8552 '</ol>', 8553 compiledListElTemplate = _.template(listElTemplate), 8554 templateOptions = _.extend({ 8555 "textStyle" : textStyle 8556 }, this.options), 8557 resolvedListEl = compiledListElTemplate(templateOptions); 8558 that.element.html(xfalib.ut.XfaUtil.prototype.encodeScriptableTags(resolvedListEl)); 8559 var control = $(that.element.children().get(0)).attr("name",this.options.name); 8560 this._attachEventHandlers(control); 8561 return control 8562 }, 8563 8564 focus: function() { 8565 if(this.$userControl.children(".item-selected").length > 0) { 8566 this.$userControl.children(".item-selected")[0].focus(); 8567 } 8568 else if(this.$userControl.children().length > 0) { 8569 this.$userControl.children()[0].focus(); 8570 } 8571 }, 8572 8573 addItem : function(itemValues){ 8574 $("<li></li>") 8575 .attr("data-save", itemValues.sSaveVal || '') 8576 .text(itemValues.sDisplayVal || '') 8577 .appendTo(this.$userControl)
8578 .click($.proxy(this._handleItemClick, this)) 8579 .focus($.proxy(this._handleItemFocus, this)); 8580 8581 // add new item as selected if the value is already present in options 8582 if (_.contains(this.options.value, itemValues.sSaveVal)) { 8583 this._selectListItem(this.$userControl.find("[data-save=" + itemValues.sSaveVal+ "]")); 8584 } 8585 }, 8586 8587 clearItems : function(){ 8588 $(this.$userControl).empty(); 8589 }, 8590 8591 deleteItem : function(nIndex){ 8592 $(this.$userControl).children('li').each(function(index,element){ 8593 if(index==nIndex){ 8594 $(element).off("click").off("focus").remove(); 8595 } 8596 }) 8597 }, 8598 8599 8600 _attachEventHandlers : function($control){ 8601 var self = this; 8602 $control.keydown($.proxy(this._hotKeys,this)) 8603 .children().on("mousedown",function() { 8604 if(self.inFocus == true) { 8605 self.mouseDown = true; 8606 } 8607 }) 8608 .click($.proxy(this._handleItemClick, this)) 8609 .focus($.proxy(this._handleItemFocus, this)) 8610 .blur($.proxy(this._handleFocusOut,this)) 8611 8612 }, 8613 8614 _hotKeys : function(event){ 8615 if(this.options.access != "open") 8616 return; 8617 if(this.itemInFocus){ 8618 switch(event.which) { 8619 case 38: //arrow up 8620 var prevSibling = $(this.itemInFocus).prev(); 8621 if(prevSibling){ 8622 this.keyDown = true; 8623 prevSibling.focus(); 8624 this.keyDown = false; 8625 } 8626 event.preventDefault(); 8627 break; 8628 case 40: //arrow down 8629 var nextSibling = $(this.itemInFocus).next(); 8630 if(nextSibling){ 8631 this.keyDown = true; 8632 nextSibling.focus(); 8633 this.keyDown = false; 8634 } 8635 event.preventDefault(); 8636 break; 8637 case 91: //left arrow 8638 case 92: //right arrow 8639 event.preventDefault(); 8640 break; 8641 case 32: 8642 this._toggleItem(this.itemInFocus); 8643 event.preventDefault(); 8644 break; 8645 default: 8646 } 8647 } 8648 }, 8649 8650 _toggleItem: function(item) { 8651 var $item = $(item), 8652 multiMode = this.options.multiSelect, // && event.ctrlKey ; 8653 that = this; 8654 //toggle selected state of this item 8655 this.$data(item, "selected", !this.$data(item, "selected")); 8656 var state = this.$data(item, "selected") 8657 8658 if(!multiMode) { 8659 var $selectedItem = this.$userControl.children(".item-selected") 8660 if($selectedItem.length) {
8661 this.$data($selectedItem[0],"selected",false) 8662 $selectedItem.removeClass("item-selected").addClass("item-selectable") 8663 } 8664 } 8665 $item.toggleClass("item-selectable",!state). 8666 toggleClass("item-selected",state) 8667 8668 this.$userControl.trigger("listboxchange"); 8669 }, 8670 8671 getCommitValue: function() { 8672 var that = this, 8673 multiMode = this.options.multiSelect; 8674 8675 8676 return this.$userControl.children().map(function(){ 8677 // intentionally using $this.attr("data-save") instead of $this.data("data") 8678 return that.$data(this, "selected") ? $(this).attr("data-save") : null; 8679 }).get(); 8680 }, 8681 8682 _handleItemFocus : function(event){ 8683 if(this.options.access != "open") 8684 return; 8685 var item = event.target; 8686 this.itemInFocus = item; 8687 8688 // overriding default widgets handleFocus 8689 if(!(this.keyDown || this.mouseDown)) { //we do not need to fire focus event if 8690 this.$userControl.trigger("listboxenter") // clicked on another li element or pressed a key to move the selectio 8691 } 8692 this.mouseDown = false; 8693 this.inFocus = true; 8694 }, 8695 8696 _handleItemClick : function(event){ 8697 // Bug#3501811 If clicked onlistbox entry more than once, exit event is not fired 8698 // Clicking on the same entry does not call focus and hence we were not resetting the state. Doing it in onClick 8699 if(this.mouseDown == true) 8700 this.mouseDown = false; 8701 if(this.options.access != "open") 8702 return; 8703 this._toggleItem(event.target) 8704 }, 8705 8706 _handleFocusOut: function(){ 8707 if(!(this.keyDown || this.mouseDown)) { 8708 this.$userControl.trigger("listboxexit"); 8709 this.inFocus = false 8710 } 8711 }, 8712 8713 _selectListItem : function ($elem) { 8714 if ($elem && $elem.length) { 8715 $elem.removeClass("item-selectable") 8716 .addClass("item-selected") 8717 .attr("tabIndex", this.options.tabIndex); 8718 } 8719 }, 8720 8721 destroy: function() { 8722 this.element. 8723 removeClass(this._widgetName). 8724 children().remove(). 8725 text(""); 8726 8727 $.xfaWidget.defaultWidget.prototype.destroy.apply(this, arguments); 8728 } 8729}); 8730})($, window._); 8731(function($) { 8732 $.widget( "xfaWidget.nwkListBox", $.xfaWidget.dropDownList, { //non-webkit listbox 8733 8734 _widgetName : "nwkListBox", 8735 8736 options : { 8737 value : [], 8738 multiSelect : false 8739 }, 8740 8741 render : function() { 8742 var $control = $.xfaWidget.dropDownList.prototype.render.apply(this, arguments); 8743 if($control){ 8744 $control.children("#emptyValue").remove(); 8745 if(this.options.multiSelect) 8746 $control.attr("multiple", "multiple"); 8747 } 8748 this._updateSelectSize($control); 8749 return $control; 8750 }, 8751 8752 addItem : function(itemValues){ 8753 $.xfaWidget.dropDownList.prototype.addItem.apply(this, arguments); 8754 this._updateSelectSize(); 8755 }, 8756 8757 clearItems : function(){ 8758 $.xfaWidget.dropDownList.prototype.clearItems.apply(this, arguments); 8759 this._updateSelectSize(); 8760 }, 8761 8762 deleteItem : function(nIndex){ 8763 $.xfaWidget.dropDownList.prototype.deleteItem.apply(this, arguments); 8764 this._updateSelectSize(); 8765 }, 8766 8767 _updateSelectSize : function($control){ 8768 $control = $control || this.$userControl; 8769 $control.attr("size", (this.options.items || []).length); 8770 }, 8771 8772 // Bug#3597771 8773 // focus and commit event happen together hence first selection was modifying the value 8774 // we do not want focus to modify the value that is about to be committed 8775 showValue : function() { 8776 8777 } 8778 8779 }); 8780})($); 8781(function ($) { 8782 $.widget("xfaWidget.xfaButton", $.xfaWidget.defaultWidget, { //commitEvent: change; commitProperty: value<Array> 8783 8784 _widgetName: "xfaButton", 8785 8786 options: { 8787 value: null, 8788 svgCaption: false //option to indicate if button already has an SVG caption 8789 }, 8790 8791 getOptionsMap: function () { 8792 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this, arguments); 8793 return $.extend({}, parentOptionsMap, { 8794 "access": function (val) { 8795 switch (val) { 8796 case "open" : 8797 this.$userControl.removeAttr("disabled"); 8798 this.$userControl.removeAttr("aria-disabled"); 8799 break; 8800 case "nonInteractive" : 8801 case "protected" : 8802 case "readOnly" : 8803 this.$userControl.attr("disabled", "disabled"); 8804 this.$userControl.attr("aria-disabled", "true"); 8805 break; 8806 default : 8807 this.$userControl.removeAttr("disabled"); 8808 this.$userControl.removeAttr("aria-disabled"); 8809 break; 8810 } 8811 }, 8812 "value": function () { 8813 }, 8814 "displayValue": function () { 8815 }, 8816 "svgCaption": function (val) { 8817 if (val) { 8818 this.$userControl.removeAttr("value"); 8819 } 8820 } 8821 }) 8822 }, 8823 8824 _attachEventHandlers: function ($control) { 8825 $control.click(function () { 8826 this.focus() 8827 }); 8828 }, 8829 8830 getCommitValue: function () { 8831 return this.options.value; 8832 }, 8833 8834 showValue: function () { 8835 }, 8836 8837 showDisplayValue: function () { 8838 } 8839 }); 8840})($);(function ($) { 8841 $.widget("xfaWidget.XfaCheckBox", $.xfaWidget.defaultWidget, { //commitEvent: change; commitProperty: value<Array> 8842 8843 _widgetName: "XfaCheckBox", 8844 8845 options: { 8846 value: null, 8847 state: -1, 8848 states: 2, 8849 values: [], 8850 mandatory: false 8851 }, 8852 8853 checkedState: false, 8854 clickPending: false, 8855 8856 getOptionsMap: function () { 8857 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this, arguments); 8858 return $.extend({}, parentOptionsMap, { 8859 "access": function (val) { 8860 switch (val) { 8861 case "open" : 8862 this.$userControl.removeAttr("disabled"); 8863 this.$userControl.removeAttr("aria-disabled"); 8864 break; 8865 case "nonInteractive" : 8866 case "protected" : 8867 case "readOnly" : 8868 this.$userControl.attr("disabled", "disabled"); 8869 this.$userControl.attr("aria-disabled", "true"); 8870 break; 8871 default : 8872 this.$userControl.removeAttr("disabled"); 8873 this.$userControl.removeAttr("aria-disabled"); 8874 break; 8875 } 8876 }, 8877 8878 "displayValue": function (val) { 8879 this.$userControl.attr(this.options.commitProperty, this.options.value); 8880 this._state(this.dIndexOf(this.options.values, this.options.value)); 8881 this.$userControl.attr("checked", this.checkedState ? "checked" : null); 8882 this.$userControl.prop("checked", this.checkedState ? "checked" : null); 8883 //for accessibility 8884 this.$userControl.attr("aria-checked", this.checkedState); 8885 if (this.options.state == 2) 8886 this.$userControl.addClass("neutral"); 8887 else if (this.options.states == 3) 8888 this.$userControl.removeClass("neutral"); // since current state != neutral 8889 }, 8890 8891 "allowNeutral": function (val) { 8892 var intVal = parseInt(val); 8893 if (intVal == 0 || intVal == 1) { 8894 this.options.states = 2 + intVal; 8895 } 8896 }, 8897 8898 "paraStyles": function (paraStyles) { 8899 parentOptionsMap.paraStyles.apply(this, arguments); 8900 this._handleVAlignOnExit(); 8901 } 8902 }) 8903 }, 8904 8905 getEventMap: function () { 8906 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getEventMap.apply(this, arguments); 8907 return $.extend({}, parentOptionsMap, { 8908 "xfacheckboxchange" : xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT, 8909 "xfacheckboxclick" : xfalib.ut.XfaUtil.prototype.XFA_CLICK_EVENT, 8910 "change": null, 8911 "click" : null 8912 }) 8913 }, 8914 8915 _attachEventHandlers: function ($control) { 8916 var that = this; 8917 var focusFunc = function (evnt) { 8918 if (!that.inFocus) { 8919 that.focus(); 8920 that.inFocus = true; 8921 } 8922 } 8923 var focusOutFunc = function (evnt) { 8924 that.inFocus = false;
8925 } 8926 $control.click(focusFunc).change(focusFunc).blur(focusOutFunc); 8927 $control.change($.proxy(this._handleChange,this)).click($.proxy(this._handleClick,this)); //LC-5106 8928 }, 8929 8930 getCommitValue: function () { 8931 this._state((this.options.state + 1) % this.options.states); 8932 this.$userControl.attr("checked", this.checkedState ? "checked" : null); 8933 //for accessibility 8934 this.$userControl.attr("aria-checked", this.checkedState) 8935 if (this.options.state == 2) { 8936 this.$userControl.addClass("neutral"); 8937 } 8938 else if (this.options.states == 3) 8939 this.$userControl.removeClass("neutral"); // since current state != neutral 8940 8941 return this.options.values[this.options.state]; 8942 }, 8943 8944 _handleVAlignOnExit: function (evnt) { 8945 //--this is being kept empty as no other browser (i.e Mozilla and Chrome) take the padding-bottom or padding-top into account. 8946 // the only browser to take it into consideration is IE. And moreover the alignment and padding considerations have already been taken into account in 8947 // calculations in CheckButtonFieldView.js. And on removing the entire function it takes up the _handleVAlignOnExit() of AbstractWidget. 8948 8949 }, 8950 8951 _handleChange: function (evnt) { 8952 this.$userControl.trigger("xfacheckboxchange"); //change is always fired 8953 if(this.clickPending === true) { 8954 this.clickPending = false; 8955 this.$userControl.trigger("xfacheckboxclick"); 8956 } else { 8957 // handling of this.clickPending is added to handle the case when clicked on checkbox/radiobutton label/caption 8958 this.clickPending = true; 8959 } 8960 }, 8961 8962 _handleClick: function (evnt) { 8963 var isChrome = xfalib.ut.XfaUtil.prototype.detectChrome(), 8964 isIE = xfalib.ut.XfaUtil.prototype.detectIE(), 8965 isSafari = xfalib.ut.XfaUtil.prototype.isSafari(), 8966 userControlType = this.$userControl.attr("type"); 8967 // click will not be fired if the previous state of the radiobutton is 'on'. 8968 // CQ-4312095: Checkbox movement - Click event works fine on chrome but not in iOS safari for collapsible fields 8969 // CQ-103023 : Click Event on Radio Button not working correctly in Chrome 53 8970 // CQ-103715 : CQ-103715 : Click Event on Check Box not working correctly in Chrome and Firefox, added handling for checkbox also 8971 // handling of this.clickPending is added to handle the case when clicked on checkbox/radiobutton label/caption 8972 if(($.browser.mozilla || isChrome || isSafari) && !isIE && this.clickPending === false && ((userControlType === "radio" && this.checkedState === false) || (userControlType === "checkbox"))) { 8973 this.clickPending = true; 8974 } 8975 else { 8976 this.$userControl.trigger("xfacheckboxclick"); 8977 this.clickPending = false; 8978 } 8979 }, 8980 8981 _state: function (newState) { 8982 if (newState == undefined) 8983 return this.options.state; 8984 else 8985 this.options.state = newState; 8986 this.checkedState = (newState == 0 || newState == 2); 8987 }, 8988 8989 click: function () { 8990 // trigger change for check box and for radio only if it is not selected 8991 // otherwise radio button will go in deselected state 8992 if (this.$userControl.attr("type") !== "radio" || this.options.state !== 0) { 8993 this.$userControl.trigger("change"); 8994 } 8995 //we should call only the handler since calling click will trigger change. 8996 this.$userControl.triggerHandler("click"); 8997 } 8998 }); 8999})($); 9000(function($, _){ 9001 $.widget( "xfaWidget.textField", $.xfaWidget.defaultWidget, { 9002 9003 _widgetName: "textField", 9004 9005 options: { 9006 curValue : null , 9007 pos:0, 9008 lengthLimitVisible: true, 9009 maxChars:0 , 9010 flag:"", 9011 // by default html5Type is set to true 9012 // we leverage pattern, maxLength support from HTML5 browser for mobile forms 9013 html5Type : "text", 9014 length : null, 9015 minLength : 0, 9016 totalLengthMessage : "", 9017 minimumLengthMessage : "", 9018 }, 9019 9020 getOptionsMap: function() { 9021 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this,arguments); 9022 return $.extend({},parentOptionsMap,{ 9023 "maxChars": function(maxchars) { 9024 if(this._maxCharsReached(this.options.value)) { 9025 var value = this.options.value.slice(0,maxchars) 9026 this._setOption("value", value); 9027 this._setOption("displayValue", value); 9028 } 9029 9030 }, 9031 9032 "multiLine ": function(val) { 9033 if(this.options.multiLine) 9034 this.$userControl.attr("aria-multiline", "true"); 9035 else 9036 this.$userControl.removeAttr("aria-multiline", "false"); 9037 }, 9038 9039 "height": function(val) { 9040 if(val) {
9041 this.$css(this.$userControl[0],{"height" :val}) 9042 this._handleVAlignOnExit(); // To Handle the case of expandable Fields 9043 } 9044 }, 9045 "width": function(val){ 9046 parentOptionsMap.width.apply(this,arguments); 9047 // handle valign on width change as well 9048 // as content height(scrollHeight) varies according to width 9049 this._handleVAlignOnExit(); 9050 }, 9051 "paraStyles": function(paraStyles){ 9052 parentOptionsMap.paraStyles.apply(this,arguments); 9053 this._handleVAlignOnExit(); 9054 } 9055 9056 }) 9057 }, 9058 9059 render : function() { 9060 var control = $.xfaWidget.defaultWidget.prototype.render.apply(this, arguments); 9061 // use the control to set HTML5 attributes 9062 if (control && control.length > 0 && this.options.html5Type) { 9063 var minLength = this.options.minLength, 9064 maxLength = this.options.maxChars, 9065 length = this.options.length; 9066 isMinLengthSet = minLength != null && minLength > 0, 9067 isMaxLengthSet = maxLength != null && maxLength > 0, 9068 isLengthSet = length != null && length > 0, 9069 isMultiline = this.options.multiLine, 9070 minLengthMsg = this.options.minimumLengthMessage, 9071 totLengthMsg = this.options.totalLengthMessage, 9072 pattern = ""; // html5 pattern is not supported for textarea 9073 9074 // order of execution matters for the below code snippet 9075 if (isMinLengthSet) { 9076 // add minLength though it is not fully supported in all browsers 9077 // hence also adding pattern attribute 9078 control.attr("minlength", parseInt(minLength)); 9079 if(minLengthMsg && minLengthMsg.length > 0) { 9080 control.attr("title", this.options.minimumLengthMessage); // html5 supported message on pattern validation failure 9081 } 9082 } 9083 9084 if (isMaxLengthSet) { 9085 control.attr("maxlength", parseInt(maxLength)); 9086 } 9087 9088 // if both min and max length is set 9089 if(isMinLengthSet && isMaxLengthSet){ 9090 pattern += ".{" + minLength + "," + maxLength + "}"; 9091 } else if(isMinLengthSet) { 9092 // if only min length set 9093 pattern += ".{" + minLength + ",}"; 9094 } 9095 9096 // if length is set then set min and max length in pattern equal to length 9097 if (isLengthSet) { 9098 if(isMultiline){ // set both min and maxlength as pattern is not supported 9099 control.attr("minlength", parseInt(length)); 9100 control.attr("maxlength", parseInt(length)); 9101 } 9102 if(totLengthMsg && totLengthMsg.length > 0) { 9103 control.attr("title", this.options.totalLengthMessage); 9104 } 9105 // reset the pattern string 9106 pattern = ".{" + length + "," + length + "}"; 9107 } 9108 // if required is set, set the required attribute, it is necessary else an empty value will be excluded from constraint validation 9109 if (this.options.required) { 9110 control.attr("required", true); 9111 } 9112 // set the pattern if not empty and check if this is not multiline, since pattern is not supported for textarea 9113 if (pattern && pattern.length > 0 && !isMultiline) { 9114 control.attr("pattern", pattern); 9115 } 9116 } 9117 return control; 9118 }, 9119 9120 /* This function aligns vAlign when: 9121 1. parastyles is present and the widget contains a value. 9122 2. During initial rendering if no content present fallback to the previous logic. 9123 3. Presence of content in widget. 9124 */ 9125 _handleVAlignOnExit: function(){ 9126 var value = this.options.displayValue, 9127 noContentPresent = _.isEmpty(this.$userControl.val() || this.options.displayValue), 9128 contentHeight,widgetHeight,diff,tempCSS; 9129 9130 //the widget doesn't have value as yet but content exists [ Rendering of widget] 9131 if (!this.options.paraStyles || noContentPresent) { 9132 //vAlign has to be handled only if there is paraStyles and widget has content 9133 return; 9134 } 9135 9136 // mozilla results in vAlign regression hence made this change only for textarea 9137 if($(this.element[0]).find("textarea").length >0 && !noContentPresent) { 9138 /* measureExtent not returning correct height of content in textarea even with all 9139 css values */ 9140 tempCSS={'height':this.$userControl.css('height'),'padding':this.$userControl.css('padding')};
9141 this.$css(this.$userControl[0],{'height':'1px','padding':'0px'}); 9142 9143 contentHeight = this._getContentHeight(); 9144 this.$css(this.$userControl[0],tempCSS); 9145 widgetHeight = this.options.height; 9146 diff = widgetHeight - contentHeight; 9147 this._calculatePaddingForVAlign(diff); 9148 } else { 9149 // widget has no initial content or is a textfield.Proceed as before. 9150 $.xfaWidget.defaultWidget.prototype._handleVAlignOnExit.apply(this,arguments); 9151 } 9152 }, 9153 9154 getEventMap: function() { 9155 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getEventMap.apply(this,arguments); 9156 return $.extend({},parentOptionsMap,{ 9157 "onKeyInput.textField" : xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT 9158 }) 9159 }, 9160 9161 _maxCharsReached: function(val) { 9162 var isMaxLengthSupported = false, 9163 elementName = this.options.multiLine ? "textarea" : "input"; 9164 // in browsers, where max length is supported, we don't custom javascript checks, we let HTML do the validation of max length 9165 if(this.options.html5Type && xfalib.view.util.HtmlUtil.elementSupportsAttribute(elementName, "maxLength")){ 9166 isMaxLengthSupported = true; 9167 } 9168 return !isMaxLengthSupported && this.options.maxChars 9169 && this.options.maxChars!=="0" 9170 && val 9171 && val.length >= this.options.maxChars 9172 }, 9173 9174 _handleKeyInput : function(event, character, code) { 9175 if(event.ctrlKey && !_.contains(['paste', 'cut'], event.type)) { 9176 return true; 9177 } 9178 9179 if(!this.options.multiLine) { 9180 $.xfaWidget.defaultWidget.prototype._handleKeyDown.apply(this, arguments); 9181 character = (code == 13) ? '' : character ; 9182 } 9183 9184 var val = this.$userControl.val(), 9185 selectionStart = xfalib.view.util.HtmlUtil.getHTMLSupportedAttr(this.$userControl[0], "selectionStart") || 0, 9186 selectionEnd = xfalib.view.util.HtmlUtil.getHTMLSupportedAttr(this.$userControl[0], "selectionEnd") || 0, 9187 pos = selectionStart, 9188 // CQ-4260239 : " " taking space of 5 chars for restricting the length to visible area 9189 newVal = (val.substr(0, selectionStart) + character + val.substr(selectionEnd)); 9190 this.options.curValue = val; 9191 if(!this.options.multiLine) { //TODO:looks like a bug 9192 this.options.lengthLimitVisible = true; 9193 this.options.pos = pos; 9194 if(this.options.hScrollDisabled && !_.contains(['keydown', 'cut'], event.type)) { 9195 var expectedWidth = xfalib.view.util.TextMetrics.measureExtent(newVal, {refEl: this.$userControl[0], maxWidth:-1}).width; 9196 if(!event.ctrlKey && expectedWidth > this.$userControl.width()){ // Why allowance of 5 required?? 9197 this.options.lengthLimitVisible = false; 9198 event.preventDefault(); 9199 return false; 9200 } 9201 } 9202 } else if (this.options.multiLine && this.options.hScrollDisabled) { // LC-4656 : wait till user input, if it causes an overflow revert to old text 9203 var $textArea = this.$userControl; 9204 $textArea.css("padding", "0px 0px 0px"); // TODO : take care of multiline selection & padding later 9205 9206 // TODO : find a scheme to avoid attaching and detaching listeners, currently $.val() causes 'input' to fire, resulting in an infinite loop 9207 $textArea.one("input", function () { 9208 if ($textArea.prop('scrollHeight') > $textArea.prop('offsetHeight')) { 9209 $textArea.val(val) 9210 .prop("selectionStart", selectionEnd) 9211 .prop("selectionEnd", selectionEnd); // LC-4656 : reset the cursor pos, afterwards 9212 character = null; 9213 code = 0; 9214 } 9215 }); 9216 } 9217 9218 if (!_.contains(['keydown', 'cut'], event.type) && this._maxCharsReached(val) && selectionStart === selectionEnd) { 9219 event.preventDefault(); 9220 return false;
9221 } 9222 9223 this.$userControl.trigger({ 9224 type : "onKeyInput.textField", 9225 originalType : event.type, 9226 character : character, // contains the pasted string or pressed key 9227 keyCode : event.keyCode || 0, 9228 charCode : event.charCode || 0, 9229 which : event.which || 0, 9230 ctrlKey : event.ctrlKey || event.metaKey || false, 9231 shiftKey : event.shiftKey || false, 9232 keyDown: false, // This property is available only for list boxes and drop-down lists 9233 selectionStart: selectionStart, 9234 selectionEnd: selectionEnd 9235 }); 9236 }, 9237 9238 _handleKeyDown : function(event){ 9239 if (event) { 9240 var code = event.charCode || event.which || event.keyCode || 0; 9241 if(code == 8 || code == 46) // backspace and del 9242 this._handleKeyInput(event, "", code); 9243 } 9244 }, 9245 9246 _handleKeyPress : function(event){ 9247 if (event) { 9248 var code = event.charCode || event.which || event.keyCode || 0, 9249 character = (code == 13) ? "\n" : String.fromCharCode(code); // modified '\r\n' -> '\n' 9250 9251 if(xfalib.ut.XfaUtil.prototype.isNonPrintableKey(event.key)) { // mozilla also generates a keypress, along with keydown 9252 return true; // for all keys, so only handling printable keys in keypress 9253 } 9254 9255 this._handleKeyInput(event, character, code); 9256 } 9257 }, 9258 9259 _compositionUpdateCallback : function (event) { 9260 var that = this; 9261 var val = that.$userControl.val(); 9262 if (event.type === "compositionupdate" && event.originalEvent.data) { 9263 // this has been deliberately done to get the actual data in case of max character. 9264 if (that.options.maxChars) { 9265 val = event.originalEvent.data; 9266 } else { 9267 val = val + event.originalEvent.data.substr(event.originalEvent.data.length - 1); 9268 } 9269 } 9270 var flag = that._maxCharsReached(val); 9271 if (flag) { 9272 // if max reached 9273 var newVal = val.substr(0, that.options.maxChars); 9274 //in case the value is not changed then we do not need to update value and close the android keyboard. 9275 if (val === newVal) { 9276 return false; 9277 } 9278 that.$userControl.val(newVal); 9279 } 9280 return flag; 9281 }, 9282 9283 _attachEventHandlers: function($control) { 9284 $.xfaWidget.defaultWidget.prototype._attachEventHandlers.apply(this, arguments); 9285 // IME specific handling, to handle japanese languages max limit 9286 $.xfaWidget.defaultWidget.prototype._attachCompositionEventHandlers.apply(this, arguments); 9287 }, 9288 9289 _handlePaste : function(event){ 9290 if (event) { 9291 var pastedChar = undefined; 9292 if (window.clipboardData && window.clipboardData.getData) { // IE 9293 pastedChar = window.clipboardData.getData('Text'); 9294 } else if (event.originalEvent.clipboardData && event.originalEvent.clipboardData.getData) { 9295 pastedChar = event.originalEvent.clipboardData.getData('text/plain'); 9296 } 9297 if(pastedChar) { 9298 this._handleKeyInput(event, pastedChar, 0); 9299 } 9300 } 9301 }, 9302 9303 _handleCut : function(event) { 9304 if (event) { 9305 this._handleKeyInput(event, "", 0); 9306 } 9307 }, 9308 9309 postProcessExit: function(evnt) { 9310 $.xfaWidget.defaultWidget.prototype.postProcessExit.apply(this,arguments); 9311 if (this.options.multiLine && this.options.hScrollDisabled) { 9312 return; 9313 } 9314 this._handleVAlignOnExit(); 9315 }, 9316 9317 preProcessEnter: function(evnt) { 9318 $.xfaWidget.defaultWidget.prototype.preProcessEnter.apply(this,arguments); 9319 if(this.options.multiLine && this.options.hScrollDisabled) 9320 return; 9321 this._handleVAlignOnEnter(); 9322 }, 9323 9324 /** 9325 * @brief: Select the given field on focus in Internet Explorer 9326 * 9327 */ 9328 _selectOnFocusInIE : function(){ 9329 // if the value is not same only then do selection in IE 9330 // For Issue: LC-9895, we check if value not same 9331 if($.browser.msie && !this._isValueSame()) { 9332 this.$userControl.select(); 9333 } 9334 else { 9335 //all other browsers behave like a good boy 9336 } 9337 }, 9338 9339 showValue : function() { 9340 $.xfaWidget.defaultWidget.prototype.showValue.apply(this,arguments); 9341 //IE doesn't show selected text if we focus and set its value all the time so force selection 9342 this._selectOnFocusInIE(); 9343 }, 9344 9345 getCommitValue: function() { 9346 var value = $.xfaWidget.defaultWidget.prototype.getCommitValue.apply(this, arguments); 9347 9348 if(this._maxCharsReached(value)) { 9349 value = value.slice(0,this.options.maxChars); 9350 } 9351 9352 this.$userControl.val(this.options.value); 9353 9354 //TODO: ask Sharad whether it is right 9355 if(this.options.multiLine && this.options.hScrollDisabled) { 9356 //var str= this._checkLines(value); 9357 //if(value != str) { 9358 return value; 9359 //} 9360 } 9361 return value; 9362 }, 9363 9364 /* 9365 ** returns the contentHeight which needs to be considered for padding for valign, 9366 ** if no contentHeight is present then fontSize is returned. 9367 */ 9368 _getContentHeight: function () {
9369 var contentHeight = Math.ceil(this.$userControl.get(0).scrollHeight); 9370 return contentHeight ? contentHeight : this.options.fontSize; 9371 } 9372 }); 9373})($, window._); 9374/************************************************************************* 9375 * 9376 * ADOBE CONFIDENTIAL 9377 * __________________ 9378 * 9379 * Copyright 2019 Adobe Systems Incorporated 9380 * All Rights Reserved. 9381 * 9382 * NOTICE: All information contained herein is, and remains 9383 * the property of Adobe Systems Incorporated and its suppliers, 9384 * if any. The intellectual and technical concepts contained 9385 * herein are proprietary to Adobe Systems Incorporated and its 9386 * suppliers and may be covered by U.S. and Foreign Patents, 9387 * patents in process, and are protected by trade secret or copyright law. 9388 * Dissemination of this information or reproduction of this material 9389 * is strictly forbidden unless prior written permission is obtained 9390 * from Adobe Systems Incorporated. 9391 **************************************************************************/ 9392 9393(function ($) { 9394 $.widget("xfaWidget.richTextField", $.xfaWidget.textField, { 9395 9396 _widgetName : "richTextField", 9397 9398 _richTextWidget : null, 9399 9400 _changeAccess : function (val) { 9401 switch (val) { 9402 case "open": 9403 if (this._richTextWidget) { 9404 this._richTextWidget.editor.enable(); 9405 this._richTextWidget.$toolbar.removeClass("hideToolbar"); 9406 } 9407 break; 9408 case "readOnly": 9409 if (this._richTextWidget) { 9410 this._richTextWidget.editor.disable(); 9411 this._richTextWidget.$toolbar.addClass("hideToolbar"); 9412 } 9413 break; 9414 } 9415 }, 9416 9417 getOptionsMap : function () { 9418 var parentOptionsMap = $.xfaWidget.textField.prototype.getOptionsMap.apply(this, arguments); 9419 return $.extend({}, parentOptionsMap, { 9420 "value" : function (val) { 9421 if (this._richTextWidget) { 9422 this._richTextWidget.setRichTextEditorContent(val); 9423 } 9424 }, 9425 "access" : function (val) { 9426 this._changeAccess(val); 9427 } 9428 }); 9429 }, 9430 9431 getEventMap : function () { 9432 // in case of IE browsers, focus event is delayed, hence adding activate method for content editable 9433 if (xfalib.ut.XfaUtil.prototype.isIE()) { 9434 var parentOptionsMap = $.xfaWidget.textField.prototype.getEventMap.apply(this, arguments); 9435 return $.extend({}, parentOptionsMap, { 9436 "activate.richTextField" : xfalib.ut.XfaUtil.prototype.XFA_ENTER_EVENT 9437 }); 9438 } else { 9439 return $.xfaWidget.textField.prototype.getEventMap.apply(this, arguments); 9440 } 9441 }, 9442 9443 render : function () { 9444 var $richTextWidget = this.element.find("div.richTextWidget").eq(0); 9445 if(!$richTextWidget.length){ 9446 var attachedTextareaClasses = this.element.children().attr('class'); 9447 var richTextWidgetElement = '<div class="richTextWidget ' + attachedTextareaClasses + '" id="richTextField_' + this.options.name + '_' + attachedTextareaClasses + '"></div>'; 9448 this.element.children().remove(); 9449 this.element.append(richTextWidgetElement); 9450 $richTextWidget = this.element.find("div.richTextWidget").eq(0); 9451 }else{ 9452 $richTextWidget.children().remove(); 9453 } 9454 $richTextWidget.append(this.options.value); 9455 return $.xfaWidget.defaultWidget.prototype.render.apply(this, arguments); 9456 }, 9457 9458 getCommitValue : function () { 9459 var value = ""; 9460 if (this._richTextWidget) { 9461 value = this._richTextWidget.getRichTextEditorContent(); 9462 } 9463 return value; 9464 }, 9465 9466 preProcessEnter : function (evnt) { 9467 $.xfaWidget.textField.prototype.preProcessEnter.apply(this, arguments); 9468 var $richTextDiv = this.$userControl.find("div.richTextWidget").eq(0); 9469 if(!$richTextDiv.length){ 9470 $richTextDiv = this.element.find("div.richTextWidget").eq(0); 9471 this.changeDefaultToolbarConfig();
9472 this.$userControl.parents('.richtextsupport').css('z-index', 'auto'); 9473 } 9474 if (window.Form === undefined || window.Form.rte === undefined) { 9475 /* Forms RTE is part of Forms Addon package only. Dont do anything if addon is not installed.*/ 9476 return; 9477 } else if (this._richTextWidget === null) { 9478 this._initializeRTEToolbar(); 9479 this._richTextWidget = new window.Form.rte.RichTextEditor({ 9480 selector : $richTextDiv.attr("id"), 9481 toolbar : window.Form.rte.RichTextEditor.MFToolbar, 9482 data : this.options.value, 9483 locale : $richTextDiv.data("locale") 9484 }); 9485 var that = this; 9486 this._richTextWidget.editor.on("blur:composer", function () { 9487 that.$userControl.trigger("blur"); 9488 }); 9489 // initialize the access 9490 if (this.options.access) { 9491 this._changeAccess(this.options.access); 9492 } 9493 } 9494 }, 9495 9496 changeDefaultToolbarConfig: function(){ 9497 if(window.Form && window.Form.rte){ 9498 var toolbarDefaultConfigData = window.Form.rte.DefaultConfig; 9499 toolbarDefaultConfigData.fontSize.defaultValue = this.options.fontSize; 9500 toolbarDefaultConfigData.fontFamily.defaultValue = this.options.fontFamily; 9501 9502 // Adding 'isFontInPx' flag and overriding two utility functions 9503 // 'getDefaultParaStyle' and 'getMissingParaStyle' are responsible for adding RTE font styling attributes to rich text elements 9504 toolbarDefaultConfigData.isFontInPx = true; 9505 this.changeDefaultParaStyleUtility(); 9506 this.changeMissingParaStyleUtility(); 9507 9508 // Adding dropdown values in default config if not available in options 9509 if(toolbarDefaultConfigData.fontSize.options.indexOf(this.options.fontSize) === -1){ 9510 toolbarDefaultConfigData.fontSize.options.push(this.options.fontSize); 9511 } 9512 if(toolbarDefaultConfigData.fontFamily.options.indexOf(this.options.fontFamily) === -1){ 9513 toolbarDefaultConfigData.fontFamily.options.push(this.options.fontFamily); 9514 } 9515 } 9516 }, 9517 9518 changeDefaultParaStyleUtility: function(){ 9519 Form.rte.util.HtmlUtils.getDefaultParaStyle = function (config) { 9520 var style = ""; 9521 if (config) { 9522 style += 'font-family:' + config.fontFamily.defaultValue + ';'; 9523 if(config.isFontInPx){ 9524 style += 'font-size:' + config.fontSize.defaultValue + 'px;'; 9525 style += 'letter-spacing:' + config.letterSpacing.defaultValue + 'px;'; 9526 }else{ 9527 style += 'font-size:' + config.fontSize.defaultValue + 'pt;'; 9528 style += 'letter-spacing:' + config.letterSpacing.defaultValue + 'pt;'; 9529 } 9530 style += 'color:#000000;'; 9531 style += 'text-align:left;'; 9532 } 9533 9534 return style; 9535 }; 9536 }, 9537 9538 changeMissingParaStyleUtility : function(){ 9539 Form.rte.util.HtmlUtils.getMissingParaStyle = function (style, config) { 9540 if (style && style.length > 0) { 9541 if (config) { 9542 if (!Form.rte.util.StringHelper.endsWith(style, ";")) { 9543 style += ";"; 9544 } 9545 if (style.indexOf("font-family") < 0) { 9546 style += 'font-family:' + config.fontFamily.defaultValue + ';'; 9547 } 9548 if (style.indexOf("font-size") < 0) { 9549 if(config.isFontInPx){ 9550 style += 'font-size:' + config.fontSize.defaultValue + 'px;'; 9551 }else{ 9552 style += 'font-size:' + config.fontSize.defaultValue + 'pt;'; 9553 } 9554 } 9555 if (style.indexOf("letter-spacing") < 0) { 9556 if(config.isFontInPx){ 9557 style += 'letter-spacing:' + config.letterSpacing.defaultValue + 'px;'; 9558 }else{ 9559 style += 'letter-spacing:' + config.letterSpacing.defaultValue + 'pt;'; 9560 } 9561 } 9562 if (style.indexOf("color") < 0) { 9563 style += 'color:#000000;'; 9564 } 9565 if (style.indexOf("text-align") < 0) { 9566 style += 'text-align:left;'; 9567 } 9568 } 9569 } else { 9570 style = Form.rte.util.HtmlUtils.getDefaultParaStyle(config); 9571 } 9572 return style; 9573 }; 9574 }, 9575 9576 _initializeRTEToolbar : function () { 9577 window.Form.rte.RichTextEditor.MFToolbar = window.Form.rte.RichTextEditor.MFToolbar || { 9578 defaultMode : 'basic', 9579 toolbars : { 9580 basic : { 9581 layout : [ 9582 { 9583 items : [Form.rte.Commands.HEADER] 9584 }, 9585 { 9586 items : [Form.rte.Commands.BOLD, Form.rte.Commands.ITALIC, Form.rte.Commands.UNDERLINE] 9587 }, 9588 { 9589 command : 'lists', 9590 icon : 'list', 9591 title : "List Type", 9592 type : 'popover', 9593 placement : 'bottom', 9594 items : [Form.rte.Commands.INSERT_UNORDERED_LIST, 9595 Form.rte.Commands.INSERT_ORDERED_LIST, 9596 Form.rte.Commands.INSERT_LOWERCASE_ALPHABET_LIST] 9597 }, 9598 { 9599 title : 'Expand', 9600 command : Form.rte.Commands.MODE, 9601 value : Form.rte.ToolbarMode.FULL, 9602 icon : 'resize-full' 9603 } 9604 ], 9605 floating : true 9606 }, 9607 full : { 9608 layout : [ 9609 { 9610 items : [Form.rte.Commands.BOLD, Form.rte.Commands.ITALIC, Form.rte.Commands.UNDERLINE] 9611 }, 9612 { 9613 items : [Form.rte.Commands.SUPERSCRIPT, Form.rte.Commands.SUBSCRIPT] 9614 }, 9615 { 9616 items : [ 9617 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 9618 ] 9619 }, 9620 { 9621 items : [Form.rte.Commands.INSERT_UNORDERED_LIST, Form.rte.Commands.INSERT_ORDERED_LIST, Form.rte.Commands.INSERT_LOWERCASE_ALPHABET_LIST 9622 ] 9623 }, 9624 { 9625 title : 'Collapse', 9626 command : Form.rte.Commands.MODE, 9627 value : Form.rte.ToolbarMode.BASIC, 9628 icon : 'resize-small', 9629 selected : true 9630 } 9631 ] 9632 } 9633 } 9634 }; 9635 } 9636 }); 9637 9638})($); 9639(function($){ 9640 $.widget( "xfaWidget.imageField", $.xfaWidget.defaultWidget, { 9641 9642 _widgetName:"imageField", 9643 9644 options: { 9645 tabIndex: 0, 9646 "role": "img" 9647 }, 9648 9649 getEventMap: function () { 9650 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getEventMap.apply(this, arguments); 9651 return $.extend({}, parentOptionsMap, { 9652 "imagechange": xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT 9653 }) 9654 }, 9655 9656 getOptionsMap: function() { 9657 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this,arguments); 9658 return $.extend({},parentOptionsMap,{ 9659 "screenReaderText": function(val) { 9660 if(val) 9661 this.$userControl.attr("alt", val) 9662 }, 9663 "displayValue": function(val) { 9664 var widgetValue; 9665 if (this.options.value) { 9666 widgetValue = "data:;base64," + this.options.value; 9667 } else { 9668 widgetValue = ""; 9669 } 9670 this.$userControl.prop(this.options.commitProperty, widgetValue); 9671 this.$userControl.attr(this.options.commitProperty, widgetValue); 9672 }, 9673 "access" : function() {}, 9674 9675 // CQ-85514 : use max-ht & max-wd to honor image's intrinsic ht & wd attributes & prevent distortion 9676 "height" : function (val) { 9677 // in case aspect is actual then we need to crop the image, which will be not possible if max height and width are set 9678 if (val && this.options.aspect != "actual") { 9679 this.$css(this.$userControl[0], {"max-height": val}); 9680 } 9681 }, 9682 "width" : function (val) { 9683 if (val && this.options.aspect != "actual") { 9684 this.$css(this.$userControl[0], {"max-width": val}); 9685 } 9686 }, 9687 "aspect" : function (val) { 9688 // value of actual turns off scaling, causing the image to be drawn at its native size, 9689 // as per xfa spec Adobe implementations crop the image 9690 if(this.options.aspect == "actual") { 9691 var right = this.$userControl.attr("width"), 9692 bottom = this.$userControl.attr("height"); 9693 right = right.indexOf("px") >= 0 ? right : right + "px"; 9694 bottom = bottom.indexOf("px") >= 0 ? bottom : bottom + "px"; 9695 this._cropImage("0px", right, bottom, "0px"); 9696 this.$userControl.removeAttr("height width"); 9697 // value of none indicates no aspect ratio 9698 // as per xfa spec image is independently scaled in the horizontal and vertical directions to exactly f
9698ill the field, 9699 // which are already set to fill the field 9700 } else if (this.options.aspect != "none") { 9701 // 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 9702 // without overflowing it in either dimension. 9703 this.$userControl.attr({"height" : "auto", "width" : "auto"}); 9704 } 9705 } 9706 }); 9707 }, 9708 9709 // crop the image using top,right, bottom, left coordiantes of the image 9710 _cropImage : function (top, right, bottom, left) { 9711 var clipRect = "rect(" + top + "," + right + "," + bottom + "," + left + ")"; 9712 var clipPathPolygon = "polygon( 0px 0px, 0px " + bottom + "," + right + " " + bottom +"," + right + " 0px)"; 9713 // clip property is deprecated but still supported by all the major browsers 9714 // clip-path replaces the deprecated clip property but still is not fully supported by all major browser 9715 this.$userControl.css({"clip" : clipRect, "clip-path" : clipPathPolygon}); 9716 }, 9717 9718 render : function() { 9719 var self = this; 9720 if (typeof FileReader !== "undefined") { 9721 this.reader = new FileReader(); 9722 } else { 9723 xfalib.ut.XfaUtil.prototype.getLogger().error("Image Field is supported only for HTML5 supported browsers."); 9724 } 9725 if (this.element) { 9726 // change event triggered when new image is selected 9727 this.$widgetInput = this.element.find("input").on("change.imageField", function() { 9728 self._handleInputChange(); 9729 }).click(function(event) { 9730 // to stop bubbling of event from input to widget 9731 event.stopPropagation(); 9732 }); 9733 this.$widgetImg = this.element.on("click.imageField", function() { 9734 self._imageClick(); 9735 }).find("img"); 9736 } 9737 if (this.reader) { 9738 //load event is triggered each time the reading operation is successfully completed 9739 this.reader.addEventListener("load", function () { 9740 self.$widgetImg.attr("src",self.reader.result); 9741 self.$widgetImg.trigger("imagechange"); 9742 }, false); 9743 } 9744 return $.xfaWidget.defaultWidget.prototype.render.apply(this, arguments); 9745 }, 9746 9747 getCommitValue: function() { 9748 return this._extractData(this.$userControl.attr("src")); 9749 }, 9750 9751 // hidden input change handler, input change will be triggered on selecting a new image 9752 _handleInputChange : function() { 9753 this._displayImage(); 9754 }, 9755 9756 _imageClick : function(clickEvent) { 9757 //as the input button is hidden we trigger click explicitly on click of the widget 9758 this.$widgetInput.trigger("click"); 9759 }, 9760 9761 // removes "data\:.*\;base64," from the image base64 string 9762 _extractData : function(value) { 9763 return value.replace(/data\:.*\;base64,/, ""); 9764 }, 9765 9766 // previews image in the imagefield widget 9767 _displayImage : function() { 9768 var imageFile = this.$widgetInput.get(0).files ? this.$widgetInput.get(0).files[0] : null; 9769 if (imageFile && this._isFileOfImageType(imageFile.name)) { 9770 if (this.reader) { 9771 //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 9772 this.reader.readAsDataURL(imageFile); 9773 } 9774 } 9775 }, 9776 9777 // Test for supported image file(jpg,jpeg,png,gif,tif,bmp) 9778 _isFileOfImageType : function(fileName) { 9779 if (fileName) { 9780 return (/\.(jpe?g|png|gif|tif|bmp)$/i.test(fileName)); 9781 } 9782 return false; 9783 } 9784}); 9785})($); 9786/** 9787 * Created with IntelliJ IDEA. 9788 * User: rpandey 9789 * Date: 12/24/12 9790 * Time: 8:06 PM 9791 * To change this template use File | Settings | File Templates. 9792 */ 9793 9794 9795(function($){ 9796 $.widget( "xfaWidget.signatureField", $.xfaWidget.defaultWidget, { 9797 9798 _widgetName:"signatureField", 9799 9800 getOptionsMap: function() { 9801 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this,arguments); 9802 return $.extend({},parentOptionsMap,{ 9803 "displayValue": function(val) {}, 9804 "access": function(val) {} 9805 }) 9806 }, 9807 9808 render : function() { 9809 var $control = $.xfaWidget.defaultWidget.prototype.render.apply(this, arguments); 9810 //pessimistic checks 9811 if($control) { 9812 $control.attr("readOnly","readonly").attr("disabled", true); 9813 } 9814 return $control; 9815 } 9816 }); 9817})($); 9818/* 9819 * ADOBE CONFIDENTIAL 9820 * ___________________ 9821 * 9822 * Copyright 2011-2012 Adobe Systems Incorporated 9823 * All Rights Reserved. 9824 *
9825 * NOTICE: All information contained herein is, and remains 9826 * the property of Adobe Systems Incorporated and its suppliers, 9827 * if any. The intellectual and technical concepts contained 9828 * herein are proprietary to Adobe Systems Incorporated and its 9829 * suppliers and may be covered by U.S. and Foreign Patents, 9830 * patents in process, and are protected by trade secret or copyright law. 9831 * Dissemination of this information or reproduction of this material 9832 * is strictly forbidden unless prior written permission is obtained 9833 * from Adobe Systems Incorporated. 9834 */ 9835 9836/** 9837 * widget definition for scribbleable field 9838 */ 9839(function($,xfalib){ 9840 9841 var TouchUtil=xfalib.ut.TouchUtil; 9842 var ScribbleUtil=(function(){ 9843 return { 9844 localeString:function(id){ 9845 return xfalib.ut.XfaUtil.prototype.encodeScriptableTags($.xfaWidget.abstractWidget.prototype.localeStrings()[id]) || id; 9846 } 9847 }; 9848 })(); 9849 var DELETE_KEY = 46; 9850 var ESC_KEY = 27; 9851 var ENTER_KEY = 13; 9852/** 9853 * Scribble class definition, used for drawing on canvas using mouse or touch 9854 */ 9855function Scribble( canvasID,image,_width,_height, callback) { 9856 this._callback = callback; 9857 this.canvasID = canvasID; 9858 this._lineWidth=5; 9859 this.canvas = $("#"+canvasID); 9860 this.context = this.canvas.get(0).getContext("2d"); 9861 this.context.clearRect(0,0,this.canvas.width,this.canvas.height); 9862 this._enabled=true; 9863 this.context.strokeStyle = "#000000"; 9864 this.canvasBorderWidth = parseInt(this.canvas.css('border-left-width'),10); // assuming top and left borders are same width 9865 this.context.lineWidth = this._lineWidth; 9866 this.lastMousePoint = {x:0, y:0}; 9867 9868 this.canvas[0].width = _width;// this.canvas.parent().innerWidth(); 9869 this.canvas[0].height = _height;//this.canvas.parent().innerHeight(); 9870 if(!image){ 9871 this.context.fillStyle = '#ffffff'; 9872 this.context.clearRect(0,0,_width,_height); 9873 } else {
9874 this.context.drawImage(image,0,0); 9875 } 9876 this.canvas.on( TouchUtil.POINTER_DOWN, this.onCanvasMouseDown() ); 9877} 9878Scribble.prototype.setLineWidth=function(w){ 9879 this._lineWidth=w; 9880}; 9881Scribble.prototype.onCanvasMouseDown = function () { 9882 var self = this; 9883 return function(event) { 9884 if(TouchUtil.getTouches(event).length < 2){ 9885 self.mouseMoveHandler = self.onCanvasMouseMove(); 9886 self.mouseUpHandler = self.onCanvasMouseUp(); 9887 //CQ-4261765 : Scribble sign scroll issue with ios 9888 //https://stackoverflow.com/questions/49500339/cant-prevent-touchmove-from-scrolling-window-on-ios 9889 //https://github.com/jquery/jquery/issues/2871 9890 document.addEventListener(TouchUtil.POINTER_MOVE, self.mouseMoveHandler,{ passive: false }); 9891 $(document).on(TouchUtil.POINTER_UP, self.mouseUpHandler ); 9892 self.updateMousePosition( event ); 9893 self.updateCanvas( event ); 9894 } 9895 } 9896}; 9897 9898Scribble.prototype.onCanvasMouseMove = function () { 9899 var self = this; 9900 return function(event) { 9901 if(TouchUtil.getTouches(event).length < 2){ 9902 self.updateCanvas( event ); 9903 event.preventDefault(); 9904 return false; 9905 } 9906 } 9907}; 9908 9909Scribble.prototype.onCanvasMouseUp = function (event) { 9910 var self = this; 9911 return function(event) { 9912 document.removeEventListener(TouchUtil.POINTER_MOVE, self.mouseMoveHandler,{ passive: false }); 9913 $(document).off(TouchUtil.POINTER_UP, self.mouseUpHandler ); 9914 self.mouseMoveHandler = null; 9915 self.mouseUpHandler = null; 9916 } 9917}; 9918 9919Scribble.prototype.updateMousePosition = function (event) { 9920 if(!this._enabled) return ; 9921 var target = TouchUtil.getTouchEvent(event); 9922 9923 var offset = this.canvas.offset(); 9924 /* In IE>=10 pageX values are incorrect when using zoom 9925 so calculate them using clientX and scrollLeft */ 9926 this.lastMousePoint.x = target.clientX + $(window).scrollLeft() - offset.left - this.canvasBorderWidth; 9927 this.lastMousePoint.y = target.clientY + $(window).scrollTop() - offset.top - this.canvasBorderWidth; 9928 9929}; 9930Scribble.prototype._isInsideCanvas = function(x,y){ 9931 return y>=0 && y<this.canvas[0].height && x>=0 && x < this.canvas[0].width; 9932}; 9933 Scribble.prototype.updateCanvas = function (event) { 9934 if(!this._enabled) { 9935 return; 9936 } 9937 var oldX,oldY,dX,dY,canDraw,scaleX,scaleY,cssWidth,cssHeight; 9938 cssWidth = parseInt(this.canvas[0].style.width,10); 9939 cssHeight = parseInt(this.canvas[0].style.height,10); 9940 scaleX = cssWidth?this.canvas[0].width/cssWidth:1; 9941 scaleY = cssHeight?this.canvas[0].height/cssHeight:1; 9942 9943 scaleX /= xfalib.ut.XfaUtil.prototype.formScaleFactor; 9944 scaleY /= xfalib.ut.XfaUtil.prototype.formScaleFactor; 9945 9946 oldX = this.lastMousePoint.x*scaleX; 9947 oldY = this.lastMousePoint.y*scaleY; 9948 9949 this.updateMousePosition( event ); 9950 9951 var newX = this.lastMousePoint.x*scaleX; 9952 var newY = this.lastMousePoint.y*scaleY; 9953 9954 dX = Math.abs(newX - oldX ); 9955 dY = Math.abs(newY - oldY ); 9956 9957 canDraw = ( dX > 0 || dY > 0 ) && this._isInsideCanvas(oldX,oldY) && this._isInsideCanvas(newX,newY);; 9958 9959 if(canDraw){ 9960 this.context.beginPath(); 9961 this.context.moveTo( oldX, oldY ); 9962 this.context.lineTo(newX, newY ); 9963 this.context.lineWidth=this._lineWidth; 9964 this.context.lineCap='round'; 9965 this.context.stroke(); 9966 9967 this._callback(); 9968 9969 } 9970}; 9971 9972Scribble.prototype.toString = function () { 9973 9974 var dataString = this.canvas.get(0).toDataURL("image/png"); 9975 //var index = dataString.indexOf( "," )+1; 9976 //dataString = dataString.substring( index ); 9977 9978 return dataString; 9979}; 9980Scribble.prototype.setEnabled=function(enable){ 9981 this._enabled=enable; 9982}; 9983Scribble.prototype.clear = function () { 9984 9985 var c = this.canvas[0]; 9986 this.context.clearRect( 0, 0, c.width, c.height ); 9987}; 9988 9989 9990// ImageEdit dialog box 9991var imageEditDialog=(function(_){ 9992 9993 // html used to construct dialog box 9994 var htmlStr=(function(){ 9995 var html=[ 9996 '<div id="iEBox_container" tabindex="0" role="dialog" aria-label="'+ScribbleUtil.localeString("pleaseSignText")+'">', 9997 '<div id="iEBox_panel">', 9998 '<div id = "iEBox_Cancel" class="iEBox_button" tabindex="0" role="button" aria-label="'+ScribbleUtil.localeString("cancel")+'" title="'+ScribbleUtil.localeString("cancel")+'" ></div>', 9999 '</div>', 10000 '<div id="iEBox_content">', 10001 '<div id="iEBox_canvases" align=center>', 10002 '<div style="display:inline-block; vertical-align:top;">', 10003 '<canvas id="iEBox_canvas" style="margin:0px;border-bottom:0px;" width="696" height="390" ></canvas>' , 10004 '<input type="text" id="keyboard_Sign_Box" name="signatureText" placeholder="'+ScribbleUtil.localeString("typeYourSignatureHere")+'">', 10005 '<fieldset id="iEBox_caption"><legend align="center">
10005'+ScribbleUtil.localeString("pleaseSignText")+'</legend></fieldset>', 10006 '</div>', 10007 '<canvas id="iEBox_geoCanvasRight" width="0" height="0" ></canvas>', 10008 '<div><canvas id="iEBox_geoCanvasBottom" width="0" height="0" ></canvas></div>', 10009 '</div>', 10010 '<div>', 10011 '<div id="iEBox_Brush" class="iEBox_button" tabindex="0" role="button" aria-label="'+ScribbleUtil.localeString("brushes")+'" title="'+ScribbleUtil.localeString("brushes")+'"></div>', 10012 '<div id="iEBox_Clear" class="iEBox_button" tabindex="0" role="button" aria-label="'+ScribbleUtil.localeString("clear")+'" title="'+ScribbleUtil.localeString("clear")+'" ></div>', 10013 '<div id="iEBox_Geo" class="iEBox_button" tabindex="0" role="button" aria-label="'+ScribbleUtil.localeString("geolocation")+'" title="'+ScribbleUtil.localeString("geolocation")+'" ></div>', 10014 '<div id="iEBox_Text" class="iEBox_button" tabindex="0" role="button" aria-label="'+ScribbleUtil.localeString("typeYourName")+'" title="'+ScribbleUtil.localeString("typeYourName")+'"></div>', 10015 '<div id="iEBox_title"></div>', 10016 '<div id="iEBox_Ok" class="iEBox_button" tabindex="0" role="button" aria-label="'+ScribbleUtil.localeString("ok")+'" title="'+ScribbleUtil.localeString("ok")+'" ></div>', 10017 '</div>' , 10018 '</div>' , 10019 '<div id="iEBox_moveframe" ></div>', 10020 '<div id="iEBox_brushList" ></div>', 10021 '</div>'].join(""); 10022 return function(){ 10023 return html; 10024 }; 10025 }); 10026 10027 /** 10028 * 10029 */ 10030 10031 var dialogObj = { 10032 verticalOffset: 0, // removing the magic value of -75 since it was not causing any impact 10033 horizontalOffset: 0, 10034 repositionOnResize: true, 10035 overlayOpacity: .75, 10036 overlayColor: '#CCCCCC', 10037 draggable: true, 10038 _brushes:[2,3,4,5,6,7,8,9,10], 10039 _buttonsEnabled:{}, 10040 _isOpen:false, 10041 show:function(title,callback){ 10042 this._show(callback); 10043 this._buttonsEnabled={Geo:true,Clear:true,Ok:true,Cancel:true,Brush:true,Text:true}; 10044 }, 10045 setEnabled:function(button,enable){ 10046 if(this._buttonsEnabled[button]!=enable){ 10047 this._buttonsEnabled[button]=enable; 10048 if(enable){ 10049 $('#iEBox_'+button).empty('<div style="background:white;width:100%;height:100%;opacity:0.75;"></div>'). 10050 removeClass("disable_button"); 10051 } else { 10052 $('#iEBox_'+button).append('<div style="background:white;width:100%;height:100%;opacity:0.75;"></div>'). 10053 addClass("disable_button"); 10054 } 10055 10056 } 10057 }, 10058 enableButtons:function(buttons){ 10059 for(var k in buttons){ 10060 this.setEnabled(k,buttons[k]); 10061 } 10062 }, 10063 toggleBrushList:function(event){ 10064 var that = this; 10065 if($('#iEBox_brushList').css('display')!='none'){ 10066 $('#iEBox_brushList').css({display:'none'}); 10067 return; 10068 } 10069 var tmpFn = document.onselectstart; 10070 document.onselectstart=function(){return false;}; 10071 $('#iEBox_brushList').css({display:'block',visibility:'hidden'}); 10072 $('#iEBox_brushList').offset($('#iEBox_Brush').offset()); 10073 $('#iEBox_brushList').offset({top:$('#iEBox_Brush').offset().top-$('#iEBox_brushList').height()}); 10074 $('#iEBox_brushList').css({display:'block',visibility:'visible'}); 10075 // $('#iEBox_brushList').focus(); 10076 $('#iEBox_brushList').one('mouseleave',function(event){ 10077 $('#iEBox_brushList').css({display:'none'}); 10078 document.onselectstart=tmpFn; 10079 }); 10080 }, 10081 _attachCallbacks: function(callback) { 10082 var that = this; 10083 var sigCanvas = $('#iEBox_canvas')[0]; 10084 var ctx=sigCanvas.getContext("2d"); 10085 var minSigCanvasFontSize=10; 10086 var maxSigCanvasFontSize=70;
10087 var sigCanvasFontSize=minSigCanvasFontSize; 10088 var initialSigCanvasFontSize=sigCanvasFontSize; 10089 var initialFontCalculatedFlag=false; 10090 var sigCanvasFontFamily="sans-serif, Georgia"; 10091 var sigCanvasFontStyle="italic"; 10092 _.each("Cancel-Clear-Geo-Ok-Brush-Text".split("-"),function(val,idx){ 10093 $("#iEBox_"+val).click( function(event) { 10094 if(that._buttonsEnabled[val]){ 10095 event.stopPropagation(); 10096 callback(val); 10097 } 10098 }); 10099 $("#iEBox_"+val).keydown( function(event) { 10100 if(that._buttonsEnabled[val] && (event.keyCode == ENTER_KEY || event.charCode == ENTER_KEY || event.which == ENTER_KEY) ){ 10101 event.stopPropagation(); 10102 callback(val); 10103 } 10104 }); 10105 }); 10106 _.each($("#iEBox_brushList").children(),function(itm,idx){ 10107 $(itm).on(TouchUtil.POINTER_UP,function(event){ 10108 callback("BrushSelect",that._brushes[idx]); 10109 $('#iEBox_brushList').css({display:'none'}); 10110 // $(itm).css({backgroundColor:'#FFFFFF'}); 10111 }); 10112 $(itm).on(TouchUtil.POINTER_DOWN,function(event){ 10113 // $(itm).css({backgroundColor:'#AAAAAA'}); 10114 event.preventDefault(); 10115 }); 10116 }); 10117 10118 $('#keyboard_Sign_Box').keydown(function (event){ 10119 var inputSign=$('#keyboard_Sign_Box')[0].value; 10120 10121 if(event.key==="Backspace") { 10122 ctx.font=sigCanvasFontStyle+sigCanvasFontSize+"px "+sigCanvasFontFamily; 10123 sigCanvasFontSize=dialogObj._increaseFontForSignature(ctx.measureText(inputSign).width,sigCanvas.width, 10124 sigCanvasFontSize,initialSigCanvasFontSize); 10125 ctx.font=sigCanvasFontStyle+" "+sigCanvasFontSize+"px "+sigCanvasFontFamily; 10126 ctx.clearRect(0, 0, sigCanvas.width, sigCanvas.height); 10127 ctx.fillText(inputSign, 3, sigCanvasFontSize, sigCanvas.width-5); 10128 } 10129 event.stopPropagation(); 10130 }); 10131 10132 $("#keyboard_Sign_Box").keyup(function (event){ 10133 var inputSign=$('#keyboard_Sign_Box')[0].value; 10134 if(inputSign.length==0) { 10135 dialogObj.enableButtons({Ok: false, Clear: false}); 10136 } 10137 if(inputSign.length>=1 && inputSign.trim().length!=0) { 10138 dialogObj.enableButtons({Ok: true, Clear: true}); 10139 } 10140 if(initialFontCalculatedFlag===false){ 10141 sigCanvasFontSize=sigCanvas.height-20; 10142 sigCanvasFontSize=sigCanvasFontSize<minSigCanvasFontSize?minSigCanvasFontSize:sigCanvasFontSize; 10143 sigCanvasFontSize=sigCanvasFontSize>maxSigCanvasFontSize?maxSigCanvasFontSize:sigCanvasFontSize; 10144 initialSigCanvasFontSize=sigCanvasFontSize; 10145 $('#keyboard_Sign_Box')[0].style.font=sigCanvasFontStyle+" 2rem "+sigCanvasFontFamily; 10146 initialFontCalculatedFlag=true; 10147 } 10148 ctx.font=sigCanvasFontStyle+sigCanvasFontSize+"px "+sigCanvasFontFamily; 10149 sigCanvasFontSize=dialogObj._decreaseFontForSignature(ctx,inputSign,sigCanvas.width, 10150 sigCanvasFontSize,sigCanvasFontFamily); 10151 ctx.font=sigCanvasFontStyle+" "+sigCanvasFontSize+"px "+sigCanvasFontFamily; 10152 ctx.clearRect(0, 0, sigCanvas.width, sigCanvas.height); 10153 ctx.fillText(inputSign,3,sigCanvasFontSize,sigCanvas.width-5); 10154 event.stopPropagation(); 10155 }); 10156 10157 // capture tab key and escape 10158 $('#iEBox_container').keydown(function(event){ 10159 var firstFocusableItem = document.querySelector("#iEBox_container"); 10160 var lastFocusableItem = document.querySelector("#iEBox_Ok"); 10161 var KEYCODE_TAB = 9; 10162 var isTabPressed = (event.key === 'Tab' || event.keyCode === KEYCODE_TAB); 10163 if((event.keyCode == ESC_KEY || event.charCode == ESC_KEY || event.which == ESC_KEY)) { 10164 event.stopPropagation(); 10165 event.preventDefault(); 10166 callback("Cancel"); 10167 } else if (isTabPressed) { 10168 // Trap focus inside the dialog box 10169 if (event.shiftKey && document.activeElement === firstFocusableItem) { 10170 // when shift + tab key is pressed 10171 lastFocusableItem.focus(); 10172 event.preventDefault(); 10173 } else if (document.activeElement === lastFocusableItem) { 10174 // when tab key is pressed 10175 firstFocusableItem.focus(); 10176 event.preventDefault(); 10177 } 10178 } 10179 10180 }); 10181 10182 if(this.draggable){ 10183 this._makeDraggable(TouchUtil.TOUCH_ENABLED); 10184 } 10185 }, 10186 10187 _decreaseFontForSignature:function(ctx,inputSign,sigCanvasWidth,fontSize,sigCanvasFontFamily){ 10188 while(ctx.measureText(inputSign).width>sigCanvasWidth-5 && fontSize>20){ 10189 fontSize=fontSize-10; 10190 ctx.font=fontSize+"px "+sigCanvasFontFamily; 10191 } 10192 return fontSize 10193 }, 10194 _increaseFontForSignature:function(textWidth,sigCanvasWidth,fontSize,initialSigCanvasFontSize){ 10195 if(sigCanvasWidth-textWidth>0){ 10196 fontSize=initialSigCanvasFontSize; 10197 } 10198 return fontSize; 10199 }, 10200 _makeDraggable:function(touchEnabled){ 10201 var _isMouseDown=false; 10202 var _that=this; 10203 var dX; 10204 var dY; 10205 var offsetPos; 10206 var _mouseMovFun; 10207 var _mouseUpFun; 10208 $('#iEBox_panel').on(TouchUtil.POINTER_DOWN,function( event ){ 10209 10210 if(TouchUtil.getTouches(event).length < 2){ 10211 if($(event.target).is('#iEBox_panel')){ 10212 $('body')[0].addEventListener(TouchUtil.POINTER_MO
10212VE,_mouseMovFun=function( event ){ 10213 if(TouchUtil.getTouches(event).length < 2 && _isMouseDown){ 10214 event.preventDefault(); 10215 var evt = TouchUtil.getTouchEvent(event); 10216 var delX = evt.pageX - dX; 10217 var delY = evt.pageY - dY; 10218 $('#iEBox_moveframe').offset({ 10219 top: offsetPos.top+delY, 10220 left: offsetPos.left+delX 10221 }); 10222 } 10223 }, { passive: false }); 10224 $('body').on(TouchUtil.POINTER_UP,_mouseUpFun=function(event){ 10225 if(_isMouseDown){ 10226 var offsetMove = $('#iEBox_moveframe').offset(); 10227 var topEdge = $(window).scrollTop(); 10228 var bottomEdge = topEdge + $(window).height(); 10229 if(offsetMove.top - topEdge < 1){ 10230 offsetMove.top = topEdge; 10231 } 10232 if(offsetMove.top - bottomEdge + $('#iEBox_panel').height() > 0 ){ 10233 offsetMove.top = bottomEdge - $('#iEBox_panel').height(); 10234 } 10235 $('#iEBox_container').offset(offsetMove ); 10236 $('#iEBox_moveframe').css({display:'none'}).offset(offsetMove); 10237 _isMouseDown=false; 10238 $('body')[0].removeEventListener(TouchUtil.POINTER_MOVE,_mouseMovFun,{ passive: false }); 10239 $('body').off(TouchUtil.POINTER_UP,_mouseUpFun); 10240 } 10241 }); 10242 10243 var evt = TouchUtil.getTouchEvent(event); 10244 _isMouseDown=true; dX = evt.pageX;dY=evt.pageY; 10245 offsetPos = $('#iEBox_container').offset(); 10246 $('#iEBox_moveframe').css({display:'block'}); 10247 $('#iEBox_moveframe').offset(offsetPos); 10248 $('#iEBox_moveframe').css('width',$('#iEBox_container').css('width')); 10249 $('#iEBox_moveframe').css('height',$('#iEBox_container').css('height')); 10250 } 10251 } 10252 }); 10253 10254 }, 10255 _createBrushes:function(){ 10256 var _that=this; 10257 _.each(this._brushes,function(val,idx){ 10258 var divel = document.createElement('DIV'); 10259 var cnv = document.createElement('CANVAS'); 10260 var ctx = cnv.getContext('2d'); 10261 cnv.style.border='1px solid #AAAAAA'; 10262 cnv.width=TouchUtil.TOUCH_ENABLED?200:100; 10263 cnv.height=TouchUtil.TOUCH_ENABLED?40:20;; 10264 ctx.lineWidth=val; 10265 ctx.beginPath(); 10266 ctx.moveTo(10,cnv.height/2); 10267 ctx.lineTo(cnv.width-10,cnv.height/2); 10268 ctx.stroke(); 10269 divel.appendChild(cnv); 10270 $('#iEBox_brushList').append(divel); 10271 }); 10272 }, 10273 getIsOpen:function(){ 10274 return dialogObj._isOpen; 10275 }, 10276 setIsOpen:function(open){ 10277 dialogObj._isOpen = open; 10278 }, 10279 _show: function(callback) { 10280 dialogObj.hide(); 10281 dialogObj._overlay('show'); 10282 10283 $("BODY").append(htmlStr()); 10284 dialogObj.setIsOpen(true); 10285 $('#iEBox_container').focus(); 10286 dialogObj._createBrushes(); 10287 10288 dialogObj._reposition(); 10289 10290 // calculate spacing around canvas area 10291 // this will be used to find canvas dimensions based on available screen area. 10292 var container_el = $('#iEBox_container'); 10293 var canvas_el = $('#iEBox_canvas'); 10294 var container_width = $('#iEBox_container').outerWidth(true);
10295 var container_height = $('#iEBox_container').outerHeight(true); 10296 var canvas_width = canvas_el[0].width; 10297 var canvas_height = canvas_el[0].height; 10298 dialogObj.canvas_spacing = { x:container_width - canvas_width, y:container_height-canvas_height}; 10299 10300 dialogObj._maintainPosition(true); 10301 10302 dialogObj._attachCallbacks(callback); 10303 }, 10304 10305 hide: function() { 10306 $("#iEBox_container").remove(); 10307 this._overlay('hide'); 10308 dialogObj.setIsOpen(false); 10309 this._maintainPosition(false); 10310 }, 10311 _overlayResize:function(event) { 10312 if($("#iEBox_overlay").height()!= $(document).height()){ 10313 $("#iEBox_overlay").height( $(document).height() ); 10314 } 10315 10316 }, 10317 _disableMove:function(event) { 10318 event.preventDefault(); 10319 }, 10320 _overlay: function(status) { 10321 switch( status ) { 10322 case 'show': 10323 this._overlay('hide'); 10324 $("BODY").append('<div id="iEBox_overlay"></div>'); 10325 $("#iEBox_overlay").css({ 10326 position: 'fixed', 10327 zIndex: 99997, 10328 top: '0px', 10329 left: '0px', 10330 width: '100%', 10331 height: $(document).height(), 10332 background: this.overlayColor, 10333 opacity: this.overlayOpacity 10334 }); 10335 if(xfalib.ut.XfaUtil.prototype.isSafari()) { 10336 $("#iEBox_overlay").on('touchmove', this._disableMove); 10337 } 10338 $(document).on('scroll',this._overlayResize); 10339 break; 10340 case 'hide': 10341 if(xfalib.ut.XfaUtil.prototype.isSafari()) { 10342 $("#iEBox_overlay").off('touchmove'); 10343 } 10344 $("#iEBox_overlay").remove(); 10345 $(document).off('scroll',this._overlayResize); 10346 break; 10347 } 10348 }, 10349 /** 10350 * resize dialog based on available screen area 10351 */ 10352 _resize:function(){ 10353 // available screen area 10354 var aWidth = $(window).width(); 10355 var aHeight = $(window).height(); 10356 10357 var sigCnv = $('#iEBox_canvas')[0]; 10358 var sigTextBox = $('#keyboard_Sign_Box')[0]; 10359 var bGeoCnv = $('#iEBox_geoCanvasBottom')[0]; 10360 var rGeoCnv = $('#iEBox_geoCanvasRight')[0]; 10361 10362 // calculate amount of width height we need to reduce 10363 10364 var totalCnvWidth = sigCnv.width + rGeoCnv.width; 10365 var totalCnvHeight = sigCnv.height + bGeoCnv.height; 10366 10367 10368 10369 10370 10371 var diffW = totalCnvWidth + dialogObj.canvas_spacing.x - aWidth; 10372 if(diffW < 0) { 10373 diffW = 0; 10374 } 10375 var diffH = totalCnvHeight + dialogObj.canvas_spacing.y - aHeight; 10376 if(diffH < 0){ 10377 diffH = 0; 10378 } 10379 10380 var newTotalCnvHeight, newTotalCnvWidth; 10381 if( diffW > 0 || diffH > 0 ){ // does any side need resize 10382 10383 if(diffH * totalCnvWidth > totalCnvHeight * diffW){ // need to reduce height 10384 newTotalCnvHeight = totalCnvHeight - diffH; 10385 newTotalCnvWidth = (newTotalCnvHeight * totalCnvWidth)/ totalCnvHeight; 10386 } else { 10387 newTotalCnvWidth = totalCnvWidth - diffW; 10388 newTotalCnvHeight = (newTotalCnvWidth * totalCnvHeight)/ totalCnvWidth; 10389 } 10390 10391 // distribute evenly the new dimensions 10392 10393 10394 var newSigCnvWidth = (newTotalCnvWidth*sigCnv.width)/totalCnvWidth; 10395 var newSigCnvHeight = (newTotalCnvHeight*sigCnv.height)/totalCnvHeight; 10396 10397 sigCnv.style.width = newSigCnvWidth + "px"; 10398 sigCnv.style.height = newSigCnvHeight + "px"; 10399 10400 sigTextBox.style.width = newSigCnvWidth + "px"; 10401 sigTextBox.style.height = newSigCnvHeight + "px"; 10402 10403 10404 bGeoCnv.style.width = newSigCnvWidth +"px"; 10405 bGeoCnv.style.height = (newTotalCnvHeight - newSigCnvHeight) +"px"; 10406 10407 rGeoCnv.style.width = (newTotalCnvWidth - newSigCnvWidth) +"px"; 10408 rGeoCnv.style.height = newSigCnvHeight + "px"; 10409 10410 10411 $('#iEBox_caption').width(Math.floor(newSigCnvWidth)); 10412 10413 } else { 10414 sigCnv.style.width = sigCnv.width + "px"; 10415 sigCnv.style.height = sigCnv.height + "px"; 10416 10417 sigTextBox.style.width = sigCnv.width + "px"; 10418 sigTextBox.style.height = sigCnv.height + "px"; 10419 10420 bGeoCnv.style.width = bGeoCnv.width + "px"; 10421 bGeoCnv.style.height = bGeoCnv.height + "px"; 10422 10423 rGeoCnv.style.width = rGeoCnv.width + "px"; 10424 rGeoCnv.style.height = rGeoCnv.height + "px"; 10425 10426 $('#iEBox_caption').width(sigCnv.width); 10427 10428 } 10429 }, 10430 _reposition: function() { 10431 var top = (($(window).height() * (1 / xfalib.ut.XfaUtil.prototype.formScaleFactor) / 2) - ($("#iEBox_container").outerHeight() / 2)) + dialogOb
10431j.verticalOffset; 10432 var left = (($(window).width() * (1 / xfalib.ut.XfaUtil.prototype.formScaleFactor) / 2) - ($("#iEBox_container").outerWidth() / 2)) + dialogObj.horizontalOffset; 10433 if( top < 0 ) top = 0; 10434 if( left < 0 ) left = 0; 10435 10436 $("#iEBox_container").css({ 10437 top: top + $(window).scrollTop() * (1 / xfalib.ut.XfaUtil.prototype.formScaleFactor) + 'px', 10438 left: left + $(window).scrollLeft() * (1 / xfalib.ut.XfaUtil.prototype.formScaleFactor) + 'px' 10439 }); 10440 $("#iEBox_container").focus(); // scroll up to the canvas 10441 $("#iEBox_overlay").height( $(document).height() ); 10442 }, 10443 _maintainDialog:function(){ 10444 dialogObj._resize(); 10445 dialogObj._reposition(); 10446 }, 10447 _maintainPosition: function(status) { 10448 if(dialogObj.repositionOnResize ) { 10449 switch(status) { 10450 case true: 10451 $(window).on('orientationchange', dialogObj._maintainDialog); // also reposition if device is tilted 10452 break; 10453 case false: 10454 $(window).off('orientationchange', dialogObj._maintainDialog); 10455 break; 10456 } 10457 } 10458 } 10459 10460 }; 10461 return dialogObj; 10462})(window._); 10463 10464/** 10465 * class definition for GeoLocationQueryRequest 10466 * encapsulated success and error handlers 10467 */ 10468function GeoLocQuery(){} 10469GeoLocQuery.prototype={ 10470 init:function(success,failure){ 10471 this._successHandler = success; 10472 this._errorHandler = failure; 10473 this._active=true; 10474 return this; 10475 }, 10476 _handleSuccess:function(data){ 10477 this._successHandler(data); 10478 }, 10479 _handleError:function(err){ 10480 this._errorHandler(err); 10481 }, 10482 query:function(){ 10483 _that=this; 10484 navigator.geolocation.getCurrentPosition(function(pos){ 10485 if(_that._active){ 10486 _that._handleSuccess(pos); 10487 } 10488 _that._active=false; 10489 },function(err){ 10490 if(_that._active){ 10491 _that._handleError(err); 10492 } 10493 _that._active=false; 10494 },{timeout:10000}); 10495 }, 10496 cancel:function(){ 10497 _that._active=false; 10498 } 10499 10500}; 10501// GeoLocQuery definition ends here 10502 10503/** 10504* 10505* Base64 encode / decode 10506* http://www.webtoolkit.info/ 10507* 10508**/ 10509 10510var Base64 = { 10511 10512 // private property 10513 _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", 10514 10515 // public method for encoding 10516 encode : function (input) { 10517 var output = ""; 10518 var chr1, chr2, chr3, enc1, enc2, enc3, enc4; 10519 var i = 0; 10520 10521 while (i < input.length) { 10522 10523 chr1 = input.charCodeAt(i++); 10524 chr2 = input.charCodeAt(i++); 10525 chr3 = input.charCodeAt(i++); 10526 10527 enc1 = chr1 >> 2; 10528 enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); 10529 enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); 10530 enc4 = chr3 & 63; 10531 10532 if (isNaN(chr2)) { 10533 enc3 = enc4 = 64; 10534 } else if (isNaN(chr3)) { 10535 enc4 = 64; 10536 } 10537 10538 output = output + 10539 this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) + 10540 this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4); 10541 10542 } 10543 10544 return output; 10545 }, 10546 10547 // public method for decoding 10548 decode : function (input) { 10549 var output = ""; 10550 var chr1, chr2, chr3; 10551 var enc1, enc2, enc3, enc4; 10552 var i = 0; 10553 10554 input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); 10555 10556 while (i < input.length) { 10557 10558 enc1 = this._keyStr.indexOf(input.charAt(i++)); 10559 enc2 = this._keyStr.indexOf(input.charAt(i++)); 10560 enc3 = this._keyStr.indexOf(input.charAt(i++)); 10561 enc4 = this._keyStr.indexOf(input.charAt(i++)); 10562 10563 chr1 = (enc1 << 2) | (enc2 >> 4); 10564 chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); 10565 chr3 = ((enc3 & 3) << 6) | enc4; 10566 10567 output = output + String.fromCharCode(chr1); 10568 10569 if (enc3 != 64) { 10570 output = output + String.fromCharCode(chr2); 10571 } 10572 if (enc4 != 64) { 10573 output = output + String.fromCharCode(chr3); 10574 } 10575 10576 } 10577 10578 return output; 10579 10580 } 10581 10582 10583 10584}; 10585 10586/** 10587 * Utility Singleton for handling PNG Data 10588 */ 10589var PNGUtil=(function(){ 10590 var slf={ 10591 _LC_Scribble_MetaDataKey:"LC_SCIBBLE_METADATA", 10592 _isPng:function(b64data){ 10593 return b64data && b64data.replace(/\s+/g, "").indexOf("iVBORw0KGgo") == 0; // LC-5711 : trim any leading WhiteSpace
10594 // 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 10595 }, 10596 _update_crc:function(crc,data){ 10597 var c = crc; 10598 var n; 10599 for(n=0;n<data.length;n++){ 10600 c = this._XOR(slf._crc_table[(this._XOR(c,data.charCodeAt(n))&0xff)>>>0],(c>>>8)); 10601 } 10602 return c; 10603 }, 10604 _XOR:function(a,b){ 10605 return (a^b)>>>0; 10606 }, 10607 _U32Int2Str:function(n){ 10608 return String.fromCharCode((n>>>24)&0xFF)+String.fromCharCode((n>>>16)&0xFF)+String.fromCharCode((n>>>8)&0xFF)+String.fromCharCode(n>>>0&0xFF); 10609 }, 10610 _init_crc_table:function(){ 10611 var c=0; 10612 var n,k; 10613 slf._crc_table=[]; 10614 for(n=0;n<256;n++){ 10615 c = n; 10616 for(k=0;k<8;k++){ 10617 if(((c&1)>>>0)>0){ 10618 c = slf._XOR(0xedb88320 , (c>>>1)); 10619 } else { 10620 c = c>>>1; 10621 } 10622 } 10623 slf._crc_table[n]=c; 10624 } 10625 }, 10626 _CRC:function(data){ 10627 if(!this._crc_table) this._init_crc_table(); 10628 return this._XOR(this._update_crc(0xffffffff,data) , 0xffffffff); 10629 }, 10630 _prepareTextChunk:function(content,pad){ 10631 // pad the data appropriately 10632 var len = content.length; 10633 var lenStr = slf._U32Int2Str(len); 10634 var chunkType="tEXt"; 10635 var checkSumStr = slf._U32Int2Str(slf._CRC(chunkType+content)); 10636 return lenStr+chunkType+content+checkSumStr; 10637 }, 10638 _start:function(str){ 10639 slf._startTime = new Date().getTime(); 10640 slf._startFun=str; 10641 }, 10642 _end:function(){ 10643 var str = "Time "+slf._startFun+": "+(new Date().getTime()-slf._startTime); 10644 // $('BODY').append("<p>"+str+"</p><br/>"); 10645 }, 10646 _readU32Int:function(ctx){ 10647 var val=0; 10648 var d=ctx.d; 10649 val=((d.charCodeAt(ctx.p++)<<24)|(d.charCodeAt(ctx.p++)<<16)|(d.charCodeAt(ctx.p++)<<8)|(d.charCodeAt(ctx.p++)))>>>0; 10650 return val; 10651 }, 10652 _readChunkType:function(ctx){ 10653 var d = ctx.d; 10654 var str = d[ctx.p++]+d[ctx.p++]+d[ctx.p++]+d[ctx.p++]; 10655 return str; 10656 }, 10657 _makeReadOnly:function(b64data){ 10658 slf._start("_makeReadOnly"); 10659 // assume a valid png image encoded in base64; 10660 var bindata = slf._atob(b64data.replace(/\s+/g, '')); // remove white spaces that might have been inserted 10661 var pngctx={p:0,d:bindata}; 10662 pngctx.p+=8;// skip pngheader 10663 // read IHDR 10664 var size = slf._readU32Int(pngctx); 10665 slf._readChunkType(pngctx); //IHDR 10666 pngctx.p+=size; //Data 10667 slf._readU32Int(pngctx);//CRC 10668 var metadataChunk = slf._prepareTextChunk(slf._LC_Scribble_MetaDataKey+String.fromCharCode(0)+"true"); 10669 var newdata = pngctx.d.substring(0,pngctx.p)+metadataChunk+pngctx.d.substring(pngctx.p); 10670 var ret= slf._btoa(newdata); 10671 slf._end(); 10672 return ret; 10673 }, 10674 _atob:function(inp){ 10675 if(window.atob){ return atob(inp); } 10676 return Base64.decode(inp); 10677 }, 10678 _btoa:function(inp){ 10679 if(window.btoa){ return btoa(inp); } 10680 return Base64.encode(inp); 10681 }, 10682 _isReadOnly:function(b64data){ 10683 slf._start("_isReadOnly"); 10684 if(slf._isPng(b64data)){ 10685 var testStr = slf._LC_Scribble_MetaDataKey+String.fromCharCode(0)+"true"; 10686 var bindata = slf._atob(b64data.replace(/\s+/g, ''));
10686 // strip white spaces 10687 var pngctx={p:0,d:bindata}; 10688 pngctx.p+=8;// skip header 10689 while(pngctx.p<pngctx.d.length){ 10690 var size = slf._readU32Int(pngctx); 10691 var type = slf._readChunkType(pngctx); 10692 if(type=="tEXt"){ 10693 if(pngctx.d.indexOf(testStr,pngctx.p)==pngctx.p){ 10694 slf._end(); 10695 return true; 10696 } 10697 10698 } 10699 pngctx.p+=size; 10700 slf._readU32Int(pngctx);// 10701 }// while end 10702 } 10703 slf._end(); 10704 return false; 10705 } 10706 }; 10707 return slf; 10708})(); 10709 10710/** 10711 * JQuery widget definition starts here 10712 */ 10713$.widget( "xfaWidget.ScribbleImageField", $.xfaWidget.imageField, { 10714 10715 _widgetName:"ScribbleImageField", 10716 _geoLocQuery:null, 10717 _emptyImageVal:null,// should be null, but for now 10718 _extraInfo:null, 10719 _defaultStatus:" ", 10720 _enforceGeoLoc:!!navigator.userAgent.match(/iPad/i), 10721 _sigCanvasWidth:696, 10722 _sigCanvasHeight:390, 10723 _geoCanvId:null, 10724 _geoLocAtBottom:false, 10725 _geoCanvasHeight:100, 10726 _geoCanvasWidth:696, 10727 10728 _is_readonly:false, 10729 10730 options: { 10731 tabIndex: 0, 10732 "role": "img" 10733 }, 10734 10735 getOptionsMap: function() { 10736 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this,arguments); 10737 return $.extend({},parentOptionsMap,{ 10738 "displayValue": function(val) { 10739 if(this.options.commitProperty) { 10740 if(!val){ 10741 this._displayValue(this._extractData(this._createEmptyImageData())); 10742 this.$userControl.addClass("emptyScribble"); 10743 this._is_readonly=false; 10744 } else { 10745 this.$userControl.removeClass("emptyScribble"); 10746 if(PNGUtil._isPng(val)){ 10747 var widgetValue = "data:image/png;base64,"+this.options.value; 10748 }else { 10749 var widgetValue = "data:;base64," + this.options.value; 10750 } 10751 this._setValue(widgetValue); 10752 } 10753 } 10754 } 10755 }) 10756 }, 10757 10758 getEventMap: function() { 10759 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getEventMap.apply(this,arguments); 10760 return $.extend({},parentOptionsMap,{ 10761 "scribblefocus":xfalib.ut.XfaUtil.prototype.XFA_ENTER_EVENT, 10762 "click":null, 10763 "scribbleclick":xfalib.ut.XfaUtil.prototype.XFA_CLICK_EVENT, 10764 "change":null, 10765 "scribblechange":xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT, 10766 "blur":null, 10767 "scribbleclose":xfalib.ut.XfaUtil.prototype.XFA_EXIT_EVENT 10768 }) 10769 }, 10770 10771 /** 10772 * This function achieves following 10773 * 1. Calculate dimensions of canvases to be used 10774 * 2. Findout if right or bottom canvas is to be used for geo location 10775 */ 10776 10777 aspectRatioToBeUsed :function(){ 10778 var aspectRatio ; 10779 if(this.options.aspectRatio && parseFloat(this.options.aspectRatio) > 0){ 10780 aspectRatio = 1/parseFloat(this.options.aspectRatio); //--in MF ratio is computed as height/width instead of width/height 10781 } else { 10782 var imgEl = this.element.children("img"), 10783 width = imgEl.attr('width'), 10784 height = imgEl.attr('height'), 10785 fieldWidth, 10786 fieldHeight; 10787 10788 if(width){ 10789 fieldWidth = parseInt(width,10); 10790 } else { 10791 fieldWidth = imgEl.width(); 10792 } 10793 if(height){ 10794 fieldHeight = parseInt(height,10); 10795 } else { 10796 fieldHeight = imgEl.height(); 10797 } 10798 aspectRatio = fieldHeight/fieldWidth; 10799 } 10800 return aspectRatio; 10801 }, 10802 10803 _setUpCanvas:function(){ 10804 var aspectRatio ; 10805 aspectRatio = this.aspectRatioToBeUsed(); 10806 10807 // max width, height of generated image 10808 var maxWidth = 640; 10809 var maxHeight = 480; 10810 10811 // width of field scaled to fit max image size 10812 var scaledWidth; 10813 var scaledHeight; 10814 10815 10816 // approx pixels required for rendering geo loc info in 12pt Arial font 10817 var approxGeoLocWidth=250; 10818 var approxGeoLocHeight=84; 10819 10820 scaledWidth = maxWidth; 10821 scaledHeight = maxWidth*aspectRatio; 10822 if(scaledHeight>maxHeight){ 10823 scaledHeight = maxHeight; 10824 scaledWidth = maxHeight/aspectRatio; 10825 } 10826 10827 // set canvas dimensions 10828 if(aspectRatio>=1){ 10829 this._geoCanvId='iEBox_geoCanvasBottom'; 10830 this._geoLocAtBottom=true; 10831 10832 10833 this._geoCanvasWidth = scaledWidth; 10834 // limit height to 30% of full height; 10835 this._geoCanvasHeight=Math.min(approxGeoLocHeight,scaledHeight/3);
10836 this._sigCanvasWidth = scaledWidth; 10837 this._sigCanvasHeight= scaledHeight-(this._enforceGeoLoc?this._geoCanvasHeight:0); 10838 } else { 10839 this._geoCanvId='iEBox_geoCanvasRight'; 10840 this._geoLocAtBottom=false; 10841 10842 10843 this._geoCanvasHeight = scaledHeight; 10844 // limit width to 30% of full width; 10845 this._geoCanvasWidth=Math.min(approxGeoLocWidth,scaledWidth/3); 10846 this._sigCanvasHeight= scaledHeight; 10847 this._sigCanvasWidth= scaledWidth-(this._enforceGeoLoc?this._geoCanvasWidth:0); 10848 } 10849 10850 }, 10851 10852 render : function() { 10853 var geoLocMandatoryOnIpad = this.options.geoLocMandatoryOnIpad; 10854 if(typeof(geoLocMandatoryOnIpad)!="undefined"){ 10855 this._enforceGeoLoc= this._enforceGeoLoc && (/^(true|1)$/i).test($.trim(geoLocMandatoryOnIpad)); 10856 } 10857 this._wgtId="wid"+~~(Math.random()*2000)+"_"+new Date().getTime(); 10858 10859 var $control = $.xfaWidget.defaultWidget.prototype.render.apply(this, arguments) 10860 10861 if(this.options.value || this.options.value != this._emptyImageVal){ 10862 this._is_readonly=!!PNGUtil._isReadOnly(this.options.value); 10863 } 10864 10865 var clearSignatureLabel = ScribbleUtil.localeString("clearSignature"); 10866 var $clearButton = $("<div></div>") 10867 .attr("id", this._wgtId) 10868 .attr("tabindex", "0") 10869 .attr("role", "button") 10870 .attr("aria-label", clearSignatureLabel) 10871 .attr("title", clearSignatureLabel) 10872 .addClass("sc_popUpMenu"); 10873 $control.after($clearButton); 10874 $control.attr("aria-label", this._is_readonly ? clearSignatureLabel : ScribbleUtil.localeString("pleaseSignText")); 10875 10876 this._setUpCanvas(); 10877 return $control; 10878 }, 10879 10880 click: function() { 10881 this.focus(); 10882 var tmpEl = this.element.length?this.element[0]:this.element; 10883 if(this.options.access != "open") 10884 return; 10885 if (TouchUtil.POINTER_ENABLED || TouchUtil.TOUCH_ENABLED) { 10886 // simulate a click event 10887 tmpEl.dispatchEvent(TouchUtil.getPointerEvent(TouchUtil.POINTER_DOWN)); 10888 tmpEl.dispatchEvent(TouchUtil.getPointerEvent(TouchUtil.POINTER_UP)); 10889 } 10890 else { 10891 this.$userControl.triggerHandler("click"); 10892 } 10893 }, 10894 10895 _attachEventHandlers:function($control){ 10896 if(TouchUtil.POINTER_ENABLED || TouchUtil.TOUCH_ENABLED){ 10897 this._attachTouchEventHandlers($control); 10898 } else { 10899 this._attachMouseEventHandlers($control); 10900 } 10901 $control.keydown($.proxy(this._handleKeyDown,this)); 10902 }, 10903 _attachEventHandlerForCrossIcon:function($control){ 10904 var _that = this; 10905 if(_that._is_readonly){ 10906 $('#'+_that._wgtId).css({display:'block'}); 10907 } 10908 setTimeout(function(){ 10909 var $icon = $("#"+_that._wgtId); 10910 $icon.click($.proxy(_that._onCrossClick,_that)); 10911 $icon.keydown(function(event){ 10912 if(event.keyCode === ENTER_KEY || event.which === ENTER_KEY || event.keyCode === 32 || event.which === 32){ 10913 event.preventDefault(); 10914 _that._onCrossClick(event); 10915 } 10916 }); 10917 },50); 10918 }, 10919 _attachTouchEventHandlers:function($control){ 10920 var _timer,_that=this; 10921 var tmpEl = this.element.length?this.element[0]:this.element; 10922 tmpEl.addEventListener(TouchUtil.POINTER_DOWN,function(event){ 10923 if(_that.options.access != "open") 10924 return; 10925 event.preventDefault(); 10926 _timer = setTimeout(function(){ 10927 _timer=0; 10928 _that._onCrossClick(event); 10929 },1000); 10930 }); 10931 tmpEl.addEventListener(TouchUtil.POINTER_UP,function(event){ 10932 if(_that.options.access != "open") 10933 return; 10934 event.preventDefault(); 10935 if(_timer){ 10936 clearTimeout(_timer); 10937 _that._onImageClick(event); 10938 } 10939 }); 10940 10941 if(TouchUtil.POINTER_ENABLED){ 10942 this._attachEventHandlerForCrossIcon($control); 10943 setTimeout(function(){ $("#"+_that._wgtId).on(TouchUtil.POINTER_UP,function(event){ 10944 event.stopPropagation(); 10945 });},50); 10946 } 10947 }, 10948 10949 _attachMouseEventHandlers:function($control){ 10950 var _timer=0,_that=this,_hoverTimer=0; 10951 $control.dblclick(function(event){ 10952 if(_that.options.access != "open") 10953 return; 10954 event.preventDefault();event.stopPropagation(); 10955 if(_timer.val){ 10956 clearTimeout(_timer);_timer =0; 10957 } 10958 _that._onCrossClick(event); 10959 }).click(function(event){ 10960 _that.$userControl.trigger("scribbleclick",event); 10961 if(_that.options.access != "open") 10962 return; 10963 event.preventDefault(); 10964 event.stopPropagation(); 10965 if(_timer){ 10966 clearTimeout(_timer);_timer=0; 10967 } else { 10968 _timer = setTimeout(function(){ 10969 _timer=0; 10970 _that._onImageClick(event); 10971 },500); 10972 } 10973 }); 10974 10975 this._attachEventHandlerForCrossIcon($control); 10976 10977 }, 10978 10979 _onCrossClick:function(event){ 10980 if(!this._is_readonly) return; 10981 this.$userControl.trigger("scribblefocus",event); 10982 this.$userControl.trigger("scribbleclick",event); 10983 event.stopPropagation(); 10984 $.alertBox.yesNo(null, 10985 this.localeStrings().clearSignatureConfirm, 10986 this.localeStrings().clearSignature, 10987 $.proxy(this._removeSigConfirmationHandler,this)); 10988 }, 10989 10990 _removeSigConfirmationHandler:function(isYes){ 10991 if(isYes){ 10992 this._saveValue(this._emptyImageVal); 10993 this._displayValue(this._extractData(this._createEmptyImageData())); 10994 this.$userControl.addClass("emptyScribble").trigger("scribbleclose",{}); 10995 this._is_readonly=false; 10996 $('#'+this._wgtId).css({display:'none'}); 10997 this.$userControl.attr("aria-label", ScribbleUtil.localeString("pleaseSignText")); 10998 // CrossIcon is now hidden so MsgBox's _previousFocus restore lands on a display:none element. 10999 // Explicitly move focus to the scribble field so keyboard users can continue. 11000 this.$userControl.focus(); 11001 } 11002 }, 11003 11004 _createEmptyImageData:function(){ 11005 if(!this._emptyImageData){ 11006 var emptyCanvasObj = document.createElement('canvas');
11007 emptyCanvasObj.style.width=this._sigCanvasWidth+'px'; 11008 emptyCanvasObj.style.height=this._sigCanvasHeight+'px'; 11009 emptyCanvasObj.width=this._sigCanvasWidth; 11010 emptyCanvasObj.height=this._sigCanvasHeight; 11011 var ctx = emptyCanvasObj.getContext('2d'); 11012 ctx.fillStyle='#ffffff'; 11013 ctx.clearRect(0,0,this._sigCanvasWidth,this._sigCanvasHeight); 11014 this._emptyImageData = emptyCanvasObj.toDataURL("image/png"); 11015 } 11016 return this._emptyImageData; 11017 }, 11018 11019 getCommitValue: function() { 11020 return this.options.value 11021 }, 11022 11023 _saveValue:function(val){ 11024 this.options.value=val; 11025 this.$userControl.trigger('scribblechange'); 11026 }, 11027 11028 _displayValue:function(val){ 11029 if(this.options.commitProperty) { 11030 //hardcode the widget VALUE by unknown image type 11031 if(val){ 11032 var widgetValue = "data:image/png;base64,"+val; 11033 this._setValue(widgetValue); 11034 } 11035 } 11036 else 11037 this.logger().debug("xfaView","[DefaultWidget._update], User Control or Commit Property is null" ); 11038 }, 11039 11040 _doOk:function(){ 11041 var mainCanvas = document.createElement('CANVAS'); 11042 var geoCnv = $('#'+this._geoCanvId)[0]; 11043 var sigCnv = $('#iEBox_canvas')[0]; 11044 var ctx = mainCanvas.getContext('2d'); 11045 11046 if(geoCnv.width>0&&geoCnv.height>0){ 11047 11048 if(this._geoLocAtBottom){ 11049 mainCanvas.width=sigCnv.width; 11050 mainCanvas.height =sigCnv.height+geoCnv.height; 11051 ctx.drawImage(sigCnv,0,0); 11052 ctx.drawImage(geoCnv,0,sigCnv.height); 11053 } else { 11054 mainCanvas.width=sigCnv.width+geoCnv.width; 11055 mainCanvas.height =sigCnv.height; 11056 ctx.drawImage(sigCnv,0,0); 11057 ctx.drawImage(geoCnv,sigCnv.width,0); 11058 } 11059 } else { 11060 mainCanvas.width=sigCnv.width; 11061 mainCanvas.height =sigCnv.height; 11062 ctx.drawImage(sigCnv,0,0); 11063 } 11064 imageEditDialog.hide(); 11065 var newdata = mainCanvas.toDataURL("image/png");//(this.myScribbleHandle||"").toString(); 11066 11067 var val,val1; 11068 if((val=/*=*/this._extractData(newdata))){ 11069 // val1 = PNGUtil._makeReadOnly(val); 11070 val = PNGUtil._makeReadOnly(val); 11071 this._saveValue(val); 11072 this._is_readonly=true; 11073 $('#'+this._wgtId).css({display:'block'}); 11074 this.$userControl.attr("aria-label", ScribbleUtil.localeString("clearSignature")); 11075 } 11076 this.$userControl.focus(); 11077 this._geoLocQuery&&this._geoLocQuery.cancel();// cancel current geo loc request; 11078 this.$userControl.trigger("scribbleclose") 11079 }, 11080 _handleOk:function(){ 11081 if(this._enforceGeoLoc){ 11082 this._geoLocQuery = new GeoLocQuery().init($.proxy(function(data){ 11083 this._geoQuerySuccessHandler(data); 11084 this._doOk(); 11085 },this),$.proxy(this._geoQueryErrorHandler,this)); 11086 this._geoLocQuery.query(); 11087 this._showMessage(this.localeStrings().fetchGeoLocation); 11088 } else { 11089 this._doOk(); 11090 } 11091 }, 11092 11093 _handleCancel:function(){ 11094 imageEditDialog.hide(); 11095 this.$userControl.focus(); 11096 this._geoLocQuery&&this._geoLocQuery.cancel();// cancel current geo loc request; 11097 this.$userControl.trigger("scribbleclose") 11098 }, 11099 11100 _handleClear:function(){ 11101 this.myScribbleHandle.setEnabled(true); 11102 this._is_readonly=false; 11103 this._makeReadOnly(this._is_readonly); 11104 $('#iEBox_canvas')[0].width=this._sigCanvasWidth; 11105 $('#iEBox_caption').width(this._sigCanvasWidth); 11106 $('#iEBox_canvas')[0].height=this._sigCanvasHeight; 11107 $('#keyboard_Sign_Box')[0].value=""; 11108 var geoCanv = $('#'+this._geoCanvId)[0]; 11109 imageEditDialog.enableButtons({Ok:false,Clear:false}); 11110 geoCanv.width=0; 11111 geoCanv.height=0; 11112 imageEditDialog._resize(); 11113 this._geoLocQuery&&this._geoLocQuery.cancel();// cancel current geo loc request; 11114 }, 11115 _makeReadOnly:function(readonly){ 11116 imageEditDialog.enableButtons({Ok:false,Clear:false,Geo:!readonly,Brush:!readonly,Text:!readonly}); 11117 if(readonly){ 11118 $('#iEBox_canvas').css({border:'1px solid gray'}); 11119 $('#iEBox_caption').css({display:'none'}); 11120 11121 } 11122 this._defaultStatus = " "; 11123 this._showMessage(this._defaultStatus); 11124 }, 11125 11126 _showMessage:function(msg){ 11127 var _that = this; 11128 if(this._msgTimeout) { clearTimeout(this._msgTimeout); this._msgTimeout=0; } 11129 $("#iEBox_title").replaceWith('<div id="iEBox_title">'+msg+'</div>'); 11130 this._msgTimeout = window.setTimeout(function(){ 11131 $("#iEBox_title").replaceWith('<div id="iEBox_title">'+_that._defaultStatus+'</div>'); 11132 },15000); 11133 }, 11134 11135 _geoQueryErrorHandler:function(err){ 11136 this._showMessage(this.localeStrings().errorFetchGeoLocation); 11137 }, 11138
11139 _getLogMessage:function(key){ 11140 return this.logMsgs()[key]||key; 11141 }, 11142 11143 _handleGeo:function(){ 11144 // initiate geolocation 11145 if(navigator.geolocation){ 11146 this._geoLocQuery = new GeoLocQuery().init($.proxy(this._geoQuerySuccessHandler,this),$.proxy(this._geoQueryErrorHandler,this)); 11147 this._geoLocQuery.query(); 11148 this._showMessage(this.localeStrings().fetchGeoLocation); 11149 } else { 11150 this.logger().debug("xfaView",this._getLogMessage("ALC-FRM-901-011")); 11151 } 11152 }, 11153 11154 // This Function is used to fetch the geolocation. 11155 calculateGeolocation: function(){ 11156 this._handleGeo(); 11157 }, 11158 11159 _handleText:function(){ 11160 var signBoxEl=document.getElementById("keyboard_Sign_Box"); 11161 var signCanvasEl=document.getElementById("iEBox_canvas"); 11162 if(signBoxEl.value.length==0){ 11163 this._handleClear(); 11164 } 11165 this._disableSignatureCanvas(); 11166 this._enableSignatureTextBox(); 11167 signBoxEl.focus(); 11168 }, 11169 11170 _disableSignatureTextBox:function(){ 11171 document.getElementById("keyboard_Sign_Box").style.display = "none"; 11172 }, 11173 11174 _enableSignatureTextBox:function(){ 11175 document.getElementById("keyboard_Sign_Box").style.display = "inline-block"; 11176 }, 11177 11178 _disableSignatureCanvas:function(){ 11179 document.getElementById("iEBox_canvas").style.display = "none"; 11180 }, 11181 11182 _enableSignatureCanvas:function(){ 11183 document.getElementById("iEBox_canvas").style.display = "inline-block"; 11184 }, 11185 11186 _handleBrushSelect:function(w){ 11187 if(this.myScribbleHandle&&!this._is_readonly) { 11188 this.myScribbleHandle.setLineWidth(w); 11189 } 11190 }, 11191 11192 _handleBrush:function(evt){ 11193 if($('#keyboard_Sign_Box')[0].value.length>0){ 11194 this._handleClear(); 11195 } 11196 this._disableSignatureTextBox(); 11197 this._enableSignatureCanvas(); 11198 imageEditDialog.toggleBrushList(evt); 11199 }, 11200 _handleKeyDown:function(event){ 11201 if(event.keyCode == ENTER_KEY || event.charCode == ENTER_KEY || event.which == ENTER_KEY) { // touch devices may return charCode 11202 event.preventDefault(); 11203 this._onImageClick(event); 11204 } else if(event.keyCode == DELETE_KEY || event.charCode == DELETE_KEY || event.which == DELETE_KEY) { 11205 this._onCrossClick(event); 11206 } 11207 }, 11208 _dialogCallback:function(button_val,arg1){ 11209 // add back on click handler 11210 // this.$userControl.click($.proxy(this._onImageClick, this)); 11211 11212 switch(button_val){ 11213 case "Ok": 11214 this._handleOk(); 11215 break; 11216 case "Cancel": 11217 this._handleCancel(); 11218 break; 11219 case "Clear": 11220 this._handleClear(); 11221 break; 11222 case "Geo": 11223 this.calculateGeolocation(); 11224 break; 11225 case "BrushSelect": 11226 this._handleBrushSelect(arg1); 11227 break; 11228 case "Brush": 11229 this._handleBrush(arg1); 11230 break; 11231 case "Text": 11232 this._handleText(); 11233 break; 11234 11235 } 11236 }, 11237 11238 _geoQuerySuccessHandler:function(data){ 11239 this._renderPosition(data); 11240 }, 11241 11242 _fitGeoLocText:function(latStr,longStr,timeStr,ctx,maxWidth,maxHeight){ 11243 var fontSize=12; 11244 ctx.font="bold "+fontSize+"pt Arial"; 11245 var width = Math.max(ctx.measureText(latStr).width,ctx.measureText(longStr).width,ctx.measureText(timeStr).width); 11246 var lineHeight = ctx.measureText("m").width*1.5; 11247 while((width>maxWidth||3*lineHeight>maxHeight)&&fontSize>1){ 11248 fontSize--; 11249 ctx.font="bold "+fontSize+"pt Arial"; 11250 width = Math.max(ctx.measureText(latStr).width,ctx.measureText(longStr).width,ctx.measureText(timeStr).width); 11251 lineHeight = ctx.measureText("m").width*1.5; 11252 } 11253 return {width:width,lineHeight:lineHeight,fontSize:fontSize}; 11254 }, 11255 11256 _renderPosition:function(position){ 11257 if(position&&position.coords){ 11258 this._showMessage(" "); 11259 var latStr = this.localeStrings().latitude+": " + position.coords.latitude; 11260 var longStr = this.localeStrings().longitude+": " + position.coords.longitude; 11261 var dateObj = new Date(); 11262 var tZone = (dateObj.getTimezoneOffset()/60*-1); 11263 11264 var timeStr = this.localeStrings().time+": "+(dateObj.getMonth()+1)+"/"+dateObj.getDate()+"/"+dateObj.getFullYear()+" "+dateObj.getHours()+":"+dateObj.getMinutes()+":"+dateObj.getSeconds()+((tZone>0)?" +":" ")+(tZone); 11265 var canvasObj = $('#'+this._geoCanvId)[0];
11266 var sigCanvas = $('#iEBox_canvas')[0]; 11267 var sigTextBox = $('#keyboard_Sign_Box')[0]; 11268 var dummyCanvas = document.createElement('canvas'); 11269 if(canvasObj){ 11270 var ctx = canvasObj.getContext('2d'); 11271 ctx.font="bold 12pt Arial"; 11272 11273 canvasObj.width=this._geoCanvasWidth; 11274 canvasObj.height=this._geoCanvasHeight; 11275 var layout = this._fitGeoLocText(latStr,longStr,timeStr,ctx,canvasObj.width,canvasObj.height); 11276 var aspectRatio ; 11277 aspectRatio = this.aspectRatioToBeUsed(); 11278 if(!this._enforceGeoLoc){ 11279 if(this._geoLocAtBottom){ 11280 dummyCanvas.height = this._sigCanvasHeight-canvasObj.height; 11281 dummyCanvas.width = dummyCanvas.height/aspectRatio; 11282 } else { 11283 dummyCanvas.width = this._sigCanvasWidth-canvasObj.width; 11284 dummyCanvas.height = dummyCanvas.width*aspectRatio; 11285 } 11286 // move drawn signature to a temporary canvas and scale it to new dimension 11287 dummyCanvas.getContext('2d').drawImage(sigCanvas,0,0,dummyCanvas.width,dummyCanvas.height); 11288 if(this._geoLocAtBottom){ 11289 sigCanvas.height = dummyCanvas.height; 11290 sigTextBox.height = dummyCanvas.height; 11291 sigCanvas.getContext('2d').drawImage(dummyCanvas,(sigCanvas.width-dummyCanvas.width)/2,0); 11292 } else { 11293 sigCanvas.width = dummyCanvas.width; 11294 sigTextBox.width = dummyCanvas.width; 11295 sigCanvas.getContext('2d').drawImage(dummyCanvas,0,(sigCanvas.height-dummyCanvas.height)/2); 11296 } 11297 $('#iEBox_caption').width(sigCanvas.width); 11298 imageEditDialog.enableButtons({Clear:true}); 11299 } 11300 11301 var fwidth = layout.width; 11302 var fheight = layout.lineHeight; 11303 var bottomMargin=2; 11304 ctx.fillStyle='#555555'; 11305 ctx.font="bold "+layout.fontSize+"pt Arial"; 11306 ctx.fillText(latStr,0,canvasObj.height-2*fheight-bottomMargin); 11307 ctx.fillText(longStr,0,canvasObj.height-fheight-bottomMargin); 11308 ctx.fillText(timeStr,0,canvasObj.height-bottomMargin); 11309 11310 imageEditDialog._resize(); 11311 } 11312 } 11313 }, 11314 _scribbleCallback:function(){ 11315 imageEditDialog.enableButtons({Clear:true,Ok:true}); // enable clear and ok buttons 11316 }, 11317 _onImageClick:function(){ 11318 if(!imageEditDialog.getIsOpen()){ 11319 var _that = this; 11320 imageEditDialog.show(" ",$.proxy(this._dialogCallback, this)); 11321 if(!this._enforceGeoLoc){ 11322 $('#iEBox_Geo').css({display:'inline-block'}); 11323 } 11324 var image = new Image(); 11325 image.onload=function(){ 11326 _that.myScribbleHandle = new Scribble("iEBox_canvas",image,image.width,image.height,$.proxy(_that._scribbleCallback,_that)); 11327 _that.myScribbleHandle.setEnabled(!_that._is_readonly); 11328 $('#iEBox_caption').width(image.width); 11329 $('#iEBox_container').css({display:'table'}); 11330 if($('#iEBox_container').length == 1){ 11331 $('#iEBox_container')[0].focus(); 11332 } 11333 imageEditDialog._resize(); 11334 imageEditDialog._reposition(); // recalculate position, so that the values are updated, esp. in iPad 11335 } 11336 if(!this.options.value||this.options.value==this._emptyImageVal){ 11337 this._is_readonly=false; 11338 this.$userControl.addClass("emptyScribble"); 11339 image.src = this._createEmptyImageData(); 11340 } else { 11341 this.$userControl.removeClass("emptyScribble"); 11342 if(PNGUtil._isPng(this.options.value)){ 11343 this._is_readonly = !!PNGUtil._isReadOnly(this.options.value); 11344 image.src = "data:image/png;base64,"+this.options.value;//this.createBl _that.$userControl.attr(_that.options.commitProperty); 11345 } else { 11346 image.src = "data:;base64," + this.options.value;//this.createBl _that.$userControl.attr(_that.options.commitProperty); 11347 } 11348 } 11349 this._makeReadOnly(this._is_readonly); 11350 } 11351 }, 11352 11353 _extractData:function(datauri){ 11354 var idx; 11355 if(datauri!=null&&datauri.length>0&&datauri.indexOf("data:")==0){ 11356 if((idx=datauri.indexOf(","))>0){ 11357 return datauri.substr(idx+1); 11358 } 11359 } 11360 }, 11361 11362 _setValue:function(val){ 11363 this.$userControl.prop(this.options.commitProperty, val); 11364 this.$userControl.attr(this.options.commitProperty, val); 11365 if(this._dummyImg){ 11366 this._dummyImg.setAttribute(this.options.commitProperty,val); 11367 } 11368 } 11369}); 11370 //hack for IOS5 touch bug 11371 $(function(){ 11372 $('body').on('touchstart', function(e) {}); 11373 }); 11374 11375})($,xfalib); 11376(function ($, window, _) { 11377 11378 var _defaults = { 11379 placeHolderText : "Enter comments here" 11380 }; 11381 11382 var AdobeFileAttachment = function (element, options) { 11383 this.options = options; 11384 this.$elementFileUploadBtn = []; 11385 this.$elementFileList = []; 11386 this.$element = $(element); 11387 if (this.$element.attr("multiple") && !xfalib.ut.Utilities._isDataContainerSupported()) { 11388 // remove multiple attribute if multi file selection in one go is not supported 11389 this.$element.removeAttr("multiple"); 11390 } 11391 this.$parent = this.$element.parent(); 11392 this.invalidFeature = { 11393 "SIZE":1, 11394 "NAME":2, 11395 "MIMETYPE":3 11396 }; 11397 Object.freeze(this.invalidFeature); 11398 // initialize the regex initially 11399 this.regexMimeTypeList = this.options.mimeType.map(function (value, i) { 11400 try { 11401 return new RegExp(value.trim()); 11402 } catch (e) { 11403 // failure during regex parsing, don't return anything specific to this value since the value contains 11404 // incorrect regex string 11405 if(window.console) { 11406 console.log(e); 11407 } 11408 } 11409 }); 11410 }; 11411 11412 var isBrowserIE9OrIE10 = ($.browser.msie && ($.browser.version === '9.0' || $.browser.version === '10.0')), 11413 fileLabelsCount = 0; 11414 11415 11416 AdobeFileAttachment.prototype = { 11417 _fileIframeName : "guide-fu-iframe", 11418 _addFile : "Add File", 11419 11420 clear: function () { 11421 this.$element.val(''); 11422 this.$elementFileList.empty(); 11423 }, 11424 11425 destroy: function () { 11426 this.$fileDomElements = $.map(this.$fileDomElements, function(item){ 11427 // since item can be null or object, doing this check 11428 if(_.isObject(item) && item.val().length === 0) { 11429 //TODO: remove item from dom, since there is a memory leak 11430 return item; 11431 } 11432 }); 11433 this.values = []; 11434 if(isBrowserIE9OrIE10){ 11435 if(_.last(this.$fileDomElements) == null){ 11436 this.cloneFileInputAndUpdateIdForIE9(); 11437 } else { 11438 this.updateLabelForAttr(_.last(this.$fileDomElements).attr("id")); 11439 } 11440 } 11441 this.$element.trigger("change.fileupload"); 11442 }, 11443 11444 _setUrl : function(url, index){ 11445 this.$elementFileList.find("span.guide-fu-fileName").eq(index).data("key", url); 11446 }, 11447 11448 _getUrl : function(index) { 11449 return this.$elementFileList.find("span.guide-fu-fileName").eq(index).data("key"); 11450 }, 11451 getSetFilePathAndReturnNamePathMap: function(valueList) { 11452 11453 var mapOfObjectsHavingTempPathAndFileNames = {}, 11454 $temp, 11455 tempPath; 11456 11457 $.each(this.$elementFileList.children(), function ( index, childLiElement) { 11458 $temp = $(childLiElement).find("span.guide-fu-fileName"); 11459 tempPath = $temp.data("key"); 11460 if(!tempPath && valueList && valueList[index]) { 11461 $temp.data("key", valueList[index]); 11462 } 11463 mapOfObjectsHavingTempPathAndFileNames[$temp.html()] = tempPath || $temp.data("key"); 11464 }); 11465 return mapOfObjectsHavingTempPathAndFileNames; 11466 }, 11467 11468 11469 value : function(value) { 11470 if(!_.isUndefined(value)) { 11471 var _self = this, 11472 comments = this.comment(), 11473 isChange = false, 11474 fileNames = _.isArray(this.options.fileNames) ? this.options.fileNames : null, 11475 oldUrls = {};
11476 // Cache the url before deletion 11477 this.$elementFileList.children().find("span.guide-fu-fileName").each(function(){ 11478 var url = $(this).data("key"); 11479 if(!_.isUndefined(url)){ 11480 var fileName = url.substring(url.lastIndexOf("/") + 1); 11481 oldUrls[fileName] = url; 11482 } 11483 }); 11484 this.$elementFileList.empty(); 11485 if(value != null) { 11486 var arr = value.split("\n"); 11487 // contruct initial file name and value map 11488 // this is done only once in entire live cycle, its done here, since we get value here 11489 if (fileNames && _.isEmpty(this._initialFileValueFileNameMap)) { 11490 for (var index = 0; index < fileNames.length; index++) { 11491 _self._initialFileValueFileNameMap[arr[index]] = fileNames[index] 11492 } 11493 } 11494 // Update the value array with the file 11495 this.values = _.map(arr, function(fileName, index){ 11496 // Check if file Name is a path, if yes get the last part after "/" 11497 var slash = fileName.lastIndexOf("/"), 11498 fileUrl = fileName, 11499 fileUploadUrl = null; 11500 if(slash !== -1) { 11501 // Store the cached url here 11502 fileUrl = fileUploadUrl = fileName; 11503 fileName = fileName.substring(slash + 1); 11504 // case: when you click on save second time 11505 if((_.isObject(_self.$fileDomElements[index]) && _self.$fileDomElements[index].val().length > 0) || _.isString(_self.$fileDomElements[index])){ 11506 isChange = true; 11507 _self.$fileDomElements[index] = null; 11508 } else if(_self.$fileDomElements[index] !== null) { // create a dummy file dom for the cached value 11509 isChange = true; 11510 _self.$fileDomElements.splice(index, 0, null); 11511 } 11512 } else if (oldUrls[fileName]) { 11513 fileUploadUrl = oldUrls[fileName]; 11514 } 11515 // if fileNames options is explicitly passed, use it 11516 if (fileNames && _self._initialFileValueFileNameMap[fileUrl]) { 11517 fileName = _self._initialFileValueFileNameMap[fileUrl]; 11518 } 11519 _self.showFileList(fileName, comments[index], fileUploadUrl); 11520 return fileUrl; 11521 }); 11522 if(isChange){ 11523 this.$element.trigger("change.fileupload"); 11524 } 11525 } else { 11526 if(_.isArray(this.values) && this.values.length !== 0){ 11527 this.destroy(); 11528 } 11529 } 11530 } 11531 else { 11532 return this.values; 11533 } 11534 }, 11535 11536 fileAttachment: function(){ 11537 return this.values; 11538 }, 11539 11540 comment : function(value){ 11541 var _self = this, 11542 $elem = null, 11543 comments; 11544 if (!_.isUndefined(value)) { 11545 if(value != null) { 11546 comments = value.split("\n"); 11547 $elem = this.$elementFileList.find('div.guide-fu-comment'); 11548 $elem.each(function(index){ 11549 $(this).text(comments[index]); 11550 }); 11551 } 11552 } 11553 else { 11554 $elem = this.$elementFileList.find('div.guide-fu-comment'); 11555 comments = []; 11556 $elem.each(function(){ 11557 comments.push($(this).text()); 11558 }); 11559 return comments; 11560 } 11561 }, 11562 11563 multiSelect : function(value){ 11564 if(value !== undefined) 11565 this.options.multiSelect = value; 11566 else 11567 return this.options.multiSelect; 11568 }, 11569 11570 fileSizeLimit : function(value){ 11571 if(value !== undefined) 11572 this.options.fileSizeLimit = value; 11573 else 11574 return this.options.fileSizeLimit; 11575 }, 11576 11577 mimeType : function(value){ 11578 if(value !== undefined) 11579 this.options.mimeType = value; 11580 else 11581 return this.options.mimeType; 11582 }, 11583 11584 access : function(value){ 11585 if(value == "readOnly") { 11586 this.$element.attr("disabled", "disabled"); 11587 //for readOnly hide the delete icon in file list
11588 $(this.$parent).addClass('guide-fu-disabled'); 11589 } 11590 else if(value == "open") { 11591 this.$element.removeAttr("disabled"); 11592 $(this.$parent).removeClass('guide-fu-disabled'); 11593 } 11594 }, 11595 11596 fileList : function(value) { 11597 var filtered, 11598 _self = this; 11599 if(value !== undefined){ 11600 this.$fileDomElements = []; 11601 _.each(value, function(item, index){ 11602 if((_.isObject(item) && (isBrowserIE9OrIE10 || item.val().length > 0)) || (_.isString(item))){ 11603 // check if index is within the length 11604 // this is written for delete case 11605 // if item is a string, then it should be set null 11606 if(_.isString(item)){ 11607 item = null; 11608 } 11609 _self.$fileDomElements[index] = item; 11610 } 11611 }); 11612 filtered = this.$fileDomElements; 11613 // In case of IE9, get the last element of fileDom and update the id for label 11614 if(isBrowserIE9OrIE10 && value !== null){ 11615 // Case: if it is single select, and then we do a restore and then after attaching another file we click save 11616 if(_.last(this.$fileDomElements) == null){ 11617 this.cloneFileInputAndUpdateIdForIE9(); 11618 } else { 11619 this.updateLabelForAttr(_.last(this.$fileDomElements).attr("id")); 11620 } 11621 } 11622 } 11623 else { 11624 // here filtered is a new array 11625 // A new array is returned over here so that the user of this API doesn't try to change the widget array directly 11626 filtered = $.map(this.$fileDomElements, function(item, index){ 11627 if(!item) { 11628 return _self._getUrl(index); 11629 } else if((item[0].files && item[0].files.length !== 0) 11630 || (_self.options.multiSelect || item[0].value.length > 0)) { 11631 return item; 11632 } 11633 }); 11634 } 11635 return filtered; 11636 }, 11637 11638 // file preview html 11639 fileItemPreview: function(){ 11640 return $("<span></span>").addClass("guide-fu-filePreview glyphicon glyphicon-ok"); 11641 }, 11642 11643 // force flag indicates that forcefully set the dom but don't update the options 11644 buttonText: function (value, force) { 11645 if (value !== undefined) { 11646 if(!force) 11647 this.options.buttonText = value; 11648 this.$elementFileUploadBtn.find('span.guide-fu-label').html(value); 11649 } else { 11650 return this.options.buttonText; 11651 } 11652 }, 11653 11654 // To change the icon of the button, the user should customize the class 11655 btnIcon: function () { 11656 return $("<span></span>").addClass("guide-fu-icon glyphicon glyphicon-folder-open"); 11657 }, 11658 11659 btnLabel: function(){ 11660 return $("<span></span>").addClass("guide-fu-label").html(this.options.buttonText); 11661 }, 11662 11663 fileItemList: function(){ 11664 return this.$parent.find(this.options.fileItemListClass); 11665 }, 11666 11667 getNewCommentElementSummary : function(text){ 11668 return $("<div title='Click to edit' tabindex='0'></p>").addClass("guide-fu-comment").text(text || _defaults.placeHolderText); 11669 }, 11670 11671 getNewCommentElement : function(text){ 11672 return $("<div contenteditable='true' tabindex='0'></div>").addClass("guide-fu-comment").text(text || ""); 11673 }, 11674 11675 fileItem: function(fileName, comment, fileUrl){ 11676 var $fileItem = $("<li></li>").addClass("guide-fu-fileItem"); 11677 var nameWithoutMarker = xfalib.ut.Utilities._getNameWithoutMarker(fileName); 11678 var $elem = $("<span tabindex='0'></span>").addClass("guide-fu-fileName").attr("aria-label", nameWithoutMarker).text(nameWithoutMarker).appendTo($fileItem).keypress(function(e) { 11679 if (e.keyCode === 13 || e.charCode === 32) { 11680 $(e.target).click(); 11681 } 11682 }).click($.proxy(this.handleFilePreview, this)); 11683 if(this.options.disablePreview) { 11684 $elem.addClass('non-preview-fileName'); 11685 } 11686 if(fileUrl != null){ 11687 $elem.attr("data-key", fileUrl); 11688 } 11689 $("<span tabindex='0'></span>").addClass("guide-fu-fileClose close").attr("role", "button").attr("aria-label", xfalib.locale.Strings.FileCloseAccessText
11689+ nameWithoutMarker).text("x").appendTo($fileItem).keypress(function(e) { 11690 if (e.keyCode === 13 || e.charCode === 32) { 11691 $(e.target).click(); 11692 } 11693 }) 11694 .click($.proxy(this.handleClick, this)); 11695 11696 this.fileItemPreview().appendTo($fileItem); 11697 11698 if(this.options.showComment){ 11699 this.getNewCommentElementSummary(comment).appendTo($fileItem).focus($.proxy(this.handleCommentClick, this)).click($.proxy(this.handleCommentClick, this)); 11700 } 11701 return $fileItem; 11702 }, 11703 11704 toggleFileUploadBtn: function(){ 11705 if(this.options.multiSelect) { 11706 // Change the look of file upload button 11707 if(this.$elementFileList.children().length > 0){ 11708 // Change the text 11709 this.buttonText(this._addFile, true); 11710 // Change the icon too 11711 this.$elementFileUploadBtn.find('span.guide-fu-icon').removeClass("glyphicon-folder-open").addClass("glyphicon-plus"); 11712 } else { 11713 this.buttonText(this.options.buttonText); 11714 this.$elementFileUploadBtn.find('span.guide-fu-icon').removeClass("glyphicon-plus").addClass("glyphicon-folder-open"); 11715 } 11716 } 11717 }, 11718 11719 showInvalidMessage: function(fileName, invalidFeature){ 11720 var that = this; 11721 var IS_IPAD = navigator.userAgent.match(/iPad/i) !== null, 11722 IS_IPHONE = (navigator.userAgent.match(/iPhone/i) !== null); 11723 if(IS_IPAD || IS_IPHONE){ 11724 setTimeout(function() { 11725 that.invalidMessage(that,fileName, invalidFeature); 11726 }, 0); 11727 } 11728 else { 11729 this.invalidMessage(this,fileName, invalidFeature); 11730 } 11731 }, 11732 11733 invalidMessage: function(refObj,fileName, invalidFeature){ 11734 if(invalidFeature === refObj.invalidFeature.SIZE) { 11735 alert(xfalib.ut.LocalizationUtil.prototype.getLocalizedMessage("", xfalib.locale.Strings["FileSizeGreater"], [fileName, refObj.options.fileSizeLimit])); 11736 } else if (invalidFeature === refObj.invalidFeature.NAME) { 11737 alert(xfalib.ut.LocalizationUtil.prototype.getLocalizedMessage("", xfalib.locale.Strings["FileNameInvalid"], [fileName])); 11738 } else if (invalidFeature === refObj.invalidFeature.MIMETYPE) { 11739 alert(xfalib.ut.LocalizationUtil.prototype.getLocalizedMessage("", xfalib.locale.Strings["FileMimeTypeInvalid"], [fileName])); 11740 } 11741 }, 11742 11743 /*** 11744 * 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 11745 * This is done since our model stores the URL too in case of draft restore or clicking on save in guide 11746 * @param text string representing the text of which the index is to be found 11747 * @param $elem reference to the jquery element. This is used if there are duplicate file names present in the file upload. 11748 * @returns {number} 11749 * @private 11750 */ 11751 _getIndexOfText : function(text, $elem){ 11752 var index = -1, 11753 self = this, 11754 isDuplicatePresent = false; 11755 _.find(this.values, function(value, iter){ 11756 // if value is a url, then compare with last 11757 var tempValue = value, 11758 // can't use getOrElse here since value can have "." in URL and getOrElse splits based on period to find key inside object 11759 fileName = (_.isObject(self._initialFileValueFileNameMap) && typeof self._initialFileValueFileNameMap[value] !== undefined) ? self._initialFileValueFileNameMap[value] : null; 11760 if(tempValue.match(/\//g) && tempValue.match(/\//g).length > 1){ 11761 tempValue = value.substring(value.lastIndexOf("/")+1); 11762 tempValue = xfalib.ut.Utilities._getNameWithoutMarker(tempValue); 11763 } 11764 // we pass file name explicityly as options, if passed use that as fallback to find the URL 11765 if(tempValue === text || fileName === text){ 11766 index = iter; 11767 isDuplicatePresent = self.values.indexOf(value, index + 1) !== -1; 11768 if($elem && isDuplicatePresent){ 11769 // now check if duplicate present and get its correct index 11770 // today all files are wrapped under .guide-fu-fileItem node 11771 index = $elem.closest(".guide-fu-fileItem").index(); 11772 } 11773 // check if there is a duplicate 11774 // this is to just break the loop 11775 return value; 11776 } 11777 }); 11778 return index; 11779 }, 11780 11781 11782 /* 11783 * Since input file element might contain multiple files. 11784 * This function takes absolute file index as parameter & returns position of the file w.r.t input file elt 11785 */ 11786 _getFileObjIdx : function (index) { 11787 if (index >= 0) { 11788 var currentIdx = 0; 11789 for (var fileInputEltIdx = 0; fileInputEltIdx < this.$fileDomElements.length; fileInputEltIdx++) { 11790 if (this.$fileDomElements[fileInputEltIdx]) { 11791 var files = this.$fileDomElements[fileInputEltIdx][0].files; 11792 if (files) { 11793 var filesLength = files.length; 11794 if ( index <= currentIdx + filesLength - 1 ) { 11795 return [fileInputEltIdx, index - currentIdx]; 11796 } 11797 currentIdx+=files.length; 11798 } 11799 } else { 11800 if (index == currentIdx) { 11801 return [fileInputEltIdx,0]; 11802 } 11803 currentIdx++; 11804 } 11805 } 11806 } 11807 return null; 11808 }, 11809 11810 /* 11811 * This function returns FileList object of the passed file array 11812 */ 11813 _getFileListItem : function (files) { 11814 try { 11815 var dataContainer = new DataTransfer() || (new ClipboardEvent("")).clipboardData; 11816 _.each(files, function (file) { 11817 dataContainer.items.add(file); 11818 }); 11819 return dataContainer.files; 11820 } catch(err) { 11821 console.error(err); 11822 throw err; 11823 } 11824 }, 11825 11826 _updateFilesInDom : function($fileDom, files) { 11827 // in safari, a change event is trigged if files property is changed dynamically 11828 // hence adding this check to clear existing state only for safari browsers 11829 this._isFileUpdate = true; 11830 $fileDom[0].files = this._getFileListItem(files); 11831 this._isFileUpdate = false;
11832 }, 11833 11834 /* 11835 * This function deletes files at specified indexes from input dom elt 11836 */ 11837 _deleteFilesFromInputDom : function ($fileDomElt, deletedIndexes) { 11838 var remainingFiles = []; 11839 _.each($fileDomElt[0].files, function(file,idx){ 11840 if(!deletedIndexes.includes(idx)){ 11841 remainingFiles.push(file); 11842 } 11843 }); 11844 try { 11845 // in safari, a change event is trigged if files property is changed dynamically 11846 // hence adding this check to clear existing state only for safari browsers 11847 this._updateFilesInDom($fileDomElt, remainingFiles); 11848 } catch(err){ 11849 console.error("Deleting files is not supported in your browser"); 11850 } 11851 }, 11852 11853 /** 11854 * This event listener gets called on click of close button in file upload 11855 * 11856 * @param event 11857 */ 11858 handleClick: function(event){ 11859 11860 var $elem = $(event.target), 11861 text = $elem.prev().text(), 11862 index = this._getIndexOfText(text, $elem), 11863 url = $elem.prev().data("key"), 11864 objectUrl = $elem.prev().data("objectUrl"); 11865 if (index != -1) { 11866 this.values.splice(index, 1); 11867 var fileObjIdx = this._getFileObjIdx(index); 11868 var $fileDomElt = this.$fileDomElements[fileObjIdx[0]]; 11869 if (!$fileDomElt || $fileDomElt[0].files.length === 1) { 11870 this.$fileDomElements.splice(fileObjIdx[0], 1); 11871 } else { 11872 this._deleteFilesFromInputDom($fileDomElt, [fileObjIdx[1]]); 11873 } 11874 if (isBrowserIE9OrIE10) { 11875 this.cloneFileInputAndUpdateIdForIE9(); 11876 } 11877 if (url != null) { 11878 // remove the data so that others don't use this url 11879 $elem.prev().removeData("key"); 11880 } 11881 if(objectUrl) { 11882 // revoke the object URL to avoid memory leaks in browser 11883 // since file is anyways getting deleted, remove the object URL's too 11884 window.URL.revokeObjectURL(objectUrl); 11885 } 11886 } 11887 // Remove the dom from view 11888 //All bound events and jQuery data associated with the element are also removed 11889 $elem.parent().remove(); 11890 // trigger the change event to update the value 11891 this.$element.trigger("change.fileupload"); 11892 // Set the focus on file upload button after click of close 11893 this.$elementFileUploadBtn.focus(); 11894 11895 }, 11896 11897 11898 displaySVG: function (objectUrl) { 11899 const url = objectUrl; 11900 const img = window.document.createElement('img'); 11901 img.src = url; 11902 const newTab = window.open('', '_blank', 'scrollbars=no,menubar=no,height=600,width=800,resizable=yes,toolbar=no,status=no'); 11903 newTab.document.body.appendChild(img); 11904 }, 11905 11906 11907 _previewFileUsingObjectUrl : function (file) { 11908 if (file) { 11909 if (window.navigator && window.navigator.msSaveOrOpenBlob) { // for IE 11910 window.navigator.msSaveOrOpenBlob(file, file.name); 11911 } else { 11912 var url = window.URL.createObjectURL(file); 11913 if (file.type === 'image/svg+xml') { 11914 this.displaySVG(url); 11915 } else { 11916 window.open(url, '', 'scrollbars=no,menubar=no,height=600,width=800,resizable=yes,toolbar=no,status=no'); 11917 } 11918 return url; 11919 } 11920 } 11921 }, 11922 11923 // this function maintains a map for 11924 handleFilePreview: function(event){ 11925 if(!this.options.disablePreview) { 11926 var $elem = $(event.target), 11927 text = $elem.text(), 11928 index = this._getIndexOfText(text, $elem), 11929 fileDom = null, 11930 fileName = null, 11931 fileUrl = null, 11932 timeStamp = new Date().getTime(); 11933 11934 // for draft usecase, if text contains "/" in it, it means the file is already uploaded 11935 // text should contain the path, assuming that the fileUrl is stored in data element 11936 11937 if (index != -1) { 11938 // Store the url of file as data 11939 if(!_.isUndefined($elem.data("key"))) 11940 fileUrl = $elem.data("key"); 11941 11942 if(fileUrl) { 11943 //prepend context path if not already appended 11944 if (!(fileUrl.lastIndexOf(this.options._getUrl, 0) === 0)) { 11945 fileUrl = this.options._getUrl + fileUrl; 11946 } 11947 this.previewFile.apply(this, [null, {"fileUrl" : fileUrl}]); 11948 } else { 11949 var previewFileObjIdx = this._getFileObjIdx(index); 11950 var previewFile = this.$fileDomElements[previewFileObjIdx[0]][0].files[previewFileObjIdx[1]]; 11951 var objectUrl = this._previewFileUsingObjectUrl(previewFile); 11952 if (objectUrl) { 11953 $elem.data("objectUrl", objectUrl); 11954 } 11955 } 11956 } 11957 } 11958 }, 11959 11960 previewFile: function(event){ 11961 var url = null; 11962 if(_.isUndefined(arguments[1])) 11963 url = this.$element[this.options.uploaderPluginName]("getFileUrl"); 11964 else 11965 url = arguments[1].fileUrl; 11966 var lastIndex = url.lastIndexOf('/'); 11967 //to make sure url has a slash '/' 11968 // added check for query param since sas url contains query params & does not have file name, encoding is not required in this case 11969 if(lastIndex >= 0 && url.indexOf('?') == -1) { 11970 //encode the filename after last slash to ensure the handling of special characters 11971 url = url.substr(0, lastIndex) +'/'+ encodeURIComponent(url.substr(lastIndex + 1)); 11972 } 11973 // this would work for dataURl or normal URL 11974 // todo: add support to preview base 64 encoded image, to preview base64 encoded binary, we would probably need 11975 // todo: the content type in the widget too 11976 window.open(url, '', 'scrollbars=no,menubar=no,height=600,width=800,resizable=yes,toolbar=no,status=no'); 11977 11978 }, 11979 11980 resetIfNotMultiSelect: function(){ 11981 if(!this.options.multiSelect){ 11982 // Reset the value and file array 11983 this.values = []; 11984 //this.comments = []; 11985 } 11986 }, 11987 11988 showFileList: function(fileName, comment, fileUrl){ 11989 if(!this.options.multiSelect || fileName == null || _.isUndefined(fileName)) { 11990 // if not multiselect, remove all the children of file list 11991 this.$elementFileList.empty(); 11992 } 11993 11994 // Add the file item 11995 // On click of close, remove the element and update the model 11996 // handle on click of preview button 11997 if(fileName != null) {
11998 this.$fileItem = this.$elementFileList.append(this.fileItem(fileName, comment, fileUrl)); 11999 } 12000 }, 12001 12002 /** 12003 * Handles the click on comment field 12004 * 12005 * TODO: Implement show/hide behaviour instead of replaceWith 12006 * This may be cause problem during bubble up of event 12007 * 12008 * @param event 12009 */ 12010 handleCommentClick : function(event){ 12011 var $commentElem = null, 12012 $elem = $(event.target); 12013 if ($elem.text() === _defaults.placeHolderText) { 12014 $commentElem = this.getNewCommentElement() 12015 } else { 12016 $commentElem = this.getNewCommentElement($(event.target).text()); 12017 } 12018 $elem.replaceWith($commentElem); 12019 // register the event again 12020 if(isBrowserIE9OrIE10){ 12021 $commentElem.focus().focusout($.proxy(this.handleCommentBlur, this)); 12022 } else { 12023 $commentElem.focus().blur($.proxy(this.handleCommentBlur, this)); 12024 } 12025 }, 12026 12027 handleCommentBlur : function(event){ 12028 var $commentSummaryElem = null, 12029 $elem = $(event.target); 12030 if ($elem.text() === _defaults.placeHolderText) { 12031 $commentSummaryElem = this.getNewCommentElementSummary(); 12032 } else { 12033 $commentSummaryElem = this.getNewCommentElementSummary($(event.target).text()); 12034 } 12035 $elem.replaceWith($commentSummaryElem); 12036 $commentSummaryElem.focus($.proxy(this.handleCommentClick,this)).click($.proxy(this.handleCommentClick,this)); 12037 // Add a div with the html 12038 this.$element.trigger("change.fileupload"); 12039 }, 12040 12041 // checks if file name is valid or not to prevent security threats 12042 isValid : function(fname) { 12043 var rg1=/^[^\\/:\*\;\$\%\?"<>\|]+$/; // forbidden characters \ / : * ? " < > | ; % $ 12044 var rg2=/^\./; // cannot start with dot (.) 12045 var rg3=/^(nul|prn|con|lpt[0-9]|com[0-9])(\.|$)/i; // forbidden file names 12046 return rg1.test(fname) && !rg2.test(fname) && !rg3.test(fname); 12047 }, 12048 12049 handleChange: function (evnt) { 12050 if (!this._isFileUpdate) { 12051 var currFileName = '', 12052 inValidSizefileNames = '', 12053 inValidNamefileNames = '', 12054 inValidMimeTypefileNames = '', 12055 $elem = $(evnt.target), 12056 files = $elem[0].files; 12057 // Initially set the invalid flag to false 12058 12059 // if not multiselect then remove the extra domELement clone 12060 if (!this.options.multiSelect && this.$fileDomElements.length > 1) { 12061 this.$fileDomElements.splice(0, 1) 12062 } 12063 12064 var isInvalidSize = false, 12065 isInvalidFileName = false, 12066 isInvalidMimeType = false;
12067 this.resetIfNotMultiSelect(); 12068 // Iterate through all the files 12069 if (isBrowserIE9OrIE10) { // IE9 doesn't support FileList, hence files variable is undefined 12070 currFileName = $elem.val().split("\\").pop(); 12071 //update the last element of array 12072 if (this.$fileDomElements.length > 0) { 12073 this.$fileDomElements[this.$fileDomElements.length - 1] = $elem; 12074 } 12075 this.cloneFileInputAndUpdateIdForIE9(); 12076 12077 // In case of IE9, only do this 12078 if (_.isUndefined(files)) { 12079 this.showFileList(currFileName); 12080 this.values.push(currFileName); 12081 // trigger the change event to update the value 12082 this.$element.trigger("change.fileupload"); 12083 } 12084 } 12085 if (!_.isUndefined(files)) { 12086 var invalidFilesIndexes = []; 12087 _.each(files, function (file, fileIndex) { 12088 var isCurrentInvalidFileSize = false, 12089 isCurrentInvalidFileName = false, 12090 isCurrentInvalidMimeType = false;
12091 currFileName = file.name.split("\\").pop(); 12092 // Now size is in MB 12093 var size = file.size / 1024 / 1024; 12094 // check if file size limit is within limits 12095 if ((size > parseFloat(this.options.fileSizeLimit))) { 12096 isInvalidSize = isCurrentInvalidFileSize = true; 12097 inValidSizefileNames = currFileName + "," + inValidSizefileNames; 12098 } else if (!this.isValid(currFileName)) { 12099 // check if file names are valid (ie) there are no control characters in file names 12100 isInvalidFileName = isCurrentInvalidFileName = true; 12101 inValidNamefileNames = currFileName + "," + inValidNamefileNames; 12102 } else if (file.type) { 12103 var isMatch = this.regexMimeTypeList.some(function (rx) { 12104 return rx.test(file.type); 12105 }); 12106 if (!isMatch) { 12107 isInvalidMimeType = isCurrentInvalidMimeType = true; 12108 inValidMimeTypefileNames = currFileName + "," + inValidMimeTypefileNames; 12109 } 12110 } else { 12111 var checkEmptyFileTypeFT = FD.isToggleEnabled("FT_FORMS-24171"); 12112 if (checkEmptyFileTypeFT) { 12113 isInvalidMimeType = isCurrentInvalidMimeType = true; 12114 inValidMimeTypefileNames = currFileName + "," + inValidMimeTypefileNames; 12115 } 12116 } 12117 12118 // if the file is not invalid, show it and push it to internal array 12119 if (!isCurrentInvalidFileSize && !isCurrentInvalidFileName && !isCurrentInvalidMimeType) { 12120 this.showFileList(currFileName); 12121 this.values.push(currFileName); 12122 } else { 12123 invalidFilesIndexes.push(fileIndex); 12124 } 12125 12126 12127 }, this); 12128 12129 if (invalidFilesIndexes.length > 0) { 12130 var currentFileDomIndex, 12131 $currentFileDomElement, 12132 filesCount; 12133 if (this.$fileDomElements.length > 0) { 12134 currentFileDomIndex = this.$fileDomElements.length - 1; 12135 $currentFileDomElement = this.$fileDomElements[currentFileDomIndex]; 12136 if ($currentFileDomElement && $currentFileDomElement.length > 0) { 12137 filesCount = $currentFileDomElement[0].files.length; 12138 //if all the files are invalid remove the input element as well otherwise only remove the invalid files. 12139 if (filesCount === invalidFilesIndexes.length) { 12140 this.$fileDomElements.splice(-1, 1); 12141 } else { 12142 this._deleteFilesFromInputDom($currentFileDomElement, invalidFilesIndexes); 12143 } 12144 } 12145 } 12146 12147 // in case of IE10, create one extra element 12148 if (isBrowserIE9OrIE10) { 12149 this.cloneFileInputAndUpdateIdForIE9(); 12150 } 12151 } 12152 12153 // trigger the change event to update the value 12154 this.$element.trigger("change.fileupload"); 12155 } 12156 12157 if (isInvalidSize) { 12158 this.showInvalidMessage(inValidSizefileNames.substring(0, inValidSizefileNames.lastIndexOf(',')), this.invalidFeature.SIZE); 12159 } else if (isInvalidFileName) { 12160 this.showInvalidMessage(inValidNamefileNames.substring(0, inValidNamefileNames.lastIndexOf(',')), this.invalidFeature.NAME); 12161 } else if (isInvalidMimeType) { 12162 this.showInvalidMessage(inValidMimeTypefileNames.substring(0, inValidMimeTypefileNames.lastIndexOf(',')), this.invalidFeature.MIMETYPE); 12163 } 12164 } 12165 }, 12166 12167 cloneFileInputAndUpdateIdForIE9 : function(){ 12168 var elem = _.last(this.$fileDomElements), 12169 elemExists = elem != null, 12170 elemHasValue = elemExists && elem.val().length > 0, 12171 elemId = null, 12172 selector = null; 12173 12174 // CQ-4237903 : create clone to handle the case when user clicks cancel in chrome and for multiselect 12175 // on clicking cancel in chrome file browser, chrome removes all the files from the input element 12176 // remove the extra clone in $fileDomElement on handleChange 12177 if(!elemExists || elemHasValue) { 12178 elem = this.$element.clone(); 12179 // copy the data attributes 12180 elem.data(this.$element.data()); 12181 if(isBrowserIE9OrIE10){ 12182 elemId = this.$element.attr("id") + (++fileLabelsCount); 12183 elem.attr("id", elemId); 12184 elem.css({ 12185 'position' : 'absolute', 12186 'top' : '-2000px', 12187 'left': '-2000px' 12188 }); 12189 elem.appendTo('body'); 12190 this.updateLabelForAttr(elemId); 12191 } 12192 elem.change($.proxy(this.handleChange, this)); 12193 this.$fileDomElements.push(elem); 12194 } 12195 // Case: if it is not multiselect and if the first file dom element is null 12196 // this case would hit when we restore a single select file attachment and attach a new file 12197 if(!this.options.multiSelect && this.$fileDomElements[0] === null){ 12198 //Splice null out of it, since we are attaching a new file 12199 this.$fileDomElements.splice(0, 1); 12200 } 12201 // if the browser is not IE9, then click it 12202 if(!isBrowserIE9OrIE10) { 12203 elem.click(); 12204 } 12205 return true; 12206 }, 12207 12208 /** 12209 * In case of IE9, get the last element of fileDom and update the id for label 12210 * 12211 * @param fileInputId 12212 */ 12213 updateLabelForAttr : function(fileInputId){ 12214 this.$label.attr("for" , fileInputId); 12215 }, 12216 12217 createLabelForFileInput : function (fileInputId){ 12218 if(isBrowserIE9OrIE10) { 12219 this.$label = $("<label></label>").addClass("guide-fu-attach-button button") 12220 .text(this.options.buttonText) 12221 .attr('for',fileInputId); 12222 this.$elementFileUploadBtn.replaceWith(this.$label); 12223 this.$label.parent().attr("tabindex", 0).attr("role", "button").attr("aria-label", this.options.screenReaderText || ""); 12224 } 12225 }, 12226 12227 12228 constructor: function () { 12229 // Initialize the self instance 12230 var _self = this, 12231 isFirst = true; 12232 //jquery instance of file upload button 12233 this.$elementFileUploadBtn = this.$parent.find(this.options.buttonClass); 12234 this.$elementFileUploadBtn.attr("aria-label", this.options.screenReaderText || ""); 12235 if(isBrowserIE9OrIE10){ 12236 this.elementId = this.$element.attr("id"); 12237 this.createLabelForFileInput(this.$element.attr("id")); 12238 } 12239 12240 // html for file list 12241 this.$elementFileList = $(this.fileItemList()); 12242 // Initialize the value and file(Refer FileList class mdn) 12243 this.values = []; 12244 this._initialFileValueFileNameMap = {}; 12245 // List of dom elements of input type file
12246 this.$fileDomElements = []; 12247 12248 var flag = false, 12249 $currElem = null; 12250 12251 $(document).mousedown(function(e) { 12252 $currElem = $(e.target); 12253 }); 12254 // Enter key should result in click of button 12255 this.$elementFileUploadBtn 12256 .focus(function(){ 12257 _self.$element.trigger("focus.fileupload"); 12258 }) 12259 .click($.proxy(this.cloneFileInputAndUpdateIdForIE9, this)) 12260 .blur(function(event){ 12261 // Check if the currElem does not belong to the fileItemList 12262 if(!flag && $currElem!= null && $currElem.closest(".guide-fu-fileItemList").length <=0){ 12263 _self.$element.trigger("focusout.fileupload"); 12264 } 12265 flag = false; 12266 }); 12267 //Initialize the filePreview Plugin 12268 this.$element[this.options.uploaderPluginName]({ 12269 iframeContainer: this.options.iframeContainer, 12270 _filePath: this.options._filePath, 12271 _uuidGenerator: this.options._uuidGenerator, 12272 _getUrl: this.options._getUrl 12273 12274 }); 12275 // Getting input file value 12276 // listening on fileuploaded event 12277 this.$element.change($.proxy(this.handleChange, this)) 12278 .on("adobeFileUploader.fileUploaded", $.proxy(this.previewFile, this)); 12279 } 12280 }; 12281 12282 $.fn.adobeFileAttachment = function (option, value) { 12283 var get = '', 12284 element = this.each(function () { 12285 // in case of input type file 12286 if ($(this).attr('type') === 'file') { 12287 var $this = $(this), 12288 data = $this.data('adobeFileAttachment'), 12289 options = $.extend({}, AdobeFileAttachment.prototype.defaults, typeof option === 'object' && option); 12290 12291 // Save the adobeFileAttachment data in jquery 12292 if (!data) { 12293 $this.data('adobeFileAttachment', (data = new AdobeFileAttachment(this, options))); 12294 data.constructor(); 12295 } 12296 12297 // code to get and set an option 12298 if (typeof option === 'string') { 12299 get = data[option](value); 12300 } 12301 } 12302 }); 12303 12304 if (typeof get !== 'undefined') { 12305 return get; 12306 } else { 12307 return element; 12308 } 12309 }; 12310 12311 // fileSizeLimit is in MB, default value is 2MB 12312 AdobeFileAttachment.prototype.defaults = { 12313 'buttonText': 'Attach', 12314 'multiSelect': false, 12315 'fileSizeLimit': 2, 12316 'uploaderPluginName': "adobeFileUploader", 12317 'mimeType' : ['audio/*', 'video/*', 'image/*', 'text/*', 'application/pdf'] 12318 }; 12319 12320})($, window, window._);(function($, _) { 12321 var xfaUtil = xfalib.ut.XfaUtil.prototype; 12322 $.widget( "xfaWidget.fileUpload", $.xfaWidget.abstractWidget, { 12323 12324 _widgetName:"fileUpload", 12325 _superPrototype : $.xfaWidget.abstractWidget.prototype, 12326 getOptionsMap: function(){ 12327 var parentOptionsMap = this._superPrototype.getOptionsMap.apply(this,arguments), 12328 newMap = $.extend({},parentOptionsMap, $.extend({}, this.options, { 12329 "value" : function(value) { 12330 this.$userControl.adobeFileAttachment("value", value); 12331 }, 12332 "fileList": function(value){ 12333 this.$userControl.adobeFileAttachment("fileList", value); 12334 }, 12335 "comment" : function(value){ 12336 this.$userControl.adobeFileAttachment("comment", value); 12337 }, 12338 // "access" can be either open or readonly 12339 "access" : function(value){ 12340 this.$userControl.adobeFileAttachment("access", value); 12341 } 12342 12343 })); 12344 12345 return newMap; 12346 12347 }, 12348 // TODO: Will need to remove this functions 12349 // will be tracked by LC-391200 12350 12351 _initializeOptions: function () { 12352 _.each(this.optionsHandler, function (value, key) { 12353 // overriding the behaviour of _initializeOptions 12354 // only for _uuidGenerator 12355 // as we font want getUUID to be called at render time 12356 if (typeof value === "function" && key !== '_uuidGenerator' ) { 12357 value.apply(this, [this.options[key]]) 12358 } 12359 }, this) 12360 }, 12361 12362 _getFileList: function(){ 12363 return this.$userControl.adobeFileAttachment("fileList"); 12364 }, 12365 12366 _getComment: function(){ 12367 return this.$userControl.adobeFileAttachment("comment"); 12368 }, 12369 _getFileNamePathMap: function (pathList) { 12370 return this.$userControl.adobeFileAttachment("getSetFilePathAndReturnNamePathMap", pathList); 12371 }, 12372 getEventMap: function() { 12373 var parentEventMap = this._superPrototype.getEventMap.apply(this, arguments), 12374 newMap = $.extend({}, parentEventMap, 12375 { 12376 "change" : null, 12377 "focusout.fileupload" : xfaUtil.XFA_EXIT_EVENT, 12378 "focus.fileupload" : xfaUtil.XFA_ENTER_EVENT, 12379 "change.fileupload" : xfaUtil.XFA_CHANGE_EVENT 12380 }); 12381 return newMap; 12382 }, 12383 render: function() { 12384 var $el = this._superPrototype.render.apply(this,arguments); 12385 $el.adobeFileAttachment(this.getOptionsMap()); 12386 return $el; 12387 }, 12388 showDisplayValue: function() { 12389 //since value can't be set in file element input, leav
12389ing this fn empty 12390 }, 12391 showValue: function() { 12392 //since value can't be set in file element input, leaving this fn empty 12393 }, 12394 getCommitValue: function() { 12395 this.options.fileList = this._getFileList(); 12396 this.options.comment = this._getComment(); 12397 return this.$userControl.adobeFileAttachment("value"); 12398 } 12399 }); 12400})($, window._); 12401 12402/** 12403 * Adobe FilePreview Widget Plugin 12404 * 12405 * Options expected by file preview is the url 12406 * 12407 * Options Required Are: 12408 * 12409 * iframeName: Name of the Iframe 12410 * iframeContainer: Container of the iframe(eg Body) 12411 * fileUploadPath: Path where the file is to be uploaded 12412 * fileUploadServlet: Servlet where the file is to be uploaded 12413 * 12414 */ 12415(function ($, _) { 12416 12417 var AdobeFileUploader = function (element, options) { 12418 this.options = options; 12419 this.$element = $(element); 12420 }; 12421 12422 AdobeFileUploader.prototype = { 12423 12424 _fileIframeName: "guide-fu-iframe", 12425 12426 _filePath: "/tmp/fd/mf", 12427 12428 _iframeContainer: "body#formBody", 12429 12430 12431 fileIframe: function (name) { 12432 return $("<iframe></iframe>").attr({ 12433 style: "display:none", 12434 name: name 12435 }); 12436 }, 12437 12438 uploadFile: function (fileObject) { 12439 var multiple = false, 12440 fileName = null, 12441 actionUrl = null, 12442 fileUploadPath = fileObject.fileUploadPath, 12443 uuid; 12444 12445 if (!fileUploadPath) { 12446 uuid = fileObject._uuidGenerator(); 12447 } 12448 12449 // if uuid exists only then upload the file in the current instance 12450 if (_.isObject(fileObject) && (fileUploadPath || uuid)) { 12451 var fileDom = fileObject.fileDom, 12452 $form = $(this.options.iframeContainer).find(".filePreview"); 12453 fileName = fileObject.fileName; 12454 multiple = fileObject.multiple; 12455 if(!fileUploadPath) { 12456 fileUploadPath = this.options.fileUploadPath + "/" + uuid; 12457 } 12458 if (fileDom !== null) { 12459 //prepend contextpath 12460 actionUrl = fileObject._getUrl + fileUploadPath; 12461 if (!multiple) { 12462 if (!(fileUploadPath.lastIndexOf(fileObject._getUrl, 0) === 0)) { 12463 this.fileUrl = fileObject._getUrl + fileUploadPath + "/" + fileName; 12464 } else { 12465 this.fileUrl = fileUploadPath + "/" + fileName; 12466 } 12467 } else { 12468 this.fileUrl = actionUrl; 12469 } 12470 // done to solve issue LC-5835 12471 if($form.length === 0) { 12472 $form = $("<form method='post' enctype='multipart/form-data'></form>") 12473 .addClass("filePreview") 12474 // create id so that it does not intercept with other forms in the page 12475 .attr({ 12476 id : "form" + new Date().valueOf(), 12477 action : actionUrl, 12478 target : this.options.iframeName 12479 }) 12480 .appendTo(this.options.iframeContainer); 12481 } else { 12482 /// first empty all children, using detach so that data is not clear 12483 $form.children().detach(); 12484 // now update the new attributes 12485 $form.attr({ 12486 action : actionUrl, 12487 target : this.options.iframeName 12488 }); 12489 } 12490 // this is done so that the other events attached at some other level in DOM Tree don't interfere 12491 $form.one("submit", function(evnt){ 12492 evnt.stopPropagation(); 12493 }); 12494 12495 var data = new FormData(); 12496 12497 if (multiple) { 12498 _.each(fileDom, function (fileDomElement, index) { 12499 // OOTB, this code is still used in dashboard 12500 if(fileDomElement !== null && !_.isString(fileDomElement)) { 12501 $(fileDomElement[0]).attr('name', fileName[index]).appendTo($form); 12502 // fileDomElement might contain multiple files so all the files needs to be added to formdata. 12503 var currentFileNames = fileName[index].split("\n"); 12504 for(var fileIndex = 0; fileIndex < currentFileNames.length; fileIndex++) { 12505 data.append(currentFileNames[fileIndex], fileDomElement[0].files[fileIndex]); 12506 } 12507 } 12508 }, this); 12509 } else { 12510 fileDom.attr('name', fileName).appendTo($form); 12511 data.append(fileName, fileDom[0].files[0]); 12512 } 12513 12514 /* UseCase: Suppose the fileName is in other language, on click of fileName, it tries to upload the file 12515 so that it could be preview, this change would ensure that the file is properly previewed supp
12515orting 12516 the given UTF-8 charset */ 12517 $("<input type='hidden' name='_charset_' value='UTF-8'/>").appendTo($form); 12518 data.append("_charset_", "UTF-8"); 12519 if (!multiple) { 12520 this.fileMap[this.fileUrl] = this.$element; 12521 } 12522 var self = this; 12523 $.ajax({ 12524 url: $form.attr("action"), 12525 data: data, 12526 cache: false, 12527 contentType: false, 12528 processData: false, 12529 method: 'POST', 12530 type: 'POST', 12531 success: function(data){ 12532 if (!multiple) { 12533 self.handleSingleFileUpload(data); 12534 } else { 12535 self.handleMultipleFileUpload(data); 12536 } 12537 }, 12538 error: function() { 12539 this.$element.trigger("adobeFileUploader.fileUploadFailed"); 12540 } 12541 }); 12542 } 12543 } 12544 return this.fileUrl; 12545 }, 12546 12547 handleMultipleFileUpload: function (data) { 12548 this.$element.trigger("adobeFileUploader.multipleFileUploaded"); 12549 }, 12550 12551 getFileUrl: function () { 12552 return this.fileUrl; 12553 }, 12554 12555 getUrlContentsFromUploadData: function (data) { 12556 var temp; 12557 if(data != null) { 12558 temp = $(data).find("#ChangeLog").text().split("br", 2)[1]; 12559 } else { 12560 var selector = this.options.iframeContainer + " iframe[name='" + this.options.iframeName + "']"; 12561 temp = $(selector).contents().find("#ChangeLog").text().split("br", 2)[1]; 12562 } 12563 12564 temp = temp.substring(temp.indexOf("created") + 9, temp.indexOf(";<")); 12565 temp = temp.substring(0, temp.length - 2); 12566 var index = temp.indexOf("/jcr:content"); 12567 if (index !== -1) 12568 temp = temp.substring(0, index); 12569 return temp; 12570 }, 12571 12572 handleSingleFileUpload: function (data) { 12573 var url = this.getUrlContentsFromUploadData(data); 12574 12575 //prepend context path 12576 url = this.options._getUrl + url; 12577 if (url in this.fileMap) { 12578 this.fileMap[url].trigger("adobeFileUploader.fileUploaded"); 12579 } 12580 }, 12581 12582 initialize: function () { 12583 // Put iframe inside the iframe container 12584 // On the load of iframe, display the contents of file 12585 // since there is only one iframe for all the file attachments, there may be race condition 12586 if (this.$iframe == null || this.$iframe.length === 0) { 12587 this.$iframe = this.fileIframe(this.options.iframeName).appendTo(this.options.iframeContainer); 12588 // since there is only iframe for the preview of all file attachments 12589 // this map is added in the closure scope 12590 // map contains the url(key) vs fileDomElement(value) 12591 // it helps avoids the race condition 12592 this.fileMap = {}; 12593 } 12594 } 12595 }; 12596 12597 $.fn.adobeFileUploader = function (option, value) { 12598 var get = '', 12599 element = this.each(function () { 12600 // in case of input type file 12601 if ($(this).attr('type') === 'file') { 12602 var $this = $(this), 12603 data = $this.data('adobeFileUploader'), 12604 options = $.extend({}, AdobeFileUploader.prototype.defaults(option, value), typeof option === 'object' && option); 12605 12606 // Save the adobeFileAttachment data in jquery 12607 if (!data) { 12608 $this.data('adobeFileUploader', (data = new AdobeFileUploader(this, options))); 12609 data.initialize(); 12610 } else { 12611 // update elements if not equal, since sometimes one can clone too 12612 if(data.$element.get(0) !== this) { 12613 data.$element = $(this); 12614 } 12615 } 12616 12617 // code to get and set an option 12618 if (typeof option === 'string') { 12619 get = data[option](value); 12620 } 12621 } 12622 }); 12623 12624 if (typeof get !== 'undefined') { 12625 return get; 12626 } else { 12627 return element; 12628 } 12629 }; 12630 12631 12632 AdobeFileUploader.prototype.defaults = function (options,value) { 12633 var propertyObject = {}; 12634 if(typeof options == 'object') { 12635 propertyObject._fileIframeName = options._fileIframeName; 12636 propertyObject._filePath = options._filePath; 12637 propertyObject.actionUrl = options.actionUrl; 12638 propertyObject._getUrl = options._getUrl; 12639 } 12640 if(typeof value == 'object') { 12641 propertyObject._fileIframeName = value._fileIframeName; 12642 propertyObject._filePath = value._filePath; 12643 propertyObject.actionUrl = value.actionUrl; 12644 propertyObject._getUrl = options._getUrl; 12645 } 12646 return { 12647 'fileUploadPath': propertyObject._filePath || AdobeFileUploader.prototype._filePath, 12648 'iframeName': AdobeFileUploader.prototype._fileIframeName + new Date().valueOf(), 12649 'fileUploadServlet': propertyObject._filePath || AdobeFileUploader.prototype._filePath,
vendor: 4,462 bytes, lines 12650-12803
12650 'iframeContainer': propertyObject._iframeContainer || AdobeFileUploader.prototype._iframeContainer, 12651 '_getUrl': propertyObject._getUrl || "" 12652 }; 12653 }; 12654 12655})($, window._); 12656 12657/*! 12658 * Bootstrap v3.4.1 (https://getbootstrap.com/) 12659 * Copyright 2011-2019 Twitter, Inc. 12660 * Licensed under the MIT license 12661 */ 12662 12663if (typeof jQuery === 'undefined') { 12664 throw new Error('Bootstrap\'s JavaScript requires jQuery') 12665} 12666 12667+function ($) { 12668 'use strict'; 12669 var version = $.fn.jquery.split(' ')[0].split('.') 12670 if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) { 12671 throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4') 12672 } 12673}(jQuery); 12674 12675/* ======================================================================== 12676 * Bootstrap: transition.js v3.4.1 12677 * https://getbootstrap.com/docs/3.4/javascript/#transitions 12678 * ======================================================================== 12679 * Copyright 2011-2019 Twitter, Inc. 12680 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 12681 * ======================================================================== */ 12682 12683 12684+function ($) { 12685 'use strict'; 12686 12687 // CSS TRANSITION SUPPORT (Shoutout: https://modernizr.com/) 12688 // ============================================================ 12689 12690 function transitionEnd() { 12691 var el = document.createElement('bootstrap') 12692 12693 var transEndEventNames = { 12694 WebkitTransition : 'webkitTransitionEnd', 12695 MozTransition : 'transitionend', 12696 OTransition : 'oTransitionEnd otransitionend', 12697 transition : 'transitionend' 12698 } 12699 12700 for (var name in transEndEventNames) { 12701 if (el.style[name] !== undefined) { 12702 return { end: transEndEventNames[name] } 12703 } 12704 } 12705 12706 return false // explicit for ie8 ( ._.) 12707 } 12708 12709 // https://blog.alexmaccaw.com/css-transitions 12710 $.fn.emulateTransitionEnd = function (duration) { 12711 var called = false 12712 var $el = this 12713 $(this).one('bsTransitionEnd', function () { called = true }) 12714 var callback = function () { if (!called) $($el).trigger($.support.transition.end) } 12715 setTimeout(callback, duration) 12716 return this 12717 } 12718 12719 $(function () { 12720 $.support.transition = transitionEnd() 12721 12722 if (!$.support.transition) return 12723 12724 $.event.special.bsTransitionEnd = { 12725 bindType: $.support.transition.end, 12726 delegateType: $.support.transition.end, 12727 handle: function (e) { 12728 if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments) 12729 } 12730 } 12731 }) 12732 12733}(jQuery); 12734 12735/* ======================================================================== 12736 * Bootstrap: alert.js v3.4.1 12737 * https://getbootstrap.com/docs/3.4/javascript/#alerts 12738 * ======================================================================== 12739 * Copyright 2011-2019 Twitter, Inc. 12740 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 12741 * ======================================================================== */ 12742 12743 12744+function ($) { 12745 'use strict'; 12746 12747 // ALERT CLASS DEFINITION 12748 // ====================== 12749 12750 var dismiss = '[data-dismiss="alert"]' 12751 var Alert = function (el) { 12752 $(el).on('click', dismiss, this.close) 12753 } 12754 12755 Alert.VERSION = '3.4.1' 12756 12757 Alert.TRANSITION_DURATION = 150 12758 12759 Alert.prototype.close = function (e) { 12760 var $this = $(this) 12761 var selector = $this.attr('data-target') 12762 12763 if (!selector) { 12764 selector = $this.attr('href') 12765 selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 12766 } 12767 12768 selector = selector === '#' ? [] : selector 12769 var $parent = $(document).find(selector) 12770 12771 if (e) e.preventDefault() 12772 12773 if (!$parent.length) { 12774 $parent = $this.closest('.alert') 12775 } 12776 12777 $parent.trigger(e = $.Event('close.bs.alert')) 12778 12779 if (e.isDefaultPrevented()) return 12780 12781 $parent.removeClass('in') 12782 12783 function removeElement() { 12784 // detach from parent, fire event then clean up data 12785 $parent.detach().trigger('closed.bs.alert').remove() 12786 } 12787 12788 $.support.transition && $parent.hasClass('fade') ? 12789 $parent 12790 .one('bsTransitionEnd', removeElement) 12791 .emulateTransitionEnd(Alert.TRANSITION_DURATION) : 12792 removeElement() 12793 } 12794 12795 12796 // ALERT PLUGIN DEFINITION 12797 // ======================= 12798 12799 function Plugin(option) { 12800 return this.each(function () { 12801 var $this = $(this) 12802 var data = $this.data('bs.alert') 12803
vendor: 59,455 bytes, lines 12804-14790
12804 if (!data) $this.data('bs.alert', (data = new Alert(this))) 12805 if (typeof option == 'string') data[option].call($this) 12806 }) 12807 } 12808 12809 var old = $.fn.alert 12810 12811 $.fn.alert = Plugin 12812 $.fn.alert.Constructor = Alert 12813 12814 12815 // ALERT NO CONFLICT 12816 // ================= 12817 12818 $.fn.alert.noConflict = function () { 12819 $.fn.alert = old 12820 return this 12821 } 12822 12823 12824 // ALERT DATA-API 12825 // ============== 12826 12827 $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close) 12828 12829}(jQuery); 12830 12831/* ======================================================================== 12832 * Bootstrap: button.js v3.4.1 12833 * https://getbootstrap.com/docs/3.4/javascript/#buttons 12834 * ======================================================================== 12835 * Copyright 2011-2019 Twitter, Inc. 12836 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 12837 * ======================================================================== */ 12838 12839 12840+function ($) { 12841 'use strict'; 12842 12843 // BUTTON PUBLIC CLASS DEFINITION 12844 // ============================== 12845 12846 var Button = function (element, options) { 12847 this.$element = $(element) 12848 this.options = $.extend({}, Button.DEFAULTS, options) 12849 this.isLoading = false 12850 } 12851 12852 Button.VERSION = '3.4.1' 12853 12854 Button.DEFAULTS = { 12855 loadingText: 'loading...' 12856 } 12857 12858 Button.prototype.setState = function (state) { 12859 var d = 'disabled' 12860 var $el = this.$element 12861 var val = $el.is('input') ? 'val' : 'html' 12862 var data = $el.data() 12863 12864 state += 'Text' 12865 12866 if (data.resetText == null) $el.data('resetText', $el[val]()) 12867 12868 // push to event loop to allow forms to submit 12869 setTimeout($.proxy(function () { 12870 $el[val](data[state] == null ? this.options[state] : data[state]) 12871 12872 if (state == 'loadingText') { 12873 this.isLoading = true 12874 $el.addClass(d).attr(d, d).prop(d, true) 12875 } else if (this.isLoading) { 12876 this.isLoading = false 12877 $el.removeClass(d).removeAttr(d).prop(d, false) 12878 } 12879 }, this), 0) 12880 } 12881 12882 Button.prototype.toggle = function () { 12883 var changed = true 12884 var $parent = this.$element.closest('[data-toggle="buttons"]') 12885 12886 if ($parent.length) { 12887 var $input = this.$element.find('input') 12888 if ($input.prop('type') == 'radio') { 12889 if ($input.prop('checked')) changed = false 12890 $parent.find('.active').removeClass('active') 12891 this.$element.addClass('active') 12892 } else if ($input.prop('type') == 'checkbox') { 12893 if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false 12894 this.$element.toggleClass('active') 12895 } 12896 $input.prop('checked', this.$element.hasClass('active')) 12897 if (changed) $input.trigger('change') 12898 } else { 12899 this.$element.attr('aria-pressed', !this.$element.hasClass('active')) 12900 this.$element.toggleClass('active') 12901 } 12902 } 12903 12904 12905 // BUTTON PLUGIN DEFINITION 12906 // ======================== 12907 12908 function Plugin(option) { 12909 return this.each(function () { 12910 var $this = $(this) 12911 var data = $this.data('bs.button') 12912 var options = typeof option == 'object' && option 12913 12914 if (!data) $this.data('bs.button', (data = new Button(this, options))) 12915 12916 if (option == 'toggle') data.toggle() 12917 else if (option) data.setState(option) 12918 }) 12919 } 12920 12921 var old = $.fn.button 12922 12923 $.fn.button = Plugin 12924 $.fn.button.Constructor = Button 12925 12926 12927 // BUTTON NO CONFLICT 12928 // ================== 12929 12930 $.fn.button.noConflict = function () { 12931 $.fn.button = old 12932 return this 12933 } 12934 12935 12936 // BUTTON DATA-API 12937 // =============== 12938 12939 $(document) 12940 .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) { 12941 var $btn = $(e.target).closest('.btn') 12942 Plugin.call($btn, 'toggle') 12943 if (!($(e.target).is('input[type="radio"], input[type="checkbox"]'))) { 12944 // Prevent double click on radios, and the double selections (so cancellation) on checkboxes 12945 e.preventDefault() 12946 // The target component still receive the focus 12947 if ($btn.is('input,button')) $btn.trigger('focus') 12948 else $btn.find('input:visible,button:visible').first().trigger('focus') 12949 } 12950 }) 12951 .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) { 12952 $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type)) 12953 }) 12954 12955}(jQuery); 12956 12957/* ======================================================================== 12958 * Bootstrap: carousel.js v3.4.1 12959 * https://getbootstrap.com/docs/3.4/javascript/#carousel 12960 * ======================================================================== 12961 * Copyright 2011-2019 Twitter, Inc. 12962 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 12963 * ======================================================================== */ 12964 12965 12966+function ($) { 12967 'use strict'; 12968 12969 // CAROUSEL CLASS DEFINITION 12970 // ========================= 12971 12972 var Carousel = function (element, options) { 12973 this.$element = $(element) 12974 this.$indicators = this.$element.find('.carousel-indicators') 12975 this.options = options 12976 this.paused = null 12977 this.sliding = null 12978 this.interval = null 12979 this.$active = null 12980 this.$items = null 12981 12982 this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this)) 12983 12984 this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element 12985 .on('mouseenter.bs.carousel', $.proxy(this.pause, this)) 12986 .on('mouseleave.bs.carousel', $.proxy(this.cycle, this)) 12987 } 12988 12989 Carousel.VERSION = '3.4.1' 12990 12991 Carousel.TRANSITION_DURATION = 600 12992 12993 Carousel.DEFAULTS = { 12994 interval: 5000, 12995 pause: 'hover', 12996 wrap: true, 12997 keyboard: true 12998 } 12999 13000 Carousel.prototype.keydown = function (e) { 13001 if (/input|textarea/i.test(e.target.tagName)) return 13002 switch (e.which) { 13003 case 37: this.prev(); break 13004 case 39: this.next(); break 13005 default: return 13006 } 13007 13008 e.preventDefault() 13009 } 13010 13011 Carousel.prototype.cycle = function (e) { 13012 e || (this.paused = false) 13013 13014 this.interval && clearInterval(this.interval) 13015 13016 this.options.interval 13017 && !this.paused 13018 && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) 13019 13020 return this 13021 } 13022 13023 Carousel.prototype.getItemIndex = function (item) { 13024 this.$items = item.parent().children('.item') 13025 return this.$items.index(item || this.$active) 13026 } 13027 13028 Carousel.prototype.getItemForDirection = function (direction, active) { 13029 var activeIndex = this.getItemIndex(active) 13030 var willWrap = (direction == 'prev' && activeIndex === 0) 13031 || (direction == 'next' && activeIndex == (this.$items.length - 1)) 13032 if (willWrap && !this.options.wrap) return active 13033 var delta = direction == 'prev' ? -1 : 1 13034 var itemIndex = (activeIndex + delta) % this.$items.length 13035 return this.$items.eq(itemIndex) 13036 } 13037 13038 Carousel.prototype.to = function (pos) { 13039 var that = this 13040 var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active')) 13041 13042 if (pos > (this.$items.length - 1) || pos < 0) return 13043 13044 if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid" 13045 if (activeIndex == pos) return this.pause().cycle() 13046 13047 return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos)) 13048 } 13049 13050 Carousel.prototype.pause = function (e) { 13051 e || (this.paused = true) 13052 13053 if (this.$element.find('.next, .prev').length && $.support.transition) { 13054 this.$element.trigger($.support.transition.end) 13055 this.cycle(true) 13056 } 13057 13058 this.interval = clearInterval(this.interval) 13059 13060 return this 13061 } 13062 13063 Carousel.prototype.next = function () { 13064 if (this.sliding) return 13065 return this.slide('next') 13066 } 13067 13068 Carousel.prototype.prev = function () { 13069 if (this.sliding) return 13070 return this.slide('prev') 13071 } 13072 13073 Carousel.prototype.slide = function (type, next) { 13074 var $active = this.$element.find('.item.active') 13075 var $next = next || this.getItemForDirection(type, $active) 13076 var isCycling = this.interval 13077 var direction = type == 'next' ? 'left' : 'right' 13078 var that = this 13079 13080 if ($next.hasClass('active')) return (this.sliding = false) 13081 13082 var relatedTarget = $next[0] 13083 var slideEvent = $.Event('slide.bs.carousel', { 13084 relatedTarget: relatedTarget, 13085 direction: direction 13086 }) 13087 this.$element.trigger(slideEvent) 13088 if (slideEvent.isDefaultPrevented()) return 13089 13090 this.sliding = true 13091 13092 isCycling && this.pause() 13093 13094 if (this.$indicators.length) { 13095 this.$indicators.find('.active').removeClass('active') 13096 var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)]) 13097 $nextIndicator && $nextIndicator.addClass('active') 13098 } 13099 13100 var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid" 13101 if ($.support.transition && this.$element.hasClass('slide')) { 13102 $next.addClass(type) 13103 if (typeof $next === 'object' && $next.length) { 13104 $next[0].offsetWidth // force reflow 13105 } 13106 $active.addClass(direction) 13107 $next.addClass(direction) 13108 $active 13109 .one('bsTransitionEnd', function () { 13110 $next.removeClass([type, direction].join(' ')).addClass('active') 13111 $active.removeClass(['active', direction].join(' ')) 13112 that.sliding = false 13113 setTimeout(function () { 13114 that.$element.trigger(slidEvent) 13115 }, 0) 13116 }) 13117 .emulateTransitionEnd(Carousel.TRANSITION_DURATION) 13118 } else { 13119 $active.removeClass('active') 13120 $next.addClass('active') 13121 this.sliding = false 13122 this.$element.trigger(slidEvent) 13123 } 13124 13125 isCycling && this.cycle() 13126 13127 return this 13128 } 13129 13130 13131 // CAROUSEL PLUGIN DEFINITION 13132 // ========================== 13133 13134 function Plugin(option) { 13135 return this.each(function () { 13136 var $this = $(this) 13137 var data = $this.data('bs.carousel') 13138 var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option) 13139 var action = typeof option == 'string' ? option : options.slide 13140 13141 if (!data) $this.data('bs.carousel', (data = new Carousel(this, options))) 13142 if (typeof option == 'number') data.to(option) 13143 else if (action) data[action]() 13144 else if (options.interval) data.pause().cycle() 13145 }) 13146 } 13147 13148 var old = $.fn.carousel 13149 13150 $.fn.carousel = Plugin 13151 $.fn.carousel.Constructor = Carousel 13152 13153 13154 // CAROUSEL NO CONFLICT 13155 // ==================== 13156 13157 $.fn.carousel.noConflict = function () { 13158 $.fn.carousel = old 13159 return this 13160 } 13161 13162 13163 // CAROUSEL DATA-API 13164 // ================= 13165 13166 var clickHandler = function (e) { 13167 var $this = $(this) 13168 var href = $this.attr('href') 13169 if (href) { 13170 href = href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7 13171 } 13172 13173 var target = $this.attr('data-target') || href 13174 var $target = $(document).find(target) 13175 13176 if (!$target.hasClass('carousel')) return 13177 13178 var options = $.extend({}, $target.data(), $this.data()) 13179 var slideIndex = $this.attr('data-slide-to') 13180 if (slideIndex) options.interval = false 13181 13182 Plugin.call($target, options) 13183 13184 if (slideIndex) { 13185 $target.data('bs.carousel').to(slideIndex) 13186 } 13187 13188 e.preventDefault() 13189 } 13190 13191 $(document) 13192 .on('click.bs.carousel.data-api', '[data-slide]', clickHandler) 13193 .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler) 13194 13195 $(window).on('load', function () { 13196 $('[data-ride="carousel"]').each(function () { 13197 var $carousel = $(this) 13198 Plugin.call($carousel, $carousel.data()) 13199 }) 13200 }) 13201 13202}(jQuery); 13203 13204/* ======================================================================== 13205 * Bootstrap: collapse.js v3.4.1 13206 * https://getbootstrap.com/docs/3.4/javascript/#collapse 13207 * ======================================================================== 13208 * Copyright 2011-2019 Twitter, Inc. 13209 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 13210 * ======================================================================== */ 13211 13212/* jshint latedef: false */ 13213 13214+function ($) { 13215 'use strict'; 13216 13217 // COLLAPSE PUBLIC CLASS DEFINITION 13218 // ================================ 13219 13220 var Collapse = function (element, options) { 13221 this.$element = $(element) 13222 this.options = $.extend({}, Collapse.DEFAULTS, options) 13223 this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' + 13224 '[data-toggle="collapse"][data-target="#' + element.id + '"]') 13225 this.transitioning = null 13226 13227 if (this.options.parent) { 13228 this.$parent = this.getParent() 13229 } else { 13230 this.addAriaAndCollapsedClass(this.$element, this.$trigger) 13231 } 13232 13233 if (this.options.toggle) this.toggle() 13234 } 13235 13236 Collapse.VERSION = '3.4.1' 13237 13238 Collapse.TRANSITION_DURATION = 350 13239 13240 Collapse.DEFAULTS = { 13241 toggle: true 13242 } 13243 13244 Collapse.prototype.dimension = function () { 13245 var hasWidth = this.$element.hasClass('width') 13246 return hasWidth ? 'width' : 'height' 13247 } 13248 13249 Collapse.prototype.show = function () { 13250 if (this.transitioning || this.$element.hasClass('in')) return 13251 13252 var activesData 13253 var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing') 13254 13255 if (actives && actives.length) { 13256 activesData = actives.data('bs.collapse') 13257 if (activesData && activesData.transitioning) return 13258 } 13259 13260 var startEvent = $.Event('show.bs.collapse') 13261 this.$element.trigger(startEvent) 13262 if (startEvent.isDefaultPrevented()) return 13263 13264 if (actives && actives.length) { 13265 Plugin.call(actives, 'hide') 13266 activesData || actives.data('bs.collapse', null) 13267 } 13268 13269 var dimension = this.dimension() 13270 13271 this.$element 13272 .removeClass('collapse') 13273 .addClass('collapsing')[dimension](0) 13274 .attr('aria-expanded', true) 13275 13276 this.$trigger 13277 .removeClass('collapsed') 13278 .attr('aria-expanded', true) 13279 13280 this.transitioning = 1 13281 13282 var complete = function () { 13283 this.$element 13284 .removeClass('collapsing') 13285 .addClass('collapse in')[dimension]('') 13286 this.transitioning = 0 13287 this.$element 13288 .trigger('shown.bs.collapse') 13289 } 13290 13291 if (!$.support.transition) return complete.call(this) 13292 13293 var scrollSize = $.camelCase(['scroll', dimension].join('-')) 13294 13295 this.$element 13296 .one('bsTransitionEnd', $.proxy(complete, this)) 13297 .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize]) 13298 } 13299 13300 Collapse.prototype.hide = function () { 13301 if (this.transitioning || !this.$element.hasClass('in')) return 13302 13303 var startEvent = $.Event('hide.bs.collapse') 13304 this.$element.trigger(startEvent) 13305 if (startEvent.isDefaultPrevented()) return 13306 13307 var dimension = this.dimension() 13308 13309 this.$element[dimension](this.$element[dimension]())[0].offsetHeight 13310 13311 this.$element 13312 .addClass('collapsing') 13313 .removeClass('collapse in') 13314 .attr('aria-expanded', false) 13315 13316 this.$trigger 13317 .addClass('collapsed') 13318 .attr('aria-expanded', false) 13319 13320 this.transitioning = 1 13321 13322 var complete = function () { 13323 this.transitioning = 0 13324 this.$element 13325 .removeClass('collapsing') 13326 .addClass('collapse') 13327 .trigger('hidden.bs.collapse') 13328 } 13329 13330 if (!$.support.transition) return complete.call(this) 13331 13332 this.$element 13333 [dimension](0) 13334 .one('bsTransitionEnd', $.proxy(complete, this)) 13335 .emulateTransitionEnd(Collapse.TRANSITION_DURATION) 13336 } 13337 13338 Collapse.prototype.toggle = function () { 13339 this[this.$element.hasClass('in') ? 'hide' : 'show']() 13340 } 13341 13342 Collapse.prototype.getParent = function () { 13343 return $(document).find(this.options.parent) 13344 .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]') 13345 .each($.proxy(function (i, element) { 13346 var $element = $(element) 13347 this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element) 13348 }, this)) 13349 .end() 13350 } 13351 13352 Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) { 13353 var isOpen = $element.hasClass('in') 13354 13355 $element.attr('aria-expanded', isOpen) 13356 $trigger 13357 .toggleClass('collapsed', !isOpen) 13358 .attr('aria-expanded', isOpen) 13359 } 13360 13361 function getTargetFromTrigger($trigger) { 13362 var href 13363 var target = $trigger.attr('data-target') 13364 || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7 13365 13366 return $(document).find(target) 13367 } 13368 13369 13370 // COLLAPSE PLUGIN DEFINITION 13371 // ========================== 13372 13373 function Plugin(option) { 13374 return this.each(function () { 13375 var $this = $(this) 13376 var data = $this.data('bs.collapse') 13377 var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) 13378 13379 if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false 13380 if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) 13381 if (typeof option == 'string') data[option]() 13382 }) 13383 } 13384 13385 var old = $.fn.collapse 13386 13387 $.fn.collapse = Plugin 13388 $.fn.collapse.Constructor = Collapse 13389 13390 13391 // COLLAPSE NO CONFLICT 13392 // ==================== 13393 13394 $.fn.collapse.noConflict = function () { 13395 $.fn.collapse = old 13396 return this 13397 } 13398 13399 13400 // COLLAPSE DATA-API 13401 // ================= 13402 13403 $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { 13404 var $this = $(this) 13405 13406 if (!$this.attr('data-target')) e.preventDefault() 13407 13408 var $target = getTargetFromTrigger($this) 13409 var data = $target.data('bs.collapse') 13410 var option = data ? 'toggle' : $this.data() 13411 13412 Plugin.call($target, option) 13413 }) 13414 13415}(jQuery); 13416 13417/* ======================================================================== 13418 * Bootstrap: dropdown.js v3.4.1 13419 * https://getbootstrap.com/docs/3.4/javascript/#dropdowns 13420 * ======================================================================== 13421 * Copyright 2011-2019 Twitter, Inc. 13422 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 13423 * ======================================================================== */ 13424 13425 13426+function ($) { 13427 'use strict'; 13428 13429 // DROPDOWN CLASS DEFINITION 13430 // ========================= 13431 13432 var backdrop = '.dropdown-backdrop' 13433 var toggle = '[data-toggle="dropdown"]' 13434 var Dropdown = function (element) { 13435 $(element).on('click.bs.dropdown', this.toggle) 13436 } 13437 13438 Dropdown.VERSION = '3.4.1' 13439 13440 function getParent($this) { 13441 var selector = $this.attr('data-target') 13442 13443 if (!selector) { 13444 selector = $this.attr('href') 13445 selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 13446 } 13447 13448 var $parent = selector !== '#' ? $(document).find(selector) : null 13449 13450 return $parent && $parent.length ? $parent : $this.parent() 13451 } 13452 13453 function clearMenus(e) { 13454 if (e && e.which === 3) return 13455 $(backdrop).remove() 13456 $(toggle).each(function () { 13457 var $this = $(this) 13458 var $parent = getParent($this) 13459 var relatedTarget = { relatedTarget: this } 13460 13461 if (!$parent.hasClass('open')) return 13462 13463 if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return 13464 13465 $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget)) 13466 13467 if (e.isDefaultPrevented()) return 13468 13469 $this.attr('aria-expanded', 'false') 13470 $parent.removeClass('open').trigger($.Event('hidden.bs.dropdown', relatedTarget)) 13471 }) 13472 } 13473 13474 Dropdown.prototype.toggle = function (e) { 13475 var $this = $(this) 13476 13477 if ($this.is('.disabled, :disabled')) return 13478 13479 var $parent = getParent($this) 13480 var isActive = $parent.hasClass('open') 13481 13482 clearMenus() 13483 13484 if (!isActive) { 13485 if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { 13486 // if mobile we use a backdrop because click events don't delegate 13487 $(document.createElement('div')) 13488 .addClass('dropdown-backdrop') 13489 .insertAfter($(this)) 13490 .on('click', clearMenus) 13491 } 13492 13493 var relatedTarget = { relatedTarget: this } 13494 $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget)) 13495 13496 if (e.isDefaultPrevented()) return 13497 13498 $this 13499 .trigger('focus') 13500 .attr('aria-expanded', 'true') 13501 13502 $parent 13503 .toggleClass('open') 13504 .trigger($.Event('shown.bs.dropdown', relatedTarget)) 13505 } 13506 13507 return false 13508 } 13509 13510 Dropdown.prototype.keydown = function (e) { 13511 if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return 13512 13513 var $this = $(this) 13514 13515 e.preventDefault() 13516 e.stopPropagation() 13517 13518 if ($this.is('.disabled, :disabled')) return 13519 13520 var $parent = getParent($this) 13521 var isActive = $parent.hasClass('open') 13522 13523 if (!isActive && e.which != 27 || isActive && e.which == 27) { 13524 if (e.which == 27) $parent.find(toggle).trigger('focus') 13525 return $this.trigger('click') 13526 } 13527 13528 var desc = ' li:not(.disabled):visible a' 13529 var $items = $parent.find('.dropdown-menu' + desc) 13530 13531 if (!$items.length) return 13532 13533 var index = $items.index(e.target) 13534 13535 if (e.which == 38 && index > 0) index-- // up 13536 if (e.which == 40 && index < $items.length - 1) index++ // down 13537 if (!~index) index = 0 13538 13539 $items.eq(index).trigger('focus') 13540 } 13541 13542 13543 // DROPDOWN PLUGIN DEFINITION 13544 // ========================== 13545 13546 function Plugin(option) { 13547 return this.each(function () { 13548 var $this = $(this) 13549 var data = $this.data('bs.dropdown') 13550 13551 if (!data) $this.data('bs.dropdown', (data = new Dropdown(this))) 13552 if (typeof option == 'string') data[option].call($this) 13553 }) 13554 } 13555 13556 var old = $.fn.dropdown 13557 13558 $.fn.dropdown = Plugin 13559 $.fn.dropdown.Constructor = Dropdown 13560 13561 13562 // DROPDOWN NO CONFLICT 13563 // ==================== 13564 13565 $.fn.dropdown.noConflict = function () { 13566 $.fn.dropdown = old 13567 return this 13568 } 13569 13570 13571 // APPLY TO STANDARD DROPDOWN ELEMENTS 13572 // =================================== 13573 13574 $(document) 13575 .on('click.bs.dropdown.data-api', clearMenus) 13576 .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) 13577 .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle) 13578 .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown) 13579 .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown) 13580 13581}(jQuery); 13582 13583/* ======================================================================== 13584 * Bootstrap: modal.js v3.4.1 13585 * https://getbootstrap.com/docs/3.4/javascript/#modals 13586 * ======================================================================== 13587 * Copyright 2011-2019 Twitter, Inc. 13588 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 13589 * ======================================================================== */ 13590 13591 13592+function ($) { 13593 'use strict'; 13594 13595 // MODAL CLASS DEFINITION 13596 // ====================== 13597 13598 var Modal = function (element, options) { 13599 this.options = options 13600 this.$body = $(document.body) 13601 this.$element = $(element) 13602 this.$dialog = this.$element.find('.modal-dialog') 13603 this.$backdrop = null 13604 this.isShown = null 13605 this.originalBodyPad = null 13606 this.scrollbarWidth = 0 13607 this.ignoreBackdropClick = false 13608 this.fixedContent = '.navbar-fixed-top, .navbar-fixed-bottom' 13609 13610 if (this.options.remote) { 13611 this.$element 13612 .find('.modal-content') 13613 .load(this.options.remote, $.proxy(function () { 13614 this.$element.trigger('loaded.bs.modal') 13615 }, this)) 13616 } 13617 } 13618 13619 Modal.VERSION = '3.4.1' 13620 13621 Modal.TRANSITION_DURATION = 300 13622 Modal.BACKDROP_TRANSITION_DURATION = 150 13623 13624 Modal.DEFAULTS = { 13625 backdrop: true, 13626 keyboard: true, 13627 show: true 13628 } 13629 13630 Modal.prototype.toggle = function (_relatedTarget) { 13631 return this.isShown ? this.hide() : this.show(_relatedTarget) 13632 } 13633 13634 Modal.prototype.show = function (_relatedTarget) { 13635 var that = this 13636 var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget }) 13637 13638 this.$element.trigger(e) 13639 13640 if (this.isShown || e.isDefaultPrevented()) return 13641 13642 this.isShown = true 13643 13644 this.checkScrollbar() 13645 this.setScrollbar() 13646 this.$body.addClass('modal-open') 13647 13648 this.escape() 13649 this.resize() 13650 13651 this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this)) 13652 13653 this.$dialog.on('mousedown.dismiss.bs.modal', function () { 13654 that.$element.one('mouseup.dismiss.bs.modal', function (e) { 13655 if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true 13656 }) 13657 }) 13658 13659 this.backdrop(function () { 13660 var transition = $.support.transition && that.$element.hasClass('fade') 13661 13662 if (!that.$element.parent().length) { 13663 that.$element.appendTo(that.$body) // don't move modals dom position 13664 } 13665 13666 that.$element 13667 .show() 13668 .scrollTop(0) 13669 13670 that.adjustDialog() 13671 13672 if (transition) { 13673 that.$element[0].offsetWidth // force reflow 13674 } 13675 13676 that.$element.addClass('in') 13677 13678 that.enforceFocus() 13679 13680 var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget }) 13681 13682 transition ? 13683 that.$dialog // wait for modal to slide in 13684 .one('bsTransitionEnd', function () { 13685 that.$element.trigger('focus').trigger(e) 13686 }) 13687 .emulateTransitionEnd(Modal.TRANSITION_DURATION) : 13688 that.$element.trigger('focus').trigger(e) 13689 }) 13690 } 13691 13692 Modal.prototype.hide = function (e) { 13693 if (e) e.preventDefault() 13694 13695 e = $.Event('hide.bs.modal') 13696 13697 this.$element.trigger(e) 13698 13699 if (!this.isShown || e.isDefaultPrevented()) return 13700 13701 this.isShown = false 13702 13703 this.escape() 13704 this.resize() 13705 13706 $(document).off('focusin.bs.modal') 13707 13708 this.$element 13709 .removeClass('in') 13710 .off('click.dismiss.bs.modal') 13711 .off('mouseup.dismiss.bs.modal') 13712 13713 this.$dialog.off('mousedown.dismiss.bs.modal') 13714 13715 $.support.transition && this.$element.hasClass('fade') ? 13716 this.$element 13717 .one('bsTransitionEnd', $.proxy(this.hideModal, this)) 13718 .emulateTransitionEnd(Modal.TRANSITION_DURATION) : 13719 this.hideModal() 13720 } 13721 13722 Modal.prototype.enforceFocus = function () { 13723 $(document) 13724 .off('focusin.bs.modal') // guard against infinite focus loop 13725 .on('focusin.bs.modal', $.proxy(function (e) { 13726 if (document !== e.target && 13727 this.$element[0] !== e.target && 13728 !this.$element.has(e.target).length) { 13729 this.$element.trigger('focus') 13730 } 13731 }, this)) 13732 } 13733 13734 Modal.prototype.escape = function () { 13735 if (this.isShown && this.options.keyboard) { 13736 this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) { 13737 e.which == 27 && this.hide() 13738 }, this)) 13739 } else if (!this.isShown) { 13740 this.$element.off('keydown.dismiss.bs.modal') 13741 } 13742 } 13743 13744 Modal.prototype.resize = function () { 13745 if (this.isShown) { 13746 $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this)) 13747 } else { 13748 $(window).off('resize.bs.modal') 13749 } 13750 } 13751 13752 Modal.prototype.hideModal = function () { 13753 var that = this 13754 this.$element.hide() 13755 this.backdrop(function () { 13756 that.$body.removeClass('modal-open') 13757 that.resetAdjustments() 13758 that.resetScrollbar() 13759 that.$element.trigger('hidden.bs.modal') 13760 }) 13761 } 13762 13763 Modal.prototype.removeBackdrop = function () { 13764 this.$backdrop && this.$backdrop.remove() 13765 this.$backdrop = null 13766 } 13767 13768 Modal.prototype.backdrop = function (callback) { 13769 var that = this 13770 var animate = this.$element.hasClass('fade') ? 'fade' : '' 13771 13772 if (this.isShown && this.options.backdrop) { 13773 var doAnimate = $.support.transition && animate 13774 13775 this.$backdrop = $(document.createElement('div')) 13776 .addClass('modal-backdrop ' + animate) 13777 .appendTo(this.$body) 13778 13779 this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) { 13780 if (this.ignoreBackdropClick) { 13781 this.ignoreBackdropClick = false 13782 return 13783 } 13784 if (e.target !== e.currentTarget) return 13785 this.options.backdrop == 'static' 13786 ? this.$element[0].focus() 13787 : this.hide() 13788 }, this)) 13789 13790 if (doAnimate) this.$backdrop[0].offsetWidth // force reflow 13791 13792 this.$backdrop.addClass('in') 13793 13794 if (!callback) return 13795 13796 doAnimate ? 13797 this.$backdrop 13798 .one('bsTransitionEnd', callback) 13799 .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : 13800 callback() 13801 13802 } else if (!this.isShown && this.$backdrop) { 13803 this.$backdrop.removeClass('in') 13804 13805 var callbackRemove = function () { 13806 that.removeBackdrop() 13807 callback && callback() 13808 } 13809 $.support.transition && this.$element.hasClass('fade') ? 13810 this.$backdrop 13811 .one('bsTransitionEnd', callbackRemove) 13812 .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : 13813 callbackRemove() 13814 13815 } else if (callback) { 13816 callback() 13817 } 13818 } 13819 13820 // these following methods are used to handle overflowing modals 13821 13822 Modal.prototype.handleUpdate = function () { 13823 this.adjustDialog() 13824 } 13825 13826 Modal.prototype.adjustDialog = function () { 13827 var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight 13828 13829 this.$element.css({ 13830 paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '', 13831 paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : '' 13832 }) 13833 } 13834 13835 Modal.prototype.resetAdjustments = function () { 13836 this.$element.css({ 13837 paddingLeft: '', 13838 paddingRight: '' 13839 }) 13840 } 13841 13842 Modal.prototype.checkScrollbar = function () { 13843 var fullWindowWidth = window.innerWidth 13844 if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8 13845 var documentElementRect = document.documentElement.getBoundingClientRect() 13846 fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left) 13847 } 13848 this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth 13849 this.scrollbarWidth = this.measureScrollbar() 13850 } 13851 13852 Modal.prototype.setScrollbar = function () { 13853 var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10) 13854 this.originalBodyPad = document.body.style.paddingRight || '' 13855 var scrollbarWidth = this.scrollbarWidth 13856 if (this.bodyIsOverflowing) { 13857 this.$body.css('padding-right', bodyPad + scrollbarWidth) 13858 $(this.fixedContent).each(function (index, element) { 13859 var actualPadding = element.style.paddingRight 13860 var calculatedPadding = $(element).css('padding-right') 13861 $(element) 13862 .data('padding-right', actualPadding) 13863 .css('padding-right', parseFloat(calculatedPadding) + scrollbarWidth + 'px') 13864 }) 13865 } 13866 } 13867 13868 Modal.prototype.resetScrollbar = function () { 13869 this.$body.css('padding-right', this.originalBodyPad) 13870 $(this.fixedContent).each(function (index, element) { 13871 var padding = $(element).data('padding-right') 13872 $(element).removeData('padding-right') 13873 element.style.paddingRight = padding ? padding : '' 13874 }) 13875 } 13876 13877 Modal.prototype.measureScrollbar = function () { // thx walsh 13878 var scrollDiv = document.createElement('div') 13879 scrollDiv.className = 'modal-scrollbar-measure' 13880 this.$body.append(scrollDiv) 13881 var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth 13882 this.$body[0].removeChild(scrollDiv) 13883 return scrollbarWidth 13884 } 13885 13886 13887 // MODAL PLUGIN DEFINITION 13888 // ======================= 13889 13890 function Plugin(option, _relatedTarget) { 13891 return this.each(function () { 13892 var $this = $(this) 13893 var data = $this.data('bs.modal') 13894 var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option) 13895 13896 if (!data) $this.data('bs.modal', (data = new Modal(this, options))) 13897 if (typeof option == 'string') data[option](_relatedTarget) 13898 else if (options.show) data.show(_relatedTarget) 13899 }) 13900 } 13901 13902 var old = $.fn.modal 13903 13904 $.fn.modal = Plugin 13905 $.fn.modal.Constructor = Modal 13906 13907 13908 // MODAL NO CONFLICT 13909 // ================= 13910 13911 $.fn.modal.noConflict = function () { 13912 $.fn.modal = old 13913 return this 13914 } 13915 13916 13917 // MODAL DATA-API 13918 // ============== 13919 13920 $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) { 13921 var $this = $(this) 13922 var href = $this.attr('href') 13923 var target = $this.attr('data-target') || 13924 (href && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7 13925 13926 var $target = $(document).find(target) 13927 var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data()) 13928 13929 if ($this.is('a')) e.preventDefault() 13930 13931 $target.one('show.bs.modal', function (showEvent) { 13932 if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown 13933 $target.one('hidden.bs.modal', function () { 13934 $this.is(':visible') && $this.trigger('focus') 13935 }) 13936 }) 13937 Plugin.call($target, option, this) 13938 }) 13939 13940}(jQuery); 13941 13942/* ======================================================================== 13943 * Bootstrap: tooltip.js v3.4.1 13944 * https://getbootstrap.com/docs/3.4/javascript/#tooltip 13945 * Inspired by the original jQuery.tipsy by Jason Frame 13946 * ======================================================================== 13947 * Copyright 2011-2019 Twitter, Inc. 13948 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 13949 * ======================================================================== */ 13950 13951+function ($) { 13952 'use strict'; 13953 13954 var DISALLOWED_ATTRIBUTES = ['sanitize', 'whiteList', 'sanitizeFn'] 13955 13956 var uriAttrs = [ 13957 'background', 13958 'cite', 13959 'href', 13960 'itemtype', 13961 'longdesc', 13962 'poster', 13963 'src', 13964 'xlink:href' 13965 ] 13966 13967 var ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i 13968 13969 var DefaultWhitelist = { 13970 // Global attributes allowed on any supplied element below. 13971 '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN], 13972 a: ['target', 'href', 'title', 'rel'], 13973 area: [], 13974 b: [], 13975 br: [], 13976 col: [], 13977 code: [], 13978 div: [], 13979 em: [], 13980 hr: [], 13981 h1: [], 13982 h2: [], 13983 h3: [], 13984 h4: [], 13985 h5: [], 13986 h6: [], 13987 i: [], 13988 img: ['src', 'alt', 'title', 'width', 'height'], 13989 li: [], 13990 ol: [], 13991 p: [], 13992 pre: [], 13993 s: [], 13994 small: [], 13995 span: [], 13996 sub: [], 13997 sup: [], 13998 strong: [], 13999 u: [], 14000 ul: [] 14001 } 14002 14003 /** 14004 * A pattern that recognizes a commonly useful subset of URLs that are safe. 14005 * 14006 * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts 14007 */ 14008 var SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi 14009 14010 /** 14011 * A pattern that matches safe data URLs. Only matches image, video and audio types. 14012 * 14013 * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts 14014 */ 14015 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 14016 14017 function allowedAttribute(attr, allowedAttributeList) { 14018 var attrName = attr.nodeName.toLowerCase() 14019 14020 if ($.inArray(attrName, allowedAttributeList) !== -1) { 14021 if ($.inArray(attrName, uriAttrs) !== -1) { 14022 return Boolean(attr.nodeValue.match(SAFE_URL_PATTERN) || attr.nodeValue.match(DATA_URL_PATTERN)) 14023 } 14024 14025 return true 14026 } 14027 14028 var regExp = $(allowedAttributeList).filter(function (index, value) { 14029 return value instanceof RegExp 14030 }) 14031 14032 // Check if a regular expression validates the attribute. 14033 for (var i = 0, l = regExp.length; i < l; i++) { 14034 if (attrName.match(regExp[i])) { 14035 return true 14036 } 14037 } 14038 14039 return false 14040 } 14041 14042 function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) { 14043 if (unsafeHtml.length === 0) { 14044 return unsafeHtml 14045 } 14046 14047 if (sanitizeFn && typeof sanitizeFn === 'function') { 14048 return sanitizeFn(unsafeHtml) 14049 } 14050 14051 // IE 8 and below don't support createHTMLDocument 14052 if (!document.implementation || !document.implementation.createHTMLDocument) { 14053 return unsafeHtml 14054 } 14055 14056 var createdDocument = document.implementation.createHTMLDocument('sanitization') 14057 createdDocument.body.innerHTML = unsafeHtml 14058 14059 var whitelistKeys = $.map(whiteList, function (el, i) { return i }) 14060 var elements = $(createdDocument.body).find('*') 14061 14062 for (var i = 0, len = elements.length; i < len; i++) { 14063 var el = elements[i] 14064 var elName = el.nodeName.toLowerCase() 14065 14066 if ($.inArray(elName, whitelistKeys) === -1) { 14067 el.parentNode.removeChild(el) 14068 14069 continue 14070 } 14071 14072 var attributeList = $.map(el.attributes, function (el) { return el }) 14073 var whitelistedAttributes = [].concat(whiteList['*'] || [], whiteList[elName] || []) 14074 14075 for (var j = 0, len2 = attributeList.length; j < len2; j++) { 14076 if (!allowedAttribute(attributeList[j], whitelistedAttributes)) { 14077 el.removeAttribute(attributeList[j].nodeName) 14078 } 14079 } 14080 } 14081 14082 return createdDocument.body.innerHTML 14083 } 14084 14085 // TOOLTIP PUBLIC CLASS DEFINITION 14086 // =============================== 14087 14088 var Tooltip = function (element, options) { 14089 this.type = null 14090 this.options = null 14091 this.enabled = null 14092 this.timeout = null 14093 this.hoverState = null 14094 this.$element = null 14095 this.inState = null 14096 14097 this.init('tooltip', element, options) 14098 } 14099 14100 Tooltip.VERSION = '3.4.1' 14101 14102 Tooltip.TRANSITION_DURATION = 150 14103 14104 Tooltip.DEFAULTS = { 14105 animation: true, 14106 placement: 'top', 14107 selector: false, 14108 template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>', 14109 trigger: 'hover focus', 14110 title: '', 14111 delay: 0, 14112 html: false, 14113 container: false, 14114 viewport: { 14115 selector: 'body', 14116 padding: 0 14117 }, 14118 sanitize : true, 14119 sanitizeFn : null, 14120 whiteList : DefaultWhitelist 14121 } 14122 14123 Tooltip.prototype.init = function (type, element, options) { 14124 this.enabled = true 14125 this.type = type 14126 this.$element = $(element) 14127 this.options = this.getOptions(options) 14128 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)) 14129 this.inState = { click: false, hover: false, focus: false } 14130 14131 if (this.$element[0] instanceof document.constructor && !this.options.selector) { 14132 throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!') 14133 } 14134 14135 var triggers = this.options.trigger.split(' ') 14136 14137 for (var i = triggers.length; i--;) { 14138 var trigger = triggers[i] 14139 14140 if (trigger == 'click') { 14141 this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) 14142 } else if (trigger != 'manual') { 14143 var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin' 14144 var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout' 14145 14146 this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) 14147 this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) 14148 } 14149 } 14150 14151 this.options.selector ? 14152 (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : 14153 this.fixTitle() 14154 } 14155 14156 Tooltip.prototype.getDefaults = function () { 14157 return Tooltip.DEFAULTS 14158 } 14159 14160 Tooltip.prototype.getOptions = function (options) { 14161 var dataAttributes = this.$element.data() 14162 14163 for (var dataAttr in dataAttributes) { 14164 if (dataAttributes.hasOwnProperty(dataAttr) && $.inArray(dataAttr, DISALLOWED_ATTRIBUTES) !== -1) { 14165 delete dataAttributes[dataAttr] 14166 } 14167 } 14168 14169 options = $.extend({}, this.getDefaults(), dataAttributes, options) 14170 14171 if (options.delay && typeof options.delay == 'number') { 14172 options.delay = { 14173 show: options.delay, 14174 hide: options.delay 14175 } 14176 } 14177 14178 if (options.sanitize) { 14179 options.template = sanitizeHtml(options.template, options.whiteList, options.sanitizeFn) 14180 } 14181 14182 return options 14183 } 14184 14185 Tooltip.prototype.getDelegateOptions = function () { 14186 var options = {} 14187 var defaults = this.getDefaults() 14188 14189 this._options && $.each(this._options, function (key, value) { 14190 if (defaults[key] != value) options[key] = value 14191 }) 14192 14193 return options 14194 } 14195 14196 Tooltip.prototype.enter = function (obj) { 14197 var self = obj instanceof this.constructor ? 14198 obj : $(obj.currentTarget).data('bs.' + this.type) 14199 14200 if (!self) { 14201 self = new this.constructor(obj.currentTarget, this.getDelegateOptions()) 14202 $(obj.currentTarget).data('bs.' + this.type, self) 14203 } 14204 14205 if (obj instanceof $.Event) { 14206 self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true 14207 } 14208 14209 if (self.tip().hasClass('in') || self.hoverState == 'in') { 14210 self.hoverState = 'in' 14211 return 14212 } 14213 14214 clearTimeout(self.timeout) 14215 14216 self.hoverState = 'in' 14217 14218 if (!self.options.delay || !self.options.delay.show) return self.show() 14219 14220 self.timeout = setTimeout(function () { 14221 if (self.hoverState == 'in') self.show() 14222 }, self.options.delay.show) 14223 } 14224 14225 Tooltip.prototype.isInStateTrue = function () { 14226 for (var key in this.inState) { 14227 if (this.inState[key]) return true 14228 } 14229 14230 return false 14231 } 14232 14233 Tooltip.prototype.leave = function (obj) { 14234 var self = obj instanceof this.constructor ? 14235 obj : $(obj.currentTarget).data('bs.' + this.type) 14236 14237 if (!self) { 14238 self = new this.constructor(obj.currentTarget, this.getDelegateOptions()) 14239 $(obj.currentTarget).data('bs.' + this.type, self) 14240 } 14241 14242 if (obj instanceof $.Event) { 14243 self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false 14244 } 14245 14246 if (self.isInStateTrue()) return 14247 14248 clearTimeout(self.timeout) 14249 14250 self.hoverState = 'out' 14251 14252 if (!self.options.delay || !self.options.delay.hide) return self.hide() 14253 14254 self.timeout = setTimeout(function () { 14255 if (self.hoverState == 'out') self.hide() 14256 }, self.options.delay.hide) 14257 } 14258 14259 Tooltip.prototype.show = function () { 14260 var e = $.Event('show.bs.' + this.type) 14261 14262 if (this.hasContent() && this.enabled) { 14263 this.$element.trigger(e) 14264 14265 var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0]) 14266 if (e.isDefaultPrevented() || !inDom) return 14267 var that = this 14268 14269 var $tip = this.tip() 14270 14271 var tipId = this.getUID(this.type) 14272 14273 this.setContent() 14274 $tip.attr('id', tipId) 14275 this.$element.attr('aria-describedby', tipId) 14276 14277 if (this.options.animation) $tip.addClass('fade') 14278 14279 var placement = typeof this.options.placement == 'function' ? 14280 this.options.placement.call(this, $tip[0], this.$element[0]) : 14281 this.options.placement 14282 14283 var autoToken = /\s?auto?\s?/i 14284 var autoPlace = autoToken.test(placement) 14285 if (autoPlace) placement = placement.replace(autoToken, '') || 'top' 14286 14287 $tip 14288 .detach() 14289 .css({ top: 0, left: 0, display: 'block' }) 14290 .addClass(placement) 14291 .data('bs.' + this.type, this) 14292 14293 this.options.container ? $tip.appendTo($(document).find(this.options.container)) : $tip.insertAfter(this.$element) 14294 this.$element.trigger('inserted.bs.' + this.type) 14295 14296 var pos = this.getPosition() 14297 var actualWidth = $tip[0].offsetWidth 14298 var actualHeight = $tip[0].offsetHeight 14299 14300 if (autoPlace) { 14301 var orgPlacement = placement 14302 var viewportDim = this.getPosition(this.$viewport) 14303 14304 placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' : 14305 placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' : 14306 placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' : 14307 placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' : 14308 placement 14309 14310 $tip 14311 .removeClass(orgPlacement) 14312 .addClass(placement) 14313 } 14314 14315 var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight) 14316 14317 this.applyPlacement(calculatedOffset, placement) 14318 14319 var complete = function () { 14320 var prevHoverState = that.hoverState 14321 that.$element.trigger('shown.bs.' + that.type) 14322 that.hoverState = null 14323 14324 if (prevHoverState == 'out') that.leave(that) 14325 } 14326 14327 $.support.transition && this.$tip.hasClass('fade') ? 14328 $tip 14329 .one('bsTransitionEnd', complete) 14330 .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : 14331 complete() 14332 } 14333 } 14334 14335 Tooltip.prototype.applyPlacement = function (offset, placement) { 14336 var $tip = this.tip() 14337 var width = $tip[0].offsetWidth 14338 var height = $tip[0].offsetHeight 14339 14340 // manually read margins because getBoundingClientRect includes difference 14341 var marginTop = parseInt($tip.css('margin-top'), 10) 14342 var marginLeft = parseInt($tip.css('margin-left'), 10) 14343 14344 // we must check for NaN for ie 8/9 14345 if (isNaN(marginTop)) marginTop = 0 14346 if (isNaN(marginLeft)) marginLeft = 0 14347 14348 offset.top += marginTop 14349 offset.left += marginLeft 14350 14351 // $.fn.offset doesn't round pixel values 14352 // so we use setOffset directly with our own function B-0 14353 $.offset.setOffset($tip[0], $.extend({ 14354 using: function (props) { 14355 $tip.css({ 14356 top: Math.round(props.top), 14357 left: Math.round(props.left) 14358 }) 14359 } 14360 }, offset), 0) 14361 14362 $tip.addClass('in') 14363 14364 // check to see if placing tip in new offset caused the tip to resize itself 14365 var actualWidth = $tip[0].offsetWidth 14366 var actualHeight = $tip[0].offsetHeight 14367 14368 if (placement == 'top' && actualHeight != height) { 14369 offset.top = offset.top + height - actualHeight 14370 } 14371 14372 var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight) 14373 14374 if (delta.left) offset.left += delta.left 14375 else offset.top += delta.top 14376 14377 var isVertical = /top|bottom/.test(placement) 14378 var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight 14379 var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight' 14380 14381 $tip.offset(offset) 14382 this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical) 14383 } 14384 14385 Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) { 14386 this.arrow() 14387 .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%') 14388 .css(isVertical ? 'top' : 'left', '') 14389 } 14390 14391 Tooltip.prototype.setContent = function () { 14392 var $tip = this.tip() 14393 var title = this.getTitle() 14394 14395 if (this.options.html) { 14396 if (this.options.sanitize) { 14397 title = sanitizeHtml(title, this.options.whiteList, this.options.sanitizeFn) 14398 } 14399 14400 $tip.find('.tooltip-inner').html(title) 14401 } else { 14402 $tip.find('.tooltip-inner').text(title) 14403 } 14404 14405 $tip.removeClass('fade in top bottom left right') 14406 } 14407 14408 Tooltip.prototype.hide = function (callback) { 14409 var that = this 14410 var $tip = $(this.$tip) 14411 var e = $.Event('hide.bs.' + this.type) 14412 14413 function complete() { 14414 if (that.hoverState != 'in') $tip.detach() 14415 if (that.$element) { // TODO: Check whether guarding this code with this `if` is really necessary. 14416 that.$element 14417 .removeAttr('aria-describedby') 14418 .trigger('hidden.bs.' + that.type) 14419 } 14420 callback && callback() 14421 } 14422 14423 this.$element.trigger(e) 14424 14425 if (e.isDefaultPrevented()) return 14426 14427 $tip.removeClass('in') 14428 14429 $.support.transition && $tip.hasClass('fade') ? 14430 $tip 14431 .one('bsTransitionEnd', complete) 14432 .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : 14433 complete() 14434 14435 this.hoverState = null 14436 14437 return this 14438 } 14439 14440 Tooltip.prototype.fixTitle = function () { 14441 var $e = this.$element 14442 if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') { 14443 $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') 14444 } 14445 } 14446 14447 Tooltip.prototype.hasContent = function () { 14448 return this.getTitle() 14449 } 14450 14451 Tooltip.prototype.getPosition = function ($element) { 14452 $element = $element || this.$element 14453 14454 var el = $element[0] 14455 var isBody = el.tagName == 'BODY' 14456 14457 var elRect = el.getBoundingClientRect() 14458 if (elRect.width == null) { 14459 // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093 14460 elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top }) 14461 } 14462 var isSvg = window.SVGElement && el instanceof window.SVGElement 14463 // Avoid using $.offset() on SVGs since it gives incorrect results in jQuery 3. 14464 // See https://github.com/twbs/bootstrap/issues/20280 14465 var elOffset = isBody ? { top: 0, left: 0 } : (isSvg ? null : $element.offset()) 14466 var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() } 14467 var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null 14468 14469 return $.extend({}, elRect, scroll, outerDims, elOffset) 14470 } 14471 14472 Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) { 14473 return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } : 14474 placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } : 14475 placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } : 14476 /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width } 14477 14478 } 14479 14480 Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) { 14481 var delta = { top: 0, left: 0 } 14482 if (!this.$viewport) return delta 14483 14484 var viewportPadding = this.options.viewport && this.options.viewport.padding || 0 14485 var viewportDimensions = this.getPosition(this.$viewport) 14486 14487 if (/right|left/.test(placement)) { 14488 var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll 14489 var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight 14490 if (topEdgeOffset < viewportDimensions.top) { // top overflow 14491 delta.top = viewportDimensions.top - topEdgeOffset 14492 } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow 14493 delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset 14494 } 14495 } else { 14496 var leftEdgeOffset = pos.left - viewportPadding 14497 var rightEdgeOffset = pos.left + viewportPadding + actualWidth 14498 if (leftEdgeOffset < viewportDimensions.left) { // left overflow 14499 delta.left = viewportDimensions.left - leftEdgeOffset 14500 } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow 14501 delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset 14502 } 14503 } 14504 14505 return delta 14506 } 14507 14508 Tooltip.prototype.getTitle = function () { 14509 var title 14510 var $e = this.$element 14511 var o = this.options 14512 14513 title = $e.attr('data-original-title') 14514 || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) 14515 14516 return title 14517 } 14518 14519 Tooltip.prototype.getUID = function (prefix) { 14520 do prefix += ~~(Math.random() * 1000000) 14521 while (document.getElementById(prefix)) 14522 return prefix 14523 } 14524 14525 Tooltip.prototype.tip = function () { 14526 if (!this.$tip) { 14527 this.$tip = $(this.options.template) 14528 if (this.$tip.length != 1) { 14529 throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!') 14530 } 14531 } 14532 return this.$tip 14533 } 14534 14535 Tooltip.prototype.arrow = function () { 14536 return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')) 14537 } 14538 14539 Tooltip.prototype.enable = function () { 14540 this.enabled = true 14541 } 14542 14543 Tooltip.prototype.disable = function () { 14544 this.enabled = false 14545 } 14546 14547 Tooltip.prototype.toggleEnabled = function () { 14548 this.enabled = !this.enabled 14549 } 14550 14551 Tooltip.prototype.toggle = function (e) { 14552 var self = this 14553 if (e) { 14554 self = $(e.currentTarget).data('bs.' + this.type) 14555 if (!self) { 14556 self = new this.constructor(e.currentTarget, this.getDelegateOptions()) 14557 $(e.currentTarget).data('bs.' + this.type, self) 14558 } 14559 } 14560 14561 if (e) { 14562 self.inState.click = !self.inState.click 14563 if (self.isInStateTrue()) self.enter(self) 14564 else self.leave(self) 14565 } else { 14566 self.tip().hasClass('in') ? self.leave(self) : self.enter(self) 14567 } 14568 } 14569 14570 Tooltip.prototype.destroy = function () { 14571 var that = this 14572 clearTimeout(this.timeout) 14573 this.hide(function () { 14574 that.$element.off('.' + that.type).removeData('bs.' + that.type) 14575 if (that.$tip) { 14576 that.$tip.detach() 14577 } 14578 that.$tip = null 14579 that.$arrow = null 14580 that.$viewport = null 14581 that.$element = null 14582 }) 14583 } 14584 14585 Tooltip.prototype.sanitizeHtml = function (unsafeHtml) { 14586 return sanitizeHtml(unsafeHtml, this.options.whiteList, this.options.sanitizeFn) 14587 } 14588 14589 // TOOLTIP PLUGIN DEFINITION 14590 // ========================= 14591 14592 function Plugin(option) { 14593 return this.each(function () { 14594 var $this = $(this) 14595 var data = $this.data('bs.tooltip') 14596 var options = typeof option == 'object' && option 14597 14598 if (!data && /destroy|hide/.test(option)) return 14599 if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) 14600 if (typeof option == 'string') data[option]() 14601 }) 14602 } 14603 14604 var old = $.fn.tooltip 14605 14606 $.fn.tooltip = Plugin 14607 $.fn.tooltip.Constructor = Tooltip 14608 14609 14610 // TOOLTIP NO CONFLICT 14611 // =================== 14612 14613 $.fn.tooltip.noConflict = function () { 14614 $.fn.tooltip = old 14615 return this 14616 } 14617 14618}(jQuery); 14619 14620/* ======================================================================== 14621 * Bootstrap: popover.js v3.4.1 14622 * https://getbootstrap.com/docs/3.4/javascript/#popovers 14623 * ======================================================================== 14624 * Copyright 2011-2019 Twitter, Inc. 14625 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 14626 * ======================================================================== */ 14627 14628 14629+function ($) { 14630 'use strict'; 14631 14632 // POPOVER PUBLIC CLASS DEFINITION 14633 // =============================== 14634 14635 var Popover = function (element, options) { 14636 this.init('popover', element, options) 14637 } 14638 14639 if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js') 14640 14641 Popover.VERSION = '3.4.1' 14642 14643 Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, { 14644 placement: 'right', 14645 trigger: 'click', 14646 content: '', 14647 template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>' 14648 }) 14649 14650 14651 // NOTE: POPOVER EXTENDS tooltip.js 14652 // ================================ 14653 14654 Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype) 14655 14656 Popover.prototype.constructor = Popover 14657 14658 Popover.prototype.getDefaults = function () { 14659 return Popover.DEFAULTS 14660 } 14661 14662 Popover.prototype.setContent = function () { 14663 var $tip = this.tip() 14664 var title = this.getTitle() 14665 var content = this.getContent() 14666 14667 if (this.options.html) { 14668 var typeContent = typeof content 14669 14670 if (this.options.sanitize) { 14671 title = this.sanitizeHtml(title) 14672 14673 if (typeContent === 'string') { 14674 content = this.sanitizeHtml(content) 14675 } 14676 } 14677 14678 $tip.find('.popover-title').html(title) 14679 $tip.find('.popover-content').children().detach().end()[ 14680 typeContent === 'string' ? 'html' : 'append' 14681 ](content) 14682 } else { 14683 $tip.find('.popover-title').text(title) 14684 $tip.find('.popover-content').children().detach().end().text(content) 14685 } 14686 14687 $tip.removeClass('fade top bottom left right in') 14688 14689 // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do 14690 // this manually by checking the contents. 14691 if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide() 14692 } 14693 14694 Popover.prototype.hasContent = function () { 14695 return this.getTitle() || this.getContent() 14696 } 14697 14698 Popover.prototype.getContent = function () { 14699 var $e = this.$element 14700 var o = this.options 14701 14702 return $e.attr('data-content') 14703 || (typeof o.content == 'function' ? 14704 o.content.call($e[0]) : 14705 o.content) 14706 } 14707 14708 Popover.prototype.arrow = function () { 14709 return (this.$arrow = this.$arrow || this.tip().find('.arrow')) 14710 } 14711 14712 14713 // POPOVER PLUGIN DEFINITION 14714 // ========================= 14715 14716 function Plugin(option) { 14717 return this.each(function () { 14718 var $this = $(this) 14719 var data = $this.data('bs.popover') 14720 var options = typeof option == 'object' && option 14721 14722 if (!data && /destroy|hide/.test(option)) return 14723 if (!data) $this.data('bs.popover', (data = new Popover(this, options))) 14724 if (typeof option == 'string') data[option]() 14725 }) 14726 } 14727 14728 var old = $.fn.popover 14729 14730 $.fn.popover = Plugin 14731 $.fn.popover.Constructor = Popover 14732 14733 14734 // POPOVER NO CONFLICT 14735 // =================== 14736 14737 $.fn.popover.noConflict = function () { 14738 $.fn.popover = old 14739 return this 14740 } 14741 14742}(jQuery); 14743 14744/* ======================================================================== 14745 * Bootstrap: scrollspy.js v3.4.1 14746 * https://getbootstrap.com/docs/3.4/javascript/#scrollspy 14747 * ======================================================================== 14748 * Copyright 2011-2019 Twitter, Inc. 14749 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 14750 * ======================================================================== */ 14751 14752 14753+function ($) { 14754 'use strict'; 14755 14756 // SCROLLSPY CLASS DEFINITION 14757 // ========================== 14758 14759 function ScrollSpy(element, options) { 14760 this.$body = $(document.body) 14761 this.$scrollElement = $(element).is(document.body) ? $(window) : $(element) 14762 this.options = $.extend({}, ScrollSpy.DEFAULTS, options) 14763 this.selector = (this.options.target || '') + ' .nav li > a' 14764 this.offsets = [] 14765 this.targets = [] 14766 this.activeTarget = null 14767 this.scrollHeight = 0 14768 14769 this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this)) 14770 this.refresh() 14771 this.process() 14772 } 14773 14774 ScrollSpy.VERSION = '3.4.1' 14775 14776 ScrollSpy.DEFAULTS = { 14777 offset: 10 14778 } 14779 14780 ScrollSpy.prototype.getScrollHeight = function () { 14781 return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight) 14782 } 14783 14784 ScrollSpy.prototype.refresh = function () { 14785 var that = this 14786 var offsetMethod = 'offset' 14787 var offsetBase = 0 14788 14789 this.offsets = [] 14790 this.targets = []
vendor: 10,384 bytes, lines 14791-15160
14791 this.scrollHeight = this.getScrollHeight() 14792 14793 if (!$.isWindow(this.$scrollElement[0])) { 14794 offsetMethod = 'position' 14795 offsetBase = this.$scrollElement.scrollTop() 14796 } 14797 14798 this.$body 14799 .find(this.selector) 14800 .map(function () { 14801 var $el = $(this) 14802 var href = $el.data('target') || $el.attr('href') 14803 var $href = /^#./.test(href) && $(href) 14804 14805 return ($href 14806 && $href.length 14807 && $href.is(':visible') 14808 && [[$href[offsetMethod]().top + offsetBase, href]]) || null 14809 }) 14810 .sort(function (a, b) { return a[0] - b[0] }) 14811 .each(function () { 14812 that.offsets.push(this[0]) 14813 that.targets.push(this[1]) 14814 }) 14815 } 14816 14817 ScrollSpy.prototype.process = function () { 14818 var scrollTop = this.$scrollElement.scrollTop() + this.options.offset 14819 var scrollHeight = this.getScrollHeight() 14820 var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height() 14821 var offsets = this.offsets 14822 var targets = this.targets 14823 var activeTarget = this.activeTarget 14824 var i 14825 14826 if (this.scrollHeight != scrollHeight) { 14827 this.refresh() 14828 } 14829 14830 if (scrollTop >= maxScroll) { 14831 return activeTarget != (i = targets[targets.length - 1]) && this.activate(i) 14832 } 14833 14834 if (activeTarget && scrollTop < offsets[0]) { 14835 this.activeTarget = null 14836 return this.clear() 14837 } 14838 14839 for (i = offsets.length; i--;) { 14840 activeTarget != targets[i] 14841 && scrollTop >= offsets[i] 14842 && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1]) 14843 && this.activate(targets[i]) 14844 } 14845 } 14846 14847 ScrollSpy.prototype.activate = function (target) { 14848 this.activeTarget = target 14849 14850 this.clear() 14851 14852 var selector = this.selector + 14853 '[data-target="' + target + '"],' + 14854 this.selector + '[href="' + target + '"]' 14855 14856 var active = $(selector) 14857 .parents('li') 14858 .addClass('active') 14859 14860 if (active.parent('.dropdown-menu').length) { 14861 active = active 14862 .closest('li.dropdown') 14863 .addClass('active') 14864 } 14865 14866 active.trigger('activate.bs.scrollspy') 14867 } 14868 14869 ScrollSpy.prototype.clear = function () { 14870 $(this.selector) 14871 .parentsUntil(this.options.target, '.active') 14872 .removeClass('active') 14873 } 14874 14875 14876 // SCROLLSPY PLUGIN DEFINITION 14877 // =========================== 14878 14879 function Plugin(option) { 14880 return this.each(function () { 14881 var $this = $(this) 14882 var data = $this.data('bs.scrollspy') 14883 var options = typeof option == 'object' && option 14884 14885 if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options))) 14886 if (typeof option == 'string') data[option]() 14887 }) 14888 } 14889 14890 var old = $.fn.scrollspy 14891 14892 $.fn.scrollspy = Plugin 14893 $.fn.scrollspy.Constructor = ScrollSpy 14894 14895 14896 // SCROLLSPY NO CONFLICT 14897 // ===================== 14898 14899 $.fn.scrollspy.noConflict = function () { 14900 $.fn.scrollspy = old 14901 return this 14902 } 14903 14904 14905 // SCROLLSPY DATA-API 14906 // ================== 14907 14908 $(window).on('load.bs.scrollspy.data-api', function () { 14909 $('[data-spy="scroll"]').each(function () { 14910 var $spy = $(this) 14911 Plugin.call($spy, $spy.data()) 14912 }) 14913 }) 14914 14915}(jQuery); 14916 14917/* ======================================================================== 14918 * Bootstrap: tab.js v3.4.1 14919 * https://getbootstrap.com/docs/3.4/javascript/#tabs 14920 * ======================================================================== 14921 * Copyright 2011-2019 Twitter, Inc. 14922 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 14923 * ======================================================================== */ 14924 14925 14926+function ($) { 14927 'use strict'; 14928 14929 // TAB CLASS DEFINITION 14930 // ==================== 14931 14932 var Tab = function (element) { 14933 // jscs:disable requireDollarBeforejQueryAssignment 14934 this.element = $(element) 14935 // jscs:enable requireDollarBeforejQueryAssignment 14936 } 14937 14938 Tab.VERSION = '3.4.1' 14939 14940 Tab.TRANSITION_DURATION = 150 14941 14942 Tab.prototype.show = function () { 14943 var $this = this.element 14944 var $ul = $this.closest('ul:not(.dropdown-menu)') 14945 var selector = $this.data('target') 14946 14947 if (!selector) { 14948 selector = $this.attr('href') 14949 selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 14950 } 14951 14952 if ($this.parent('li').hasClass('active')) return 14953 14954 var $previous = $ul.find('.active:last a') 14955 var hideEvent = $.Event('hide.bs.tab', { 14956 relatedTarget: $this[0] 14957 }) 14958 var showEvent = $.Event('show.bs.tab', { 14959 relatedTarget: $previous[0] 14960 }) 14961 14962 $previous.trigger(hideEvent) 14963 $this.trigger(showEvent) 14964 14965 if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return 14966 14967 var $target = $(document).find(selector) 14968 14969 this.activate($this.closest('li'), $ul) 14970 this.activate($target, $target.parent(), function () { 14971 $previous.trigger({ 14972 type: 'hidden.bs.tab', 14973 relatedTarget: $this[0] 14974 }) 14975 $this.trigger({ 14976 type: 'shown.bs.tab', 14977 relatedTarget: $previous[0] 14978 }) 14979 }) 14980 } 14981 14982 Tab.prototype.activate = function (element, container, callback) { 14983 var $active = container.find('> .active') 14984 var transition = callback 14985 && $.support.transition 14986 && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length) 14987 14988 function next() { 14989 $active 14990 .removeClass('active') 14991 .find('> .dropdown-menu > .active') 14992 .removeClass('active') 14993 .end() 14994 .find('[data-toggle="tab"]') 14995 .attr('aria-expanded', false) 14996 14997 element 14998 .addClass('active') 14999 .find('[data-toggle="tab"]') 15000 .attr('aria-expanded', true) 15001 15002 if (transition) { 15003 element[0].offsetWidth // reflow for transition 15004 element.addClass('in') 15005 } else { 15006 element.removeClass('fade') 15007 } 15008 15009 if (element.parent('.dropdown-menu').length) { 15010 element 15011 .closest('li.dropdown') 15012 .addClass('active') 15013 .end() 15014 .find('[data-toggle="tab"]') 15015 .attr('aria-expanded', true) 15016 } 15017 15018 callback && callback() 15019 } 15020 15021 $active.length && transition ? 15022 $active 15023 .one('bsTransitionEnd', next) 15024 .emulateTransitionEnd(Tab.TRANSITION_DURATION) : 15025 next() 15026 15027 $active.removeClass('in') 15028 } 15029 15030 15031 // TAB PLUGIN DEFINITION 15032 // ===================== 15033 15034 function Plugin(option) { 15035 return this.each(function () { 15036 var $this = $(this) 15037 var data = $this.data('bs.tab') 15038 15039 if (!data) $this.data('bs.tab', (data = new Tab(this))) 15040 if (typeof option == 'string') data[option]() 15041 }) 15042 } 15043 15044 var old = $.fn.tab 15045 15046 $.fn.tab = Plugin 15047 $.fn.tab.Constructor = Tab 15048 15049 15050 // TAB NO CONFLICT 15051 // =============== 15052 15053 $.fn.tab.noConflict = function () { 15054 $.fn.tab = old 15055 return this 15056 } 15057 15058 15059 // TAB DATA-API 15060 // ============ 15061 15062 var clickHandler = function (e) { 15063 e.preventDefault() 15064 Plugin.call($(this), 'show') 15065 } 15066 15067 $(document) 15068 .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler) 15069 .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler) 15070 15071}(jQuery); 15072 15073/* ======================================================================== 15074 * Bootstrap: affix.js v3.4.1 15075 * https://getbootstrap.com/docs/3.4/javascript/#affix 15076 * ======================================================================== 15077 * Copyright 2011-2019 Twitter, Inc. 15078 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 15079 * ======================================================================== */ 15080 15081 15082+function ($) { 15083 'use strict'; 15084 15085 // AFFIX CLASS DEFINITION 15086 // ====================== 15087 15088 var Affix = function (element, options) { 15089 this.options = $.extend({}, Affix.DEFAULTS, options) 15090 15091 var target = this.options.target === Affix.DEFAULTS.target ? $(this.options.target) : $(document).find(this.options.target) 15092 15093 this.$target = target 15094 .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this)) 15095 .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this)) 15096 15097 this.$element = $(element) 15098 this.affixed = null 15099 this.unpin = null 15100 this.pinnedOffset = null 15101 15102 this.checkPosition() 15103 } 15104 15105 Affix.VERSION = '3.4.1' 15106 15107 Affix.RESET = 'affix affix-top affix-bottom' 15108 15109 Affix.DEFAULTS = { 15110 offset: 0, 15111 target: window 15112 } 15113 15114 Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) { 15115 var scrollTop = this.$target.scrollTop() 15116 var position = this.$element.offset() 15117 var targetHeight = this.$target.height() 15118 15119 if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false 15120 15121 if (this.affixed == 'bottom') { 15122 if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom' 15123 return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom' 15124 } 15125 15126 var initializing = this.affixed == null 15127 var colliderTop = initializing ? scrollTop : position.top 15128 var colliderHeight = initializing ? targetHeight : height 15129 15130 if (offsetTop != null && scrollTop <= offsetTop) return 'top' 15131 if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom' 15132 15133 return false 15134 } 15135 15136 Affix.prototype.getPinnedOffset = function () { 15137 if (this.pinnedOffset) return this.pinnedOffset 15138 this.$element.removeClass(Affix.RESET).addClass('affix') 15139 var scrollTop = this.$target.scrollTop() 15140 var position = this.$element.offset() 15141 return (this.pinnedOffset = position.top - scrollTop) 15142 } 15143 15144 Affix.prototype.checkPositionWithEventLoop = function () { 15145 setTimeout($.proxy(this.checkPosition, this), 1) 15146 } 15147 15148 Affix.prototype.checkPosition = function () { 15149 if (!this.$element.is(':visible')) return 15150 15151 var height = this.$element.height() 15152 var offset = this.options.offset 15153 var offsetTop = offset.top 15154 var offsetBottom = offset.bottom 15155 var scrollHeight = Math.max($(document).height(), $(document.body).height()) 15156 15157 if (typeof offset != 'object') offsetBottom = offsetTop = offset 15158 if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element) 15159 if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element) 15160
15161 var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom) 15162 15163 if (this.affixed != affix) { 15164 if (this.unpin != null) this.$element.css('top', '') 15165 15166 var affixType = 'affix' + (affix ? '-' + affix : '') 15167 var e = $.Event(affixType + '.bs.affix') 15168 15169 this.$element.trigger(e) 15170 15171 if (e.isDefaultPrevented()) return 15172 15173 this.affixed = affix 15174 this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null 15175 15176 this.$element 15177 .removeClass(Affix.RESET) 15178 .addClass(affixType) 15179 .trigger(affixType.replace('affix', 'affixed') + '.bs.affix') 15180 } 15181 15182 if (affix == 'bottom') { 15183 this.$element.offset({ 15184 top: scrollHeight - height - offsetBottom 15185 }) 15186 } 15187 } 15188 15189 15190 // AFFIX PLUGIN DEFINITION 15191 // ======================= 15192 15193 function Plugin(option) { 15194 return this.each(function () { 15195 var $this = $(this) 15196 var data = $this.data('bs.affix') 15197 var options = typeof option == 'object' && option 15198 15199 if (!data) $this.data('bs.affix', (data = new Affix(this, options))) 15200 if (typeof option == 'string') data[option]() 15201 }) 15202 } 15203 15204 var old = $.fn.affix 15205 15206 $.fn.affix = Plugin 15207 $.fn.affix.Constructor = Affix 15208 15209 15210 // AFFIX NO CONFLICT 15211 // ================= 15212 15213 $.fn.affix.noConflict = function () { 15214 $.fn.affix = old 15215 return this 15216 } 15217 15218 15219 // AFFIX DATA-API 15220 // ============== 15221 15222 $(window).on('load', function () { 15223 $('[data-spy="affix"]').each(function () { 15224 var $spy = $(this) 15225 var data = $spy.data() 15226 15227 data.offset = data.offset || {} 15228 15229 if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom 15230 if (data.offsetTop != null) data.offset.top = data.offsetTop 15231 15232 Plugin.call($spy, data) 15233 }) 15234 }) 15235 15236}(jQuery); 15237 15238/* 15239 * jQuery Templating Plugin 15240 * Copyright 2010, John Resig 15241 * Dual licensed under the MIT or GPL Version 2 licenses. 15242 */ 15243(function( jQuery, undefined ){ 15244 var oldManip = jQuery.fn.domManip, tmplItmAtt = "_tmplitem", htmlExpr = /^[^<]*(<[\w\W]+>)[^>]*$|\{\{\! /, 15245 newTmplItems = {}, wrappedItems = {}, appendToTmplItems, topTmplItem = { key: 0, data: {} }, itemKey = 0, cloneIndex = 0, stack = []; 15246 15247 function newTmplItem( options, parentItem, fn, data ) { 15248 // Returns a template item data structure for a new rendered instance of a template (a 'template item'). 15249 // The content field is a hierarchical array of strings and nested items (to be 15250 // removed and replaced by nodes field of dom elements, once inserted in DOM). 15251 var newItem = { 15252 data: data || (parentItem ? parentItem.data : {}), 15253 _wrap: parentItem ? parentItem._wrap : null, 15254 tmpl: null, 15255 parent: parentItem || null, 15256 nodes: [], 15257 calls: tiCalls, 15258 nest: tiNest, 15259 wrap: tiWrap, 15260 html: tiHtml, 15261 update: tiUpdate 15262 }; 15263 if ( options ) { 15264 jQuery.extend( newItem, options, { nodes: [], parent: parentItem } ); 15265 } 15266 if ( fn ) { 15267 // Build the hierarchical content to be used during insertion into DOM 15268 newItem.tmpl = fn; 15269 newItem._ctnt = newItem._ctnt || newItem.tmpl( jQuery, newItem ); 15270 newItem.key = ++itemKey; 15271 // Keep track of new template item, until it is stored as jQuery Data on DOM element 15272 (stack.length ? wrappedItems : newTmplItems)[itemKey] = newItem; 15273 } 15274 return newItem; 15275 } 15276 15277 // Override appendTo etc., in order to provide support for targeting multiple elements. (This code would disappear if integrated in jquery core). 15278 jQuery.each({ 15279 appendTo: "append", 15280 prependTo: "prepend", 15281 insertBefore: "before", 15282 insertAfter: "after", 15283 replaceAll: "replaceWith" 15284 }, function( name, original ) { 15285 jQuery.fn[ name ] = function( selector ) { 15286 var ret = [], insert = jQuery( selector ), elems, i, l, tmplItems, 15287 parent = this.length === 1 && this[0].parentNode; 15288 15289 appendToTmplItems = newTmplItems || {}; 15290 if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) { 15291 insert[ original ]( this[0] ); 15292 ret = this; 15293 } else { 15294 for ( i = 0, l = insert.length; i < l; i++ ) { 15295 cloneIndex = i; 15296 elems = (i > 0 ? this.clone(true) : this).get(); 15297 jQuery.fn[ original ].apply( jQuery(insert[i]), elems ); 15298 ret = ret.concat( elems ); 15299 } 15300 cloneIndex = 0; 15301 ret = this.pushStack( ret, name, insert.selector ); 15302 } 15303 tmplItems = appendToTmplItems; 15304 appendToTmplItems = null; 15305 jQuery.tmpl.complete( tmplItems ); 15306 return ret; 15307 }; 15308 }); 15309 15310 jQuery.fn.extend({ 15311 // Use first wrapped element as template markup. 15312 // Return wrapped set of template items, obtained by rendering template against data. 15313 tmpl: function( data, options, parentItem ) { 15314 return jQuery.tmpl( this[0], data, options, parentItem ); 15315 }, 15316 15317 // Find which rendered template item the first wrapped DOM element belongs to 15318 tmplItem: function() { 15319 return jQuery.tmplItem( this[0] ); 15320 }, 15321 15322 // Consider the first wrapped element as a template declaration, and get the compiled template or store it as a named template. 15323 template: function( name ) { 15324 return jQuery.template( name, this[0] ); 15325 }, 15326 15327 domManip: function( args, table, callback, options ) { 15328 // This appears to be a bug in the appendTo, etc. implementation 15329 // it should be doing .call() instead of .apply(). See #6227 15330 if ( args[0] && args[0].nodeType ) { 15331 var dmArgs = jQuery.makeArray( arguments ), argsLength = args.length, i = 0, tmplItem; 15332 while ( i < argsLength && !(tmplItem = jQuery.data( args[i++], "tmplItem" ))) {} 15333 if ( argsLength > 1 ) { 15334 dmArgs[0] = [jQuery.makeArray( args )]; 15335 } 15336 if ( tmplItem && cloneIndex ) { 15337 dmArgs[2] = function( fragClone ) { 15338 // Handler called by oldManip when rendered template has been inserted into DOM. 15339 jQuery.tmpl.afterManip( this, fragClone, callback ); 15340 }; 15341 } 15342 oldManip.apply( this, dmArgs ); 15343 } else { 15344 oldManip.apply( this, arguments ); 15345 } 15346 cloneIndex = 0; 15347 if ( !appendToTmplItems ) { 15348 jQuery.tmpl.complete( newTmplItems ); 15349 } 15350 return this; 15351 } 15352 }); 15353 15354 jQuery.extend({ 15355 // Return wrapped set of template items, obtained by rendering template against data. 15356 tmpl: function( tmpl, data, options, parentItem ) { 15357 var ret, topLevel = !parentItem; 15358 if ( topLevel ) { 15359 // This is a top-level tmpl call (not from a nested template using {{tmpl}}) 15360 parentItem = topTmplItem; 15361 tmpl = jQuery.template[tmpl] || jQuery.template( null, tmpl ); 15362 wrappedItems = {}; // Any wrapped items will be rebuilt, since this is top level 15363 } else if ( !tmpl ) { 15364 // The template item is already associated with DOM - this is a refresh. 15365 // Re-evaluate rendered template for the parentItem 15366 tmpl = parentItem.tmpl; 15367 newTmplItems[parentItem.key] = parentItem; 15368 parentItem.nodes = []; 15369 if ( parentItem.wrapped ) { 15370 updateWrapped( parentItem, parentItem.wrapped ); 15371 } 15372 // Rebuild, without creating a new template item 15373 return jQuery( build( parentItem, null, parentItem.tmpl( jQuery, parentItem ) )); 15374 } 15375 if ( !tmpl ) { 15376 return []; // Could throw... 15377 } 15378 if ( typeof data === "function" ) { 15379 data = data.call( parentItem || {} ); 15380 } 15381 if ( options && options.wrapped ) { 15382 updateWrapped( options, options.wrapped ); 15383 } 15384 ret = jQuery.isArray( data ) ? 15385 jQuery.map( data, function( dataItem ) { 15386 return dataItem ? newTmplItem( options, parentItem, tmpl, dataItem ) : null; 15387 }) : 15388 [ newTmplItem( options, parentItem, tmpl, data ) ]; 15389 return topLevel ? jQuery( build( parentItem, null, ret ) ) : ret; 15390 }, 15391 15392 // Return rendered template item for an element. 15393 tmplItem: function( elem ) { 15394 var tmplItem; 15395 if ( elem instanceof jQuery ) { 15396 elem = elem[0]; 15397 } 15398 while ( elem && elem.nodeType === 1 && !(tmplItem = jQuery.data( elem, "tmplItem" )) && (elem = elem.parentNode) ) {} 15399 return tmplItem || topTmplItem; 15400 }, 15401 15402 // Set: 15403 // Use $.template( name, tmpl ) to cache a named template, 15404 // where tmpl is a template string, a script element or a jQuery instance wrapping a script element, etc. 15405 // Use $( "selector" ).template( name ) to provide access by name to a script block template declaration. 15406 15407 // Get: 15408 // Use $.template( name ) to access a cached template. 15409 // Also $( selectorToScriptBlock ).template(), or $.template( null, templateString ) 15410 // will return the compiled template, without adding a name reference. 15411 // If templateString includes at least one HTML tag, $.template( templateString )
vendor: 15,878 bytes, lines 15411-15741
15411is equivalent 15412 // to $.template( null, templateString ) 15413 template: function( name, tmpl ) { 15414 if (tmpl) { 15415 // Compile template and associate with name 15416 if ( typeof tmpl === "string" ) { 15417 // This is an HTML string being passed directly in. 15418 tmpl = buildTmplFn( tmpl ) 15419 } else if ( tmpl instanceof jQuery ) { 15420 tmpl = tmpl[0] || {}; 15421 } 15422 if ( tmpl.nodeType ) { 15423 // If this is a template block, use cached copy, or generate tmpl function and cache. 15424 tmpl = jQuery.data( tmpl, "tmpl" ) || jQuery.data( tmpl, "tmpl", buildTmplFn( tmpl.innerHTML )); 15425 } 15426 return typeof name === "string" ? (jQuery.template[name] = tmpl) : tmpl; 15427 } 15428 // Return named compiled template 15429 return name ? (typeof name !== "string" ? jQuery.template( null, name ): 15430 (jQuery.template[name] || 15431 // If not in map, treat as a selector. (If integrated with core, use quickExpr.exec) 15432 jQuery.template( null, htmlExpr.test( name ) ? name : jQuery( name )))) : null; 15433 }, 15434 15435 encode: function( text ) { 15436 // Do HTML encoding replacing < > & and ' and " by corresponding entities. 15437 return ("" + text).split("<").join("<").split(">").join(">").split('"').join(""").split("'").join("'"); 15438 } 15439 }); 15440 15441 jQuery.extend( jQuery.tmpl, { 15442 tag: { 15443 "tmpl": { 15444 _default: { $2: "null" }, 15445 open: "if($notnull_1){_=_.concat($item.nest($1,$2));}" 15446 // tmpl target parameter can be of type function, so use $1, not $1a (so not auto detection of functions) 15447 // This means that {{tmpl foo}} treats foo as a template (which IS a function). 15448 // Explicit parens can be used if foo is a function that returns a template: {{tmpl foo()}}. 15449 }, 15450 "wrap": { 15451 _default: { $2: "null" }, 15452 open: "$item.calls(_,$1,$2);_=[];", 15453 close: "call=$item.calls();_=call._.concat($item.wrap(call,_));" 15454 }, 15455 "each": { 15456 _default: { $2: "$index, $value" }, 15457 open: "if($notnull_1){$.each($1a,function($2){with(this){", 15458 close: "}});}" 15459 }, 15460 "if": { 15461 open: "if(($notnull_1) && $1a){", 15462 close: "}" 15463 }, 15464 "else": { 15465 _default: { $1: "true" }, 15466 open: "}else if(($notnull_1) && $1a){" 15467 }, 15468 "html": { 15469 // Unecoded expression evaluation. 15470 open: "if($notnull_1){_.push($1a);}" 15471 }, 15472 "=": { 15473 // Encoded expression evaluation. Abbreviated form is ${}. 15474 _default: { $1: "$data" }, 15475 open: "if($notnull_1){_.push($.encode($1a));}" 15476 }, 15477 "!": { 15478 // Comment tag. Skipped by parser 15479 open: "" 15480 } 15481 }, 15482 15483 // This stub can be overridden, e.g. in jquery.tmplPlus for providing rendered events 15484 complete: function( items ) { 15485 newTmplItems = {}; 15486 }, 15487 15488 // Call this from code which overrides domManip, or equivalent 15489 // Manage cloning/storing template items etc. 15490 afterManip: function afterManip( elem, fragClone, callback ) { 15491 // Provides cloned fragment ready for fixup prior to and after insertion into DOM 15492 var content = fragClone.nodeType === 11 ? 15493 jQuery.makeArray(fragClone.childNodes) : 15494 fragClone.nodeType === 1 ? [fragClone] : []; 15495 15496 // Return fragment to original caller (e.g. append) for DOM insertion 15497 callback.call( elem, fragClone ); 15498 15499 // Fragment has been inserted:- Add inserted nodes to tmplItem data structure. Replace inserted element annotations by jQuery.data. 15500 storeTmplItems( content ); 15501 cloneIndex++; 15502 } 15503 }); 15504 15505 //========================== Private helper functions, used by code above ========================== 15506 15507 function build( tmplItem, nested, content ) { 15508 // Convert hierarchical content into flat string array 15509 // and finally return array of fragments ready for DOM insertion 15510 var frag, ret = content ? jQuery.map( content, function( item ) { 15511 return (typeof item === "string") ? 15512 // Insert template item annotations, to be converted to jQuery.data( "tmplItem" ) when elems are inserted into DOM. 15513 (tmplItem.key ? item.replace( /(<\w+)(?=[\s>])(?![^>]*_tmplitem)([^>]*)/g, "$1 " + tmplItmAtt + "=\"" + tmplItem.key + "\" $2" ) : item) : 15514 // This is a child template item. Build nested template. 15515 build( item, tmplItem, item._ctnt ); 15516 }) : 15517 // 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()}}. 15518 tmplItem; 15519 if ( nested ) { 15520 return ret; 15521 } 15522 15523 // top-level template 15524 ret = ret.join(""); 15525 15526 // Support templates which have initial or final text nodes, or consist only of text 15527 // Also support HTML entities within the HTML markup. 15528 ret.replace( /^\s*([^<\s][^<]*)?(<[\w\W]+>)([^>]*[^>\s])?\s*$/, function( all, before, middle, after) { 15529 frag = jQuery( middle ).get(); 15530 15531 storeTmplItems( frag ); 15532 if ( before ) { 15533 frag = unencode( before ).concat(frag); 15534 } 15535 if ( after ) { 15536 frag = frag.concat(unencode( after )); 15537 } 15538 }); 15539 return frag ? frag : unencode( ret ); 15540 } 15541 15542 function unencode( text ) { 15543 // Use createElement, since createTextNode will not render HTML entities correctly 15544 var el = document.createElement( "div" ); 15545 el.innerHTML = text; 15546 return jQuery.makeArray(el.childNodes); 15547 } 15548 15549 // Generate a reusable function that will serve to render a template against data 15550 function buildTmplFn( markup ) { 15551 return new Function("jQuery","$item", 15552 "var $=jQuery,call,_=[],$data=$item.data;" + 15553 15554 // Introduce the data as local variables using with(){} 15555 "with($data){_.push('" + 15556 15557 // Convert the template into pure JavaScript 15558 jQuery.trim(markup) 15559 .replace( /([\\'])/g, "\\$1" ) 15560 .replace( /[\r\t\n]/g, " " ) 15561 .replace( /\$\{([^\}]*)\}/g, "{{= $1}}" ) 15562 .replace( /\{\{(\/?)(\w+|.)(?:\(((?:[^\}]|\}(?!\}))*?)?\))?(?:\s+(.*?)?)?(\(((?:[^\}]|\}(?!\}))*?)\))?\s*\}\}/g, 15563 function( all, slash, type, fnargs, target, parens, args ) { 15564 var tag = jQuery.tmpl.tag[ type ], def, expr, exprAutoFnDetect; 15565 if ( !tag ) { 15566 throw "Template command not found: " + type; 15567 } 15568 def = tag._default || []; 15569 if ( parens && !/\w$/.test(target)) { 15570 target += parens; 15571 parens = ""; 15572 } 15573 if ( target ) { 15574 target = unescape( target ); 15575 args = args ? ("," + unescape( args ) + ")") : (parens ? ")" : ""); 15576 // Support for target being things like a.toLowerCase(); 15577 // In that case don't call with template item as 'this' pointer. Just evaluate... 15578 expr = parens ? (target.indexOf(".") > -1 ? target + parens : ("(" + target + ").call($item" + args)) : target; 15579 exprAutoFnDetect = parens ? expr : "(typeof(" + target + ")==='function'?(" + target + ").call($item):(" + target + "))"; 15580 } else { 15581 exprAutoFnDetect = expr = def.$1 || "null"; 15582 } 15583 fnargs = unescape( fnargs ); 15584 return "');" + 15585 tag[ slash ? "close" : "open" ] 15586 .split( "$notnull_1" ).join( target ? "typeof(" + target + ")!=='undefined' && (" + target + ")!=null" : "true" ) 15587 .split( "$1a" ).join( exprAutoFnDetect ) 15588 .split( "$1" ).join( expr ) 15589 .split( "$2" ).join( fnargs ? 15590 fnargs.replace( /\s*([^\(]+)\s*(\((.*?)\))?/g, function( all, name, parens, params ) { 15591 params = params ? ("," + params + ")") : (parens ? ")" : ""); 15592 return params ? ("(" + name + ").call($item" + params) : all; 15593 }) 15594 : (def.$2||"") 15595 ) + 15596 "_.push('"; 15597 }) + 15598 "');}return _;" 15599 ); 15600 } 15601 function updateWrapped( options, wrapped ) { 15602 // Build the wrapped content. 15603 options._wrap = build( options, true, 15604 // Suport imperative scenario in which options.wrapped can be set to a selector or an HTML string. 15605 jQuery.isArray( wrapped ) ? wrapped : [htmlExpr.test( wrapped ) ? wrapped : jQuery( wrapped ).html()] 15606 ).join(""); 15607 } 15608 15609 function unescape( args ) { 15610 return args ? args.replace( /\\'/g, "'").replace(/\\\\/g, "\\" ) : null; 15611 } 15612 function outerHtml( elem ) { 15613 var div = document.createElement("div"); 15614 div.appendChild( elem.cloneNode(true) ); 15615 return div.innerHTML; 15616 } 15617 15618 // Store template items in jQuery.data(), ensuring a unique tmplItem data data structure for each rendered template instance. 15619 function storeTmplItems( content ) { 15620 var keySuffix = "_" + cloneIndex, elem, elems, newClonedItems = {}, i, l, m; 15621 for ( i = 0, l = content.length; i < l; i++ ) { 15622 if ( (elem = content[i]).nodeType !== 1 ) { 15623 continue; 15624 } 15625 elems = elem.getElementsByTagName("*"); 15626 for ( m = elems.length - 1; m >= 0; m-- ) { 15627 processItemKey( elems[m] ); 15628 } 15629 processItemKey( elem ); 15630 } 15631 function processItemKey( el ) { 15632 var pntKey, pntNode = el, pntItem, tmplItem, key; 15633 // Ensure that each rendered template inserted into the DOM has its own template item, 15634 if ( (key = el.getAttribute( tmplItmAtt ))) { 15635 while ( pntNode.parentNode && (pntNode = pntNode.parentNode).nodeType === 1 && !(pntKey = pntNode.getAttribute( tmplItmAtt ))) { } 15636 if ( pntKey !== key ) { 15637 // The next ancestor with a _tmplitem expando is on a different key than this one. 15638 // So this is a top-level element within this template item 15639 // Set pntNode to the key of the parentNode, or to 0 if pntNode.parentNode is null, or pntNode is a fragment. 15640 pntNode = pntNode.parentNode ? (pntNode.nodeType === 11 ? 0 : (pntNode.getAttribute( tmplItmAtt ) || 0)) : 0; 15641 if ( !(tmplItem = newTmplItems[key]) ) { 15642 // The item is for wrapped content, and was copied from the temporary parent wrappedItem. 15643 tmplItem = wrappedItems[key]; 15644 tmplItem = newTmplItem( tmplItem, newTmplItems[pntNode]||wrappedItems[pntNode], null, true ); 15645 tmplItem.key = ++itemKey; 15646 newTmplItems[itemKey] = tmplItem; 15647 } 15648 if ( cloneIndex ) { 15649 cloneTmplItem( key ); 15650 } 15651 } 15652 el.removeAttribute( tmplItmAtt ); 15653 } else if ( cloneIndex && (tmplItem = jQuery.data( el, "tmplItem" )) ) { 15654 // This was a rendered element, cloned during append or appendTo etc. 15655 // TmplItem stored in jQuery data has already been cloned in cloneCopyEvent. We must replace it with a fresh cloned tmplItem. 15656 cloneTmplItem( tmplItem.key ); 15657 newTmplItems[tmplItem.key] = tmplItem; 15658 pntNode = jQuery.data( el.parentNode, "tmplItem" ); 15659 pntNode = pntNode ? pntNode.key : 0; 15660 } 15661 if ( tmplItem ) { 15662 pntItem = tmplItem; 15663 // Find the template item of the parent element. 15664 // (Using !=, not !==, since pntItem.key is number, and pntNode may be a string) 15665 while ( pntItem && pntItem.key != pntNode ) { 15666 // Add this element as a top-level node for this rendered template item, as well as for any 15667 // ancestor items between this item and the item of its parent element 15668 pntItem.nodes.push( el ); 15669 pntItem = pntItem.parent; 15670 } 15671 // Delete content built during rendering - reduce API surface area and memory use, and avoid exposing of stale data after rendering... 15672 delete tmplItem._ctnt; 15673 delete tmplItem._wrap; 15674 // Store template item as jQuery data on the element 15675 jQuery.data( el, "tmplItem", tmplItem ); 15676 } 15677 function cloneTmplItem( key ) { 15678 key = key + keySuffix; 15679 tmplItem = newClonedItems[key] = 15680 (newClonedItems[key] || newTmplItem( tmplItem, newTmplItems[tmplItem.parent.key + keySuffix] || tmplItem.parent, null, true )); 15681 } 15682 } 15683 } 15684 15685 //---- Helper functions for template item ---- 15686 15687 function tiCalls( content, tmpl, data, options ) { 15688 if ( !content ) { 15689 return stack.pop(); 15690 } 15691 stack.push({ _: content, tmpl: tmpl, item:this, data: data, options: options }); 15692 } 15693 15694 function tiNest( tmpl, data, options ) { 15695 // nested template, using {{tmpl}} tag 15696 return jQuery.tmpl( jQuery.template( tmpl ), data, options, this ); 15697 } 15698 15699 function tiWrap( call, wrapped ) { 15700 // nested template, using {{wrap}} tag 15701 var options = call.options || {}; 15702 options.wrapped = wrapped; 15703 // Apply the template, which may incorporate wrapped content, 15704 return jQuery.tmpl( jQuery.template( call.tmpl ), call.data, options, call.item ); 15705 } 15706 15707 function tiHtml( filter, textOnly ) { 15708 var wrapped = this._wrap; 15709 return jQuery.map( 15710 jQuery( jQuery.isArray( wrapped ) ? wrapped.join("") : wrapped ).filter( filter || "*" ), 15711 function(e) { 15712 return textOnly ? 15713 e.innerText || e.textContent : 15714 e.outerHTML || outerHtml(e); 15715 }); 15716 } 15717 15718 function tiUpdate() { 15719 var coll = this.nodes; 15720 jQuery.tmpl( null, null, null, this).insertBefore( coll[0] ); 15721 jQuery( coll ).remove(); 15722 } 15723})( jQuery ); 15724/*! 15725 * jQuery Mobile 1.4.1 15726 * Git HEAD hash: 18c1e32bfc4e0e92756dedc105d799131607f5bb <> Date: Wed Feb 12 2014 22:15:20 UTC 15727 * http://jquerymobile.com 15728 * 15729 * Copyright 2010, 2014 jQuery Foundation, Inc. and other contributors 15730 * Released under the MIT license. 15731 * http://jquery.org/license 15732 * 15733 */ 15734/*! 15735 * code snippet for just swipe-right and swipe-left 15736 */ 15737(function( $, window, undefined ) { 15738 var $document = $(document), 15739 TouchUtil = xfalib.ut.TouchUtil, 15740 touchStartEvent = TouchUtil.POINTER_DOWN, 15741 touchStopEvent = TouchUtil.POINTER_UP,
15742 touchMoveEvent = TouchUtil.POINTER_MOVE; 15743 15744 function triggerCustomEvent( obj, eventType, event, bubble ) { 15745 var originalType = event.type; 15746 event.type = eventType; 15747 if ( bubble ) { 15748 $.event.trigger( event, undefined, obj ); 15749 } else { 15750 $.event.dispatch.call( obj, event ); 15751 } 15752 event.type = originalType; 15753 } 15754 15755 $.event.special.swipe = { 15756 15757 // More than this horizontal displacement, and we will suppress scrolling. 15758 scrollSupressionThreshold: 30, 15759 15760 // More time than this, and it isn't a swipe. 15761 durationThreshold: 1000, 15762 15763 // Swipe horizontal displacement must be more than this. 15764 horizontalDistanceThreshold: 30, 15765 15766 // Swipe vertical displacement must be less than this. 15767 verticalDistanceThreshold: 30, 15768 15769 getLocation: function ( event ) { 15770 var winPageX = window.pageXOffset, 15771 winPageY = window.pageYOffset, 15772 x = event.clientX || event.originalEvent.clientX, 15773 y = event.clientY || event.originalEvent.clientY; 15774 15775 if ( event.pageY === 0 && Math.floor( y ) > Math.floor( event.pageY ) || 15776 event.pageX === 0 && Math.floor( x ) > Math.floor( event.pageX ) ) { 15777 15778 // iOS4 clientX/clientY have the value that should have been 15779 // in pageX/pageY. While pageX/page/ have the value 0 15780 x = x - winPageX; 15781 y = y - winPageY; 15782 } else if ( y < ( event.pageY - winPageY) || x < ( event.pageX - winPageX ) ) { 15783 15784 // Some Android browsers have totally bogus values for clientX/Y 15785 // when scrolling/zooming a page. Detectable since clientX/clientY 15786 // should never be smaller than pageX/pageY minus page scroll 15787 x = event.pageX - winPageX; 15788 y = event.pageY - winPageY; 15789 } 15790 15791 return { 15792 x: x, 15793 y: y 15794 }; 15795 }, 15796 15797 start: function( event ) { 15798 var data = event.originalEvent.touches ? 15799 event.originalEvent.touches[ 0 ] : event, 15800 location = $.event.special.swipe.getLocation( data ); 15801 return { 15802 time: ( new Date() ).getTime(), 15803 coords: [ location.x, location.y ], 15804 origin: $( event.target ) 15805 }; 15806 }, 15807 15808 stop: function( event ) { 15809 var data = event.originalEvent.touches ? 15810 event.originalEvent.touches[ 0 ] : event, 15811 location = $.event.special.swipe.getLocation( data ); 15812 return { 15813 time: ( new Date() ).getTime(), 15814 coords: [ location.x, location.y ] 15815 }; 15816 }, 15817 15818 handleSwipe: function( start, stop, thisObject, origTarget ) { 15819 if ( stop.time - start.time < $.event.special.swipe.durationThreshold && 15820 Math.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.horizontalDistanceThreshold && 15821 Math.abs( start.coords[ 1 ] - stop.coords[ 1 ] ) < $.event.special.swipe.verticalDistanceThreshold ) { 15822 var direction = start.coords[0] > stop.coords[ 0 ] ? "swipeleft" : "swiperight"; 15823 15824 triggerCustomEvent( thisObject, direction,$.Event( direction, { target: origTarget, swipestart: start, swipestop: stop } ), true ); 15825 return true; 15826 } 15827 return false; 15828 15829 }, 15830 15831 // This serves as a flag to ensure that at most one swipe event event is 15832 // in work at any given time 15833 eventInProgress: false, 15834 15835 setup: function() { 15836 var events, 15837 thisObject = this, 15838 $this = $( thisObject ), 15839 context = {}; 15840 15841 // Retrieve the events data for this element and add the swipe context 15842 events = $.data( this, "mobile-events" ); 15843 if ( !events ) { 15844 events = { length: 0 }; 15845 $.data( this, "mobile-events", events ); 15846 } 15847 events.length++; 15848 events.swipe = context; 15849 15850 context.start = function( event ) { 15851 // If its not a touch event on IE, ignore 15852 if (event.originalEvent.pointerType !== undefined && !(event.originalEvent.pointerType === 2 || event.originalEvent.pointerType === "touch")) { 15853 return; 15854 } 15855 15856 // Bail if we're already working on a swipe event 15857 if ( $.event.special.swipe.eventInProgress ) { 15858 return; 15859 } 15860 $.event.special.swipe.eventInProgress = true; 15861 15862 var stop, 15863 start = $.event.special.swipe.start( event ), 15864 origTarget = event.target, 15865 emitted = false;
15866 15867 context.move = function( event ) { 15868 if ( !start ) { 15869 return; 15870 } 15871 15872 stop = $.event.special.swipe.stop( event ); 15873 if ( !emitted ) { 15874 emitted = $.event.special.swipe.handleSwipe( start, stop, thisObject, origTarget ); 15875 if ( emitted ) { 15876 15877 // Reset the context to make way for the next swipe event 15878 $.event.special.swipe.eventInProgress = false; 15879 } 15880 } 15881 // prevent scrolling 15882 if ( Math.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.scrollSupressionThreshold ) { 15883 event.preventDefault(); 15884 } 15885 }; 15886 15887 context.stop = function() { 15888 emitted = true; 15889 15890 // Reset the context to make way for the next swipe event 15891 $.event.special.swipe.eventInProgress = false; 15892 $document.off( touchMoveEvent, context.move ); 15893 context.move = null; 15894 }; 15895 15896 $document.on( touchMoveEvent, context.move ) 15897 .one( touchStopEvent, context.stop ); 15898 }; 15899 $this.on( touchStartEvent, context.start ); 15900 }, 15901 15902 teardown: function() { 15903 var events, context; 15904 15905 events = $.data( this, "mobile-events" ); 15906 if ( events ) { 15907 context = events.swipe; 15908 delete events.swipe; 15909 events.length--; 15910 if ( events.length === 0 ) { 15911 $.removeData( this, "mobile-events" ); 15912 } 15913 } 15914 15915 if ( context ) { 15916 if ( context.start ) { 15917 $( this ).off( touchStartEvent, context.start ); 15918 } 15919 if ( context.move ) { 15920 $document.off( touchMoveEvent, context.move ); 15921 } 15922 if ( context.stop ) { 15923 $document.off( touchStopEvent, context.stop ); 15924 } 15925 } 15926 } 15927 }; 15928 $.each({ 15929 swipeleft: "swipe", 15930 swiperight: "swipe" 15931 }, function( event, sourceEvent ) { 15932 // Ignoring mouse events, for all browsers except IE 10>, which has pointer events. 15933 if (TouchUtil.POINTER_DOWN !== "mousedown") { 15934 $.event.special[ event ] = { 15935 setup: function() { 15936 $( this ).on( sourceEvent, $.noop ); 15937 }, 15938 teardown: function() { 15939 $( this ).off( sourceEvent ); 15940 } 15941 }; 15942 } 15943 }); 15944 15945})( jQuery, this ); 15946 15947/************************************************************************* 15948 * 15949 * ADOBE CONFIDENTIAL 15950 * __________________ 15951 * 15952 * Copyright 2017 Adobe Systems Incorporated 15953 * All Rights Reserved. 15954 *
15955 * NOTICE: All information contained herein is, and remains 15956 * the property of Adobe Systems Incorporated and its suppliers, 15957 * if any. The intellectual and technical concepts contained 15958 * herein are proprietary to Adobe Systems Incorporated and its 15959 * suppliers and may be covered by U.S. and Foreign Patents, 15960 * patents in process, and are protected by trade secret or copyright law. 15961 * Dissemination of this information or reproduction of this material 15962 * is strictly forbidden unless prior written permission is obtained 15963 * from Adobe Systems Incorporated. 15964 **************************************************************************/ 15965 15966(function (window, $) { 15967 15968 var DefaultPanelProvider = { 15969 15970 /** 15971 * Makes an ajax call and returns an object containing the template json of the template ids 15972 * Note: Constructs dispatcher/CDN friendly suffix-based URL internally (parameters embedded in path) 15973 * URL format: /path.jsonhtmlemitter/templateId-id1/templateId-id2/templateId-id3/fetchMultipleJson-true.json 15974 * @returns {Object} 15975 * @param options {Object}
15975 This object contains the base path, list of templateIds, and success handler 15976 */ 15977 getMultipleTemplateJson : function (options) { 15978 var basePath = options.path, 15979 listOfTemplateIds = options.listOfTemplateIds; 15980 if (listOfTemplateIds.length > 0) { 15981 // Construct URL with multiple templateId parameters in suffix format 15982 // Example: /templateId-id1/templateId-id2/templateId-id3/fetchMultipleJson-true.json 15983 var urlSuffix = ""; 15984 for (var i = 0; i < listOfTemplateIds.length; i++) { 15985 urlSuffix += "/templateId-" + listOfTemplateIds[i]; 15986 } 15987 urlSuffix += "/fetchMultipleJson-true.json"; 15988 15989 $.ajax({ 15990 url : basePath + urlSuffix, 15991 type : "GET", 15992 async : false, 15993 success : function (response) { 15994 options.success.call(this, JSON.parse(response.multipleJson)); 15995 }, 15996 error : function (error) { 15997 window.guideBridge._guide().logger().log(error); 15998 } 15999 }); 16000 } 16001 }, 16002 16003 /** 16004 * Makes an ajax call and gets json and html of the lazy loaded panel 16005 * @param options {Object}
16005 This object contains the templateId, fetchJson parameter and fetchHtml parameter. 16006 * These can be set to true or false depending on whether the respective content 16007 * needs to be fetched or not. Options object also contains the success, error, and complete handler as well. 16008 * @returns {JSONObject} The JSON object has two entries, json and html. 16009 */ 16010 getHtmlJson : function (options) { 16011 var ajaxOptions = { 16012 url : options.path, 16013 type : "GET", 16014 async : options.async !== undefined ? options.async : false, 16015 success : options.success, 16016 error : options.error, 16017 complete : options.complete 16018 }; 16019 16020 // Only add data parameters if they are present in options 16021 if (options.templateId || options.fetchJSON || options.fetchHTML) { 16022 ajaxOptions.data = {}; 16023 if (options.templateId) { 16024 ajaxOptions.data.templateId = options.templateId; 16025 } 16026 if (options.fetchJSON) { 16027 ajaxOptions.data.fetchJSON = options.fetchJSON; 16028 } 16029 if (options.fetchHTML) { 16030 ajaxOptions.data.fetchHTML = options.fetchHTML; 16031 } 16032 } 16033 16034 $.ajax(ajaxOptions); 16035 } 16036 }; 16037 16038 window.addEventListener("bridgeInitializeStart", function (evnt) { 16039 var bridge = evnt.detail.guideBridge; 16040 if (bridge) { 16041 bridge.registerPanelProvider(DefaultPanelProvider); 16042 } 16043 }); 16044 16045}(window, $)); 16046 16047// jscs:disable requireDotNotation 16048/************************************************************************* 16049 * 16050 * ADOBE CONFIDENTIAL 16051 * __________________ 16052 * 16053 * Copyright 2014 Adobe Systems Incorporated 16054 * All Rights Reserved. 16055 *
16056 * NOTICE: All information contained herein is, and remains 16057 * the property of Adobe Systems Incorporated and its suppliers, 16058 * if any. The intellectual and technical concepts contained 16059 * herein are proprietary to Adobe Systems Incorporated and its 16060 * suppliers and may be covered by U.S. and Foreign Patents, 16061 * patents in process, and are protected by trade secret or copyright law. 16062 * Dissemination of this information or reproduction of this material 16063 * is strictly forbidden unless prior written permission is obtained 16064 * from Adobe Systems Incorporated. 16065 **************************************************************************/ 16066 16067(function ($, _) { 16068 Function.prototype.bind = Function.prototype.bind || function (ctx) { 16069 var that = this; 16070 return function () { 16071 that.call(ctx, arguments); 16072 }; 16073 }; 16074 16075 var nValidationContext = 0, 16076 /** 16077 * flag to check if adaptive forms is online or not 16078 * @type {boolean} 16079 */ 16080 checkAFOffline = false, 16081 _focusedSubmitButtonModel = null, 16082 sValidationContext = ""; 16083 16084 /** 16085 * Class representing the result of {@link GuideBridge} API. This class provides API to access the result of the 16086 * GuideBridge API and retrieve any error messages the API has thrown. 16087 * @class GuideResultObject 16088 * @docStatus review 2016-05-03 16089 * @since 6.0 16090 */ 16091 var GuideResultObject = function () { 16092 var _message = []; 16093 var _errorCode = []; 16094 var _somExpression = []; 16095 /** 16096 * The value of this property is true if the API succeeded, otherwise false. The 16097 * {@link GuideResultObject#getNextMessage|getNextMessage} API can be used to retrieve the error messages in 16098 * case the value of this property is false. 16099 * @summary whether the API succeeded or failed. 16100 * 16101 * @type {boolean} 16102 * @member errors 16103 * @memberof GuideResultObject 16104 * @instance 16105 * @readonly 16106 * @since 6.0 16107 */ 16108 this.errors = false; 16109 /** 16110 * The type of the data is specific to the API and documentation of that API provides more details about the 16111 * data 16112 * @summary data returned by GuideBridge API 16113 * 16114 * @member {*} data 16115 * @memberof GuideResultObject 16116 * @instance 16117 * @readonly 16118 * @since 6.0 16119 */ 16120 this.data; 16121 16122 /** 16123 * API to add a message in the GuideResultObject 16124 * @private 16125 * @memberof GuideResultObject 16126 * @instance 16127 * @since 6.0 16128 */ 16129 this.addMessage = function (code, msg, som) { 16130 this.errors = true; 16131 _message.push(msg); 16132 _somExpression.push(som); 16133 _errorCode.push(code); 16134 }; 16135 16136 /** 16137 * Error Message returned by GuideBridge API 16138 * @typedef {object} GuideResultObject~ErrorMessage 16139 * @property {number} code Error Code 16140 * @property {?string} somExpression Som Expression of the GuideNode the error is related to. It can be null if 16141 * error is not related to a GuideNode. For example, server failure when submitting the form. 16142 * @property {string} message User friendly message for the error. 16143 * @see GuideNode#somExpression 16144 */ 16145 /** 16146 * When a GuideBridge API fails, it throws an error message. This is indicated by the 16147 * {@link GuideResultObject#errors|errors} property. To get the errors, one has to call this API. The API can throw 16148 * multiple errors and the user has to call this API until it returns null indicating no more errors. 16149 * @summary Returns the error message thrown by the GuideBridge API. 16150 * @function getNextMessage 16151 * @memberof GuideResultObject 16152 * @instance 16153 * @return {GuideResultObject~ErrorMessage} object containing the error message 16154 * @since 6.0 16155 */ 16156 this.getNextMessage = function () { 16157 if (_errorCode.length == 0) { 16158 return null; 16159 } 16160 return { 16161 code : _errorCode.pop(), 16162 somExpression : _somExpression.pop(), 16163 message : _message.pop() 16164 }; 16165 }; 16166 }; 16167 16168 var GUIDE_BRIDGE_VERSION = "1.0"; 16169 /* 16170 * Callback to accept result of asynchronous GuideBridge APIs. 16171 * @callback GuideBridge~AsyncAPIResultCallback 16172 * @param {GuideResultObject}
16172 guideResultObject object containing the result of the API 16173 */ 16174 /* 16175 * Signature of the input to be passed to GuideBridge asynchronous APIs 16176 * @typedef {object} GuideBridge~AsyncAPIInput 16177 * @property {GuideBridge~AsyncAPIResultCallback} [success] callback which receives the result of the API in case of 16178 * success. The argument this callback will recieve will have its {@link GuideResultObject#errors|errors} property 16179 * as false. 16180 * @property {GuideBridge~AsyncAPIResultCallback} [error] callback which receives the result of the API in case of 16181 * failure. The argument this callback will recieve will have its {@link GuideResultObject#errors|errors} property 16182 * as true. 16183 * @param {object} [context] _this_ object inside the _success_ and _error_ callback will point to this 16184 * object 16185 */ 16186 /** 16187 * GuideBridge provides an interface using which, wrapper html (page hosting/embedding adaptive forms) or external 16188 * window scripts like Parent window javascript (in case form is embedded in an iframe), can communicate with 16189 * current Adaptive Form and manipulate or query it's current state. 16190 * 16191 * Some of the use cases for using this API 16192 * * Submit Adaptive Form from a custom button present outside the Form. 16193 * * Get current Adaptive Form state and save it in local storage for restoring it later on. 16194 * * Plugging in custom widgets. 16195 * * Manipulate the Adaptive Form component properties, like value, visibility from outside the Form 16196 * * Listen to bridge events and send data to Analytics server for reporting 16197 * 16198 * ### Accessing the Instance of GuideBridge 16199 * To access the GuideBridge APIs, one needs to get hold of an instance of GuideBridge. The object is 16200 * available on the window after the GuideBridge script is loaded. One can directly access it by using 16201 * `window.guideBridge`. But 16202 * that requires the user script is written after the GuideBridge script is loaded. In certain cases, a user might 16203 * not be 16204 * aware of when their script gets loaded, in those cases the recommended approach is to listen to the 16205 * {@link GuideBridge.event:bridgeInitializeStart|bridgeInitializeStart} event which provides an instance of 16206 * GuideBridge object. 16207 *``` 16208 * window.addEventListener("bridgeInitializeStart", function(evnt) { 16209 * // get hold of the guideBridge object 16210 * var gb = evnt.detail.guideBridge; 16211 * }) 16212 * ``` 16213 * 16214 * **Or**, if you are sure that your script will execute after GuideBridge Script is loaded, then you can directly 16215 * use `window.guideBridge`. In cases like your script is present at the bottom of the page or you are executing on 16216 * jquery dom ready event. 16217 * ``` 16218 * $(function () { 16219 * // one can directly access guideBridge object here. 16220 * window.guideBridge.connect(function () { 16221 * //call guideBridge APIs 16222 * }) 16223 * }) 16224 * ``` 16225 * 16226 * <a name="wait-form-ready"></a> 16227 * ### Wait for Form to get ready 16228 * After getting the GuideBridge object one needs to wait for the Form to get initialized. This can be done by 16229 * providing a callback to the {@link GuideBridge#connect|connect} API 16230 * ``` 16231 * guideBridge.connect(function (){ 16232 * //this callback will be called after adaptive form is initialized 16233 * // do your custom processing 16234 * }) 16235 * ``` 16236 * 16237 * _**Note:** There is no link between Dom ready events and the connect API. If one wants to access the HTML DOM 16238 * from inside the connect callback, the recommended approach is to listen on the jQuery 16239 * [ready](https://api.jquery.com/ready/) event or the native 16240 * [DOMContentLoaded](https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded) event. Similarly if one 16241 * wants to access GuideBridge APIs one needs to wait for the connect callback to get fired._ 16242 * 16243 * <a name="guidebridge-api-usage"></a> 16244 * ### Using the GuideBridge API 16245 * APIs are provided for external applications to connect with Adaptive Form and FormDom. The APIs can be
16246 * loosely divided into two categories, **synchronous** and **asynchronous**. 16247 * 16248 * The synchronous getter API returns a {@link GuideResultObject} which represents the result of the API whereas 16249 * each setter API throws an exception in case of error(s) and it is the responsibility of the API to catch those 16250 * exceptions. The {@link GuideResultObject} either contains error or the return value of the API and provides easy 16251 * mechanism to access each of them. 16252 * 16253 * ``` 16254 * var result = guideBridge.hideGlobalToolbar() 16255 * if (result.errors) { 16256 * console.error("Unable to hide toolbar"); 16257 * var msg = guideResultObject.getNextMessage(); 16258 * while (msg != null) { 16259 * console.error(msg.message); 16260 * msg = guideResultObject.getNextMessage(); 16261 * } 16262 * } else { 16263 * console.log("toolbar hidden successfully"); 16264 * } 16265 * ``` 16266 * 16267 * Each asynchronous API provides callback mechanism to return the result of the API. Each API takes a Javascript 16268 * Object having success and error handlers. The success and error handlers receive {@link GuideResultObject} as input. 16269 * In the success callback, the arguments {@link GuideResultObject#data|data} property is set to the return value 16270 * of the API, while in the error callback the {@link GuideResultObject#errors|errors} property is set to _true_. 16271 * Some APIs might need extra input and that will be defined by the API 16272 * ``` 16273 * guideBridge.getData({ 16274 * success : function (guideResultObject) { 16275 * console.log("data received" + guideResultObject.data); 16276 * } 16277 * error : function (guideResultObject) { 16278 * console.error("API Failed"); 16279 * var msg = guideResultObject.getNextMessage(); 16280 * while (msg != null) { 16281 * console.error(msg.message); 16282 * msg = guideResultObject.getNextMessage(); 16283 * } 16284 * } 16285 * }); 16286 * ``` 16287 * _**Note:** Some APIs do not follow the above norm and it is mentioned in the documentation of that API_ 16288 * 16289 * <a name="guidebridge-events"></a> 16290 * ### GuideBridge Events 16291 * 16292 * GuideBridge API triggers a set of events to notify the current action a user has taken. Developers can listen on 16293 * that event using the {@link GuideBridge#on|on} API and perform some tasks. For example a developer can listen on 16294 * {@link GuideBridge.event:elementFocusChanged|elementFocusChanged} and capture for how long a user spends time 16295 * on that field. All the events triggered by GuideBridge are mentioned below. 16296 * 16297 * GuideBridge provides an event object which contains extra information about the event. For 16298 * example _elementFocusChanged_ event provides information about the previous field that was in focus and the 16299 * current field that came to focus. 16300 * 16301 * The {@link GuideBridge#on|on} API takes a {@link GuideBridge~GuideBridgeEventCallback|GuideBridgeEventCallback} 16302 * as input. The callback is passed two arguments, event and payload where the extra information is passed in the 16303 * payload argument. The documentation of each event lists the values of different properties of the payload 16304 * object. 16305 * 16306 * ``` 16307 * guideBridge.on(eventName, function (event, payload) { 16308 * // access payload properties 16309 * ... 16310 * }) 16311 * ``` 16312 * 16313 * @class GuideBridge 16314 * @docStatus review 2016-05-03 16315 * @since 6.0 16316 */ 16317 var GuideBridge = function () { 16318 this._$target = null; 16319 this._guide = null; 16320 this._guideView = null; 16321 this._version = GUIDE_BRIDGE_VERSION; 16322 this._guideInitHandler = {}; 16323 // _guideModelInitHandler is for internal use only 16324 this._guideModelInitHandler = {}; 16325 $(window).on("guideModelInitialized", this._guideModelInitialized.bind(this)); 16326 $(window).on("guideInitialized", this._guideInitialized.bind(this)); 16327 $(window).on("guideInitializationError", this._guideError); 16328 this.userConfig = {}; 16329 this.panelProvider = null; 16330 // set the host name whether it is client or server, by default it is client 16331 this.hostName = "client"; 16332 }; 16333 16334 var _formInstanceUUID;
16335 var GUIDE_TEMP_STORAGE_PATH = "/tmp/fd/af", 16336 FM_DAM_ROOT = "/content/dam/formsanddocuments/", 16337 FM_AF_ROOT = "/content/forms/af/", 16338 _isAutoSaveEnabled = false, 16339 LOCAL_METADATA_SELECTOR = "local"; 16340 16341 var defaultErrorHandler = function (obj) { 16342 if (typeof(console) == "undefined") { 16343 return; 16344 } 16345 var d = obj.getNextMessage(); 16346 while (d) { 16347 this._guide.logger().log(d.message); 16348 d = obj.getNextMessage(); 16349 } 16350 }; 16351 16352 /** 16353 * 16354 * Default function to check Validations errors after getting the data from the 16355 * server with getDataXML call. 16356 * @private 16357 */ 16358 var defaultValidationChecker = function (validations, obj) { 16359 if (validations && validations.length > 0) { 16360 for (var i = 0; i < validations.length; i++) { 16361 obj.addMessage(0, validations[i], ""); 16362 } 16363 return false; 16364 } 16365 return true; 16366 }; 16367 16368 function getOrElse() { 16369 return xfalib.ut.XfaUtil.prototype.getOrElse.apply(null, arguments); 16370 } 16371 16372 $.extend(GuideBridge.prototype, { 16373 16374 /** 16375 * Dispatched when the instance of GuideBridge is available. The GuideBridge object 16376 * will be passed to the listener and further communication can be done using that object. 16377 * 16378 * _**Note :** bridgeInitializeStart event is dispatched at window_ 16379 * 16380 * @summary Notifies when the instance of GuideBridge is available. 16381 * 16382 * @event bridgeInitializeStart 16383 * @property {Object} detail an object containing guideBridge 16384 * @property {GuideBridge} detail.guideBridge GuideBridge Instance 16385 * @memberof GuideBridge 16386 * @since 6.0 16387 * @example 16388 * window.addEventListener("bridgeInitializeStart", function(evnt) { 16389 * // get hold of the guideBridge object 16390 * var gb = evnt.detail.guideBridge; 16391 * //wait for the completion of adaptive forms 16392 * gb.connect(function (){ 16393 * //this function will be called after adaptive form is initialized 16394 * }) 16395 * }) 16396 */ 16397 GUIDE_BRIDGE_INITIALIZE_START : "bridgeInitializeStart", 16398 16399 /** 16400 * @summary Dispatched when the initialization of Adaptive Form is complete. 16401 * 16402 * @name bridgeInitializeComplete 16403 * @event 16404 * @property {object} payload payload passed to the event listener 16405 * @property {object} payload.target instance of GuideBridge object 16406 * @memberof GuideBridge 16407 * @deprecated since 6.3 this event is deprecated. Please use {@link GuideBridge#connect|connect} API 16408 * @since 6.0 16409 * @example 16410 * guideBridge.on("bridgeInitializeComplete" , function(event, payload) { 16411 * var gb = payload.target; 16412 * assert(gb === guideBridge) 16413 * } 16414 */ 16415 GUIDE_BRIDGE_INITIALIZE_COMPLETE : "bridgeInitializeComplete", 16416 16417 /** 16418 * @summary Dispatched when visibility of any Adaptive Form component(Panel or Field) changes. 16419 * @name elementVisibleChanged 16420 * @event 16421 * @property {object} payload payload containing more information about the event 16422 * @property {Scriptable} payload.target Adaptive Form component whose {@link Scriptable#visible|visible} property has 16423 * changed. 16424 * @property {boolean} payload.oldText old value of the visible property 16425 * @property {boolean} payload.newText new value of the visible property 16426 * @memberof GuideBridge 16427 * @since 6.0 16428 * @example 16429 * guideBridge.on("elementVisibleChanged" , function(event, payload) { 16430 * var component = payload.target; // scripting model of the component whose visibility has changed 16431 * var newValue = payload.newText; 16432 * if (newValue) { 16433 * console.log(component.name + " is visible now"; 16434 * } else { 16435 * console.log(component.name + " is hidden now"; 16436 * } 16437 * } 16438 * 16439 */ 16440 GUIDE_ELEMENT_VISIBLE_CHANGED : "elementVisibleChanged", 16441 16442 /** 16443 * @summary Dispatched when any Adaptive Form component is enabled/disabled, i.e. 16444 * {@link Scriptable#enabled|enabled} property of a component changes. 16445 * @name elementEnableChanged 16446 * @event 16447 * @property {object} payload payload containing more information about the event 16448 * @property {Scriptable} payload.target component whose {@link Scriptable#enabled|enabled} property has changed 16449 * @property {boolean} payload.oldText old value of the enabled property 16450 * @property {boolean} payload.newText new value of the enabled property 16451 * @memberof GuideBridge 16452 * @since 6.0 16453 * @example 16454 * guideBridge.on("elementEnableChanged" , function(event, payload) { 16455 * var component = payload.target; // scripting model of the component whose enabled property has changed 16456 * var newValue = payload.newText; 16457 * if (newValue) { 16458 * console.log(component.name + " is enabled now"; 16459 * } else { 16460 * console.log(component.name + " is disabled now"; 16461 * } 16462 * } 16463 */ 16464 GUIDE_ELEMENT_ENABLE_CHANGED : "elementEnableChanged", 16465 16466 /** 16467 * @summary Dispatched when value of any Field changes. 16468 * @name elementValueChanged 16469 * @event 16470 * @property {object} payload payload containing more information about the event 16471 * @property {Field} payload.target Field whose {@link Field#value|value} has changed 16472 * @property {string|number} payload.oldText old value of the Field 16473 * @property {string|number} payload.newText new value of the Field 16474 * @memberof GuideBridge 16475 * @since 6.0 16476 * @example 16477 * guideBridge.on("elementValueChanged" , function(event, payload) { 16478 * var component = payload.target; // Field whose value has changed 16479 * console.log("Value of component " + component.name + " was " + payload.oldText); 16480 * console.log("Value of component " + component.name + " is " + payload.newText); 16481 * } 16482 */ 16483 GUIDE_ELEMENT_VALUE_CHANGED : "elementValueChanged", 16484 16485 /** 16486 * In layouts like Wizard or Tabbed layout, when a user navigates from one tab to another, this event is 16487 * triggered 16488 * @summary Event to notify that the user has navigated from one Panel to another. 16489 * 16490 * @name elementNavigationChanged 16491 * @event 16492 * @property {object} payload payload containing more information about the event 16493 * @property {Panel} payload.target Panel to which the user moved to 16494 * @property {string} payload.prevText SomExpression of the panel from which user moved 16495 * @property {string} payload.newText SomExpression of the panel to which user moved 16496 * @memberof GuideBridge 16497 * @see GuideNode#somExpression 16498 * @since 6.0 16499 * @example 16500 * guideBridge.on("elementNavigationChanged" , function(event, payload) { 16501 * var component = payload.target;
16502 * console.log("old panel's SOM Expression: " + payload.oldText); 16503 * console.log("new panel's SOM Expression: " + payload.newText); 16504 * } 16505 */ 16506 GUIDE_ELEMENT_NAVIGATION_CHANGED : "elementNavigationChanged", 16507 16508 /** 16509 * @summary Dispatched whenever a Field/Panel gets Focus 16510 * @name elementFocusChanged 16511 * @event 16512 * @property {object} payload payload containing more information about the event 16513 * @property {Panel|Field} payload.target new focused component 16514 * @property {string} oldText SOM Expression of component that was previously in focus or null 16515 * @property {string} newText SOM Expression of the component that is currently in focus or null 16516 * @memberof GuideBridge 16517 * @see GuideNode#somExpression 16518 * @see {@link GuideBridge#setFocus|setFocus API} 16519 * @since 6.0 16520 * @example 16521 * guideBridge.on("elementFocusChanged" , function(event, payload) { 16522 * var component = payload.target; 16523 * console.log("old elements's SOM Expression: " + payload.oldText); 16524 * console.log("new elements's SOM Expression: " + payload.newText); 16525 * } 16526 */ 16527 GUIDE_ELEMENT_FOCUS_CHANGED : "elementFocusChanged", 16528 16529 /** 16530 * @summary Dispatched when a user looks at the help description of any Adaptive Form component(Panel or field) 16531 * @name elementHelpShown 16532 * @event 16533 * @property {object} payload payload containing more information about the event 16534 * @property {Panel|Field} payload.target component whose help is being shown 16535 * @property {string} payload._property what kind of help is being shown. The value can be 16536 * * shortDescription (if Short Description becomes visible) 16537 * * longDescription (if Long Description becomes visible) 16538 * @property {string} payload.prevText empty string 16539 * @property {object} payload.newText object containing the help content 16540 * @property {string} payload.newText.help help content of the component 16541 * @memberof GuideBridge 16542 * @since 6.0 16543 * @see {@link https://helpx.adobe.com/aem-forms/6-1/authoring-in-field-help.html|Help Description in Adaptive Form} 16544 * @example 16545 * guideBridge.on("elementHelpShown" , function(event, payload) { 16546 * var component = payload.target; 16547 * console.log("component whose help is shown " + payload.target.name); 16548 * console.log("Help shown: " + payload._property); 16549 * console.log("Help Content: " + payload.newText.help); 16550 * } 16551 */ 16552 GUIDE_ELEMENT_HELP_SHOWN : "elementHelpShown", 16553 16554 /** 16555 * @summary Dispatched when validity of a Field changes. 16556 * @name elementValidationStatusChanged 16557 * @event 16558 * @property {object} payload payload containing more information about the event 16559 * @property {Field} payload.target Field which either became valid/invalid 16560 * @property {boolean} payload.prevText old validation status 16561 * @property {boolean} payload.newText new validation status 16562 * @memberof GuideBridge 16563 * @see Field#validate 16564 * @see Field#validationState 16565 * @since 6.0 16566 * @example 16567 * guideBridge.on("elementValidationStatusChanged" , function(event, payload) { 16568 * var component = payload.target; 16569 * if (payload.prevText) { 16570 * console.log("component became invalid" ); 16571 * } else { 16572 * console.log("component became valid" ); 16573 * } 16574 * } 16575 */ 16576 GUIDE_ELEMENT_VALIDATION_STATUS_CHANGED : "elementValidationStatusChanged", 16577 16578 /** 16579 * Developers must not modify the Form Fields inside the listener. This is mostly use to update the UI outside 16580 * the Form or capture some data for analytics. If you want to modify form field value on the click of a button 16581 * please use the [Click Expression](https://helpx.adobe.com/aem-forms/6-1/adaptive-form-expressions.html#main-pars_header_6) 16582 * provided in the Forms Authoring. 16583 * 16584 * @summary Dispatched when a Button component is clicked. 16585 * 16586 * @name elementButtonClicked 16587 * @event 16588 * @property {object} payload payload containing more information about the event 16589 * @property {Button} payload.target Button which was clicked 16590 * @memberof GuideBridge 16591 * @since 6.0 16592 * @see {@link https://helpx.adobe.com/aem-forms/6-1/adaptive-form-expressions.html#main-pars_header_6|Click Expression in Buttons} 16593 * @example 16594 * guideBridge.on("elementButtonClicked" , function(event, payload) { 16595 * var component = payload.target; // Button which wass clicked 16596 * console.log("Button which was clicked " + component.name); 16597 * } 16598 */ 16599 GUIDE_ELEMENT_BUTTON_CLICKED : "elementButtonClicked", 16600 16601 /** 16602 * Whenever the full form validations are run via the {@link GuideBridge#validate|val
16602idate} API, this event is triggered. 16603 * @summary Dispatched when the validation of all the Adaptive Form fields are completed. 16604 * 16605 * @name validationComplete 16606 * @event 16607 * @property {object} payload payload containing more information about the event 16608 * @property {GuideContainerNode} payload.target root Node of the Adaptive Form 16609 * @property {boolean} payload.prevText result of running the validation. true if validations are successful, 16610 * false otherwise 16611 * @property {Field~ValidationError[]} payload.newText List of objects containing error messages. 16612 * @memberof GuideBridge 16613 * @since 6.0 16614 * @example 16615 * guideBridge.on("validationComplete" , function(event, payload) { 16616 * if (payload.prevText) { 16617 * console.log("validation success"); 16618 * } else { 16619 * console.log("validation failure"); 16620 * if (payload.newText.length) { 16621 * payload.newText.forEach(function (error) { 16622 * console.log("validation failed for " + error.som + " with message " + error.errorText); 16623 * }) 16624 * } 16625 * } 16626 * } 16627 */ 16628 GUIDE_VALIDATION_COMPLETE : "validationComplete", 16629 16630 /** 16631 * Adaptive Form can be configured to be saved automatically at regular intervals. This can be controlled 16632 * dynamically based on the values filled in the Form. Authors can write custom scripts which can enable/disable 16633 * auto save functionality dynamically 16634 * @summary Dispatched when auto save gets enabled in the Form 16635 * @name guideAutoSaveStart 16636 * @event 16637 * @property {object} payload payload containing more information about the event 16638 * @property {GuideContainerNode} payload.target root Node of the Adaptive Form 16639 * @memberof GuideBridge 16640 * @since 6.1 16641 * @see {@link https://helpx.adobe.com/aem-forms/6-1/auto-save-an-adaptive-form.html|Auto Save an Adaptive Form} 16642 * @example 16643 * guideBridge.on("guideAutoSaveStart" , function(event, payload) { 16644 * console.log("Forms is now being saved as draft automatically"); 16645 * } 16646 */ 16647 GUIDE_AUTO_SAVE_START : "guideAutoSaveStart", 16648 16649 /** 16650 * @summary Dispatched when save of adaptive form data has started 16651 * @name saveStarted 16652 * @event 16653 * @memberof GuideBridge 16654 * @since 6.1 16655 * @example 16656 * guideBridge.on("saveStarted" , function(event) { 16657 * console.log("Save of Adaptive Form data is about to start"); 16658 * } 16659 */ 16660 GUIDE_SAVE_START : "saveStarted", 16661 16662 /** 16663 * @summary Dispatched when save of adaptive form data is completed 16664 * @name saveCompleted 16665 * @event 16666 * @memberof GuideBridge 16667 * @since 6.1 16668 * @example 16669 * guideBridge.on("saveCompleted" , function(event) { 16670 * console.log("Save of Adaptive Form data is completed"); 16671 * } 16672 */ 16673 GUIDE_SAVE_COMPLETED : "saveCompleted", 16674 16675 /** 16676 * Users can add some pre submit code in the listener to this event. 16677 * @summary Dispatched when the user clicks on the submit button 16678 * @name submitStart 16679 * @event 16680 * @memberof GuideBridge 16681 * @since 6.0 16682 * @example 16683 * guideBridge.on("submitStart" , function(event) { 16684 * // do some pre submit processing 16685 * } 16686 */ 16687 GUIDE_SUBMIT_START : "submitStart", 16688 GUIDE_PATH : "guidePath", 16689 GUIDE_NAME : "guideName", 16690 GUIDE_DESC : "guideDesc", 16691 GUIDE_TYPE : "guideType", 16692 16693 /** 16694 * @summary Dispatched when an Adaptive Form fragment is lazily loaded successfully 16695 * @name elementLazyLoaded 16696 * @property {object} payload payload containing more information about the event 16697 * @property {Panel} payload.target Adaptive Form Fragment which is lazily loaded 16698 * @event 16699 * @memberof GuideBridge 16700 * @since 6.1 FP1 16701 * @see {@link https://helpx.adobe.com/aem-forms/6-1/lazy-loading-adaptive-forms.html|Lazy Loading Adaptive Form} 16702 * @example 16703 * guideBridge.on("elementLazyLoaded" , function(event, payload) { 16704 * var component = payload.target; 16705 * console.log("Panel " + component.name + " loaded"); 16706 * } 16707 */ 16708 GUIDE_ELEMENT_LAZY_LOADED : "elementLazyLoaded", 16709 16710 /** 16711 * All GuideBridge APIs (except {@link GuideBridge#connect|connect}) require Adaptive Form to be initialized. 16712 * Checking the return value of this API is not necessary if guideBridge API is called only after the 16713 * <a href="#wait-form-ready">Form is initialized</a> 16714 * @summary Whether the Adaptive Form has been initialized or not 16715 * 16716 * @method 16717 * @memberof GuideBridge 16718 * @returns {boolean} true if the Adaptive Form is ready for interaction, false otherwise 16719 * @since 6.0 16720 * @instance 16721 */ 16722 isConnected : function () { 16723 if (this._guide) { 16724 return true; 16725 } 16726 return false;
16727 }, 16728 16729 /** 16730 * Registers a callback that runs once the form model is created. 16731 * 16732 * This works perfectly when the server merges prefill data into the model 16733 * before delivering it to the browser (server-side merge). In that case, 16734 * by the time the model is created the data is already there, so connect() 16735 * callbacks see the full prefilled form. 16736 * 16737 * However, with client-side merge the browser fetches prefill data 16738 * asynchronously AFTER the model is created. connect() callbacks may 16739 * therefore run before fields have their prefilled values. This only 16740 * matters if your callback actually depends on prefilled data (e.g. 16741 * reading field values, setting up cascading dropdowns). 16742 * 16743 * On AEM 6.5 both server-side and client-side merge are available, so 16744 * connect() may work fine depending on the setup. On Forms as a Cloud 16745 * Service only client-side merge is used, so callbacks that depend on 16746 * prefilled data should use viewConnect instead. 16747 * 16748 * Recommended alternatives: 16749 * - viewConnect -- runs after model + prefill data + rendering are ALL done. 16750 * - modelConnect -- runs after the model is created but before rendering. 16751 * 16752 * @summary Register a callback for form model initialization 16753 * @param {function} handler callback to run 16754 * @param {object} [context] "this" inside the callback 16755 * @since 6.0 16756 * @instance 16757 * @method 16758 * @memberof GuideBridge 16759 * @example 16760 * // Deprecated: 16761 * guideBridge.connect(function() { ... }); 16762 * 16763 * // Recommended -- pick the one that fits: 16764 * guideBridge.viewConnect(function() { ... }); // after prefill + render 16765 * guideBridge.modelConnect(function() { ... }); // after model, before render 16766 */ 16767 connect : function (handler, context) { 16768 context = context || guideBridge; 16769 if (this.isConnected()) { 16770 // handle exceptions gracefully since it executes in our thread 16771 try { 16772 handler.call(context); 16773 } catch (exception) { 16774 // guide model should be initialized in bridge in connect, still adding a null check 16775 if (this._guide) { 16776 this._guide.logger().log(exception); 16777 } 16778 } 16779 } else { 16780 this._guideInitHandler.handler = this._guideInitHandler.handler || []; 16781 this._guideInitHandler.handler.push(handler); 16782 this._guideInitHandler.context = this._guideInitHandler.context || []; 16783 this._guideInitHandler.context.push(context); 16784 } 16785 }, 16786 16787 /** 16788 * Register a callback to be executed when the Adaptive Form is fully initialized — 16789 * model created, prefill data merged, and view rendered. 16790 * 16791 * Use this when your callback depends on prefilled data being available -- 16792 * for example, reading field values, setting up cascading dropdowns, or 16793 * toggling panel visibility based on prefilled data. 16794 * 16795 * Background: 16796 * There are two ways prefill data reaches the form: 16797 * - Server-side merge: the server merges data into the model before 16798 * sending it to the browser. Data is already there when the model 16799 * is created, so connect() works fine in this case. 16800 * - Client-side merge: the browser fetches prefill data asynchronously 16801 * after the model is created. connect() callbacks can run before 16802 * that data arrives. 16803 * 16804 * On AEM 6.5 both modes are available. On Forms as a Cloud Service 16805 * only client-side merge is used. viewConnect works correctly in 16806 * both modes -- it simply waits until everything is done. 16807 * 16808 * If the form is already fully initialized when you call this, the 16809 * callback runs immediately. 16810 * 16811 * @summary Register a callback for when model + prefill + view are all done 16812 * @param {function} handler callback to run when the form is fully ready 16813 * @param {object} [context] "this" inside the callback 16814 * @since Forms as a Cloud Service (FaaCS) 16815 * @instance 16816 * @method 16817 * @memberof GuideBridge 16818 * @example 16819 * guideBridge.viewConnect(function() { 16820 * // Safe to read prefilled values here 16821 * var province = guideBridge.getFieldValue("PROVINCIA"); 16822 * if (province) { 16823 * loadComarcas(province); 16824 * } 16825 * }); 16826 */ 16827 viewConnect : function (handler, context) { 16828 this._viewConnect(handler, context); 16829 }, 16830 16831 _viewConnect : function (handler, context) { 16832 // ideally connect should do this but not changing the original function 16833 if (this._guideView && this._guide) { 16834 try { 16835 handler.call(context); 16836 } catch (exception) { 16837 // guide model should be initialized in bridge in connect, still adding a null check 16838 if (this._guide) { 16839 this._guide.logger().log(exception); 16840 } 16841 } 16842 } else { 16843 this._guideInitHandler.handler = this._guideInitHandler.handler || []; 16844 this._guideInitHandler.handler.push(handler); 16845 this._guideInitHandler.context = this._guideInitHandler.context || []; 16846 this._guideInitHandler.context.push(context); 16847 } 16848 }, 16849 16850 /** 16851 * Registers a callback that runs after the form model is created but BEFORE 16852 * the form is rendered on screen. 16853 * 16854 * Use this when you need to manipulate the model early -- for example, 16855 * pre-loading lazy fragment models so their fields exist by the time the 16856 * view renders. 16857 * 16858 * This is an early hook. Prefill data may not be available yet at this 16859 * point (especially with client-side merge). If your callback depends on 16860 * prefilled data, use viewConnect() instead. 16861 * 16862 * If the model is already created when you call this, the callback runs 16863 * immediately. 16864 * 16865 * @summary Register a callback for after model creation, before rendering 16866 * @param {function} handler callback to run when the model is ready 16867 * @param {object} [context] "this" inside the callback 16868 * @since Forms as a Cloud Service (FaaCS) 16869 * @instance 16870 * @method 16871 * @memberof GuideBridge 16872 * @example 16873 * guideBridge.modelConnect(function() { 16874 * this.loadAllLazyFragmentModels(); 16875 * }); 16876 * 16877 * // For embedded forms, register via the bridgeInitializeStart event: 16878 * window.addEventListener("bridgeInitializeStart", function(evnt) { 16879 * evnt.detail.guideBridge.modelConnect(function() { 16880 * this.loadAllLazyFragmentModels(); 16881 * }); 16882 * }); 16883 * @example <caption>With custom context</caption> 16884 * var myContext = { customProp: "value" }; 16885 * window.guideBridge._modelConnect(function() { 16886 * console.log(this.customProp); // "value" 16887 * window.guideBridge.loadAllLazyFragmentModels(); 16888 * }, myContext); 16889 */ 16890 modelConnect : function (handler, context) { 16891 this._modelConnect(handler, context); 16892 }, 16893 16894 _modelConnect : function (handler, context) { 16895 context = context || guideBridge; 16896 if (this.isConnected()) { 16897 // handle exceptions gracefully since it executes in our thread 16898 try { 16899 handler.call(context); 16900 } catch (exception) { 16901 // guide model should be initialized in bridge in connect, still adding a null check 16902 if (this._guide) { 16903 this._guide.logger().log(exception); 16904 } 16905 } 16906 } else { 16907 this._guideModelInitHandler.handler = this._guideModelInitHandler.handler || []; 16908 this._guideModelInitHandler.handler.push(handler); 16909 this._guideModelInitHandler.context = this._guideModelInitHandler.context || []; 16910 this._guideModelInitHandler.context.push(context); 16911 } 16912 }, 16913 16914 _guideModelInitialized : function (e) { 16915 this._guide = e.guide; 16916 if (this._guideModelInitHandler.handler) { 16917 for (var i = 0; i < this._guideModelInitHandler.handler.length; i++) { 16918 try { 16919 this._guideModelInitHandler.handler[i].call(this._guideModelInitHandler.context[i]); 16920 } catch (exception) { 16921 // guide model should be initialized in bridge in connect, still adding a null check 16922 if (this._guide) { 16923 this._guide.logger().log(exception); 16924 } 16925 } 16926 } 16927 } 16928 }, 16929 16930 /* 16931 * 16932 * Handler for guideInitialized event which is fired by Adaptive Form library after Adaptive Form Dom is initialized 16933 * 16934 * @private 16935 */ 16936 _guideInitialized : function (e) { 16937 if (this._guideInitHandler.handler) { 16938 for (var i = 0; i < this._guideInitHandler.handler.length; i++) { 16939 try { 16940 this._guideInitHandler.handler[i].call(this._guideInitHandler.context[i]); 16941 } catch (exception) { 16942 // guide model should be initialized in bridge in connect, still adding a null check 16943 if (this._guide) { 16944 this._guide.logger().log(exception); 16945 } 16946 } 16947 } 16948 } 16949 window.guideBridge.trigger("bridgeInitializeComplete", 16950 guidelib.event.GuideModelEvent.createEvent( 16951 "bridgeInitializeComplete", 16952 guideBridge 16953 ) 16954 ); 16955 }, 16956 _setGuideView : function (guideView) { 16957 this._guideView = guideView; 16958 }, 16959 _guideError : function (e) { 16960 this._guide.logger().debug("AF", e); 16961 }, 16962 _checkGuide : function (obj) { 16963 if (!this._guide) { 16964 obj.addMessage(1, "Guide Dom not Initialized", ""); 16965 return false;
16966 } 16967 return true; 16968 }, 16969 /** 16970 * @summary returns the version of GuideBridge library 16971 * @returns {string} the version of the GuideBridge library 16972 * @method getBridgeVersion 16973 * @memberof GuideBridge 16974 * @instance 16975 * @since 6.0 16976 */ 16977 getBridgeVersion : function () { 16978 return this._version; 16979 }, 16980 16981 /** 16982 * Callback to execute when bridgeInitializeStart is triggered. 16983 * @callback GuideBridge~postExternalCallback 16984 * @param {string} name constant string `bridgeInitializeStart` 16985 * @param {object} data object containing the GuideBridge instance 16986 * @param {GuideBridge} data.guideBridge instance of GuideBridge 16987 * @since 6.0 16988 * @deprecated since 6.3 this callback is deprecated. One must do the handling in 16989 * {@link GuideBridge.events:bridgeInitializeStart} event 16990 * @memberof GuideBridge 16991 * @see GuideBridge#registerConfig 16992 * @see GuideBridge~postExternalMessageConfig 16993 */ 16994 /** 16995 * @typedef {object} GuideBridge~postExternalMessageConfig 16996 * @property {GuideBridge~postExternalCallback} postExternalHandler callback to be executed when GuideBridge 16997 * instance is available 16998 * @since 6.0 16999 * @deprecated since 6.3 this configuration is deprecated. One must do the handling in 17000 * {@link GuideBridge.events:bridgeInitializeStart} event 17001 * @memberof GuideBridge 17002 * @see GuideBridge#registerConfig 17003 */ 17004 /** 17005 * @typedef {object} GuideBridge~submitConfig 17006 * @property {HTMLFormElement} form During submission Adaptive Form creates a new HTMLFormElement and puts all the 17007 * value in that Form. One can provide an existing HTMLFormElement that will be reused for submitting the Form. The 17008 * action and method property of the Form element will be ignored. 17009 * @property {boolean} useAjax submit the form via a XMLHttpRequest rather than using a HTMLFormElement 17010 * instance is available 17011 * @property {function} submitSuccessHandler success Handler to be called post submission. This option is ignored 17012 * if _useAjax_ is set to false 17013 * @since 6.0 17014 * @memberof GuideBridge 17015 * @see GuideBridge#registerConfig 17016 */ 17017 /** 17018 * @typedef {object} GuideBridge~renderConfig 17019 * @property {boolean} enableFocusOnFirstField option to enable focus on first field. Default value is true. 17020 * @since 6.5 17021 * @memberof GuideBridge 17022 * @see GuideBridge#registerConfig 17023 */ 17024 /** 17025 * Adaptive Form uses some default named configurations to provide its default behaviour. This configurations 17026 * can be modified by providing a new configuration. 17027 * 17028 * The API accepts the name of the configuration and updated configuration. Based on value of the new 17029 * configuration the behaviour of the Form gets changed. 17030 * Currently supported configurations are: 17031 * #### postExternalMessageConfig 17032 * 17033 * <div class="deprecated"><span class="deprecated-heading">Deprecated :</span><span> since 6.2 this 17034 * configuration is deprecated. Use the {@link GuideBridge.events:bridgeInitializeStart} event to do the same 17035 * handling</span> 17036 * </div> 17037 * In case Adaptive Form is embedded inside an iframe, this configuration allows developers to provide 17038 * GuideBridge Instance to parent or child windows.
17039 * 17040 * By default, GuideBridge instance is only available to the current window and to the parent window if it 17041 * doesn't violate the cross-origin policy. Now there may be a case when this doesn't solves the problem, then 17042 * one can take advantage of this configuration to extend this functionality. 17043 * 17044 * For the signature of the configuration see 17045 * {@link GuideBridge~postExternalMessageConfig|postExternalMessageConfig} 17046 * ##### Example 17047 * To provide the GuideBridge instance to a child window 17048 * ``` 17049 * window.on("bridgeInitializeStart", function (evnt) { 17050 * var gb = evnt.detail.guideBridge; 17051 * gb.registerConfig("postExternalMessageConfig", { 17052 * "postExternalHandler" : function(data) { 17053 * // assume we have a child window with an id 'childWindowId' 17054 * var childWindow = document.getElementById("#childWindowId").contentWindow; 17055 * var tmpEvent = document.createEvent("CustomEvent"); 17056 * tmpEvent.initCustomEvent(data.name, true, true, data.data); 17057 * childWindow.dispatchEvent(tmpEvent); 17058 * } 17059 * }); 17060 * }); 17061 * ``` 17062 * #### widgetConfig 17063 * The configuration is used to modify the appearance of a specific Field. Adaptive Form allows developers to 17064 * [create custom widgets](http://helpx.adobe.com/aem-forms/6-1/custom-appearance-widget-adaptive-form.html) and 17065 * use them in their Forms. 17066 * 17067 * The signature of the config is 17068 * ``` 17069 * { "<component-identifier> : "<widget-name>"} 17070 * ``` 17071 * where `<component-identifier>` can be either the name or classname of Adaptive Form Field, 17072 * while widget name is the name of the jQuery Widget. 17073 * 17074 * #### submitConfig 17075 * To modify the default submit behaviour one can provide this configuration. The signature of the config is 17076 * defined {@link GuideBridge~submitConfig|below} 17077 * ``` 17078 * guideBridge.registerConfig("submitConfig", {"useAjax" : true}); 17079 * ``` 17080 * 17081 * #### renderConfig 17082 * To modify the default render behaviour one can provide this configuration. The signature of the config is 17083 * defined {@link GuideBridge~renderConfig|below} 17084 * ``` 17085 * guideBridge.registerConfig("renderConfig", {"enableFocusOnFirstField" : false}); 17086 * ``` 17087 * @summary Registers user/portal specific configurations to GuideBridge 17088 * @returns {GuideResultObject} {@link GuideResultObject} with {@link GuideResultObject#data|data} having the 17089 * old configuration against the same _key_ 17090 * 17091 * @param key {string} configuration name. one of the following 17092 * * postExternalMessageConfig 17093 * * widgetConfig 17094 * * submitConfig 17095 * * renderConfig 17096 * @param {widgetConfig|GuideBridge~submitConfig|GuideBridge~renderConfig|GuideBridge~postExternalMessageConfig} [config] configuration object for the configuration 17097 * @method 17098 * @memberof GuideBridge 17099 * @since 6.0 17100 * @instance 17101 */ 17102 registerConfig : function (key, config) { 17103 var obj = new GuideResultObject(); 17104 obj.data = this.userConfig[key]; 17105 this.userConfig[key] = config; 17106 obj.completed = true; 17107 return obj; 17108 }, 17109 17110 /** 17111 * Their exists a customPropertyMap which can be set from the server. For prefilling files 17112 * fileAttachmentMap key should be present in the map. 17113 * @name customContextProperty 17114 * @param value {object} object to be replaced with the current customPropertyMap. 17115 * @memberof GuideBridge 17116 * @method 17117 * since 6.0 17118 */ 17119 17120 /** 17121 * Their exists a customPropertyMap which can be set from the server. For prefilling files 17122 * fileAttachmentMap key should be present in the map. 17123 * @name customContextProperty 17124 * @param property {string} object to be replaced with the current customPropertyMap. 17125 * @method 17126 * @memberof GuideBridge 17127 * since 6.0 17128 */ 17129 17130 /** 17131 * Their exists a customPropertyMap which can be set from the server. For prefilling files 17132 * fileAttachmentMap key should be present in the map. 17133 * @param property {string} property to update in the custom property map 17134 * @param value {*} value of the property 17135 * @return {*} old value of the property 17136 * since 6.0 17137 */ 17138 customContextProperty : function (property, value) { 17139 var customPropertyMap = getOrElse(guidelib, "__runtime__.guideContext.customPropertyMap", {}); 17140 // use both the customContextProperty map since customers also access that 17141 var newCustomPropertyMap = _.extend({}, customPropertyMap, getOrElse(this._guide, "runtime.guideContext.customPropertyMap", {})); 17142 if (_.isUndefined(value)) { 17143 if (_.isObject(property)) { 17144 guideBridge._modelConnect((function (newCustomPropertyMap, property) { 17145 return function () { 17146 var localMap = _.extend({}, guideBridge._guide.runtime.guideContext.customPropertyMap, newCustomPropertyMap); 17147 _.extend(localMap, property); 17148 guideBridge._guide.runtime.guideContext.customPropertyMap = localMap; 17149 }; 17150 })(newCustomPropertyMap, property)); 17151 } else { 17152 return newCustomPropertyMap[property]; 17153 } 17154 } else { 17155 var oldValue = newCustomPropertyMap[property]; 17156 guideBridge._modelConnect((function (property, value, newCustomPropertyMap) { 17157 return function () { 17158 var localMap = _.extend({}, guideBridge._guide.runtime.guideContext.customPropertyMap, newCustomPropertyMap); 17159 localMap[property] = value; 17160 guideBridge._guide.runtime.guideContext.customPropertyMap = localMap; 17161 }; 17162 })(property, value, newCustomPropertyMap)); 17163 return oldValue; 17164 } 17165 }, 17166 17167 getNavigablePanel : function (somExpression) { 17168 return this._guideView.getSomOnNavigableAncestor(somExpression); 17169 }, 17170 17171 /** 17172 * Sets the value of a property for a set of {@link GuideNode} to a different value. Property must be a valid 17173 * writable property for that Node 17174 * 17175 * Each entry in _somList_ should have a corresponding entry in the _valueList_. Mismatch in the length of these
17176 * two arguments will make the function do nothing 17177 * @summary Modify a property for a set of Nodes 17178 * @method setProperty 17179 * @param {string[]} somList an array having someExpression for the nodes. Invalid SomExpressions and 17180 * the corresponding value in the _valueList_ are ignored. 17181 * @param {string} propertyName name of the property which has to be modified 17182 * @param {Array.<*>} valueList an array containing value of the _propertyName_ for each element in _somList_ 17183 * 17184 * @memberof GuideBridge 17185 * @instance 17186 * @since 6.0 17187 * @see GuideNode#somExpression 17188 * @example <caption>Modifying the value of a set of fields</caption> 17189 * guideBridge.setProperty(["SOM_OF_FIELD_1", "SOM_OF_FIELD_2"...... "SOM_OF_FIELD_N"] 17190 * "value" 17191 * [VALUE_1, VALUE_2 .... VALUE_N]); 17192 * @example <caption>Hiding a single field</caption> 17193 * guideBridge.setProperty(["SOM_OF_FIELD_1"] 17194 * "visibility" 17195 * [false]); 17196 */ 17197 setProperty : function (somList, propertyName, valueList) { 17198 if (!propertyName) { 17199 return; 17200 } 17201 if (!_.isArray(somList) || !_.isArray(valueList)) { 17202 return; 17203 } 17204 if (somList.length !== valueList.length) { 17205 return; 17206 } 17207 var gb = this; 17208 _.each(somList, function (som, index) { 17209 var node = gb.resolveNode(som); 17210 if (node) { 17211 node[propertyName] = valueList[index]; 17212 } else { 17213 gb._guide.logger().log("som not valid:" + som); 17214 } 17215 }); 17216 if (!this._guide._currentContext) { 17217 this._guide.runPendingExpressions(); 17218 } 17219 }, 17220 17221 /** 17222 * Used to retrieve the Form data as XML. The API gets the data xml synchronously/asynchronously based on the 17223 * _async_ option and invokes the success/error handlers passed in the arguments upon completion. 17224 * 17225 * In the success callback the {@link GuideResultObject#data|data} parameter contains the xml string. 17226 * 17227 * The success and error handlers receive {@link GuideResultObject} as input. 17228 * @summary Return Form data as XML. 17229 * 17230 * @param {object} options input to the getDataXML API 17231 * @param {function} [options.success] callback which receives the result of the API 17232 * in case of success. 17233 * @param {function} [options.error] callback which receives the result of the API in 17234 * case of failure. 17235 * {@link GuideResultObject#errors|errors} property as true. 17236 * @param {object} [options.context] _this_ object inside the _success_ and _error_ callback will point to this 17237 * object 17238 * @param {boolean} [options.async=true] whether to make the server call asynchronously or not. If false, the 17239 * browser will wait for the server to return the XML and then execute the success or error callbacks object 17240 * @see <a href="#guidebridge-api-usage" >GuideBridge API Usage</a> 17241 * @method 17242 * @memberof GuideBridge 17243 * @since 6.0 17244 * @instance 17245 * @example 17246 * guideBridge.getDataXML({ 17247 * success : function (guideResultObject) { 17248 * console.log("xml data received" + guideResultObject.data); 17249 * } 17250 * error : function (guideResultObject) { 17251 * console.error("API Failed"); 17252 * var msg = guideResultObject.getNextMessage(); 17253 * while (msg != null) { 17254 * console.error(msg.message); 17255 * msg = guideResultObject.getNextMessage(); 17256 * } 17257 * } 17258 * }); 17259 * 17260 * @deprecated since 6.3 this API is deprecated. Use getData API instead. 17261 * @param options 17262 */ 17263 getDataXML : function (options) { 17264 guideBridge.getData(options); 17265 }, 17266 17267 /** 17268 * Used to retrieve the Form data as XML or JSON depending on the Schema Type. Only for JSON Schema based Forms 17269 * and Form Data Model based forms, the data will be in JSON format while for others, the data will be in XML format. 17270 * The API gets the data synchronously/asynchronously based on the 17271 * _async_ option and invokes the success/error handlers passed in the arguments upon completion. 17272 * 17273 * In the success callback the {@link GuideResultObject#data|data} parameter contains the data string. 17274 * 17275 * The success and error handlers receive {@link GuideResultObject} as input. 17276 * @summary Return Form data as XML or JSON depending on the Schema Type. 17277 * 17278 * @param {object} options input to the getData API 17279 * @param {function} [options.success] callback which receives the result of the API 17280 * in case of success. 17281 * @param {function} [options.error] callback which receives the result of the API in 17282 * case of failure. 17283 * {@link GuideResultObject#errors|errors} property as true. 17284 * @param {object} [options.context] _this_ object inside the _success_ and _error_ callback will point to this 17285 * object 17286 * @param {boolean} [options.async=true] whether to make the server call asynchronously or not. If false, the 17287 * browser will wait for the server to return the data (XML or JSON) and then execute the success or error callbacks object 17288 * @see <a href="#guidebridge-api-usage" >GuideBridge API Usage</a> 17289 * @method 17290 * @memberof GuideBridge 17291 * @since 6.3 17292 * @instance 17293 * @example 17294 * guideBridge.getData({ 17295 * success : function (guideResultObject) { 17296 * console.log("data received" + guideResultObject.data); 17297 * } 17298 * error : function (guideResultObject) { 17299 * console.error("API Failed"); 17300 * var msg = guideResultObject.getNextMessage(); 17301 * while (msg != null) { 17302 * console.error(msg.message); 17303 * msg = guideResultObject.getNextMessage(); 17304 * } 17305 * } 17306 * }); 17307 * @deprecated use {@link GuideBridge#getFormDataString} instead 17308 */ 17309 getData : function (options) { 17310 options = options || {}; 17311 17312 /* Earlier this API would support boundData for getting data tro be merged in PDF. Now that flag has been renamed to dorData 17313 * Earlier, boundData flag now maps to boundData for backward compatibility. 17314 * */ 17315 options.dorData = options.dorData || options.boundData; 17316 17317 var resultObject = new GuideResultObject(); 17318 if (!options.guideState && !this._checkGuide(resultObject)) { 17319 options.error.call(options.context, resultObject); 17320 return; 17321 } 17322 17323 this._submitInternal({ 17324 success : function (data) { 17325 var resultJson = data || {}; 17326 resultObject.completed = true; 17327 if (options.dorData) { 17328 resultObject.data = resultJson["dorDataXml"]; 17329 } else { 17330 resultObject.data = resultJson["data"]; 17331 } 17332 if (_.isFunction(options.success)) { 17333 options.success.call(options.context, resultObject); 17334 } 17335 }, 17336 error : function (xhr, txtStatus, errorThrown) { 17337 var msg = "Error in getData API"; 17338 resultObject.completed = false;
17339 resultObject.addMessage(2, msg, ""); 17340 if (_.isFunction(options.error)) { 17341 options.error.call(options.context, resultObject); 17342 } 17343 }, 17344 guideState : options.guideState, 17345 async : options.async, 17346 fileUploadPath : options.fileUploadPath, 17347 excludeFormState : options.excludeFormState || false, 17348 dorData : options.dorData || false 17349 }); 17350 }, 17351 17352 /** 17353 * returns form data object {@link FormData} 17354 * @returns {*} 17355 * @private 17356 */ 17357 _getFormDataObj : function () { 17358 guideBridge._updateAFSubmissionInfo(); 17359 guideBridge._guide.internal.liveDataUtils.updateLiveData(null, true); // fetching client side data 17360 guideBridge._guide.internal.liveDataUtils.insertSubmissionInfo(guideBridge._guide.runtime.guideContext.afSubmissionInfo); 17361 var data = guideBridge._guide.internal.liveDataUtils.getLiveDataStr(); 17362 var contentType = "application/xml"; 17363 if (guideBridge._guide.internal.liveDataUtils instanceof guidelib.model.LiveJsonUtils) { 17364 contentType = "application/json"; 17365 } 17366 return new guidelib.model.FormData({ 17367 "data" : data, 17368 "contentType" : contentType, 17369 "attachments" : guideBridge.getFileAttachmentWrapper() 17370 }); 17371 }, 17372 17373 /** 17374 * invoked inside server-side-validation to return excludeFromDor data. 17375 * @param {Object} guide input to _getExcludeFromDorData API 17376 * @returns {Array} containing excludeFromDoR info 17377 * */ 17378 _getExcludeFromDorData : function (guide) { 17379 var newGuide = guide ? guide : guideBridge._guide; 17380 var excludeFromDorData = null; 17381 window.guideBridge._updateAFSubmissionInfo(newGuide); 17382 var afSubmissionInfo = newGuide.runtime.guideContext.afSubmissionInfo; 17383 if(afSubmissionInfo && afSubmissionInfo.excludeFromDoR) { 17384 excludeFromDorData = afSubmissionInfo.excludeFromDoR; 17385 } 17386 return excludeFromDorData; 17387 }, 17388 17389 /** 17390 * returns FormData object {@link FormData} containing form data xml or json and attachments 17391 * @param {object} options input to the getFormDataObject API 17392 * @param {function} [options.success] callback which receives the result of the API 17393 * in case of success. 17394 * @method 17395 * @memberof GuideBridge 17396 * @since Forms As A Cloud Service 17397 * @instance 17398 */ 17399 getFormDataObject : function (options) { 17400 var formDataObj = guideBridge._getFormDataObj(); 17401 var resultObject = new GuideResultObject(); 17402 resultObject.data = formDataObj; 17403 // using typeof for built in types 17404 if (options && typeof options.success === 'function') { 17405 options.success(resultObject); 17406 } 17407 }, 17408 17409 /** 17410 * returns string representation of form data xml or json 17411 * @param {object} options input to the getData API 17412 * @param {function} [options.success] callback which receives the result of the API 17413 * in case of success. 17414 * @method 17415 * @memberof GuideBridge 17416 * @since 6.5 17417 * @instance 17418 */ 17419 getFormDataString : function (options) { 17420 var formDataObj = guideBridge._getFormDataObj(); 17421 var resultObject = new GuideResultObject(); 17422 resultObject.data = formDataObj.data; 17423 if (options && typeof options.success === 'function') { 17424 options.success(resultObject); 17425 } 17426 }, 17427 17428 17429 /** 17430 * Imports form data from a given string, which can be either JSON or XML format. 17431 * This is useful for initializing a form with pre-filled data received as a string. 17432 * 17433 * @param {Object} options - The options for importing data. 17434 * @param {string} options.data - The string representation of form data (XML or JSON). 17435 * @method 17436 * @memberof GuideBridge 17437 * @since Forms As A Cloud Service 17438 * @instance 17439 * @example 17440 * guideBridge.importData({ data: jsonString }); // For JSON data 17441 * guideBridge.importData({ data: xmlString }); // For XML data 17442 */ 17443 importData : function (options) { 17444 // todo: add support for attachments and custom context later 17445 var prefillData = { 17446 data: options.data, 17447 isMergedJson: false 17448 // customContext: {} 17449 // fileAttachmentMap: {} 17450 // fileAttachmentWrappers: 17451 // attachments: '[]' 17452 }; 17453 guidelib.model.mergeData(prefillData, guideBridge._guide, guideBridge._guide.runtime.guideContext); 17454 }, 17455 17456 /** 17457 * @summary Hides all the submit buttons present in the Adaptive Form 17458 * 17459 * @returns {GuideResultObject} the data property of GuideResultObject would be undefined. The API will fail if
17460 * the Form is not initialized which would be indicated by the {@link GuideResultObject#errors|errors} property. 17461 * @memberof GuideBridge 17462 * @instance 17463 * @since 6.0 17464 */ 17465 hideSubmitButtons : function () { 17466 return this._hideElements("guideButton", "submit"); 17467 }, 17468 17469 /** 17470 * @returns {string} Current Locale of the Form 17471 * @method 17472 * @memberof GuideBridge 17473 * @since Forms As A Cloud Service 17474 * @instance 17475 */ 17476 getFormLocale : function() { 17477 return this._readRuntimeLocale(); 17478 }, 17479 17480 /** 17481 * @returns {string} ID of the Form 17482 * @method 17483 * @memberof GuideBridge 17484 * @since Forms As A Cloud Service 17485 * @instance 17486 */ 17487 getFormId : function() { 17488 var guidePath = guideBridge._guide.jsonModel["jcr:path"]; 17489 return btoa(guidePath); 17490 }, 17491 17492 /** 17493 * Gets the Document of Record. If options is not passed or if success function is not defined, 17494 * then the default behaviour is to download the Document of Record PDF in user's system. 17495 * @param {object} options options to control the behaviour after Document of Record (DOR) is retrieved 17496 * @param {function} [options.success] callback which receives the result of the API 17497 * {@link GuideResultObject#errors|errors} property as false. 17498 * @param {function} [options.error] callback for error handling 17499 * {@link GuideResultObject#errors|errors} property as true. 17500 * @method 17501 * @memberof GuideBridge 17502 * @since Forms As A Cloud Service 17503 * @instance 17504 * @example <caption>Getting the Document of Record</caption> 17505 * guideBridge.getDocumentOfRecord({ 17506 * success: function (guideResultObject) {}, 17507 * error: function (guideResultObject) {} 17508 * }) 17509 */ 17510 getDocumentOfRecord : function(options) { 17511 var self = this; 17512 var formName = self._getFormName(self.getGuidePath()); 17513 if (!options) { 17514 options = {}; 17515 } 17516 if (!_.isFunction(options.success)) { 17517 options.success = function (guideResultObject) { 17518 if (guideResultObject.completed && guideResultObject.data) { 17519 var blob = new Blob([guideResultObject.data], {type: 'application/pdf'}); 17520 var downloadUrl = URL.createObjectURL(blob); 17521 var a = document.createElement("a"); 17522 a.setAttribute('href', downloadUrl); 17523 a.setAttribute('download', formName); 17524 a.setAttribute('style', 'display:none'); 17525 document.body.appendChild(a); 17526 a.click(); 17527 } 17528 } 17529 } 17530 if (!_.isFunction(options.error)) { 17531 options.error = function(guideResultObject) { 17532 console.error(guideResultObject.data); 17533 } 17534 } 17535 function _getDocumentOfRecord(formData) { 17536 var formId = self.getFormId(); 17537 var locale = self.getFormLocale(); 17538 var dorGenerationURL = self._getUrl("/adobe/forms/af/dor/" + formId + "?locale=" + locale); 17539 $.ajax({ 17540 url : dorGenerationURL, 17541 type : "POST", 17542 processData : false, 17543 cache : false, 17544 contentType : false, 17545 data : formData, 17546 xhrFields:{ 17547 responseType: 'blob' 17548 }, 17549 success : function(blob) { 17550 var guideResultObject = new GuideResultObject(); 17551 guideResultObject.data = blob; 17552 guideResultObject.completed = true; 17553 options.success(guideResultObject); 17554 }, 17555 error : function (exception) { 17556 var guideResultObject = new GuideResultObject(); 17557 guideResultObject.data = exception; 17558 guideResultObject.completed = false;
17559 options.error(guideResultObject); 17560 } 17561 }); 17562 }; 17563 17564 self.getFormDataString({ 17565 success: function(result) { 17566 var attachedFilesList = self._getFileAttachmentsList(); 17567 var fileNameDomMap = self._juiceOutNameAndFileDomMap(attachedFilesList); 17568 var dataForm = new FormData(); 17569 var fileAttachmentPromise = self._appendFileAttachmentsToFormData(dataForm, fileNameDomMap, attachedFilesList); 17570 fileAttachmentPromise.then(function (dataForm) { 17571 dataForm.append('data', result.data); 17572 _getDocumentOfRecord(dataForm); 17573 }).catch(function (e) { 17574 console.error(e); 17575 }); 17576 } 17577 }) 17578 }, 17579 17580 /** 17581 * This API is designed to evaluate the expression entered by the author. 17582 * This API is given only to enable Auto Save meta information use case. 17583 * @returns value obtained after executing the expression. 17584 * @method 17585 * @private 17586 * @memberof GuideBridge 17587 * @deprecated since 6.3 this API is deprecated 17588 */ 17589 _evaluateExpression : function (expression) { 17590 if (this._guide) { 17591 var compiledExpression = this._guide._compileExpression(expression, null); 17592 return compiledExpression.apply(this._guide); 17593 } 17594 }, 17595 17596 /** 17597 * Adaptive Form can be configured to save draft automatically. This property indicates whether Adaptive Form is 17598 * configured to save draft automatically or not. 17599 * 17600 * Enabling auto save doesn't mean that AF will create the draft when the Form is loaded. Based on the result of 17601 * **Auto save start expression** the draft will be created. Once the expression returns true, drafts will be 17602 * saved at regular interval or at specific events as configured. 17603 * 17604 * @summary Whether autoSave is enabled for this Adaptive Form or not 17605 * @returns {boolean} true if auto save is enabled otherwise false. 17606 * @method 17607 * @memberof GuideBridge 17608 * @instance 17609 * @since 6.1 FP1 17610 * @see {@link https://helpx.adobe.com/aem-forms/6-1/auto-save-an-adaptive-form.html|Saving an adaptive Form} 17611 */ 17612 getAutoSaveEnabledStatus : function () { 17613 var _isAutoSaveEnable = false; 17614 // check if form is loaded or not, if loaded then check for auto save 17615 if (this.isConnected()) { 17616 _isAutoSaveEnable = this._guide.enableAutoSave; 17617 } 17618 return _isAutoSaveEnable; 17619 }, 17620 17621 /** 17622 * This API indicates that auto save is enabled and draft is being saved at the configured location. 17623 * @summary Whether Adaptive Form data is being saved as draft or not. 17624 * @returns {Boolean} whether autoSave has started. 17625 * @method 17626 * @memberof GuideBridge 17627 * @instance 17628 * @since 6.1 FP1 17629 * @see {@link https://helpx.adobe.com/aem-forms/6-1/auto-save-an-adaptive-form.html|Saving an adaptive Form} 17630 **/ 17631 hasAutoSaveStarted : function () { 17632 return this._guide && this._guide.enableAutoSave && this._guide.autoSaveStart; 17633 }, 17634 17635 /** 17636 * @summary the autoSaveinfo that is stored at the guideContainer. 17637 * @returns {object}
17637 object contains the additional meta information stored along with form data 17638 * @method 17639 * @memberof GuideBridge 17640 * @instance 17641 * @since 6.1 FP1 17642 * @deprecated since 6.3 17643 */ 17644 getAutoSaveInfo : function () { 17645 return this._guide.autoSaveInfo; 17646 }, 17647 17648 /** 17649 * The API is used to provide extra information to be saved in Final data XML. It can also be used to retrieve 17650 * that information. 17651 * 17652 * If _value_ is null then the value of the _property_ is returned 17653 * @summary store or retrieve submission related information 17654 * @param {string} property name of the property against which to save the value or retrieve the value of 17655 * property 17656 * @param {string} [value] value to save. 17657 * @returns {*} old value of the property 17658 * @method 17659 * @since 6.1 FP1 17660 * @memberof GuideBridge 17661 * @instance 17662 * @deprecated since 6.3 17663 */ 17664 afSubmissionInfo : function (property, value) { 17665 var afSubmissionInfo = guideBridge._guide.runtime.guideContext.afSubmissionInfo || {}; 17666 if (_.isUndefined(value)) { 17667 return afSubmissionInfo[property]; 17668 } else { 17669 var oldValue = afSubmissionInfo[property]; 17670 afSubmissionInfo[property] = value; 17671 guideBridge._guide.runtime.guideContext.afSubmissionInfo = afSubmissionInfo; 17672 return oldValue; 17673 } 17674 }, 17675 17676 /** 17677 * @summary this API returns the globalMetaInfo stored in global context (in globalMetaInfo tab). 17678 * @returns {object} 17679 * @method 17680 * @memberof GuideBridge 17681 * @instance 17682 * @deprecated since 6.3 17683 */ 17684 getGlobalMetaInfo : function () { 17685 return this._guide.globalMetaInfo; 17686 }, 17687 17688 /** 17689 * @summary this API returns the metadata configured for submission. Value depends on the selection of metadata 17690 * type, local or global. 17691 * @returns {Object} 17692 * @method 17693 * @since 6.1 FP1 17694 * @memberof GuideBridge 17695 * @instance 17696 * @deprecated since 6.3 17697 */ 17698 getSubmissionMetadataInfo : function () { 17699 if (this._guide.submissionMetaInfo && this._guide.submissionMetaInfo.metadataselector === LOCAL_METADATA_SELECTOR) { 17700 // In order to maintain backward compatibility, this piece of code will always be here. 17701 // For the cases where metadata selection is being configured for submit actions 17702 return getOrElse(this._guide, "submissionMetaInfo.metadata", null); 17703 } else { 17704 //From 6.2 onwards, we are asking author to provide metadata only at one place, which is global to whole form 17705 // In case, metadataselector's value is "global" or not configured at all, this block will get executed 17706 return getOrElse(this._guide, "globalMetaInfo.metadata", null); 17707 } 17708 }, 17709 17710 /** 17711 * The API enables auto save in Adaptive Form 17712 * @summary enable auto save in Adaptive Form. 17713 * @param value {boolean} true to enable auto save otherwise false. 17714 * @method 17715 * @memberof GuideBridge 17716 * @instance 17717 * @since 6.1 FP1 17718 * @see {@link GuideBridge#getAutoSaveEnabledStatus|getAutoSaveEnabledStatus} 17719 * @see {@link https://helpx.adobe.com/aem-forms/6-1/auto-save-an-adaptive-form.html|Auto Save an Adaptive Form} 17720 */ 17721 setEnabledAutoSave : function (value) { 17722 this._guide.enableAutoSave = value; 17723 }, 17724 17725 /** 17726 * @summary Hides all the file attachment listing buttons present in the Adaptive Form 17727 * 17728 * @returns {GuideResultObject} the data property of GuideResultObject would be undefined. The API will fail if 17729 * the Form is not initialized which would be indicated by the {@link GuideResultObject#errors} property. 17730 * @memberof GuideBridge 17731 * @instance 17732 * @since 6.0 17733 */ 17734 hideFileAttachmentListingButtons : function () { 17735 return this._hideElements("guideListFileAttachmentButton"); 17736 }, 17737 17738 /** 17739 * @todo: Function can change as per usecase, it can behave as a wrapper 17740 * where it can use the configuration provided through registerConfig and invoke any callback if required 17741 * 17742 * @returns {boolean} boolean indicating whether Adaptive Form is offline 17743 * @private 17744 */ 17745 isOffline : function () { 17746 return checkAFOffline; 17747 }, 17748 17749 /** 17750 * function to set the status of Adaptive Form (online or offline) 17751 * @type {boolean} 17752 * @private 17753 */ 17754 setIsOffline : function (value) { 17755 checkAFOffline = value; 17756 }, 17757 17758 /** 17759 * @summary Hide all the File Attachment component present in the Adaptive Form 17760 * 17761 * @returns {GuideResultObject} the data property of GuideResultObject would be undefined. The API will fail if
17762 * the Form is not initialized which would be indicated by the {@link GuideResultObject#errors} property. 17763 * @memberof GuideBridge 17764 * @instance 17765 * @since 6.0 17766 */ 17767 hideFileAttachments : function () { 17768 return this._hideElements("guideFileUpload"); 17769 }, 17770 17771 /** 17772 * @summary Hides the global toolbar of the Adaptive Form. 17773 * @returns {GuideResultObject} the data property of GuideResultObject would be undefined. The API will fail if 17774 * the Form is not initialized which would be indicated by the {@link GuideResultObject#errors} property. 17775 * @memberof GuideBridge 17776 * @instance 17777 * @since 6.0 17778 */ 17779 hideGlobalToolbar : function () { 17780 var resultObject = new GuideResultObject(), 17781 $toolbar; 17782 17783 // If guide dom not initialized, return 17784 if (!this._checkGuide(resultObject)) { 17785 return resultObject; 17786 } 17787 17788 if (guideBridge._guide.toolbar) { 17789 $toolbar = this._getGuideDomElement(guideBridge._guide.toolbar.somExpression); 17790 if ($toolbar && $toolbar.length > 0) { 17791 $toolbar.hide(); 17792 } 17793 } 17794 17795 resultObject.completed = true; 17796 return resultObject; 17797 }, 17798 17799 /* 17800 * 17801 * This API is designed to return all the toolbar buttons present in the Adaptive Form(except submit, save, reset and file attachment listing) 17802 * 17803 * @returns {GuideResultObject} data contains an array of all the tool bar buttons available(except submit, save, reset and file attachment listing) 17804 * Each element of data property is an object holding model and html property. 17805 * The html string does not contain any script tags, this is to avoid crosss site scripting attacks 17806 */ 17807 /* 17808 getToolbarButtons : function(){ 17809 var resultObject = new GuideResultObject(), 17810 resultData = [], 17811 $elem = null; 17812 // If guide dom not initialized, return 17813 if (!this._checkGuide(resultObject)) { 17814 return resultObject; 17815 } 17816 resultObject.completed = true; 17817 this.visit(function(node){ 17818 // Check if this node is a guide button and if it resides inside a guideToolBar 17819 if(node.className === "guideButton" && node.parent.className === "guideToolbar"){ 17820 if(node.type !== "submit" && node.type !== "save" && node.type !== "fileattachmentlisting" && node.type !== "next" && node.type !=="prev") { 17821 $elem = this._getGuideDomElement(node.somExpression); 17822 // Remove the script tag from the $html, we don't support execution of Adaptive Form Scripts in parent or other domain 17823 // This is to avoid cross site scripting attacks 17824 $elem.find("script").remove(); 17825 resultData.push({ 17826 "model" : node, 17827 "html" : $elem.html() 17828 }); 17829 } 17830 } 17831 }); 17832 resultObject.data = resultData; 17833 return resultObject; 17834 }, */ 17835 17836 /** 17837 * @summary Hides all the save buttons present in the Adaptive Form 17838 * 17839 * @returns {GuideResultObject} the data property of GuideResultObject would be undefined. The API will fail if 17840 * the Form is not initialized which would be indicated by the {@link GuideResultObject#errors} property. 17841 * @memberof GuideBridge 17842 * @instance 17843 * @since 6.0 17844 */ 17845 hideSaveButtons : function () { 17846 return this._hideElements("guideButton", "save"); 17847 }, 17848 17849 /** 17850 * @summary Hides all the reset buttons present in the Adaptive Form 17851 * 17852 * @returns {GuideResultObject} the data property of GuideResultObject would be undefined. The API will fail if 17853 * the Form is not initialized which would be indicated by the {@link GuideResultObject#errors} property. 17854 * @memberof GuideBridge 17855 * @instance 17856 * @since 6.3 17857 */ 17858 hideResetButtons : function () { 17859 return this._hideElements("guideButton", "reset"); 17860 }, 17861 17862 /** 17863 * The API can be used to retrieve the value of a specific property for a list of AF components. If the property 17864 * doesn't exists for a component then the corresponding value in the resulting array will be null. 17865 * 17866 * The {@link GuideResultObject#data|data} element of the return object will be an array containing the values 17867 * of the _property_ for each component in the list of components 17868 * 17869 * The API fails if the Form is not initiailzed 17870 * 17871 * **_Note:_** If a somExpression provided doesn't points to a valid {@link GuideNode} null is returned for 17872 * that element and an error message is added in the returned object 17873 * @summary returns the value of a specific property for a set of Adaptive Form Components 17874 * 17875 * @param {object}
17875 options input object containing the propertyName and the list of components 17876 * @param {string} options.propertyName name of the property whose value has to be returned 17877 * @param {string[]} options.somExpression list of somExpression of the components for which the value is to be 17878 * returned. 17879 * 17880 * @returns {GuideResultObject} The {@link GuideResultObject#data|data} member of the object contains the property 17881 * values 17882 * @method 17883 * @memberof GuideBridge 17884 * @since 6.0 17885 * @instance 17886 * @deprecated since 6.3 17887 * @see GuideNode#somExpression 17888 * @example 17889 * var result = guideBridge.getElementProperty({ 17890 * propertyName: "value", 17891 * somExpression: ["somExpression1", "somExpression2"] 17892 * }); 17893 * if (result.errors) { 17894 * console.log("some som expressions were invalid"); 17895 * var err = result.getNextMessage(); 17896 * while(err != null) { 17897 * //err.somExpression will point to the invalid somExpression in the Field. 17898 * console.log(err.message); 17899 * } 17900 * } 17901 * for(var i = 0; i< result.data.length; i++) { 17902 * console.log(result.data[i]); 17903 * } 17904 */ 17905 getElementProperty : function (options) { 17906 var somExpressions = options.somExpressions; 17907 var propertyName = options.propertyName; 17908 var resultObject = new GuideResultObject(); 17909 if (!this._checkGuide(resultObject)) { 17910 return resultObject; 17911 } 17912 resultObject.data = []; 17913 for (var i = 0; i < somExpressions.length; i++) { 17914 var element = this.resolveNode(somExpressions[i]); 17915 if (element == null) { 17916 resultObject.addMessage(0, "No element " + somExpressions[i] + " exists", somExpressions[i]); 17917 resultObject.data.push(null); 17918 } else { 17919 resultObject.completed = true; 17920 resultObject.data.push(element[propertyName]); 17921 } 17922 } 17923 return resultObject; 17924 }, 17925 17926 _getGuideDomElement : function (somExpression, option) { 17927 if (this._guideView) { 17928 return this._guideView._getGuideDomElement(somExpression, option); 17929 } else { 17930 return null; 17931 } 17932 }, 17933 17934 /** 17935 * File Attachment object 17936 * @typedef {object} GuideBridge~FileAttachementObject 17937 * @property {string} name name of the uploaded File 17938 * @property {string} path path of the uploaded File 17939 * @memberof GuideBridge 17940 * @since 6.0 17941 */ 17942 /** 17943 * Success callback that is called from {@link GuideBridge#getFileAttachmentsInfo} with the list of File 17944 * Attachments 17945 * @callback GuideBridge~FileAttachmentInfoHandler 17946 * @param {GuideBridge~FileAttachementObject[]} fileAttachementList list of file attachement objects uploaded 17947 * in the Form 17948 */ 17949 /** 17950 * The API provides a list containing File Names and File URLS for the Files Attached by the user using the 17951 * File Attachment component. The API is a asynchronous API and takes success handler which is called with 17952 * the list of File Names and URLs. 17953 * 17954 * @param {object} options Object containing the callback which will be invoked with the result of this API 17955 * @param {function} options.success success callback which will be invoked. The signature of the callback should 17956 * match the signature of {@link GuideBridge~FileAttachmentInfoHandler|FileAttachmentInfoHandler} 17957 * @param {object} [options.context] _this_ parameter in the success handler will point to this object 17958 * 17959 * @example <caption>Example usage of the getFileAttachmentsInfo API</caption> 17960 * guideBridge.getFileAttachmentsInfo({ 17961 * success:function(list) { 17962 * for(var i = 0; i< list.length; i++) { 17963 * console.log(list[i].name + " "+ list[i].path); 17964 * } 17965 * } 17966 * }); 17967 * @method 17968 * @memberof GuideBridge 17969 * @since 6.0 17970 * @deprecated since Forms As a Cloud Service 17971 * @instance 17972 */ 17973 getFileAttachmentsInfo : function (options) { 17974 console.error("getFileAttachmentsInfo API is not supported on Forms As a Cloud Service"); 17975 options.success.call(options.context, []); 17976 }, 17977 17978 /** 17979 * Syntax - argObject : {"options" : options to be passed to the callback, 17980 * "fileAttachmentsList" : fileAttachmentsList, 17981 * "fileUploadPath" :fileUploadPath 17982 * "callback" :callback, "errorCallback" :errorCallback} 17983 * @param {object}
17983 argObject Input object containing the callbacks that will be invoked 17984 * to provide the result of the API 17985 * @private 17986 * @memberof GuideBridge 17987 * @since 6.0 17988 */ 17989 _getGuideAttachments : function (argObject) { 17990 var fileDoms = [], 17991 fileNames = [], 17992 fileUrl = null, 17993 didSubmit = false, 17994 contextRoot = this._getContextRoot(), 17995 options = argObject.options, 17996 fileAttachmentsList = argObject.fileAttachmentsList, 17997 fileUploadPath = argObject.fileUploadPath, 17998 callback = argObject.callback, 17999 errorCallback = argObject.errorCallback, 18000 fileNameDomMap; 18001 18002 // In the case of draft, url comes with context root. Need to remove it so that correct 18003 // value gets stored in model 18004 if (contextRoot) { 18005 if (fileUploadPath.indexOf(contextRoot) === 0) { 18006 fileUploadPath = fileUploadPath.substring(contextRoot.length); 18007 } 18008 } 18009 // File attachment list is an array containing the list of file attachments 18010 // We need to fetch the fileNameDomMap even when there's no fileAttachmentsList as there can be 18011 // lazy loaded file attachment models as well. 18012 fileNameDomMap = this._juiceOutNameAndFileDomMap(fileAttachmentsList); 18013 fileDoms = fileNameDomMap.fileDom; 18014 fileNames = fileNameDomMap.fileName; 18015 if (fileDoms.length > 0) { 18016 // since there can be a dom element which is null, in case of draft reload, get the first 18017 // non null file dom 18018 var firstNonNullFileDom = _.indexOf(fileDoms, _.find(fileDoms, function (item) { 18019 return item !== null && !_.isString(item); 18020 })); 18021 // fileUploadPath doesn't contain the context path and hence we need to to pass the baseURL 18022 // FileUploader takes a _getUrl option which is baseUrl/contextPath 18023 if (firstNonNullFileDom !== -1 && fileUploadPath) { 18024 var uploaderPluginName = guideBridge.userConfig.uploaderPluginName || "adobeFileUploader"; 18025 fileUrl = fileDoms[firstNonNullFileDom][uploaderPluginName]("uploadFile", { 18026 'fileName' : fileNames, 18027 'fileDom' : fileDoms, 18028 'fileUploadPath' : fileUploadPath, 18029 'multiple' : true, 18030 _getUrl : guideBridge._getUrl("") 18031 }); 18032 18033 // The file url returned by file upload widget can contain context root. 18034 // Remove it so that correct value gets stored in model. 18035 if (contextRoot) { 18036 if (fileUrl.indexOf(contextRoot) === 0) { 18037 fileUrl = fileUrl.substring(contextRoot.length); 18038 } 18039 } 18040 18041 fileDoms[firstNonNullFileDom].one("adobeFileUploader.multipleFileUploaded", 18042 $.proxy(callback, { 18043 "attachments" : fileNames, 18044 "fileUrl" : fileUrl, 18045 "fileAttachmentsList" : fileAttachmentsList, 18046 "options" : options 18047 }) 18048 ); 18049 if (errorCallback) { 18050 fileDoms[firstNonNullFileDom].one("adobeFileUploader.fileUploadFailed", 18051 $.proxy(errorCallback, { 18052 "attachments" : fileNames, 18053 "fileUrl" : fileUrl, 18054 "fileAttachmentsList" : fileAttachmentsList, 18055 "options" : options 18056 }) 18057 ); 18058 } 18059 didSubmit = true; 18060 } 18061 // if fileUrl is not yet set, default it to fileUploadPath 18062 if (fileUrl === null && fileUploadPath) { 18063 fileUrl = fileUploadPath; 18064 } 18065 } 18066 if (!didSubmit) { 18067 // if there are no files attached, still call the callback to submit the json contents 18068 // if there is only one file attachment component with no files, in this case else is
18068important 18069 callback.apply({ 18070 "attachments" : fileNames, 18071 "fileUrl" : fileUrl, 18072 "fileAttachmentsList" : fileAttachmentsList, 18073 "options" : options 18074 }); 18075 } 18076 }, 18077 /** 18078 * Iterates over all the components in the Adaptive Form and invokes its {@link GuideNode#visit|visit} method 18079 * passing the _callback_ to the API. 18080 * 18081 * @summary Traverse all the components in the Adaptive Form and invoke callback function for each of the 18082 * component 18083 * @param {function} callback Function to be called for every Adaptive Form Component present 18084 * in the Form. The signature of the callback matches the signature of 18085 * {@link GuideNode~VisitorCallback|VisitorCallback} 18086 * @param {object} [context=window] _this_ object in the callback will point to this object 18087 * 18088 * @example <caption>Creating a list of all components having name <i>testName</i></caption> 18089 * var myList = [] 18090 * guideBridge.visit(function(cmp) { 18091 * if(cmp.name === "testName") { 18092 * myList.push[cmp]; 18093 * } 18094 * }}; 18095 * @method 18096 * @memberof GuideBridge 18097 * @since 6.0 18098 * @instance 18099 */ 18100 visit : function (callback, context) { 18101 this._guide.visit(callback, context || window); 18102 }, 18103 18104 /** 18105 * 18106 * Hides the elements of the specified class name. 18107 * In case of guideButton, it checks for type too, if no type is specified in "guideButton", then that button 18108 * cannot be made hidden 18109 * 18110 * @param className String representing the classname of the node 18111 * @param type [optional] type will be used only if the classname is "guideButton" 18112 * @private 18113 */ 18114 _hideElements : function (className, type) { 18115 var resultObject = new GuideResultObject(); 18116 // If guide dom not initialized, return 18117 if (!this._checkGuide(resultObject)) { 18118 return resultObject; 18119 } 18120 resultObject.completed = true; 18121 this.visit(function (node) { 18122 // if the class name is guide button only the use the type 18123 if (node.className === "guideButton") { 18124 if (node.type === type) { 18125 node.visible = false; 18126 } 18127 } else { 18128 // else just compare the classname and hide it 18129 if (node.className === className) { 18130 node.visible = false; 18131 } 18132 } 18133 }); 18134 return resultObject; 18135 }, 18136 18137 /** 18138 * In Adaptive Form there is a summary component to show the summary of submission. This API hides the parent 18139 * panel of the summary component. If the component is not present inside the Form, this operation doesn't do 18140 * anything 18141 * @summary Hides the panel that contains the summary component. 18142 * 18143 * @returns {GuideResultObject} the data property of GuideResultObject would be undefined. The API will fail if 18144 * the Form is not initialized which would be indicated by the {@link GuideResultObject#errors} property. 18145 * @memberof GuideBridge 18146 * @instance 18147 * @since 6.0 18148 */ 18149 hideSummaryPanel : function () { 18150 var resultObject = new GuideResultObject(); 18151 // If guide dom not initialized, return 18152 if (!this._checkGuide(resultObject)) { 18153 return resultObject; 18154 } 18155 resultObject.completed = true; 18156 this.visit(function (node) { 18157 if (node.className === "guideNode" && node.jsonModel['sling:resourceType'] === "fd/afaddon/components/summary") { 18158 node.panel.visible = false; 18159 } 18160 }); 18161 return resultObject; 18162 }, 18163 18164 _getFileAttachmentsList : function () { 18165 var fileAttachmentsList = []; 18166 this.visit(function (node) { 18167 if (node.className === "guideFileUpload") { 18168 fileAttachmentsList.push(node); 18169 } 18170 }); 18171 return fileAttachmentsList; 18172 }, 18173 18174 /** 18175 * @summary the captchaData which will be submitted to server for validation purposes. 18176 * @param captchaModel 18177 * @returns {object}
18177 object contains the captchaData which includes captcha service provider name, its SOM exp and 18178 * data coming from OOTB/third-party captcha widget. 18179 * @method 18180 * @memberof GuideBridge 18181 * @instance 18182 * @since 6.3 18183 */ 18184 _getCaptchaData : function (captchaModel) { 18185 if (captchaModel) { 18186 return { 18187 serviceType : captchaModel.captchaService, 18188 somExpression : captchaModel.somExpression, 18189 validationMessage : captchaModel.validateExpMessage, 18190 mandatoryMessage : captchaModel.mandatoryMessage, 18191 data : captchaModel.value 18192 }; 18193 } 18194 return {}; 18195 }, 18196 18197 /** 18198 * This function returns the additional action Field information that is required during submit. 18199 * 18200 * @returns {object} object having the action Field information. 18201 * @memberof GuideBridge 18202 */ 18203 _getAdditionalSubmitInfo : function () { 18204 var additionalSubmitInfo = {}, 18205 actionFieldDiv = $("#actionField"); 18206 var thankYouPage = this._getThankYouPageFromConfig(); 18207 if (typeof thankYouPage === "string") { 18208 document.getElementById(":redirect").value = thankYouPage; 18209 } 18210 var actionFields = actionFieldDiv.find('input') 18211 .each(function () { 18212 additionalSubmitInfo[$(this).attr("name")] = $(this).val(); 18213 if ($(this).attr("name") == "_guideValueMap" && $(this).val() == "yes") { 18214 var guideKeyValue = {}; 18215 window.guideBridge._guide._collectValues(guideKeyValue); 18216 additionalSubmitInfo['_guideValuesMap'] = JSON.stringify(guideKeyValue); 18217 } 18218 }); 18219 return additionalSubmitInfo; 18220 }, 18221 18222 /** 18223 * Gets the guideDom based on whether reducedJSON option is true or not. 18224 * If reducedJSON is true, only the white-listed properties are included. 18225 * 18226 * @returns {object} guideDom 18227 * @memberof GuideBridge 18228 */ 18229 18230 _getGuideDom : function (options) { 18231 var guideDom; 18232 if (options.reducedJSON) { 18233 guideDom = guideBridge._guide._getReducedJSON(); 18234 } else { 18235 guideDom = guideBridge._guide.jsonModel; 18236 } 18237 return guideDom; 18238 }, 18239 18240 /** 18241 * Creates the guideState and the liveXml. 18242 * 18243 * @param options {object} options should contain a GuideResultObject [{obj:"<GuideResultObject type>"}] 18244 * @memberof GuideBridge 18245 * Steps performed by the function - 18246 * 1) creates the xfaState 18247 * 2) creates the guideState that consists of guideDom, guideContext and additionalSubmitInfo 18248 * 3) creates guideLiveData 18249 * 4) adds xfaState and guideLiveData to the guideState 18250 * 18251 * @private 18252 */ 18253 _createGuideStateAndLiveXml : function (options) { 18254 var obj = new GuideResultObject(); 18255 // add the guideResultObject to options so that it can be passed to the success handler 18256 options.obj = obj; 18257 18258 if (!this._checkGuide(obj)) { 18259 return; 18260 } 18261 18262 var saveXfaXml = function (xfaResultObj) { 18263 if (!xfaResultObj.errors && xfaResultObj.completed) { 18264 xfaState.currentContext = {'data' : xfaResultObj.data}; 18265 } 18266 }; 18267 18268 obj.data = {}; 18269 var xfaState = null; 18270 if (this._isXfaGuide() && this._isValidXFAGuide()) { 18271 var xfaResultObject = null; 18272 if (options.reducedJSON) { 18273 //If reduceJson is asked, then xfaState should also be reduced by passing the diff and bSubmit flag to true 18274 xfaResultObject = window.formBridge.getFormState(true, true); 18275 } else { 18276 xfaResultObject = window.formBridge.getFormState(); 18277 } 18278 if (xfaResultObject.errors) { 18279 guideBridge._guide.logger().log("Error in getting Xfa State:" + JSON.stringify(xfaResultObject.getNextMessage())); 18280 alert(guidelib.util.GuideUtil.getLocalizedMessage("AF", guidelib.i18n.LogMessages["AEM-AF-901-001"])); 18281 } 18282 xfaState = xfaResultObject.data; 18283 } 18284 18285 var guideDom = guideBridge._getGuideDom(options); 18286 18287 //adding additionalSubmitInfo in the guideState. 18288 //additionalSubmitInfo contains the information about action fields. 18289 var additionalSubmitInfo = guideBridge._getAdditionalSubmitInfo(); 18290 //set the updated file attachment map in the customPropertyMap 18291 guideBridge.customContextProperty("fileAttachmentMap", JSON.stringify(this.getFileAttachmentMap())); 18292 var guideState = { 18293 guideDom : guideDom, 18294 //save renderContext in guide state to enable deferred submit even if guide is not open 18295 guideContext : guideBridge._guide.runtime.guideContext, 18296 additionalSubmitInfo : additionalSubmitInfo 18297 }; 18298 18299 if (guideBridge._guide.allLazyChildren.length > 0) { 18300 guideBridge._guide.internal.liveDataUtils.updateLiveData(); 18301 var listOfDirtyPanels = guideBridge._guide.internal.GuideDirtyMarkerAndVisitor.flatten
18301DirtyPanelMapToCSV(); 18302 if (listOfDirtyPanels.length > 0) { 18303 this.afSubmissionInfo("afDraft", listOfDirtyPanels); 18304 } 18305 // save live xml & xfa state as xml for restoration of lazy model on 'restore' 18306 guideState.guideLiveData = guideBridge._guide.internal.liveDataUtils.getLiveDataStr(); 18307 if (this._isXfaGuide() && this._isValidXFAGuide()) { 18308 formBridge.getDataXML({"success" : saveXfaXml}); // currently xfa restore relies on formBridge.getDataXML being sync 18309 } 18310 } 18311 obj.data.guideState = guideState; 18312 if (xfaState) { 18313 obj.data.guideState.xfaState = xfaState; 18314 } 18315 18316 }, 18317 18318 _updateAFSubmissionInfo : function (guide) { 18319 if (guideBridge.isGuideLoaded(true) && !guide) { 18320 var previousFocusSom = this._guideView._previousFocusItemSom; 18321 var previousItemModel = guideBridge.resolveNode(this._guideView._previousFocusItemSom); 18322 if (getOrElse(previousItemModel, "parent.className", undefined) === "guideToolbar") { 18323 previousFocusSom = previousItemModel.parent.parent.somExpression; 18324 } 18325 this.afSubmissionInfo("lastFocusItem", this._guideView.getSomOnNavigableAncestor(previousFocusSom)); 18326 } 18327 var newGuide = guide ? guide : guideBridge._guide; 18328 this.afSubmissionInfo("excludeFromDoR", newGuide._getExcludeFromDorMap()); 18329 // send state override on in cases when we have dor 18330 var stateOverrides = {}; 18331 if (newGuide.dorType && "none" !== newGuide.dorType) { 18332 stateOverrides = newGuide._getStateOverrideMap(); 18333 } 18334 this.afSubmissionInfo("stateOverrides", stateOverrides); 18335 // Add signers to af submission info 18336 this.afSubmissionInfo("signers", newGuide._getSigners()); 18337 18338 }, 18339 18340 /** 18341 * Adaptive Form stores its state in the form of JSON. The Files attached in the component are uploaded 18342 * onto the server and their paths are returned in the JSON state except in certain conditions mentioned below. 18343 * The API is an asynchronous call which calls the success and error handlers with the data. 18344 * 18345 * In the below mentioned scenarios the file will not be uploaded 18346 * * User doesn't have **write permissions** on the _fileUploadPath_ provided 18347 * * The _fileUploadPath_ property doesn't point to a node of type _**sling:Folder**_ 18348 * 18349 * @summary Retrieve the current state of Adaptive Form as json string 18350 * @param {object} options Input object containing the callbacks that will be invoked 18351 * to provide the result of the API 18352 * @param {function} [options.success] callback which receives the result of the API 18353 * in case of success. 18354 * {@link GuideResultObject#errors|errors} property as false. 18355 * @param {function} [options.error] callback which receives the result of the API in 18356 * case of failure. 18357 * {@link GuideResultObject#errors|errors} property as true. 18358 * @param {object} [options.context] _this_ object inside the _success_ and _error_ callback will point to this 18359 * object 18360 * @param {string} [options.fileUploadPath] controls whether the files in the File Attachment component have to be 18361 * uploaded or not. If _fileUploadPath_ is non null, only then file gets uploaded and the model's value is 18362 * updated with the file url 18363 * 18364 * @method 18365 * @memberof GuideBridge 18366 * @since 6.0 18367 * @instance 18368 */ 18369 getGuideState : function (options) { 18370 18371 // walk through the model to get the list of file attachment components 18372 var fileAttachmentsList = this._getFileAttachmentsList(); 18373 guideBridge._updateAFSubmissionInfo(); 18374 18375 if (guideBridge.isGuideLoaded(true)) { 18376 this.customContextProperty("lastFocusItem", this._guideView.getSomOnNavigableAncestor(this._guideView._previousFocusItemSom)); 18377 } 18378 18379 // Walk through the list of file Attachment components 18380 // and update the value of every item 18381 // Get the list of file Attachments 18382 if (options.fileUploadPath) { 18383 var optionArgument = {"options" : options, 18384 "fileAttachmentsList" : fileAttachmentsList, 18385 "fileUploadPath" : options.fileUploadPath, 18386 "callback" : window.guideBridge._collectFileUrls, 18387 "errorCallback" : window.guideBridge._fileUploadFailed}; 18388 18389 this._getGuideAttachments(optionArgument); 18390 } else { 18391 this._createGuideStateAndLiveXml(options); 18392 if (options.success) { 18393 options.success.call(options.context, options.obj); 18394 } 18395 } 18396 18397 }, 18398 18399 /** 18400 * Validates the Adaptive Form or it's specific panel and return the validation status. The API also moves 18401 * focus to first invalid element 18402 * @summary validate the entire Form or a component in Adaptive Form 18403 * @param {Field~ValidationError[]} errorList Input must be an empty array. The array will be filled with list 18404 * of Adaptive Form Components that failed validation. 18405 * @param {string}
18405 [somExpression] SOM Expression of the Guide Node for which validation should be triggered. 18406 * If not provided, it would validate the entire Adaptive Form 18407 * @param {boolean} [setFocus=true] If true, set focus to the first invalid element. 18408 * @returns {boolean} true if the component/form was valid, false otherwise 18409 * @method 18410 * @memberof GuideBridge 18411 * @since 6.0 18412 * @instance 18413 * @see Field#validate 18414 * @see Panel#validate 18415 */ 18416 validate : function (errorList, somExpression, setFocus, guide) { 18417 // guide parameter is not to be documented and it is meant for internal use only 18418 var guideNode = null, 18419 isFocusEnabled = _.isUndefined(setFocus) ? true : setFocus, 18420 ec = guidelib.util.ErrorConstants, 18421 validationContext, 18422 afContainer = guide ? guide : this._guide; // done, to keep this thread safe 18423 // get Json of all the dirty , non visited (templateJson missing from cache) 18424 if (afContainer.allLazyChildren.length > 0) { 18425 afContainer.guideLazyUtil.putDirtyToTemplateCacheIfMissing(afContainer); 18426 } 18427 if (somExpression) { 18428 guideNode = this.resolveNode(somExpression); 18429 // how to know if the panel is navigable from the model. We do not bring the nonNavigable property ? 18430 if (guideNode instanceof guidelib.model.GuidePanel) { 18431 validationContext = ec.CONTEXT_NAVIGATION; 18432 } 18433 } else { 18434 guideNode = afContainer; 18435 validationContext = ec.CONTEXT_SUBMISSION; 18436 } 18437 this.setValidationContext(validationContext); 18438 var status = false; 18439 if (!errorList) { 18440 errorList = []; 18441 } 18442 status = guideNode.validate(errorList); 18443 18444 try { 18445 // there can be errors in the user script, hence handling the exception gracefully, and resetting the global error state properly 18446 this._guide._triggerOnBridge("validationComplete", this._guide, status, "", errorList); 18447 if (!status && isFocusEnabled) { 18448 var errorSom = errorList[0]["som"]; 18449 18450 guideBridge._guide.on(guidelib.event.GuideModelEvent.LAZY_LOADED, function () { 18451 var errorField = guideBridge.resolveNode(errorSom); 18452 if (errorField) { 18453 errorField.validate(); 18454 } 18455 }, {}); 18456 18457 this.setFocus(errorSom); 18458 18459 guideBridge._guide.off(guidelib.event.GuideModelEvent.LAZY_LOADED); 18460 } 18461 18462 } catch (exception) { 18463 this._guide.logger().log(exception); 18464 } finally { 18465 // since the errors have been published reset the state back to normal 18466 //guidelib.runtime.errorManager.setGlobalError(false); 18467 this.unsetValidationContext(validationContext); 18468 return status; 18469 } 18470 18471 }, 18472 18473 // todo: submit behaviour should make sure that if the value of file upload 18474 /** 18475 * Adaptive Form can be restore in three ways 18476 * * by passing the JSON data obtained from {@link GuideBridge#getGuideState}. This can be done by setting 18477 * _**data**_ property . 18478 * * by passing a URL pointing to a resource that returns JSON/XML data that should be used. This can be done by setting 18479 * _**dataRef**_ property. The data can be obtained by calling the 18480 * {@link GuideBridge#getData|getData} API. 18481 * * by passing a URL pointing to a resource that returns JSON data obtained from {@link GuideBridge#getGuideState}. 18482 * This can be done by setting _**guideStatePathRef**_ property . 18483 * 18484 * When restoring from dataRef, only values and other properties, that are dependant on value, are restored. For 18485 * example, If a Field was hidden based on the click of a Button then 18486 * when restoring from data XML/JSON the Field will not remain hidden. 18487 * 18488 * **NOTE:** The _data_, _dataRef_ and _guideStatePathRef_ must not be null simultaneously and only one property 18489 * must be specified. Specifying more than one can lead to undesired results. 18490 * @summary restore/prepopulate the state of Adaptive Form from an earlier saved state 18491 * @param {object}
18491 options object containing the callbacks to be invoked on 18492 * success/failure and data from where to restore the object. 18493 * @param {function} [options.success] callback which receives the result of the API 18494 * in case of success 18495 * {@link GuideResultObject#errors|errors} property as false. 18496 * @param {function} [options.error] callback which receives the result of the API in 18497 * case of failure. 18498 * {@link GuideResultObject#errors|errors} property as true. 18499 * @param {object} [options.context] _this_ object inside the _success_ and _error_ callback will point to this 18500 * object. 18501 * @param {object} [options.data] It must be the value of the {@link GuideResultObject#data|data} property passed to 18502 * the _success_ handler of {@link GuideBridge#getGuideState|getGuideState} API. 18503 * @param {string} [options.dataRef] URL pointing to the data XML/JSON. 18504 * @param {string} [options.guideStatePathRef] URL pointing to the JSON state of Adaptive Form. 18505 * 18506 * @method 18507 * @memberof GuideBridge 18508 * @since 6.0 18509 * @instance 18510 * @example <caption>Restoring from JSON data</caption> 18511 * var jsonData; 18512 * guideBridge.getGuideState({ 18513 * success : function (guideResultObj) { 18514 * jsonData = guideResultObj.data; 18515 * }, 18516 * error : function (guideResultObj) { 18517 * // log error 18518 * } 18519 * }); 18520 * 18521 * // after some time or on click of a button or reloading the page 18522 * guideBridge.restoreGuideState({ 18523 * guideState : jsonData.guideState, 18524 * error : function (guideResultObject) { 18525 * // log the errors 18526 * } 18527 * }) 18528 * 18529 * @example <caption>Restoring from data XML/JSON</caption> 18530 * guideBridge.getData({ 18531 * success : function (guideResultObj) { 18532 * var data = guideResultObj.data; 18533 * //post the data to a server that saves it at say http://abc.com/my/data.xml 18534 * //or http://abc.com/my/data.json 18535 * }, 18536 * error : function (guideResultObj) { 18537 * // log the errors 18538 * } 18539 * }); 18540 * 18541 * // after some time or on click of a button or reloading the page 18542 * guideBridge.restoreGuideState({ 18543 * dataRef : "http://abc.com/my/data.xml", 18544 * error : function (guideResultObject) { 18545 * // log the errors 18546 * } 18547 * }) 18548 * 18549 * @example <caption>Restoring from URL to a JSON</caption> 18550 * guideBridge.getGuideState({ 18551 * success : function (guideResultObj) { 18552 * var json = guideResultObj.data; 18553 * //post the JSON to a server that saves it at say http://abc.com/my/data.json 18554 * }, 18555 * error : function (guideResultObj) { 18556 * // log the errors 18557 * } 18558 * }); 18559 * 18560 * // after some time or on click of a button or reloading the page 18561 * guideBridge.restoreGuideState({ 18562 * guideStatePathRef : "http://abc.com/my/data.json", 18563 * error : function (guideResultObject) { 18564 * // log the errors 18565 * } 18566 * }) 18567 **/ 18568 restoreGuideState : function (options) { 18569 var parameters, 18570 path; 18571 if (options && options.dataRef) { 18572 parameters = {"dataRef" : options.dataRef}; 18573 } else if (options && options.guideStatePathRef) { 18574 parameters = {"guideStatePathRef" : options.guideStatePathRef}; 18575 } 18576 // if parameters have DataRef or guideStatePathRef, a recursive call is made to restoreGuideState. 18577 if (parameters) { 18578 path = window.guideBridge.getGuidePath(); 18579 path = path + ".guidejson"; 18580 $.ajax({ 18581 url : path, 18582 type : "GET", 18583 async : false, 18584 cache : false, 18585 data : parameters, 18586 success : function (response) { 18587 //case where section information exist in guideState 18588 if (response.guideState && response.guideState.guideContext 18589 && response.guideState.guideContext.customPropertyMap 18590 && response.guideState.guideContext.customPropertyMap.sections 18591 && response.guideState.guideContext.customPropertyMap.sections.length > 0) { 18592 // todo: add safe check for string vs array 18593 window.guideBridge.customContextProperty.sections = response.guideState.guideContext.customPropertyMap.sections; 18594 } 18595 //passing the options again, but with DataRef or guideStatePathRef removed from it. 18596 window.guideBridge.restoreGuideState(_.extend( 18597 {}, 18598 options, 18599 { 18600 guideState : response.guideState, 18601 dataRef : undefined, 18602 guideStatePathRef : undefined 18603 } 18604 )); 18605 }, 18606 error : function (response) { 18607 window.guideBridge._guide.logger().log("Error: " + response); 18608 } 18609 }); 18610 return; 18611 } 18612 18613 /* 18614 * We have to merge the runtime guideContext with the guideContext passed in the guideState 18615 * so that no custom properties that were set in the guideState.guideContext are ignored. 18616 */ 18617 guidelib.__runtime__.guideContext = guidelib.__runtime__.guideContext || {}; 18618 if (guideBridge.isGuideLoaded()) { 18619 guideBridge._guide.runtime.guideContext = guideBridge._guide.runtime.guideContext || {}; 18620 } 18621 var gc = getOrElse(options, "guideState.guideContext", undefined); 18622 if (!_.isUndefined(options.guideState.guideContext)) { 18623 /* Runtime custom property map is set by external application and hence, shallow copy will set the value 18624 * as set externally. If no value was set, the guideState custom property map keys stay. 18625 */ 18626 _.extend(gc.customPropertyMap, guidelib.__runtime__.guideContext.customPropertyMap); 18627 if (guideBridge.isGuideLoaded()) { 18628 _.extend(gc.customPropertyMap, guideBridge._guide.runtime.guideContext.customPropertyMap); 18629 } 18630 } 18631 // not setting at guidelib runtime, but honoring if anyone has set customPropertyMap 18632 // through guidelib.runtime.guideContext directly 18633 if (guideBridge.isGuideLoaded()) { 18634 _.extend(guideBridge._guide.runtime.guideContext, gc); 18635 } 18636 18637 if (!this._guide) { 18638 this.storage = {}; 18639 this.storage.guideState = options.guideState; 18640 //NOCHECKMARX - This is error callback to be provided by the user of this API. 18641 this.storage.error = options.error; 18642 this.storage.success = options.success; 18643 this.storage.context = options.context; 18644 } else { 18645 this._playGuideJson(options); 18646 // Trigger the event 18647 // If guide has restore state, call sync guide node to html 18648 // Case 1: If this is called before view gets initialized, there would be no listener present, hence nothing would happen 18649 // Case 2: If it is called after view gets initialized(using restore guide state in mobile workspace), then the model would sync to view 18650 // using this event 18651 // If view is initialized, which means a listener would to MODEL_REFRESH would be set, hence just trigger the event for execution 18652 if (this._guideView) { 18653 this._guide._triggerEvent(guidelib.event.GuideModelEvent.MODEL_REFRESH, "jsonModel", null, null); 18654 } 18655 } 18656 18657 }, 18658 18659 /** 18660 * Adaptive Form can set data in three ways: 18661 * * by passing the JSON data obtained from {@link GuideBridge#getGuideState}. This can be done by setting 18662 * _**data**_ property . 18663 * * by passing a URL pointing to a resource that returns data JSON/XML that should be used. This can be done by setting 18664 * _**dataRef**_ property. The data can be obtained by calling the 18665 * {@link GuideBridge#getData|getData} API. 18666 * * by passing a URL pointing to a resource that returns JSON data obtained from {@link GuideBridge#getGuideState}. 18667 * This can be done by setting _**guideStatePathRef**_ property . 18668 * 18669 * When setting data from dataRef, only values and other properties, that are dependant on value, are set. For 18670 * example, If a Field was hidden based on the click of a Button in the data passed then 18671 * when setting data from XML/JSON the Field will not remain hidden. 18672 * 18673 * **NOTE:** The _data_, _dataRef_ and _guideStatePathRef_ must not be null simultaneously and only one property 18674 * must be specified. Specifying more than one can lead to undesired results. 18675 * @summary Populate the Adaptive Form from the data. 18676 * @param {object}
18676 options object containing the callbacks to be invoked on 18677 * success/failure and data from where to restore the object. 18678 * @param {function} [options.success] callback which receives the result of the API 18679 * in case of success 18680 * {@link GuideResultObject#errors|errors} property as false. 18681 * @param {function} [options.error] callback which receives the result of the API in 18682 * case of failure. 18683 * {@link GuideResultObject#errors|errors} property as true. 18684 * @param {object} [options.context] _this_ object inside the _success_ and _error_ callback will point to this 18685 * object. 18686 * @param {object} [options.data] It must be the value of the {@link GuideResultObject#data|data} property passed to 18687 * the _success_ handler of {@link GuideBridge#getGuideState|getGuideState} API. 18688 * @param {string} [options.dataRef] URL pointing to the data JSON/XML. 18689 * @param {string} [options.guideStatePathRef] URL pointing to the JSON state of Adaptive Form. 18690 * 18691 * @method 18692 * @memberof GuideBridge 18693 * @since 6.3 18694 * @instance 18695 * @example <caption>Setting data from JSON data</caption> 18696 * var jsonData; 18697 * guideBridge.getGuideState({ 18698 * success : function (guideResultObj) { 18699 * jsonData = guideResultObj.data; 18700 * }, 18701 * error : function (guideResultObj) { 18702 * // log the errors 18703 * } 18704 * }); 18705 * 18706 * guideBridge.setData({ 18707 * guideState : jsonData, 18708 * error : function (guideResultObject) { 18709 * // log the errors 18710 * } 18711 * }) 18712 * 18713 * @example <caption>Setting data from XML/JSON</caption> 18714 * guideBridge.getData({ 18715 * success : function (guideResultObj) { 18716 * var data = guideResultObj.data; 18717 * //post the XML/JSON to a server that saves it at say http://abc.com/my/data.xml 18718 * //or http://abc.com/my/data.json 18719 * }, 18720 * error : function (guideResultObj) { 18721 * // log the errors 18722 * } 18723 * }); 18724 * 18725 * guideBridge.setData({ 18726 * dataRef : "http://abc.com/my/data.xml", 18727 * error : function (guideResultObject) { 18728 * // log the errors 18729 * } 18730 * }) 18731 * 18732 * @example <caption>Setting data from URL to a JSON</caption> 18733 * guideBridge.getGuideState({ 18734 * success : function (guideResultObj) { 18735 * var json = guideResultObj.data; 18736 * //post the JSON to a server that saves it at say http://abc.com/my/data.json 18737 * }, 18738 * error : function (guideResultObj) { 18739 * // log the errors 18740 * } 18741 * }); 18742 * 18743 * guideBridge.setData({ 18744 * guideStatePathRef : "http://abc.com/my/data.json", 18745 * error : function (guideResultObject) { 18746 * // log the errors 18747 * } 18748 * }) 18749 **/ 18750 setData : function (options) { 18751 guideBridge.restoreGuideState(options); 18752 }, 18753 18754 /* 18755 * @private 18756 */ 18757 _getStorage : function () { 18758 var storage = null; 18759 if (this.storage) { 18760 // Get the storage 18761 storage = this.storage; 18762 this.storage = null; 18763 } 18764 return storage; 18765 }, 18766 18767 getGuideContext : function () { 18768 var obj = new GuideResultObject(); 18769 obj.data = jQuery.extend(true, {}, (this._guide ? this._guide.runtime.guideContext : null)); 18770 return obj; 18771 }, 18772 18773 _getContextRoot : function () { 18774 return this.userConfig["contextPath"]; 18775 }, 18776 18777 _getEnableFocusOnFirstField : function () { 18778 var renderConfig = this.userConfig.renderConfig || {}, 18779 enableFocusOnFirstField = renderConfig.enableFocusOnFirstField === undefined ? true : renderConfig.enableFocusOnFirstField, 18780 // convert "true"/"false" strings to boolean too 18781 enableFocusOnFirstFieldAsBoolean = enableFocusOnFirstField === 'true' || (enableFocusOnFirstField === 'false' ? false : enableFocusOnFirstField); 18782 // default value is true 18783 return enableFocusOnFirstFieldAsBoolean; 18784 }, 18785 18786 _updateAjaxUrl : function (baseUrl) { 18787 if (this.hostName === "server") { 18788 $.ajaxPrefilter(function (options, originalOptions, jqXHR) { 18789 // 'Rebase' the URL if required. 18790 var thisUrl = options.url; 18791 if ((thisUrl.lastIndexOf('http://', 0) !== 0) && (thisUrl.lastIndexOf('https://', 0) !== 0)) { 18792 // thisUrl is relative. 18793 // thisUrl may or may not begin with slash
18794 // encoding taken care by the ajax call 18795 if (thisUrl.indexOf("/") === 0) { 18796 // if begins with slash 18797 thisUrl = baseUrl + thisUrl; 18798 } else { 18799 thisUrl = baseUrl + "/" + thisUrl; 18800 } 18801 options.url = thisUrl; 18802 } 18803 }); 18804 18805 // Native XHR Wrapper 18806 var originalOpen = XMLHttpRequest.prototype.open; 18807 XMLHttpRequest.prototype.open = function(method, url) { 18808 if ((url.lastIndexOf('http://', 0) !== 0) && (url.lastIndexOf('https://', 0) !== 0)) { 18809 // url is relative 18810 if (url.indexOf("/") === 0) { 18811 url = baseUrl + url; 18812 } else { 18813 url = baseUrl + "/" + url; 18814 } 18815 } 18816 originalOpen.apply(this, arguments); 18817 }; 18818 } 18819 }, 18820 18821 _getUrl : function (url) { 18822 var baseUrl = this.userConfig["baseUrl"], 18823 contextPath = this.userConfig["contextPath"]; 18824 if (baseUrl) { 18825 return baseUrl + url; 18826 } else if (contextPath && contextPath !== "/" && url.indexOf(contextPath) !== 0 && (url.length === 0 || url.indexOf("/") === 0)) { 18827 //if url does not have contextPath and starts with /, pre-pend contextPath 18828 // Also url.length check because I need to pass "" to getUrl and get context path 18829 return contextPath + url; 18830 } 18831 return url; 18832 }, 18833 18834 _getGuidePathUrl : function (urlSuffix, guidePath) { 18835 // guidePath here refers to the path got from json state of guide 18836 // we use this path, if there is no guidePath set in guidelib.runtime.guideContext, cases where guide is not initialized but 18837 // guideBridge is present 18838 var path = guidePath || this.getGuidePath(), 18839 url = path + (urlSuffix || ""); 18840 return this._getUrl(url); 18841 }, 18842 18843 /** 18844 * @summary Returns the path which refers to the location of 18845 * the content resource of adaptive form container 18846 * @returns {String} Path to the content resource of the adaptive form container 18847 * @method 18848 * @memberof GuideBridge 18849 * @since 6.5 18850 * @instance 18851 */ 18852 getGuidePath : function () { 18853 var guideContext = this.getGuideContext().data; 18854 if (guideContext && guideContext.hasOwnProperty("guidePath")) { 18855 return guideContext["guidePath"]; 18856 } 18857 return null; 18858 }, 18859 18860 /** 18861 * @summary Given a somExpression, return the {@link GuideNode} having the same somExpression. 18862 * @param {string} somExpression somExpression of the Adaptive Form component 18863 * @returns {GuideNode} GuideNode matching the som expression or null if not found 18864 * @method 18865 * @memberof GuideBridge 18866 * @since 6.0 18867 * @instance 18868 * @see GuideNode#somExpression 18869 */ 18870 resolveNode : function (somExpression) { 18871 return this._guide.resolveNode(somExpression); 18872 }, 18873 /* 18874 * Internal API. Should be used carefully. 18875 */ 18876 _resolveId : function (id) { 18877 var node = this._guide._modelTemplateCacheStore.getModel(id); 18878 return node; 18879 }, 18880 18881 /** 18882 * Helper method for accesibility announcements 18883 * Is part of the fix for FORMS-7071 (CQ-4276669) 18884 */ 18885 _ariaLiveAnnouncement : function (text) { 18886 var ariaLiveElement = $("#ariaLiveElement"); 18887 setTimeout(function() { 18888 $(ariaLiveElement).text(text); 18889 return (setTimeout(function() { 18890 $(ariaLiveElement).text(""); 18891 }, 2000)) 18892 }, 500); 18893 }, 18894 18895 /** 18896 * Invokes {@link Field#resetData}
18896 API for all the Fields inside the Form to reset their values to default 18897 * @summary Reset the values of all the Fields to their default values. 18898 * 18899 * @method 18900 * @memberof GuideBridge 18901 * @instance 18902 * @since 6.0 18903 */ 18904 reset : function () { 18905 if (window.xfalib && window.xfalib.runtime && window.xfalib.runtime.xfa) { 18906 var xfa = window.xfalib.runtime.xfa; 18907 xfa.host.resetData(); 18908 } 18909 this._guide.resetData(); 18910 18911 if (this._guide.internal.liveDataUtils.isLiveDataInitialized()) { 18912 this._guide.internal.liveDataUtils.updateLiveData(); 18913 } 18914 18915 var guideDirtyMarkerAndVisitor = this._guide.internal.GuideDirtyMarkerAndVisitor; 18916 guideDirtyMarkerAndVisitor.visitMap = guidelib.model.util.CommonUtils.createMap(this._guide.allLazyChildren, 0); 18917 18918 this._ariaLiveAnnouncement(guidelib.i18n.strings["formHasBeenReset"]); 18919 }, 18920 18921 _getPreviousFocus : function () { 18922 return this._guideView._previousFocusItemSom; 18923 }, 18924 18925 /** 18926 * Returns the somExpression of the current {@link Panel} or current {@link Field} in Focus. The API can also 18927 * be used to get the somExpression of the Navigable Panel that contains the current Element in Focus. 18928 * 18929 * @summary return the somExpression of the {@link Panel} or {@link Field} that is currently in focus 18930 * @param {object} options configuration to be passed to the API to get the desired result 18931 * @param {?string} [options.focusOption] Currently the following value of this option are supported 18932 * * `navigablePanel`: if one wants to get the somExpression of the Navigable Panel 18933 * @returns {string} somExpression of Adaptive Form component representing the field or panel. 18934 * @method 18935 * @memberof GuideBridge 18936 * @instance 18937 * @since 6.0 18938 * @see {GuideNode#somExpression} 18939 * @example 18940 * guideBridge.getFocus({"focusOption": "navigablePanel"}) 18941 */ 18942 getFocus : function (options) { 18943 var focusOption; 18944 if (_.isUndefined(options)) { 18945 return this._guideView.currentFocusItemSom; 18946 } 18947 if ((focusOption = getOrElse(options, "focusOption", null)) === "navigablePanel") { 18948 return this._guideView._lastFocussedPanelForNonActionFields; 18949 } 18950 this._guide.logger().log("Invalid Focus option.", focusOption); 18951 }, 18952 18953 /** 18954 * The API is equivalent to calling 18955 * `guideBridge.setFocus(options.somExpression, options.focusOption, options.runCompletionScript)` 18956 * @summary An alternate signature to the {@link GuideBridge#setFocus|setFocus} API 18957 * @method setFocus 18958 * @memberof GuideBridge 18959 * @instance 18960 * @since 6.1 FP1 18961 * @param {object} options options passed to the API 18962 * @param {string} options.somExpression somExpression to set the focus to 18963 * @param {string} options.focusOption item inside the Panel to focus to 18964 * @param {string} options.runCompletionScript whether to run the completion script or not. 18965 * @return {boolean} true if the focus was set successfully otherwise false. 18966 */ 18967 18968 /** 18969 * In Adaptive Form one can focus a Field/Panel. Setting focus on a Panel means setting focus to its first 18970 * child. This can be controlled using the _focusOption_ provided in this API. 18971 * 18972 * The API provides two mechanism to focus a Field/Panel. 18973 * * **Direct** : By providing the somExpression of the Field/Panel. If the somExpression of Panel is provided, 18974 * then based on the focusOption one of its child (or their child) is set to Focus 18975 * * **Indirect** : By providing an item's relative position inside a Panel, first or last item inside of a 18976 * Panel, sibling of current focussed Item of a Panel, etc. If the item is a Panel then the First Item of 18977 * that Panel (if that is again a Panel, this process continues until a Field is found) is activated. 18978 * 18979 * The first way is trivial, by providing the _somExpression_ of a {@link Field} to the API, the focus will be 18980 * set to the Field. 18981 * 18982 * If that Field is inside a Panel that is not currently open because of tabbed/wizard navigation, then that tab 18983 * would be opened and focus would be set to the Field/Panel. 18984 * 18985 * The API can also execute the 18986 * [completion expression](https://helpx.adobe.com/aem-forms/6-1/adaptive-form-expressions.html#main-pars_header_8) 18987 * of the current Panel and only if the expression returns true set focus to the required element. 18988 * 18989 * **Note:** 18990 * * If _focusOption_ is either of nextItemDeep or prevItemDeep then _somExpression_ parameter must not be 18991 * passed. Otherwise the API will throw an exception 18992 * * If _somExpression_ points to a {@link Field} and _focusOption_ is not _nextItemDeep_ or _prevItemDeep_ then 18993 * _focusOption_ is ignored. 18994 * 18995 * @summary Sets focus to a {@link Field} or {@link Panel} 18996 * @param {?string} somExpression SOM Expression of the Adaptive Form Field or Panel which has to be activated. 18997 * @param {string} [focusOption=firstItem] The option provides the mechanism to focus onto an sibling of the 18998 * current active item. 18999 * * **_firstItem_** - Focuses to the first focusable item of the Panel whose _SOM Expression_ is provided 19000 * * **_lastItem_** - Focuses to the last focusable item of the Panel whose _SOM Expression_ is provided 19001 * 19002 * If either the _firstItem_ or _lastItem_ is a Panel, then the _firstItem_ of that Panel (until a Field is 19003 * found) is set to Focus. 19004 * 19005 * * **_nextItem_** - Next sibling component of the current active Item of the Panel whose _somExpression_ is 19006 * provided. It is equivalent to the result of `panel.navigationContext.nextItem` API. 19007 * * **prevItem** - Previous sibling component of the current active Item of the Panel show _somExpression_ is 19008 * provided. It is equivalent to the result of `panel.navigationContext.prevItem` API. 19009 * 19010 * * **_nextItemDeep_** - Focus is set to the next Navigable Panel of root Panel in DFS Order 19011 * * **_prevItemDeep_** - Focus is set to the next Navigable Panel of root Panel in DFS Order 19012 * @param {boolean} [runCompletionScript=false] indicating whether to execute the completion expression or not. 19013 * @returns {boolean} true if the focus was set to requested field successfully otherwise false 19014 * @method 19015 * @memberof GuideBridge 19016 * @since 6.0 19017 * @instance 19018 * @example 19019 * setFocus(somExpression); // Focus is set to the specified somExpression. 19020 * setFocus(this.panel.somExpression,'nextItem',true); // Focus is set to next item in the Panel. 19021 * setFocus(null,'nextItemDeep',true); // Focus is set to next navigable Panel in rootPanel 19022 */ 19023 setFocus : function (somExpression, focusOption, runCompletionScript) { 19024 var options, 19025 focusDone, 19026 originalSkipFieldFocus; 19027 if (_.isObject(somExpression)) { 19028 options = somExpression; 19029 } else { 19030 options = { 19031 somExpression : somExpression, 19032 focusOption : focusOption, 19033 runCompletionScript : runCompletionScript 19034 }; 19035 } 19036 try { 19037 originalSkipFieldFocus = this._guideView.skipFieldFocus; 19038 /** 19039 * Setting of this._guideView.skipFieldFocus was added for issue LC-3911361 19040 * Here we set a skipFieldFocus property for gudeContainerView, which prevents 19041 * actual 'input' / widget focus. This was done to prevent opening of keyboard or dropdown spinner 19042 * or date picker.. in case of swipe and use of deep navigators in mobile view of Adaptive Form. 19043 * 19044 * when user validates Adaptive Form, skipFieldFocus is set to options.skipFieldFocus based on somExpression 19045 * which has default value of'undefined' else the skipFieldFocus set to the negated value of global variable 19046 * enableFocusOnFirstField to enable/disable focus on first field of Adaptive Form. 19047 */ 19048 var fallbackSkipFieldFocus = !this._guide.enableFocusOnFirstField; 19049 if (!fallbackSkipFieldFocus) { 19050 fallbackSkipFieldFocus = !guideBridge._getEnableFocusOnFirstField(); 19051 } 19052 this._guideView.skipFieldFocus = options.somExpression ? options.skipFieldFocus : fallbackSkipFieldFocus; 19053 focusDone = this._guideView.setFocus(options); 19054 } finally { 19055 this._guideView.skipFieldFocus = originalSkipFieldFocus; //moving back to original state 19056 } 19057 //TODO: need a more common place to do that. 19058 if (!this._guide._currentContext) { 19059 this._guide.runPendingExpressions(); 19060 } 19061 return focusDone; 19062 }, 19063 19064 /** 19065 * Loads the lazy fragment specified by somExpression 19066 * @param {string} somExpression somexpression of the lazy loaded fragment 19067 * @param {object} options options to control the behaviour of loadLazyFragment API. 19068 * @param {object} [options.async] options to control if the fragment is to be loaded lazily 19069 * @param {function} [options.error] callback which receives the result of the API in 19070 * case of failure. 19071 * @method 19072 * @memberof GuideBridge 19073 * @since 6.4 19074 * @instance 19075 * @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 19076 * would load both</caption> 19077 * guideBridge.loadLazyFragment("x[0].y[0].z[0]"); 19078 * 19079 */ 19080 loadLazyFragment : function (somExpression, options) { 19081 options = options || {}; 19082 if (!_.isUndefined(somExpression)) { 19083 var relativeSom = guidelib.util.GuideUtil.relativeSom(this._guide.rootPanel.somExpression, somExpression); 19084 if (relativeSom) { 19085 var somTokens = relativeSom.split("."); 19086 var currItem = this._guide.rootPanel; 19087 _.each(somTokens, function (qName, index) { 19088 if (currItem != null) { 19089 var arr = currItem._findChildren(qName, false); 19090 if (arr.length > 0) { 19091 var node = arr[0]; 19092 if (node && node._lazyReference && !node._itemsLoaded) { 19093 this._guide.internal.liveDataUtils.updateLiveData(); 19094 if (options.async) { 19095 var successFunc = (function () { 19096 return function (complete) { 19097 if (options.success) { // Check if success callback exists 19098 options.success.call(this, {lazyLoadingComplete: complete}); 19099 } 19100 } 19101 }(index === somTokens.length - 1)) 19102 } 19103 node._loadLazyFragment(options); 19104 } 19105 currItem = options.async === true ? null : node; 19106 } else { 19107 currItem = null; 19108 } 19109 } 19110 }, this); 19111 } 19112 } 19113 }, 19114 19115 /** 19116 * Pre-loads models for all lazy loaded fragments without creating views or fetching HTML. 19117 * This allows existing user scripts to access lazy fragment fields immediately at form initialization 19118 * without waiting for user navigation. The actual view creation and HTML loading happens on-demand 19119 * when the user navigates to the lazy fragment, optimizing both initialization time and runtime performance. 19120 * 19121 * Note: This API should be called after the guide model is initialized but before view creation. 19122 * Use {@link GuideBridge#_modelConnect|_modelConnect} to ensure proper timing. 19123 * 19124 * IMPORTANT LIMITATION: Global bound fields in lazy fragments will NOT receive their prefilled values 19125 * when using this API, because it executes before prefill data is applied. If your lazy fragments contain 19126 * global bound fields that need prefill data, you have two options: 19127 * 1. Do not use this API and rely on on-demand lazy loading 19128 * 2. Manually apply prefill values to these fields after calling this API 19129 * 19130 * @summary Pre-loads lazy fragment models from cache to ensure script compatibility 19131 * @method 19132 * @memberof GuideBridge 19133 * @since 6.5 19134 * @instance 19135 * @param {Object} [options] - Optional configuration 19136 * @param {Function} [options.preFetch] - Callback invoked before loading models (e.g., show loading indicator). Registered for reuse during subsequent lazy loads. 19137 * @param {Function} [options.postFetch] - Callback invoked after loading models (e.g., hide loading indicator). Registered for reuse during subsequent lazy loads. 19138 * @example <caption>Pre-load all lazy fragment models during form initialization</caption> 19139 * window.guideBridge._modelConnect(function() { 19140 * this.loadAllLazyFragmentModels(); 19141 * }); 19142 * @example <caption>Using bridgeInitializeStart event</caption> 19143 * window.addEventListener("bridgeInitializeStart", function(evnt) { 19144 * var gb = evnt.detail.guideBridge; 19145 * gb._modelConnect(function() { 19146 * gb.loadAllLazyFragmentModels(); 19147 * }); 19148 * }); 19149 * @example <caption>With custom loading callbacks</caption> 19150 * window.guideBridge._modelConnect(function() { 19151 * this.loadAllLazyFragmentModels({ 19152 * preFetch: function() { $("#customLoader").show(); }, 19153 * postFetch: function() { $("#customLoader").hide(); } 19154 * }); 19155 * }); 19156 */ 19157 loadAllLazyFragmentModels : function (options) { 19158 var guide = this._guide; 19159 options = options || {}; 19160 19161 if (!guide) { 19162 this.logger().error("AF", "Guide model is not initialized"); 19163 return; 19164 } 19165 19166 // Default loading callbacks (same as used in _loadLazyFragment) 19167 var defaultPreFetch = function () { 19168 var loadingPage = document.getElementById("loadingPage"); 19169 if (loadingPage) { 19170 loadingPage.classList.add("guideLoading"); 19171 } 19172 }; 19173 var defaultPostFetch = function () { 19174 var loadingPage = document.getElementById("loadingPage"); 19175 if (loadingPage) { 19176 loadingPage.classList.remove("guideLoading"); 19177 } 19178 }; 19179 19180 // Register callbacks for reuse during subsequent lazy loads (handleVisibleChanged) 19181 // These callbacks will be invoked when lazy panels are auto-loaded on
19181navigation 19182 // Use provided callbacks, or preserve existing, or fall back to defaults 19183 guide._lazyLoadCallbacks = { 19184 preFetch: options.preFetch || (guide._lazyLoadCallbacks && guide._lazyLoadCallbacks.preFetch) || defaultPreFetch, 19185 postFetch: options.postFetch || (guide._lazyLoadCallbacks && guide._lazyLoadCallbacks.postFetch) || defaultPostFetch 19186 }; 19187 19188 // Invoke preFetch callback (e.g., show loading indicator) 19189 var preFetchCallback = options.preFetch || defaultPreFetch; 19190 if (typeof preFetchCallback === 'function') { 19191 preFetchCallback(); 19192 } 19193 19194 try { 19195 // Mark dirty panels and ensure template cache is populated 19196 if (guide.allLazyChildren && guide.allLazyChildren.length > 0) { 19197 window.guidelib.model.markDirtyPanels(guide.allLazyChildren, "", [], guide); 19198 19199 if (guide.guideLazyUtil) { 19200 guide.guideLazyUtil.putDirtyToTemplateCacheIfMissing(guide); 19201 } 19202 } 19203 19204 // Visit all fields and pre-load lazy fragment models 19205 this.visit(function (field) { 19206 // Check if this is a lazy reference that hasn't been loaded yet 19207 if (field._lazyReference && 19208 window.guidelib.util.GuideUtil.isLazyJson(field.jsonModel) && 19209 (!field._children || field._children.length === 0)) { 19210 19211 var modelTemplateCacheStore = guide._modelTemplateCacheStore, 19212 templateJson, 19213 templateId = field.templateId, 19214 uniquePrefix; 19215 19216 // Try to get JSON from cache 19217 templateJson = modelTemplateCacheStore._getTemplate(templateId, true); 19218 19219 if (templateJson && templateJson.items) { 19220 // Generate unique prefix if parent is repeatable 19221 if (field._ancestorRepeatable) { 19222 uniquePrefix = window.guidelib.util.GuideUtil.generateUID(); 19223 } 19224 19225 // Only embed model - no HTML, no view creation 19226 // This allows user scripts to access fields immediately 19227 // View and HTML will be loaded on-demand when user navigates to this panel 19228 field._embedJson(templateJson.items, uniquePrefix); 19229 19230 // Note: We intentionally do NOT call field.prepare() here 19231 // prepare() executes initScript immediately, but initScript should run AFTER prefill data 19232 // is applied (which happens later in the initialization sequence). Calling prepare() here 19233 // would break the normal initialization order. The prepare() call will happen later in 19234 // _postProcessLazyLoad when the fragment is actually loaded on-demand, maintaining the 19235 // correct sequence: model creation -> prefill -> playLiveData -> prepare (with initScript). 19236 19237 // Note: We intentionally do NOT set _itemsLoaded here 19238 // _itemsLoaded indicates that BOTH model AND view are fully loaded 19239 // Since we've only loaded the model, we leave it undefined 19240 // This signals to _loadLazyFragment that HTML and view still need to be fetched 19241 } 19242 } 19243 }); 19244 } catch (error) { 19245 // Log error but ensure postFetch callback is always invoked in finally block 19246 window.console && console.error("Error while loading lazy fragment models:", error); 19247 } finally { 19248 // Invoke postFetch callback (e.g., hide loading indicator) 19249 // This is in finally block to ensure it's always called, even if an error occurs above 19250 var postFetchCallback = options.postFetch || defaultPostFetch; 19251 if (typeof postFetchCallback === 'function') { 19252 postFetchCallback(); 19253 } 19254 } 19255 }, 19256 19257 /* 19258 * Get the download link of signed document set by signing service. 19259 * @return: url from where the signed document can be accessed, empty in case its not set by signing service. 19260 */ 19261 getSignedDocDownloadLink : function () { 19262 var url = ""; 19263 if (!_.isUndefined(FD) 19264 && !_.isUndefined(FD.AFaddon) 19265 && !_.isUndefined(FD.AFaddon.Signing) 19266 && !_.isUndefined(FD.AFaddon.Signing.signedDocDownloadLink)) { 19267 url = FD.AFaddon.Signing.signedDocDownloadLink; 19268 } 19269 return url; 19270 }, 19271 19272 /* 19273 If true is passed to the function then it checks for model and view both, 19274 if false or no parameter is passed, then it checks the model only. 19275 */ 19276 isGuideLoaded : function (complete) { 19277 if (complete) { 19278 return !_.isEmpty(window.guideBridge._guide && window.guideBridge._guideView); 19279 } 19280 return !_.isEmpty(window.guideBridge._guide); 19281 }, 19282 19283 _doInternalSubmit : function (options) { 19284 if (options.excludeFormState) { 19285 var submissionInfo = options.guideState.data.guideState.guideContext.afSubmissionInfo; 19286 if (submissionInfo && submissionInfo.hasOwnProperty('lastFocusItem')) { 19287 submissionInfo.lastFocusItem = undefined; 19288 } 19289 } 19290 // Make a clone of options so that original options are not modified. 19291 // Remove additionalSubmitInfo from the guideState so that no extra information 19292 // is sent to the server. 19293 var clonedGuideState = JSON.parse(JSON.stringify(options.guideState)); 19294 if (!_.isEmpty(clonedGuideState.data.guideState.additionalSubmitInfo)) { 19295 clonedGuideState.data.guideState.additionalSubmitInfo = {}; 19296 } 19297 var guideState = clonedGuideState, 19298 strContent = this.getMultipartData({ 19299 guideState : JSON.stringify(guideState.data), 19300 dorData : options.dorData || false, 19301 _charset_ : "UTF-8" 19302 }), 19303 // check if guide state is present, if yes get guide path from guide state 19304 // Specifically written for mobile workspace to getDataXML from current json state 19305 guidePath = ((guideState && guideState.data) ? guideState.data.guideState.guideContext.guidePath : null); 19306 19307 $.ajax({ 19308 url : this._getGuidePathUrl(".af.internalsubmit.jsp", guidePath), 19309 type : "POST", 19310 async : options.async || false, 19311 contentType : "multipart/form-data; charset=UTF-8; boundary=" + strContent[0], 19312 data : strContent[1], 19313 success : options.success, 19314 error : options.error 19315 }); 19316 }, 19317 19318 _submitInternal : function (options) { 19319 var self = this; 19320 options = options || {}; 19321 if (!options.guideState) { 19322 this.getGuideState({ 19323 "diff" : "diff", 19324 "fileUploadPath" : options.fileUploadPath, 19325 "success" : function (guideState) { 19326 self._doInternalSubmit({ 19327 guideState : guideState, 19328 success : options.success, 19329 error : options.error, 19330 async : options.async, 19331 excludeFormState : options.excludeFormState, 19332 dorData : options.dorData 19333 }); 19334 }, 19335 "error" : options.error, 19336 reducedJSON : true 19337 }); 19338 } else { 19339 this._doInternalSubmit({ 19340 guideState : options.guideState, 19341 success : options.success, 19342 error : options.error, 19343 async : options.async, 19344 excludeFormState : options.excludeFormState, 19345 dorData : options.dorData 19346 }); 19347 } 19348 }, 19349 19350 getMultipartData : function (data) { 19351 //Start multipart formatting 19352 var initBoundary = this.randomString(); 19353 var strBoundary = "--" + initBoundary; 19354 var strMultipartBody = ""; 19355 var strCRLF = "\r\n"; 19356 19357 //Create multipart for each element of the form 19358 for (var key in data) { 19359 if (data.hasOwnProperty(key)) { 19360 var value = _.isObject(data[key]) ? JSON.stringify(data[key]) : data[key]; 19361 strMultipartBody += 19362 strBoundary + 19363 strCRLF + 19364 "Content-Disposition: form-data; name=\"" + key + "\"" + 19365 strCRLF + 19366 strCRLF + 19367 value + 19368 strCRLF; 19369 } 19370 } 19371 //End the body by delimiting it 19372 strMultipartBody += strBoundary + "--" + strCRLF; 19373 //Return boundary without -- and the multipart content 19374 return [initBoundary, strMultipartBody]; 19375 }, 19376 19377 randomString : function () { 19378 var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz"; 19379 var string_length = 8; 19380 var randomstring = ''; 19381 for (var i = 0; i < string_length; i++) { 19382 var rnum = Math.floor(Math.random() * chars.length); 19383 randomstring += chars.substring(rnum, rnum + 1); 19384 } 19385 return randomstring; 19386 }, 19387 19388 /* 19389 * Get the file Attachment map that contains a mapping of som expression vs path when files have been uploaded 19390 * and som expression vs name when the files have not yet been uploaded . 19391 * @return: map of som expression and paths. 19392 * @private 19393 */ 19394 getFileAttachmentMap : function () { 19395 var fileAttachmentMap = {}, 19396 fileAttachmentsList = window.guideBridge._getFileAttachmentsList(); 19397 for (var i = 0; i < fileAttachmentsList.length; i++) { 19398 var node = fileAttachmentsList[i]; 19399 if (!_.isEmpty(node.fileAttachment.value)) { 19400 fileAttachmentMap[node.somExpression] = node.fileAttachment.value; 19401 } 19402 } 19403 19404 var lazyAttachmentMap = this._guide.internal.liveDataUtils._getLazyAttachmentMap(); 19405 _.each(lazyAttachmentMap, function (mapObject, key) { 19406 fileAttachmentMap[key] = mapObject.value; 19407 }); 19408 return fileAttachmentMap; 19409 }, 19410 19411 /* 19412 * sets the value of the file attachment component based on the map that is passed. 19413 * @private 19414 */ 19415 putFileAttachmentMap : function (fileAttachmentMap) { 19416 _.each(fileAttachmentMap, function (value, som) { 19417 var node = guideBridge.resolveNode(som); 19418 node.fileAttachment.value = value; 19419 }); 19420 }, 19421 19422 _appendFileAttachmentsToFormData : function (dataForm, fileNameDomMap, fileAttachmentsList) { 19423 var fileNamesIndex, 19424 fileDoms = fileNameDomMap.fileDom, 19425 fileNames = fileNameDomMap.fileName,
19426 faPromise = {}, 19427 rejectedFileNames = [], 19428 isIOS = guidelib.util.GuideUtil._isIOS(), 19429 createUnorderedList = function (list, bulletChar) { 19430 var result = ""; 19431 for (var i = 0; i < list.length; ++i) { 19432 result += bulletChar + " " + list[i] + "\n"; 19433 } 19434 return "\n" + result; 19435 }, 19436 throwException = function (fileNames) { 19437 if (fileNames && fileNames.length > 0) { 19438 throw guidelib.util.GuideUtil.getLocalizedMessage("AF", guidelib.i18n.LogMessages["AEM-AF-901-024"], [createUnorderedList(fileNames, "•")]); 19439 } 19440 }; 19441 for (fileNamesIndex = 0; fileNamesIndex < fileNames.length; fileNamesIndex++) { 19442 // multiple files inside one filedom element & draft save case is handled. 19443 var currentFileNames = fileNames[fileNamesIndex].split("\n"); 19444 for (var fileIndex = 0; fileIndex < currentFileNames.length; fileIndex++) { 19445 if (currentFileNames[fileIndex] && _.isString(fileDoms[fileNamesIndex])) { 19446 //handle draft save scenario when fileDoms[fileNamesIndex] is string(URL) & currentFileNames[fileIndex] is a url 19447 dataForm.append("_guideFileAttachment." + guideBridge._getRelativeFilePath(currentFileNames[fileIndex]), fileDoms[fileNamesIndex]); 19448 } 19449 } 19450 } 19451 dataForm.append("_guideAttachments", fileNames.toString()); 19452 if (isIOS) { 19453 var allFAPromises = []; 19454 _.each(fileAttachmentsList, function (fileAttachmentModel, index) { 19455 var fileAttachmentWrapperPromises = fileAttachmentModel._fileAttachmentWrapperIOS; 19456 if (fileAttachmentWrapperPromises) { 19457 var submissionNames = fileAttachmentModel._getInputFileSubmissionNames(); 19458 _.each(fileAttachmentWrapperPromises, function (fileAttachmentWrapperPromise, wrapperIndex) { 19459 allFAPromises.push(Promise.resolve(fileAttachmentWrapperPromise).then(function (fileAttachmentWrapper) { 19460 return { 19461 wrapper : fileAttachmentWrapper, 19462 submissionName : submissionNames[wrapperIndex] 19463 }; 19464 })); 19465 }); 19466 } 19467 }); 19468 faPromise = Promise.allSettled(allFAPromises).then(function (results) { 19469 for (var pIndex = 0; pIndex < results.length; pIndex++) { 19470 // if status rejected, fail submission 19471 if (results[pIndex].status === "rejected") { 19472 rejectedFileNames.push(results[pIndex].reason); 19473 } else { 19474 var resultValue = results[pIndex].value.wrapper; 19475 var partFileName = results[pIndex].value.submissionName || resultValue.name; 19476 var completeNameOfFile = resultValue.formElementName + "/" + partFileName; 19477 dataForm.append(completeNameOfFile, resultValue.dataURLtoBlob(), resultValue.name); 19478 } 19479 } 19480 // to fail this promise, throw an exception here 19481 throwException(rejectedFileNames); 19482 return dataForm; 19483 }); 19484 } else { 19485 var allFileAccessPromise = []; 19486 for (fileNamesIndex = 0; fileNamesIndex < fileNames.length; fileNamesIndex++) { 19487 // multiple files inside one filedom element & draft save case is handled. 19488 var currentFileNames = fileNames[fileNamesIndex].split("\n"); 19489 for (var fileIndex = 0; fileIndex < currentFileNames.length; fileIndex++) { 19490 // in case of IOS, file binary is from file object, we use the in-memory data 19491 if (fileDoms[fileNamesIndex] && !_.isString(fileDoms[fileNamesIndex]) && fileDoms[fileNamesIndex].length > 0) { 19492 // promise is not supported in IE11 19493 // for IE11, we don't read file bytes 19494 if (window.Promise) {
19495 var fileAccessPromise = guidelib.util.GuideUtil._checkIfFileIsAccessible(currentFileNames[fileIndex], fileDoms[fileNamesIndex][0].files[fileIndex]); 19496 allFileAccessPromise.push(fileAccessPromise); 19497 } else { 19498 // append each file of input file element to formdata 19499 dataForm.append(currentFileNames[fileIndex], fileDoms[fileNamesIndex][0].files[fileIndex]); 19500 } 19501 19502 } 19503 } 19504 } 19505 // promise is not supported in IE11 19506 if (window.Promise) { 19507 faPromise = Promise.allSettled(allFileAccessPromise).then(function (results) { 19508 for (var pIndex = 0; pIndex < results.length; pIndex++) { 19509 // if status rejected, fail submission 19510 if (results[pIndex].status === "rejected") { 19511 rejectedFileNames.push(results[pIndex].reason); 19512 } else { 19513 var resultValue = results[pIndex].value; 19514 dataForm.append(resultValue.fileName, resultValue.file); 19515 } 19516 } 19517 throwException(rejectedFileNames); 19518 return dataForm; 19519 }); 19520 } else { 19521 faPromise = $.Deferred().resolve(dataForm); 19522 } 19523 } 19524 return faPromise; 19525 }, 19526 19527 doAjaxSubmitWithFileAttachment : function (actionUrl, submitData, options, fileAttachmentsList) { 19528 var _options = options || {}, 19529 self = this, 19530 dataForm = new FormData(), 19531 fileNameDomMap = this._juiceOutNameAndFileDomMap(fileAttachmentsList), 19532 faPromise = this._appendFileAttachmentsToFormData(dataForm, fileNameDomMap, fileAttachmentsList); 19533 19534 var _submitForm = function () { 19535 $.ajax({ 19536 url : actionUrl, 19537 type : "POST", 19538 processData : false, 19539 cache : false, 19540 contentType : false, 19541 dataType : 'json', 19542 data : dataForm, 19543 success : function (data) { 19544 self.doAjaxSubmitSuccess(data, _options); 19545 }, 19546 error : function (data) { 19547 self.doAjaxSubmitError(data, _options); 19548 } 19549 }); 19550 }; 19551 faPromise.then(function (dataForm) { 19552 $.each(submitData, function (key, val) { 19553 if (typeof val == "object") { 19554 val = JSON.stringify(val); 19555 } 19556 dataForm.append(key, val); 19557 }); 19558 _submitForm(); 19559 }) 19560 .catch(function (e) { 19561 // handle errors here 19562 console.error(e); 19563 if (typeof e === "string") { 19564 guideBridge._handleSubmitError("", e); 19565 } else { 19566 guideBridge._handleSubmitError({ 19567 "status" : 400 19568 }); 19569 } 19570 19571 }); 19572 }, 19573 19574 doAjaxSubmit : function (actionUrl, submitData, options) { 19575 var _options = options || {}, 19576 self = this, 19577 asyncSubmit = _options.async !== false, 19578 strContent = this.getMultipartData(submitData); 19579 $.ajax({ 19580 url : actionUrl, 19581 type : "POST", 19582 traditional : true, 19583 async : asyncSubmit, 19584 contentType : "multipart/form-data; charset=UTF-8; boundary=" + strContent[0], 19585 data : strContent[1], 19586 success : function (data) { 19587 self.doAjaxSubmitSuccess(data, _options); 19588 }, 19589 error : function (data) { 19590 self.doAjaxSubmitError(data, _options); 19591 } 19592 }); 19593 }, 19594 19595 KEY_AF_SUCCESS_PAYLOAD : "afSuccessPayload", 19596 KEY_AF_SUCCESS_DOCUMENT_OF_RECORD : "afSuccessDocumentOfRecord", 19597 19598 doAjaxSubmitSuccess : function (data, options) { 19599 var guideResultObject = new GuideResultObject(); 19600 guideResultObject.data = data; 19601 guideResultObject.completed = true; 19602 // remove the submitting message too after success of ajax submit 19603 guideBridge._showGuideLoading(false); 19604 if (_.isFunction(options.success)) { 19605 options.success.call(options.context, guideResultObject); 19606 } else { 19607 if (data.hasOwnProperty("signingURL")) { 19608 // Adobe sign : FormFiller enabled case. 19609 window.location.href = data.signingURL; 19610 } else { 19611 var payload = {}; 19612 if (data.hasOwnProperty(guideBridge.KEY_AF_SUCCESS_PAYLOAD)) { 19613 try { 19614 payload = JSON.parse(data[guideBridge.KEY_AF_SUCCESS_PAYLOAD]); 19615 payload.data = this._guide.internal.afdata; 19616 if(data.hasOwnProperty(guideBridge.KEY_AF_SUCCESS_DOCUMENT_OF_RECORD)) { 19617 payload.dorUri = data[guideBridge.KEY_AF_SUCCESS_DOCUMENT_OF_RECORD]; 19618 } 19619 var schemaType = this._guide.runtime.guideContext.schemaType; 19620 if (!schemaType) { 19621 //TODO define a constant for schema Type. 19622 schemaType = "xmlschema"; 19623 } 19624 payload.contentType = schemaType; 19625 } catch (e) { 19626 guideBridge._guide.logger().log("Error while parsing AF Success Payload: " + e); 19627 } 19628 } 19629 guideBridge._guide.executeExpression("submitSuccess", payload); // Executing Rule Editor code for submit success. 19630 if (data.agreementId && guideBridge._guide._isFirstSignerFormFiller()) { 19631 guidelib.util.GuideUtil.redirectWithDelay(data.afSuccessRedirectUrl, 3000); 19632 } 19633 } 19634 } 19635 }, 19636 19637 doAjaxSubmitError : function (data, options) { 19638 var guideResultObject = new GuideResultObject(); 19639 guideResultObject.data = data; 19640 guideResultObject.completed = false;
19641 guideResultObject.addMessage(2, "Error in Async Submit", ""); 19642 guideBridge._showGuideLoading(false); 19643 if (_.isFunction(options.error)) { 19644 options.error.call(options.context, guideResultObject); 19645 } else { 19646 var errorPayload = {}; 19647 try { 19648 errorPayload = JSON.parse(data.responseText); 19649 } catch (e) { 19650 guideBridge._guide.logger().log("Error while parsing errorPayload." + e); 19651 } 19652 guideBridge._guide.executeExpression("submitError", errorPayload); //Executing Rule Editor code for submitError 19653 } 19654 }, 19655 19656 handleUpload : function () { 19657 self = this.self; 19658 this.submitData['_guideAttachments'] = this.attachments.toString(); 19659 _.each(this.attachments, function (att) { 19660 this.submitData["_guideFileAttachment." + att] = this.submitData['fileUrl'] + "/" + att; 19661 }, this); 19662 delete this.submitData['fileUrl']; 19663 self.doAjaxSubmit(this.actionUrl, this.submitData, this.options); 19664 }, 19665 19666 _handleSubmitError : function (data, message) { 19667 // case: show message if it exists, for example, there could be client side errors during submit 19668 if (message) { 19669 alert(message); 19670 } else { 19671 // based on http status show error, these errors are based on server side http response codes 19672 var status = Number(data.status); 19673 switch (status) { 19674 case 502: 19675 alert(guidelib.util.GuideUtil.getLocalizedMessage("AF", guidelib.i18n.LogMessages["AEM-AF-901-003"])); 19676 break; 19677 case 400: 19678 alert(guidelib.util.GuideUtil.getLocalizedMessage("AF", guidelib.i18n.LogMessages["AEM-AF-901-022"])); 19679 break; 19680 default: 19681 alert(guidelib.util.GuideUtil.getLocalizedMessage("AF", guidelib.i18n.LogMessages["AEM-AF-901-004"])); 19682 break; 19683 } 19684 } 19685 guideBridge._showGuideLoading(false); 19686 }, 19687 19688 updateSubmitData : function (fileAttachmentsList, submitData, fileList) { 19689 var fileCount = 0, 19690 attachments = [], 19691 name; 19692 if (fileList.length === 0 && fileAttachmentsList.length > 0) { 19693 _.each(fileAttachmentsList, function (fileUploadComponentId, index) { 19694 var currentCount = 0; 19695 var componentInModel = window.guideBridge._resolveId(fileUploadComponentId); 19696 var fileNameList = componentInModel["fileAttachment"].value; 19697 if (fileNameList) { 19698 var fileNames = fileNameList.split("\n"); 19699 _.each(fileNames, function (fileUrl, index) { 19700 name = componentInModel.name + "/" + fileUrl.substring(fileUrl.lastIndexOf("/") + 1); 19701 if (name) { 19702 attachments[fileCount++] = name; 19703 submitData["_guideFileAttachment." + name] = fileUrl; 19704 } 19705 }, this); 19706 } 19707 }, this); 19708 submitData['_guideAttachments'] = attachments; 19709 } else if (fileList.length > 0) { 19710 _.each(fileList, function (file, index) { 19711 name = guideBridge._getRelativeFilePath(file); 19712 attachments[fileCount++] = name; 19713 submitData["_guideFileAttachment." + name] = file; 19714 }, this); 19715 submitData['_guideAttachments'] = attachments; 19716 } 19717 }, 19718 19719 _collectFileUrls : function (event) { 19720 var list = [], 19721 fileUploadError = false; 19722 19723 // Populate list to have path of all the uploaded files. The file Attachment component whose model was 19724 // loaded would have their fileNames first followed by the list of file names of unloaded file upload components. 19725 _.each(this.attachments, function (attachment) { 19726 _.each(attachment.split("\n"), function (att) { 19727 // check if att is a url and hence push it directly to list 19728 if (_.isString(att) && att.match(/\//g).length > 1) { 19729 list.push(att); 19730 } else { 19731 list.push(this.fileUrl + "/" + att); 19732 } 19733 }, this); 19734 }, this); 19735 19736 var options = { 19737 fileUrlList : list, 19738 fileUploadModelsList : this.fileAttachmentsList, 19739 lazyAttachmentMap : guideBridge._guide.internal.liveDataUtils._getLazyAttachmentMap() 19740 }; 19741 guidelib.util.GuideUtil._updateFileModelsAndLazyMap(options); 19742 19743 var submitOptions = this.options.ajaxSubmitObject; 19744 if (submitOptions && submitOptions.ajaxSubmitDataHandler) { 19745 submitOptions.ajaxSubmitDataHandler.call(this.options.context, submitOptions.fileAttachmentsList, submitOptions.submitData, list); 19746 window.guideBridge.doAjaxSubmit(submitOptions.actionUrl, submitOptions.submitData, this.options); 19747 } else if (this.options.success) { 19748 //create the guideState now as the model has been updated with the latest values. 19749 //do this only during getGuideState and not on ajax submit 19750 guideBridge._createGuideStateAndLiveXml(this.options); 19751 this.options.success.call(this.options.context, this.options.obj); 19752 } 19753 19754 }, 19755 19756 _fileUploadFailed : function (event) { 19757 $.proxy(guideBridge._handleSubmitError({ 19758 "status" : "500" 19759 }), guideBridge); 19760 }, 19761 19762 // This function extracts the form name from the guideContainerPath. 19763 _getFormName : function (guidePath) { 19764 var formName = ""; 19765 if (guidePath) { 19766 var index = guidePath.indexOf("/jcr:content/guideContainer"); 19767 guidePath = guidePath.substring(0, index); 19768 formName = guidePath.substring(guidePath.lastIndexOf("/") + 1); 19769 } 19770 return formName; 19771 }, 19772 19773 /** 19774 * returns the form element to be used for submission in case of non-ajax 19775 * submit. 19776 * The function looks in the submitConfig for a form and if not present, 19777 * creates a new form 19778 * @returns {object} jQuery object for form element 19779 * @private 19780 */ 19781 _getFormForSubmission : function () { 19782 var submitConfig = this.userConfig.submitConfig || {}, 19783 form = submitConfig.form || $("<form method='post' enctype='multipart/form-data'></form>").appendTo($("body")); 19784 return $(form); 19785 }, 19786 19787 _getThankYouPageFromConfig : function () { 19788 var submitConfig = this.userConfig.submitConfig || {}; 19789 return submitConfig.thankyouPage; 19790 }, 19791 19792 /** 19793 * This function prepare the guideValueMap and returns it. 19794 * @returns A map consisting of name and value for all the unbound components 19795 * @private 19796 */ 19797 _prepareGuideValueMap : function () { 19798 var guideValueMap = {}, visitedMap = {}; 19799 this.visit(function (node) { 19800 if (!node.bindRef && !visitedMap[node.somExpression]) { 19801 if (node instanceof guidelib.model.Field && node.value) { 19802 visitedMap[node.somExpression] = true; 19803 guideValueMap[node.getAttribute("name")] = node.value; 19804 } else if (node instanceof guidelib.model.GuideCompositeField) { 19805 var obj = guideValueMap[node.getAttribute("name")] = {}; 19806 _.each(node.items, function (childNode, index) { 19807 visitedMap[childNode.somExpression] = true; 19808 if (childNode.value) { 19809 obj[childNode.getAttribute("name")] = childNode.value; 19810 } 19811 }, this); 19812 } 19813 } 19814 }); 19815 return guideValueMap; 19816 }, 19817 19818 _showGuideLoading : function (flag, msg) { 19819 if(!flag){ 19820 if(_focusedSubmitButtonModel){ 19821 _focusedSubmitButtonModel.enabled = true; 19822 _focusedSubmitButtonModel = null; 19823 } 19824 } 19825 var util = guidelib.util.GuideUtil; 19826 if (util) { 19827 util.showGuideLoading(flag); 19828 if (msg !== undefined) { 19829 util.showMessages(msg); 19830 } else { 19831 util.removeAllMessages(); 19832 } 19833 } 19834 }, 19835 19836 _submitAfterValidation : function (options, submitSuccess, submitError) { 19837 var self = this; 19838 if (guidelib.util.GuideUtil) { 19839 var msg = guidelib.i18n.strings.submittingForm; 19840 if (options && options.submissionSelector === 'agreement') { 19841 msg = guidelib.i18n.strings.generatingSignAgreement; 19842 } 19843 guidelib.util.GuideUtil.showMessages(msg); 19844 } 19845 // Trigger submitStart before calling internal submit. 19846 if (guideBridge.isGuideLoaded() && self._guide._triggerOnBridge) { 19847 self._guide._triggerOnBridge("submitStart", "", "", "", ""); 19848 } 19849 var excludeFormState = true; 19850 if (options && options.hasOwnProperty("excludeFormState")) { 19851 excludeFormState = options.excludeFormState; 19852 } 19853 try { 19854 var guideState = getOrElse(options, "guideState", null); 19855 if (guideState || guideBridge.isGuideLoaded()) { 19856 var twoStepSubmission = getOrElse(options, "twoStepSubmission", false); 19857 if (guideState || self._guide.xdpRef || twoStepSubmission) { 19858 self._submitInternal({ 19859 guideState : guideState, 19860 success : function () { 19861 try { 19862 submitSuccess.apply(self, arguments); 19863 } catch (e) { 19864 self._handleInternalSubmitError(submitError, self, arguments); 19865 } 19866 }, 19867 error : function () { 19868 self._handleInternalSubmitError(submitError, self, arguments); 19869 }, 19870 async : true, 19871 excludeFormState : excludeFormState 19872 }); 19873 } else { 19874 self.getFormDataString({ 19875 success : function () { 19876 try { 19877 submitSuccess.apply(self, arguments); 19878 } catch (e) { 19879 self._handleInternalSubmitError(submitError, self, arguments); 19880 } 19881 } 19882 }); 19883 } 19884 } else { 19885 console.error("Form Submission failed as the form doesn't exist on the page"); 19886 } 19887 } catch (e) { 19888 self._showGuideLoading(false); 19889 if (console && console.error) { 19890 console.error(e); 19891 } 19892 } 19893 }, 19894 19895 _handleCaptchaTimeout : function () { 19896 window.alert(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.LogMessages["AEM-AF-901-025"])); 19897 window.guideBridge.setEnabledAutoSave(_isAutoSaveEnabled); 19898 guideBridge._showGuideLoading(false); 19899 return; 19900 }, 19901 19902 /** 19903 * Validate and submits the data of the Adaptive Form to the pre-configured submit action. 19904 * 19905 * The success handler provided in the argument is executed only if the Adaptive Form is configured to use AJAX 19906 * for submission using {@link GuideBridge#registerConfig|registerConfig} API 19907 * @summary submits the Adaptive Form 19908 * @param {object} options options to control the behaviour of submit API. 19909 * @param {string} [options.submissionSelector] url selector governs the submission behaviour at server 19910 * Default value is "submit", other options are "agreement", "signSubmit" 19911 * @param {function} [options.success] callback which receives the result of the API 19912 * in case of success. 19913 * {@link GuideResultObject#errors|errors} property as false. 19914 * @param {function} [options.error] callback which receives the result of the API in 19915 * case of failure. 19916 * {@link GuideResultObject#errors|errors} property as true. 19917 * @param {object} [options.context] _this_ object inside the _success_ and _error_ callback will point to this 19918 * object 19919 * @param {boolean} [options.validate=true] whether to validate the form before submission or not 19920 * @method 19921 * @memberof GuideBridge 19922 * @since 6.0 19923 * @instance 19924 * @example <caption>Submitting the form without validation</caption> 19925 * guideBridge.submit({ 19926 * validate: false, 19927 * error : function (guideResultObject) {//log message} 19928 * }); 19929 * @example <caption>Submitting the form and showing a success message</caption> 19930 * guideBridge.registerConfig("submitConfig" : {"useAjax" : true}); 19931 * guideBridge.submit({ 19932 * validate: false, 19933 * error : function (guideResultObject) {//log message} 19934 * success : function (guideResultObject) {alert("data submitted successfully") 19935 * }); 19936 */ 19937 19938 submit : function (options) { 19939 // Disabling the submit button 19940 var focusedElementSOM = guideBridge.getFocus(); 19941 if(focusedElementSOM){ 19942 _focusedSubmitButtonModel = guideBridge.resolveNode(focusedElementSOM); 19943 _focusedSubmitButtonModel.enabled = false;
19944 } 19945 _isAutoSaveEnabled = window.guideBridge.getAutoSaveEnabledStatus(); 19946 //Disable auto save till submission is not completed 19947 if (_isAutoSaveEnabled) { 19948 window.guideBridge.setEnabledAutoSave(false); 19949 } 19950 var self = this; 19951 var guideContextFromOptions, 19952 runtimeGuideContext = getOrElse(this._guide, "runtime.guideContext", {}); 19953 if (getOrElse(options, "guideState", "")) { 19954 guideContextFromOptions = options.guideState.data.guideState.guideContext; 19955 } 19956 var localGuideContext = guideContextFromOptions || runtimeGuideContext; 19957 // to submit guideContainerForm which will be stopped so that autocomplete values can be remembered 19958 $(".guideContainerFormSubmitButton").click(); 19959 19960 window.guideBridge._populateBindRefToSomMap(); 19961 19962 function submitError(data) { 19963 self._ariaLiveAnnouncement(guidelib.i18n.strings["formSubmitFail"]); 19964 if (options && options.error) { 19965 options.error.call(options.context || this, data); 19966 } else { 19967 $.proxy(guideBridge._handleSubmitError(data), guideBridge); 19968 } 19969 } 19970 19971 function submitSuccess(result) { 19972 var isAjaxSubmit = false; 19973 19974 if (options) { 19975 isAjaxSubmit = options.success ? true : false; 19976 } 19977 options = options || {}; 19978 options.success = options.success || (self.userConfig.submitConfig || {}).submitSuccessHandler; 19979 isAjaxSubmit = isAjaxSubmit || (self.userConfig.submitConfig || {useAjax : false}).useAjax || guideBridge._guide.enableAsyncSubmission; 19980 var submitData = {}; 19981 19982 if (this.isGuideLoaded()) { 19983 var guideCaptchaList = []; 19984 this.visit(function (node) { 19985 if (node.className === "guideCaptcha") { 19986 guideCaptchaList.push(node); 19987 } 19988 }); 19989 var captchaModel = guideCaptchaList[0]; 19990 if (captchaModel) { 19991 var captchaData = window.guideBridge._getCaptchaData(captchaModel); 19992 submitData['captchaData'] = captchaData; 19993 } 19994 } 19995 19996 // check if guide state is present, if yes get guide path from guide state 19997 var guidePath = getOrElse(options, "guideState.data.guideState.guideContext.guidePath", ""), 19998 guideContainerPath = guidePath || window.guideBridge.getGuidePath(), 19999 aemFormComponentPath = this.userConfig.submitConfig ? this.userConfig.submitConfig.aemFormComponentPath : "", 20000 submissionSelector = options.submissionSelector || "submit", 20001 actionUrl = window.guideBridge._getGuidePathUrl(".af." + submissionSelector + ".jsp", guideContainerPath); 20002 20003 submitData['guideContainerPath'] = guideContainerPath; 20004 submitData['aemFormComponentPath'] = aemFormComponentPath; 20005 submitData['_asyncSubmit'] = isAjaxSubmit; 20006 submitData['_charset_'] = "UTF-8"; 20007 var customPropMap = localGuideContext.customPropertyMap || {}; 20008 // need to remove lastFocusItem from being sent as a different property 20009 // as it being sent in xml and with afSubmissionInfo as well. 20010 var whiteListedProperties = ["lastFocusItem"]; 20011 for (var prop in customPropMap) { 20012 if (customPropMap.hasOwnProperty(prop) && whiteListedProperties.indexOf(prop) < 0) { 20013 submitData[prop] = customPropMap[prop]; 20014 } 20015 } 20016 // todo: Have to remove the excludeFromDor map from the submission info, is this required ? 20017 if (this.isGuideLoaded()) {
20018 submitData['afSubmissionInfo'] = this._guide.runtime.guideContext.afSubmissionInfo || {}; 20019 } 20020 var resultJson = result, 20021 guideJson, 20022 data, 20023 fileAttachmentsList, 20024 attachments = [], 20025 fileCount = 0; 20026 if (resultJson.hasOwnProperty("guideValue")) { 20027 guideJson = resultJson.guideValue; 20028 } else if (!_.isUndefined(options.guideValueMap)) { 20029 guideJson = options.guideValueMap; 20030 } else { 20031 // todo: why is this required in client ? 20032 guideJson = window.guideBridge._prepareGuideValueMap(); 20033 } 20034 if (resultJson.hasOwnProperty("data")) { 20035 data = resultJson["data"]; 20036 } 20037 20038 if (resultJson.hasOwnProperty("fileAttachmentsList")) { 20039 fileAttachmentsList = resultJson["fileAttachmentsList"]; 20040 } 20041 20042 for (var key in guideJson) { 20043 if (guideJson.hasOwnProperty(key)) { 20044 submitData[key] = guideJson[key]; 20045 } 20046 } 20047 20048 if (data) { 20049 submitData['jcr:data'] = data; 20050 submitData['jcr:data@TypeHint'] = "Binary"; 20051 if (self.isGuideLoaded()) { 20052 self._guide.internal.afdata = data; 20053 } 20054 } 20055 if (!_.isUndefined(options.fileAttachmentMap)) { 20056 submitData.fileAttachmentMap = options.fileAttachmentMap; 20057 } else { 20058 //send the fileAttachmentMap through submit data to restore submission attachments for read only viewing 20059 submitData.fileAttachmentMap = JSON.stringify(guideBridge._getFileAttachmentMapForSubmit()); 20060 } 20061 // read the additional information from the guideState if it is passed in options 20062 // otherwise get the additional information from the DOM 20063 var additionalSubmitInfo = {}; 20064 if (options.guideState && options.guideState.data.guideState.additionalSubmitInfo) { 20065 additionalSubmitInfo = options.guideState.data.guideState.additionalSubmitInfo; 20066 } else { 20067 additionalSubmitInfo = guideBridge._getAdditionalSubmitInfo(); 20068 } 20069 // append additionalSubmitInfo to the submitData 20070 $.extend(true, submitData, additionalSubmitInfo); 20071 20072 if (isAjaxSubmit && isAjaxSubmit === true) { 20073 // 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. 20074 // we just update the submitData with the attachment information 20075 if (options.fileAttachmentMap) { 20076 var attachmentMap = JSON.parse(options.fileAttachmentMap); 20077 var keys = _.keys(attachmentMap); 20078 for (var i = 0; i < keys.length; i++) { 20079 if (attachmentMap[keys[i]]) { 20080 var fileNames = attachmentMap[keys[i]].split("\n"); 20081 for (var j = 0; j < fileNames.length; j++) { 20082 var name = guideBridge._getRelativeFilePath(fileNames[j]); 20083 attachments[fileCount++] = name; 20084 submitData["_guideFileAttachment." + name] = fileNames[j]; 20085 } 20086 } 20087 } 20088 submitData['_guideAttachments'] = attachments; 20089 self.doAjaxSubmit(actionUrl, submitData, options); 20090 } else { 20091 var attachedFilesList = []; 20092 var currentCount = 0; 20093 // need to check if the guide is loaded, as it is not available for mobile workspace app use case 20094 if (guideBridge.isGuideLoaded()) { 20095 attachedFilesList = window.guideBridge._getFileAttachmentsList(); 20096 } 20097 _.each(attachedFilesList, function (object) { 20098 var fileNameList = object["fileAttachment"].value; 20099 if (fileNameList) { 20100 currentCount++; 20101 } 20102 }); 20103 // If a file has been attached and isAjaxSubmit is true, then a UUID is generated and 20104 // the files are uploaded at temp storage path. 20105 // The submit data is updated with the attached files and then 20106 // doAjaxSubmit is called. 20107 if (currentCount > 0) { 20108 self.doAjaxSubmitWithFileAttachment(actionUrl, submitData, options, attachedFilesList); 20109 } else { 20110 self.doAjaxSubmit(actionUrl, submitData, options); 20111 } 20112 } 20113 } else { 20114 var $form = self._getFormForSubmission(); 20115 $form.attr('action', actionUrl); 20116 $form.attr('data-name', 'afSubmissionForm'); 20117 for (var fields in submitData) { 20118 if (submitData.hasOwnProperty(fields)) { 20119 var value = submitData[fields]; 20120 $("<input>").attr("type", "hidden") 20121 .attr("name", fields) 20122 .val(_.isObject(value) ? JSON.stringify(value) : value) 20123 .appendTo($form); 20124 } 20125 } 20126 /* 20127 * This means we did not do any preprocessing 20128 * for file attachments so fileAttachment list won't be present 20129 * so posting DOM for the files. 20130 * */ 20131 var attachmentNameDomMap = guideBridge._getFileNameFileDomMap(), 20132 fileNameList = [], 20133 _guideAttachments = ""; 20134 // A string containing the names of all the files that are attached is stored in the variable _guideAttachments. 20135 // For all the files that have been uploaded already and don't have a dom element are 20136 // added to $form with prefix "_guideFileAttachment." 20137 if (attachmentNameDomMap && attachmentNameDomMap.fileDom) { 20138 fileNameList = attachmentNameDomMap.fileName; 20139 _.each(attachmentNameDomMap.fileDom, function (file, index) { 20140 if (!_.isString(file)) { 20141 file.attr("name", fileNameList[index].split["\n"]) 20142 .attr("class", "hidden") 20143 .appendTo($form); 20144 _guideAttachments += fileNameList[index] + ","; 20145 } else { 20146 if (fileNameList[index]) { 20147 var name = guideBridge._getRelativeFilePath(fileNameList[index]); 20148 $("<input>").attr("type", "hidden") 20149 .attr("name", "_guideFileAttachment." + name) 20150 .attr("value", file) 20151 .appendTo($form); 20152 _guideAttachments += name + ","; 20153 } 20154 } 20155 }); 20156 } 20157 $("<input>").attr("type", "hidden") 20158 .attr("name", "_guideAttachments") 20159 .attr("value", _guideAttachments) 20160 .appendTo($form); 20161 20162 $form.submit(); 20163 } 20164 } 20165 20166 self._showGuideLoading(true, guidelib.i18n.strings.val
20166idatingForm); 20167 // since validate is synchronous call, putting this in timeout 20168 // so that html changes can be display 20169 setTimeout(function () { 20170 // update the snapshot just before validating 20171 // so that we get true state of play before loading panels 20172 if (guideBridge.isGuideLoaded() && guideBridge._guide.allLazyChildren && guideBridge._guide.allLazyChildren.length > 0) { 20173 self._guide.internal.liveDataUtils.updateLiveData(); 20174 } 20175 var isValid = false; 20176 try { 20177 isValid = self._performConditionalValidation(options); 20178 } catch (e) { 20179 isValid = false; 20180 } finally { 20181 self._showGuideLoading(true); 20182 } 20183 if (isValid) { 20184 /* Handle Invisible Recaptcha on form submission */ 20185 var recaptchaInvisibleElement = $("#captchaInvisible"); 20186 if (recaptchaInvisibleElement != undefined && recaptchaInvisibleElement.attr("af-recaptcha-execute") == "") { 20187 recaptchaInvisibleElement.trigger({ 20188 type: "recaptchaExecution", 20189 submitParameters: { 20190 options: options, 20191 success: submitSuccess, 20192 error: submitError 20193 }, 20194 triggerPostSubmission: true 20195 }); 20196 return; 20197 } 20198 guideBridge._submitAfterValidation(options, submitSuccess, submitError); 20199 } else { 20200 window.guideBridge.setEnabledAutoSave(_isAutoSaveEnabled); 20201 self._showGuideLoading(false); 20202 return; 20203 } 20204 }, 1); 20205 }, 20206 20207 /** 20208 * Save draft of the current adaptive form loaded 20209 * @param saveBtnConfig {object} Optional parameter for providing 20210 * @param options {object} Optional parameter options can consist of following - 20211 * <ul> 20212 * <li> success: {function} Handler executed in case when the draft is successfully saved</li> 20213 * <li> error: {function} Handler executed in case of draft failure</li> 20214 * <li> context {object} The context with which the success or error handler needs to be executed</li> 20215 * </ul> 20216 * 20217 */ 20218 handleDraftSave : function (saveBtnConfig, custom_options) { 20219 custom_options = $.extend({ 20220 success : $.noop, 20221 error : $.noop, 20222 context : this 20223 }, custom_options); 20224 // isAutoSaveTriggered is not a documented property. 20225 //handleDraftSave method is also called via auto save component,where we pass this value as true. 20226 // This flag is just set to understand if the call is triggered by auto save strategy or not 20227 custom_options.isAutoSaveTriggered = custom_options.isAutoSaveTriggered || false; 20228 20229 var options = { 20230 success : function (result) { 20231 var draftId = result.data.draftId; 20232 window.guideBridge.customContextProperty("draftId", draftId); 20233 /** if (!isAutoSaveTriggered) { 20234 $(".__FP_Saved_Message").show(); 20235 $(".__FP_Saved_Message").fadeOut(1600, "linear"); 20236 }**/ 20237 20238 window.guideBridge.trigger( 20239 "saveCompleted", 20240 window.guidelib.event.GuideModelEvent.createEvent("saveCompleted") 20241 ); 20242 var payload = {}; 20243 payload.draftId = draftId; 20244 payload.isAutoSaveTriggered = custom_options.isAutoSaveTriggered; 20245 guideBridge._guide.executeExpression("saveSuccess", payload); // Executing Rule Editor code for save success. 20246 // window.guideBridge._defaultSaveSuccessHandler(); 20247 custom_options.success.call(custom_options.context); 20248 }, 20249 error : function (result) { 20250 if (!custom_options.isAutoSaveTriggered) { 20251 if (result.status == "503") { 20252 alert(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.LogMessages["AEM-AF-901-008"])); 20253 } else { 20254 alert(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.LogMessages["AEM-AF-901-009"])); 20255 } 20256 } 20257 var errorPayload = {}; 20258 errorPayload.result = result; 20259 errorPayload.isAutoSaveTriggered = custom_options.isAutoSaveTriggered; 20260 guideBridge._guide.executeExpression("saveError", errorPayload); //Executing Rule Editor code for saveError 20261 custom_options.error.call(custom_options.context); 20262 } 20263 }; 20264 var guidePath = window.guideBridge.getGuidePath(); 20265 var draftId = window.guideBridge.customContextProperty("draftId") || ""; 20266 20267 var contextPath = window.guideBridge._getUrl(guidePath); 20268 var self = this; 20269 guideBridge.getFormDataObject({ 20270 "success" : function (resultObj) { 20271 window.guideBridge.trigger( 20272 "saveStarted", 20273 window.guidelib.event.GuideModelEvent.createEvent("saveStarted") 20274 ); 20275 var afFormData, 20276 htmlFormData; 20277 afFormData = resultObj.data; 20278 htmlFormData = afFormData.toHTMLFormData(); 20279 htmlFormData.append('draftId', draftId); 20280 self._doAjaxSubmitWithHTMLFormData(contextPath + ".af.save.jsp", htmlFormData, options); 20281 } 20282 }); 20283 }, 20284 20285 /** 20286 * @private 20287 */ 20288 _doAjaxSubmitWithHTMLFormData : function (actionURL, htmlFormData, options) { 20289 var self = this; 20290 $.ajax({ 20291 url : actionURL, 20292 type : "POST", 20293 processData : false, 20294 cache : false, 20295 contentType : false, 20296 dataType : 'json', 20297 data : htmlFormData, 20298 success : function (data) { 20299 self.doAjaxSubmitSuccess(data, options); 20300 }, 20301 error : function (data) { 20302 self.doAjaxSubmitError(data, options); 20303 } 20304 }); 20305 }, 20306 20307 /** 20308 * @private 20309 */ 20310 _handleInternalSubmitError : function (submitError, selfVar, args
20310) { 20311 try { 20312 submitError.apply(selfVar, args); 20313 } catch (e) { 20314 //ignoring the error 20315 } finally { 20316 guideBridge._showGuideLoading(false); 20317 20318 } 20319 }, 20320 /** 20321 * @private 20322 */ 20323 _getFileAttachmentMapForSubmit : function () { 20324 var fileAttachmentMap = {}, 20325 fileAttachmentsList = window.guideBridge._getFileAttachmentsList(); 20326 for (var i = 0; i < fileAttachmentsList.length; i++) { 20327 var node = fileAttachmentsList[i]; 20328 if (!_.isUndefined(node.value) && node.value.length > 0) { 20329 var attachmentList = node.value.split("\n"); 20330 for (var j = 0; j < attachmentList.length; j++) { 20331 attachmentList[j] = node.name + "/" + attachmentList[j]; 20332 } 20333 fileAttachmentMap[node.somExpression] = attachmentList.join('\n'); 20334 } 20335 } 20336 20337 var lazyAttachmentMap = this._guide.internal.liveDataUtils._getLazyAttachmentMap(); 20338 _.each(lazyAttachmentMap, function (mapObject, key) { 20339 var attachmentList = mapObject.value.split("\n"); 20340 for (var j = 0; j < attachmentList.length; j++) { 20341 attachmentList[j] = guidelib.util.GuideUtil.guideSomToComponentName(key) + "/" + attachmentList[j]; 20342 } 20343 fileAttachmentMap[key] = attachmentList.join('\n'); 20344 }); 20345 return fileAttachmentMap; 20346 }, 20347 20348 ERROR_CAUSED_BY : { 20349 CAPTCHA_VALIDATION : "CAPTCHA_VALIDATION", 20350 SERVER_SIDE_VALIDATION : "SERVER_SIDE_VALIDATION", 20351 FORM_SUBMISSION : "FORM_SUBMISSION", 20352 AGREEMENT_CREATION : "AGREEMENT_CREATION", 20353 SERVICE_INVOCATION_FAILURE: "SERVICE_INVOCATION_FAILURE" 20354 }, 20355 20356 /** 20357 * This API displays validation error messages at the field level corresponding to the input errorJson object 20358 * @summary Displays validation error messages at field level 20359 * @memberof GuideBridge 20360 * @instance 20361 * @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) 20362 * @see {@link https://helpx.adobe.com/experience-manager/6-5/forms/using/custom-validation-message-adaptive-forms.html%7CCustom validation message in adaptive form} 20363 */ 20364 handleServerValidationError : function (errorJson) { 20365 var self = this; 20366 if (errorJson) { 20367 var errors = errorJson.errors; 20368 if (errors && errors.length > 0) { 20369 var firstFocusableSom; 20370 _.each(errors, function (object, i) { 20371 var errMsg; 20372 if (object.errorMessages) { 20373 errMsg = object.errorMessages.join("\n"); 20374 } else { 20375 errMsg = object.errorMessage; 20376 } 20377 var som = (object.somExpression) ? object.somExpression : self._guide._bindRefMap[object.bindRef]; 20378 var node = self.resolveNode(som); 20379 20380 if (node) { 20381 if (!firstFocusableSom) { 20382 firstFocusableSom = som; 20383 } 20384 node.markAsInvalid(errMsg); 20385 } 20386 }); 20387 // set focus to first invalid node 20388 if (firstFocusableSom) { 20389 self.setFocus(firstFocusableSom); 20390 } 20391 } 20392 } 20393 }, 20394 20395 /* Handle the server side validation failure in case of submission fails. 20396 * This function handles Captcha validation as well as server side validation. 20397 * @private 20398 */ 20399 _handleServerValidationError : function (errorJson) { 20400 var self = this; 20401 window.guideBridge.setEnabledAutoSave(_isAutoSaveEnabled); 20402 if (errorJson) { 20403 if (errorJson.errorCausedBy && errorJson.errorCausedBy === this.ERROR_CAUSED_BY.CAPTCHA_VALIDATION) { 20404 var errors = errorJson.errors, 20405 firstFocusableSom = errors[0].somExpression; 20406 _.each(errors, function (object, i) { 20407 var somExpression = object.somExpression, 20408 errorMessage = object.errorMessage, 20409 guideCaptcha; 20410 /*Setting focus to load captcha's view. 20411 This is required when panel's children get loaded later. 20412 Setting focus ensures that view is loaded properly so that model can throw 20413 'guide.errorChanged' event and view can listen the same. 20414 */ 20415 self.setFocus(somExpression); 20416 guideCaptcha = self.resolveNode(somExpression); 20417 if (guideCaptcha) { 20418 guideCaptcha.showCaptchaError(errorMessage); 20419 } 20420 });
20421 //Setting focus to the first captcha element. 20422 self.setFocus(firstFocusableSom); 20423 } else if (errorJson.errorCausedBy && errorJson.errorCausedBy === this.ERROR_CAUSED_BY.FORM_SUBMISSION 20424 || errorJson.errorCausedBy === this.ERROR_CAUSED_BY.AGREEMENT_CREATION) { 20425 if (errorJson.errors && errorJson.errors.length > 0) { 20426 window.guideBridge.handleServerValidationError(errorJson); 20427 } else { 20428 var statusCode = errorJson.originCode ? Number(errorJson.originCode) : 500, 20429 errorMessage = statusCode === 400 ? (errorJson.errorMessage ? errorJson.errorMessage : "") : ""; 20430 // show the message returned by server only if if the HTTP status code is 400 20431 // this is done so that users could act upon the error and re-submit the form 20432 $.proxy(guideBridge._handleSubmitError({ 20433 "status" : statusCode 20434 }, errorMessage), guideBridge); 20435 } 20436 } else { 20437 //Everything else is "SERVER_SIDE_VALIDATION". Calling this as it was being called. 20438 window.guideBridge.handleServerValidationError(errorJson); 20439 } 20440 } 20441 }, 20442 20443 /* 20444 * Populates bindRefToSomMap. 20445 * This function is called during submission and during unloading of a lazy fragment 20446 * @param {node} is equal to the lazy loaded fragment model if this is called during lazy fragment unloading 20447 * @private 20448 */ 20449 _populateBindRefToSomMap : function (node) { 20450 20451 /* 20452 * While populating bindRefToSomMap we basically check if any panel is repeatable panel. 20453 * If a panel is repeatable, in that node and its descendant nodes we replace the bindRef 20454 * by corresponding json-pointer in the map. 20455 * parameter {jsonp} refers to the json-pointer of the parent node. It is valid if 20456 * some ancestor of current node in the hierarchy was a repeatable panel 20457 */ 20458 var bindRefToSomMapper = function (node, map, jsonp) { 20459 var path, bindref; 20460 if (node.bindRef) { 20461 if (node.repeatable) { // current node is a repeatable panel 20462 if (jsonp) { // some ancestor panel in the hierarchy was a repeatable panel 20463 path = jsonp + "/" + node.bindRef.split("/").slice(-1)[0] + "/" + node.index; 20464 bindref = path; 20465 } else { // current node is the first repeatable panel in the hierarchy 20466 path = node.bindRef + "/" + node.index; 20467 bindref = path; 20468 } 20469 } else { 20470 if (jsonp) { // some panel in the upper level was a repeatable panel 20471 path = jsonp + "/" + node.bindRef.split("/").slice(-1)[0]; 20472 bindref = path; 20473 } else { // no repeatable panel till now 20474 bindref = node.bindRef; 20475 } 20476 } 20477 map[bindref] = node.somExpression; 20478 } 20479 20480 if (node._children) { 20481 node._children.forEach(function (element) { 20482 bindRefToSomMapper(element, map, path); 20483 }); 20484 } 20485 }; 20486 var jsonp; 20487 20488 // since we support lazy-loading for a fragment upto only two level deep, the immediate parent panel 20489 // of a lazy-loaded fragment can atmost be a repeatable panel. so we only check the repeatability for the parent 20490 if (node && node.parent && node.parent.repeatable && node.parent.bindRef) { 20491 jsonp = node.parent.bindRef + "/" + node.parent.index; 20492 } 20493 20494 if (!node) { 20495 node = window.guideBridge._guide; 20496 } 20497 20498 if (window.guideBridge.isGuideLoaded()) { 20499 if (!window.guideBridge._guide._bindRefMap) { 20500 window.guideBridge._guide._bindRefMap = {}; 20501 } 20502 bindRefToSomMapper(node, window.guideBridge._guide._bindRefMap, jsonp); 20503 } 20504 }, 20505 20506 SELECTOR_FORM_CONTAINER : "#guideContainerForm", 20507 20508 THANK_YOU_OPTION : { 20509 PAGE : "page", 20510 MESSAGE : "message" 20511 }, 20512 20513 addDorDownloadLink: function (thankYouContent, dorUri) { 20514 var guidePath = window.guideBridge.getGuidePath(); 20515 var contextPath = window.guideBridge._getUrl(guidePath); 20516 dorUri = contextPath + ".af.dor.pdf?submissionId="+dorUri; 20517 var dorVariable = "$%7BAF_DocumentOfRecord%7D"; 20518 if (thankYouContent && thankYouContent.indexOf(dorVariable) !== -1) { 20519 var tempElement = document.createElement("div"); 20520 tempElement.innerHTML = thankYouContent; 20521 var anchorTags = tempElement.querySelectorAll("a"); 20522 for (var i=0; i<anchorTags.length; i++) { 20523 var tag = anchorTags.item(i); 20524 if(tag.getAttribute("href") == dorVariable) { 20525 tag.setAttribute("href", dorUri); 20526 tag.setAttribute("download", tag.getAttribute("title")); 20527 thankYouContent = tempElement.innerHTML; 20528 } 20529 } 20530 } 20531 return thankYouContent; 20532 }, 20533 /* 20534 * default Submit Success Handler. 20535 * This function handles the Thank You Page/Message 20536 */ 20537 _defaultSubmitSuccessHandler : function (successPayload) { 20538 if (successPayload) { 20539 if (successPayload.thankYouOption === this.THANK_YOU_OPTION.MESSAGE) { 20540 successPayload.thankYouContent = this.addDorDownloadLink(successPayload.thankYouContent, successPayload.dorUri); 20541 var tyMessage = $("<div class='tyMessage'>" + successPayload.thankYouContent + "</div>"); 20542 $(this.SELECTOR_FORM_CONTAINER).replaceWith(tyMessage); 20543 tyMessage.attr({'tabindex': '-1', 20544 'role': 'alertdialog'}); 20545 tyMessage.focus(); 20546 } else if (successPayload.thankYouOption === this.THANK_YOU_OPTION.PAGE) { 20547 window.location.href = encodeURI(successPayload.thankYouContent); 20548 } 20549 } 20550 }, 20551 20552 _defaultSaveSuccessHandler : function (successPayload) { 20553 alert(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings["formSavedMessage"])); 20554 }, 20555 20556 _defaultSaveErrorHandler : function () { 20557 alert(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings["formSaveError"])); 20558 }, 20559 20560 // This function gets the relative path of the file.
20561 // Suppose the component Name is attachment and the file name is a.jpg, 20562 // then it will return "attachment/a.jpg" as the path 20563 _getRelativeFilePath : function (fileName) { 20564 var relPath = fileName; 20565 if (fileName.indexOf("/") !== -1) { 20566 var splitPath = fileName.split("/"); 20567 if (splitPath.length > 2) { 20568 relPath = splitPath[splitPath.length - 2] + "/" + splitPath[splitPath.length - 1]; 20569 } 20570 } 20571 return relPath; 20572 }, 20573 20574 // We do not need to validate if options.validate = false. 20575 // This function makes sure that validations are not performed when validate flag is false. 20576 // Validation is performed in all the other cases. 20577 _performConditionalValidation : function (options) { 20578 if (getOrElse(options, "validate", true)) { 20579 return guideBridge.validate(null, null, true, false); 20580 } 20581 return true; 20582 }, 20583 20584 /** 20585 * This API returns the HTML content of another Adaptive Form and optionally load the Form inside an HTML 20586 * element 20587 * 20588 * The {@link GuideResultObject#data|data} property of the result passed to success handler will contain the HTML of 20589 * the Form 20590 * @summary load an Adaptive Form given its path 20591 * @param {object} options object to pass to the API 20592 * @param {function} [options.success] callback which receives the result of the API 20593 * in case of success. 20594 * {@link GuideResultObject#errors|errors} property as false. 20595 * @param {function} [options.error] callback which receives the result of the API in 20596 * case of failure. 20597 * {@link GuideResultObject#errors|errors} property as true. 20598 * @param {object} [options.context] _this_ object inside the _success_ and _error_ callback will point to this 20599 * object 20600 * @param {string} options.path Path of the Adaptive Form whose HTML is required. If sever is running at a 20601 * context path, this parameter must have the context path 20602 * @param {string} [options.dataRef] URL of the resource that returns the XML. The protocol of the URL must 20603 * match the supported URL protocols 20604 * @param {string} [options.containerSelector] jquery Selector of the HTML element where to insert the HTML 20605 * of the form. 20606 * @method 20607 * @memberof GuideBridge 20608 * @since 6.1 FP1 20609 * @instance 20610 * @example 20611 * guideBridge.loadAdaptiveForm({ 20612 * success : function (guideResultObj) {console.log("html is " + guideResultObj.data)}, 20613 * error : function (guideResultObj) { //log errors}, 20614 * dataRef : "http://url/of/the/dataRef", 20615 * path : "/contextpath/content/dam/formsanddocuments/form1" 20616 * }) 20617 * @see {@link https://api.jquery.com/category/selectors/|jQuery selectors} 20618 * @see <a href="#guidebridge-api-usage" >GuideBridge API Usage</a> 20619 */ 20620 loadAdaptiveForm : function (options) { 20621 if (options && options.path) { 20622 // Let's covert the adaptive form asset path or af path 20623 // @todo: add notion of channel type in the options to load adaptive form 20624 var path = options.path.replace(FM_DAM_ROOT, FM_AF_ROOT); 20625 path += "/jcr:content/guideContainer.html"; 20626 $.ajax({ 20627 url : path, 20628 type : "GET", 20629 data : { 20630 // lets set the wcmmode to disabled 20631 wcmmode : "disabled", 20632 // Set the data reference 20633 "dataRef" : options.dataRef 20634 }, 20635 async : false, 20636 success : function (data) { 20637 // Get the container selector and do a replaceWith HTML 20638 // not using jquery since jquery create a separate array objects for script, link etc 20639 if (options.containerSelector) { 20640 //NOCHECKMARX - data is coming from serverside preventing Reflective XSS All Clients. 20641 $(options.containerSelector).html(data); 20642 } 20643 var guideResultObject = new GuideResultObject(); 20644 // data would here be html 20645 guideResultObject.data = data; 20646 guideResultObject.completed = true; 20647 if (options.success && _.isFunction(options.success)) { 20648 options.success.call(options.context, guideResultObject); 20649 } 20650 }, 20651 error : function (data) { 20652 var guideResultObject = new GuideResultObject();
20653 // data is an object containing xhr request, status and error 20654 guideResultObject.data = data; 20655 guideResultObject.completed = false; 20656 guideResultObject.addMessage(2, "Error in getting HTML of Adaptive Form: " + options.path, ""); 20657 if (options.error && _.isFunction(options.error)) { 20658 options.error.call(options.context, guideResultObject); 20659 } 20660 } 20661 }); 20662 } else { 20663 if (typeof(console) !== "undefined") { 20664 console.log("Path of Adaptive Form not specified to loadAdaptiveForm API"); 20665 } 20666 } 20667 }, 20668 20669 /** 20670 * Unloads the Form loaded using the {@link GuideBridge#loadAdaptiveForm|loadAdaptiveForm} API 20671 * @summary Unloads an adaptive Form from the browser, removing all the existing event listeners, data, html. 20672 * @param containerSelector jQuery Selector of the container, which contains the HTML of the Adaptive Form 20673 * @method 20674 * @memberof GuideBridge 20675 * @since 6.1 FP1 20676 * @instance 20677 * @see {@link https://api.jquery.com/category/selectors/|jQuery selectors} 20678 */ 20679 unloadAdaptiveForm : function (containerSelector) { 20680 guidelib.util.GuideUtil._unloadAdaptiveForm(containerSelector); 20681 }, 20682 20683 /** 20684 * Disables all the fields and global toolbar 20685 * @private 20686 */ 20687 _disableForm : function () { 20688 var rootPanel = guideBridge.resolveNode("guide[0].guide1[0].guideRootPanel[0]"), 20689 globalToolbar = guideBridge.resolveNode("guide[0].guide1[0].toolbar[0]"); 20690 20691 // The following API disables the loaded fields 20692 rootPanel.disableAllFields(); 20693 // The following API disables the form toolbar 20694 if (globalToolbar) { 20695 globalToolbar.disableAllFields(); 20696 } 20697 }, 20698 20699 /** 20700 * @summary Disables the adaptive form, i.e. it disables all the fields and buttons, including toolbar's button 20701 * @method 20702 * @memberof GuideBridge 20703 * @since 6.3 20704 */ 20705 disableForm : function () { 20706 guideBridge._disableForm(); 20707 //Listening on guideBridge for "elementLazyLoaded" event to disable lazily loaded fields 20708 guideBridge.on("elementLazyLoaded", guideBridge._disableForm); 20709 }, 20710 20711 _playGuideJson : function (options) { 20712 this._guide.setGuideState(guidelib.model.GuideSchema.prototype.GuideStateConstants.GUIDE_STATE_MERGE_PROGRESS); 20713 /* 20714 * no need to check here since merged json will not have xfaState if
20715 * xdp is invalid 20716 */ 20717 if (this._isXfaGuide() && options.guideState.xfaState && options.guideState.xfaState.xfaDom) { 20718 var that = this; 20719 window.formBridge.restoreFormState({ 20720 formState : options.guideState.xfaState, 20721 context : this, 20722 //NOCHECKMARX - This is error callback to be provided by the user of this API. 20723 error : options.error || defaultErrorHandler, 20724 success : function () { 20725 that._playNonXfaJson(options); 20726 } 20727 }); 20728 } else { 20729 this._playNonXfaJson(options); 20730 } 20731 }, 20732 20733 _playNonXfaJson : function (options) { 20734 // try to get xml-s from restore state 1st as they will be more relevant than the prefill state 20735 var xmlStr = getOrElse(options, "guideState.guideLiveData", null) 20736 || getOrElse(options, "guideState.guidePrefillXml", null), 20737 xfaXmlStr = getOrElse(options, "guideState.xfaState.currentContext.data", null) 20738 || JSON.parse(getOrElse(options, "guideState.xfaState.xfaRenderContext", "{}")).data, 20739 jsonStr = getOrElse(options, "guideState.guidePrefillJson", null); 20740 if (xmlStr || xfaXmlStr) { 20741 this._guide.internal.liveDataUtils.initLiveData(xmlStr, xfaXmlStr, 20742 _.isString(this._guide.xdpRef), _.isString(this._guide.xsdRef), 20743 this._guide.getAttribute("xsdRootElement")); 20744 this._guide.internal.liveModel.prefillCrossFragFields(this._guide); 20745 this._guide.internal.liveDataUtils.dropXfaXml(); 20746 } else if (jsonStr) { 20747 this._guide.internal.liveDataUtils.initLiveData(jsonStr, this._guide.runtime.guideContext); 20748 } else { 20749 this._guide.internal.liveDataUtils.initLiveData(null, null, 20750 _.isString(this._guide.xdpRef), _.isString(this._guide.xsdRef), 20751 this._guide.getAttribute("xsdRootElement")); 20752 } 20753 20754 // If the restore state is not stored in local storage,then use it from the json passed from the server 20755 if (options.guideState.guideDom) { 20756 this._guide.playJson(options.guideState.guideDom, options.attachments); 20757 } 20758 if (options.guideState.unboundDataMap && options.guideState.unboundDataMap.data) { 20759 this.visit(function (node) { 20760 // Fileupload value should not be set again, as it replaces the url with the file name 20761 if (!(node instanceof guidelib.model.GuideFileUpload) && (node instanceof guidelib.model.Field || node instanceof guidelib.model.GuideCompositeField) 20762 && !node.getAttribute("bindRef") && options.guideState.unboundDataMap.data[node.name]) { 20763 var nodeValue = options.guideState.unboundDataMap.data[node.name]; 20764 //If the xml had empty tag, an empty object will come in the map, so set to null. 20765 if (_.isObject(nodeValue) && _.isEmpty(nodeValue)) { 20766 node._setGuideValue(null); 20767 } else { 20768 node._setGuideValue(nodeValue); 20769 } 20770 20771 if (node.className === "guideRadioButton") { 20772 node.prevOnItem = node.getSelectedIndex(node.jsonModel._value); 20773 } 20774 } 20775 }); 20776 } 20777 this._guide.setGuideState(guidelib.model.GuideSchema.prototype.GuideStateConstants.GUIDE_STATE_MERGE_COMPLETE); 20778 this._guide.prepare(); 20779 20780 if (options.success) { 20781 options.success.call(this); 20782 } 20783 }, 20784 20785 _postExternalMessage : function (message) { 20786 if (this.userConfig["postExternalMessageConfig"] && _.isFunction(this.userConfig["postExternalMessageConfig"]["postExternalHandler"])) { 20787 var externalHandler = this.userConfig["postExternalMessageConfig"]["postExternalHandler"]; 20788 externalHandler(message); 20789 } 20790 }, 20791 20792 _isXfaGuide : function () { 20793 if (this._guide.xdpRef) { 20794 return true; 20795 } else { 20796 return false;
20797 } 20798 }, 20799 _readRuntimeLocale : function (runtimeLocale) { 20800 return this.customContextProperty("runtimeLocale", runtimeLocale); 20801 20802 }, 20803 20804 /* 20805 * checks whether xdp present in Adaptive Form is valid or not 20806 * This is verified by checking the xdpRef property in guideContext 20807 */ 20808 _isValidXFAGuide : function () { 20809 return !_.isUndefined(this._guide.runtime.guideContext.xdpRef); 20810 }, 20811 20812 _isEditDesignMode : function () { 20813 if (window.CQ && window.CQ.WCM && (window.CQ.WCM.isEditMode() || window.CQ.WCM.isDesignMode())) { 20814 return true; 20815 } else { 20816 return false; 20817 } 20818 }, 20819 20820 /** 20821 * @private 20822 */ 20823 _getUUID : function () { 20824 if (this._formInstanceUUID) { 20825 return this._formInstanceUUID; 20826 } 20827 //Generate the UUID for the form instance on client side 20828 this._formInstanceUUID = guideBridge._produceUUID(); 20829 return this._formInstanceUUID; 20830 }, 20831 20832 /** 20833 * This will produce new UUID 20834 * @returns {string} 20835 * @private 20836 */ 20837 _produceUUID : function () { 20838 var uuid = $('div.guideContainerWrapperNode').data("tmproot"), 20839 uuidSuffix = Math.floor((Math.random() * 10000) + 1), 20840 uuidCurrentTime = new Date().getTime(); 20841 return uuid + "_" + uuidCurrentTime + uuidSuffix; 20842 }, 20843 20844 /** 20845 * Signature of the callback for the GuideBridgeEvent Listener. It must be passed as handler in the 20846 * {@link GuideBridge#on|on} API. 20847 * @callback GuideBridge~GuideBridgeEventCallback 20848 * @param {jQuery.Event} event jQuery Event Object with target property being the instance of GuideBridge 20849 * @param {Object} payload Payload containing extra information in the API 20850 * @see {@link http://api.jquery.com/category/events/event-object/|jQuery.Event} 20851 * @since 6.0 20852 */ 20853 /** 20854 * The API can be used to add an event listener for events triggered by GuideBridge object 20855 * 20856 * @summary add a listener on a GuideBridge Event. 20857 * @param eventName {string} name of the event for which listener has to be added. It must be one of the 20858 * following events 20859 * * bridgeInitializeComplete 20860 * * elementEnableChanged 20861 * * elementFocusChanged 20862 * * elementHelpShown 20863 * * elementLazyLoaded 20864 * * elementNavigationChanged 20865 * * elementValidationStatusChanged 20866 * * elementValueChanged 20867 * * elementVisibleChanged: 20868 * * guideAutoSaveStart 20869 * * submitStart 20870 * * validationComplete 20871 * @param {function} handler callback to be invoked whenever the event is triggered. The signature of the 20872 * callback is {@link GuideBridge~GuideBridgeEventCallback|GuideBridgeEventCallback} 20873 * @param {object} [context] The _this_ object in the _handler_ will point to _context_ 20874 * 20875 * @method on 20876 * @memberof GuideBridge 20877 * @instance 20878 * @since 6.0 20879 */ 20880 on : function (eventName, handler, context) { 20881 this._$target.on(eventName, handler, context); 20882 }, 20883 20884 /** 20885 * Unregister the event registered using the {@link GuideBridge#on|on} function 20886 * 20887 * @param eventName {string} name of the event to un-register. 20888 * @param [selector] {string} selector which should match the one originally passed to guideBridge's on() while registering handlers 20889 * @param [handler] {function} handler which needs to un-registered. If not provided all the event listeners 20890 * will be unregistered 20891 * 20892 * @method off 20893 * @memberof GuideBridge 20894 * @instance 20895 * @since 6.0 20896 */ 20897 20898 off : function (eventName, selector, handler) { 20899 this._$target.off(eventName, selector, handler); 20900 }, 20901 20902 /** 20903 * Internal API 20904 * @param extraParamerts 20905 * @param eventName 20906 * @private 20907 */ 20908 trigger : function (eventName, extraParamerts) { 20909 this._$target.trigger(eventName, extraParamerts); 20910 }, 20911 20912 /** 20913 * If the name of the file attachments have to be made unique then the 20914 * vaule of this function would be true else false 20915 * @returns {*} 20916 * @private 20917 */ 20918 _makeFileNameUnique : function () { 20919 if (this._guide && this._guide.runtime && this._guide.runtime.guideContext) { 20920 return this._guide.runtime.guideContext.makeFileNameUnique; 20921 } 20922 }, 20923 /*this function is used to mince out 20924 * file attachmenemts name and dom in case of 20925 * anonymous user 20926 * */ 20927 _getFileNameFileDomMap : function () { 20928 var fileAttachmentsList = this._getFileAttachmentsList(); 20929 return this._juiceOutNameAndFileDomMap(fileAttachmentsList); 20930 }, 20931 20932 /** 20933 * Returns a list of file attachment wrapper object represeting all file binaries 20934 * @returns reference of {@link guidelib.model.FileAttachmentWrapper} 20935 * @method 20936 * @memberof GuideBridge 20937 * @since FaaCS 20938 * @instance 20939 */ 20940 getFileAttachmentWrapper : function () { 20941 var fileNameDomBindRefMap = this._getFileNameFileDomMap(), 20942 attachments = [], 20943 fileDoms = fileNameDomBindRefMap.fileDom, 20944 fileNames = fileNameDomBindRefMap.fileName, 20945 bindRefs = fileNameDomBindRefMap.fileBindRef, 20946 contentTypes = fileNameDomBindRefMap.fileContentType, 20947 _getFileName = function (fileName, componentName) { 20948 // if file name contains component name 20949 if (fileName.indexOf(componentName) !== -1) { 20950 return fileName.replace(componentName + "/", ""); 20951 } else if (fileName.indexOf("/") !== -1) { 20952 // if file name is a URL 20953 return fileName.substring(fileName.lastIndexOf('/') + 1); 20954 } 20955 }; 20956 20957 var fileNamesIndex; 20958 for (fileNamesIndex = 0; fileNamesIndex < fileNames.length; fileNamesIndex++) { 20959 // multiple files inside one filedom element & draft save case is handled. 20960 var currentFileNames = fileNames[fileNamesIndex].split("\n"); 20961 for (var fileIndex = 0; fileIndex < currentFileNames.length; fileIndex++) { 20962 if (fileDoms[fileNamesIndex] && !_.isString(fileDoms[fileNamesIndex]) && fileDoms[fileNamesIndex].length > 0) { 20963 // append each file of input file element 20964 attachments.push(new guidelib.model.FileAttachmentWrapper({ 20965 name : _getFileName(currentFileNames[fileIndex], bindRefs[fileNamesIndex]), 20966 data : fileDoms[fileNamesIndex][0].files[fileIndex], 20967 contentType : fileDoms[fileNamesIndex][0].files[fileIndex].type, 20968 bindRef : bindRefs[fileNamesIndex] 20969 })); 20970 } else if (currentFileNames[fileIndex]) { 20971 //handle draft save scenario when fileDoms[fileNamesIndex] is null & currentFileNames[fileIndex] is a url 20972 attachments.push(new guidelib.model.FileAttachmentWrapper({ 20973 name : _getFileName(guideBridge._getRelativeFilePath(currentFileNames[fileIndex]), bindRefs[fileNamesIndex]), 20974 data : fileDoms[fileNamesIndex], 20975 contentType : contentTypes[fileNamesIndex], 20976 bindRef : bindRefs[fileNamesIndex] 20977 })); 20978 20979 } 20980 } 20981 } 20982 return attachments; 20983 }, 20984 20985 /** 20986 * Returns the file attachment name and dom (input type=file) element
20987 * The returned object contains a list of file Doms and a list of corresponding file Names. 20988 * If the file is already uploaded, then the file DOM is null and file Name contains the URL. 20989 * @param fileAttachmentsList object list of file attachment models 20990 * @returns {{fileName: Array, fileDom: Array}} 20991 * @private 20992 */ 20993 _juiceOutNameAndFileDomMap : function (fileAttachmentsList) { 20994 var fileDoms = [], 20995 fullFileNames = [], 20996 fullContentTypes = [], 20997 fileBindRefs = [], 20998 fileContentTypes = [], 20999 fileCount = 0, 21000 loadedFileDoms = [], 21001 loadedBindRefs = [], 21002 loadedContentTypes = [], 21003 loadedFileNames = []; 21004 21005 _.each(fileAttachmentsList, function (fileAttachmentModel, index) { 21006 var fileName = fileAttachmentModel._getFileAttachmentNames(), 21007 fileAttachmentModelValue = fileAttachmentModel.value, 21008 effectiveBindRef = fileAttachmentModel._getEffectiveBindRef(), 21009 fileNameList = fileName; // even in case of makeFileNameUnique context set, fileName has the correct unique value 21010 if (fileNameList) { 21011 var fileNames = fileNameList.split("\n"); 21012 var fileList = $.extend(true, [], fileAttachmentModel.fileList); 21013 var fileNamesIndex = 0; 21014 21015 _.each(fileList, function (inputFileDOM, currIndex) { 21016 var fileNamesOfFileDom = null; 21017 21018 // case: if there is a file dom 21019 if (!_.isString(inputFileDOM)) { 21020 _.each(inputFileDOM[0].files, function (file) { 21021 var fileName = fileNames[fileNamesIndex++]; 21022 if (fileName) { 21023 if (fileNamesOfFileDom) { 21024 fileNamesOfFileDom += "\n" + fileAttachmentModel.name + "/" + fileName; 21025 } else { 21026 fileNamesOfFileDom = fileAttachmentModel.name + "/" + fileName; 21027 } 21028 } 21029 }); 21030 if (fileNamesOfFileDom != null) { 21031 // Check if the value exist in the file, this is done because in IE9 and IE10 the list 21032 // will have an extra empty dom 21033 if ($(inputFileDOM).val().length > 0) { 21034 $(inputFileDOM).attr('name', fileNamesOfFileDom); 21035 loadedFileNames[fileCount] = fileNamesOfFileDom; 21036 loadedBindRefs[fileCount] = effectiveBindRef; 21037 // since the api is internal, we are not setting this 21038 loadedContentTypes[fileCount] = null; // we don't set "\n" separated content type here 21039 loadedFileDoms[fileCount++] = $(inputFileDOM); 21040 } 21041 } 21042 } else { 21043 // these values are nothing but field present as part of guidelib.model.FileAttachmentWrapper 21044 // @note: to minimize the refactoring, not reusing the same model 21045 // since there is no file dom in case of draft reload, make it null 21046 loadedFileNames[fileCount] = fileAttachmentModel.name + "/" + fileNames[currIndex]; 21047 loadedBindRefs[fileCount] = effectiveBindRef; // we add effective bindRef here 21048 loadedContentTypes[fileCount] = fileAttachmentModel._getContentType(fileList[currIndex]); // we add effective bindRef here 21049 loadedFileDoms[fileCount++] = fileList[currIndex]; // we add the file URL in fileDom 21050 fileNamesIndex++; 21051 } 21052 }, this); 21053 21054 } 21055 }, this); 21056 21057 // create the dom and name map for lazy file upload components as well 21058 var lazyFileMap = this._guide.internal.liveDataUtils._getLazyAttachmentMap(), 21059 lazyFileDom = [], 21060 lazyFileBindRef = [], 21061 lazyFileContentType = [], 21062 lazyFileName = []; 21063 _.each(lazyFileMap, function (mapObject, key) { 21064 var fileList = mapObject.fileList; 21065 var fileUploadValue = mapObject.value.split("\n"); 21066 var fileUploadBindRef = mapObject.bindRef; 21067 var fileNames = mapObject.fileNames.split("\n"); 21068 var fileNamesIndex = 0; 21069 _.each(fileList, function (value) { 21070 if (!_.isString(value)) { 21071 var fileNamesOfFileDom = null; 21072 _.each(value[0].files, function (file) { 21073 var fileName = fileUploadValue[fileNamesIndex++]; 21074 if (fileName) { 21075 var fullName = guidelib.util.GuideUtil.guideSomToComponentName(key) + "/" + fileName; 21076 if (fileNamesOfFileDom) { 21077 fileNamesOfFileDom += "\n" + fullName; 21078 } else { 21079 fileNamesOfFileDom = fullName; 21080 } 21081 } 21082 }); 21083 21084 lazyFileDom.push(value); 21085 lazyFileName.push(fileNamesOfFileDom); 21086 } else { 21087 var fullName = guidelib.util.GuideUtil.guideSomToComponentName(key) + "/" + fileNames[fileNamesIndex]; 21088 lazyFileDom.push(value); 21089 lazyFileName.push(fullName); 21090 fileNamesIndex++; 21091 } 21092 lazyFileBindRef.push(fileUploadBindRef); 21093 lazyFileContentType.push(null); // todo: check if this use-case would ever hit 21094 }); 21095 }); 21096 21097 // concatenate the arrays for loaded and unloaded file doms and names 21098 fileDoms = loadedFileDoms.concat(lazyFileDom); 21099 fullFileNames = loadedFileNames.concat(lazyFileName); 21100 fileBindRefs = loadedBindRefs.concat(lazyFileBindRef); 21101 fileContentTypes = loadedContentTypes.concat(lazyFileContentType); 21102 21103 return { 21104 "fileName" : fullFileNames, 21105 "fileDom" : fileDoms, 21106 "fileBindRef" : fileBindRefs,
21107 "fileContentType" : fileContentTypes 21108 }; 21109 }, 21110 21111 setValidationContext : function (context) { 21112 var ec = guidelib.util.ErrorConstants; 21113 if (typeof ec[context] === "number") { 21114 var nContext = ec[context]; 21115 if (nValidationContext < nContext) { 21116 nValidationContext = nContext; 21117 sValidationContext = context; 21118 } 21119 } 21120 }, 21121 21122 unsetValidationContext : function (context) { 21123 if (context === sValidationContext) { 21124 nValidationContext = 0; 21125 sValidationContext = ""; 21126 } 21127 }, 21128 21129 getValidationContext : function () { 21130 return sValidationContext; 21131 }, 21132 21133 /** 21134 * @summary Enable/Disable the swipe gesture for navigation on touch devices. 21135 * @param swiptLeft boolean flag to enable(true)/disable(false) the swipe left gesture to perform next item navigation 21136 * @param swipeRight boolean flag to enable(true)/disable(false) the swipe right gesture to perform previous item navigation 21137 * @method 21138 * @memberof GuideBridge 21139 * @instance 21140 * @since 6.3 21141 */ 21142 enableSwipeGesture : function (swiptLeft, swipeRight) { 21143 $guideWrapperNode = $('.guideContainerWrapperNode'); 21144 $guideWrapperNode.off('swipeleft', window.guideBridge._performItemDeepNavigationNext); 21145 $guideWrapperNode.off('swiperight', window.guideBridge._performItemDeepNavigationPrevious); 21146 if (swiptLeft) { 21147 $guideWrapperNode.on('swipeleft', window.guideBridge._performItemDeepNavigationNext); 21148 } 21149 if (swipeRight) { 21150 $guideWrapperNode.on('swiperight', window.guideBridge._performItemDeepNavigationPrevious); 21151 } 21152 }, 21153 21154 /** 21155 * Enable the next item navigation (deep) using swipe left gesture 21156 * @private 21157 */ 21158 _performItemDeepNavigationNext : function () { 21159 window.guideBridge.setFocus({ 21160 somExpression : null, 21161 focusOption : 'nextItemDeep', 21162 runCompletionScript : true, 21163 skipFieldFocus : true 21164 }); 21165 }, 21166 21167 /** 21168 * Enable the previous item navigation (deep) using swipe right gesture 21169 * @private 21170 */ 21171 _performItemDeepNavigationPrevious : function () { 21172 window.guideBridge.setFocus({ 21173 somExpression : null, 21174 focusOption : 'prevItemDeep', 21175 runCompletionScript : true, 21176 skipFieldFocus : true 21177 }); 21178 }, 21179 21180 /** 21181 * Update the model popup that appears at click of file attachment listing button 21182 * This function is currently run of the clickExp of fileAttachmentListingButton 21183 * @param node 21184 * @private 21185 */ 21186 _updateFileListing : function (node) { 21187 var somExpression = node.somExpression, 21188 viewOfListingButton = guideBridge._guideView.getView(somExpression); 21189 viewOfListingButton._clearFileListing(); 21190 guideBridge.visit($.proxy(viewOfListingButton._updateFileListing, viewOfListingButton)); 21191 21192 }, 21193 21194 registerPanelProvider : function (panelProvider) { 21195 var resultObj = new GuideResultObject(); 21196 if (this.panelProvider == null) { 21197 resultObj.data = panelProvider; 21198 this.panelProvider = panelProvider; 21199 return resultObj; 21200 } 21201 resultObj.addMessage(2, "registrationError: PanelProvider already registered", ""); 21202 return resultObj; 21203 } 21204 }); 21205 21206 window.guideBridge = new GuideBridge(); 21207 window.guideBridge._$target = $(window.guideBridge); 21208 window.guideBridge.on("af.invisibleMandatoryRecaptchaInitialization", function (event, data) { 21209 var model = data.jsonModel.target.jsonModel; 21210 var formContainerSelector = FD.isToggleEnabled("FT_FORMS-11858") ? guidelib.util.GuideUtil.GUIDE_CONTAINER_FORM_CLASS : ".guideContainer,.aemformcontainer"; 21211 $(formContainerSelector).append('<div id="captchaInvisible"></div>'); 21212 var captchaInvisibleElement = $("#captchaInvisible"), captchaElement = $("[data-captchaservice]"); 21213 21214 captchaInvisibleElement.attr({ 21215 "modelId" : model.id || model.templateId, 21216 "af-recaptcha-execute" : "", 21217 "data-locale" : captchaElement.attr("data-locale") 21218 }); 21219 21220 if (model.captchaService === 'turnstile') { 21221 captchaInvisibleElement.on("recaptchaExecution", guidelib.util.CaptchaUtil.captchaExecution); 21222 var turnstileParameters = { 21223 'sitekey' : model.siteKey, 21224 'theme' : model.theme || 'light', 21225 'size' : model.size, 21226 'language' : captchaElement.attr('data-locale'), 21227 'execution' : 'execute' 21228 }; 21229 guidelib.util.CaptchaUtil.renderCaptcha(captchaInvisibleElement, model, 21230 model.clientJsUrl, 'cf-turnstile-response', turnstileParameters); 21231 } else if (model.captchaService === 'hcaptcha') { 21232 captchaInvisibleElement.on("recaptchaExecution", guidelib.util.CaptchaUtil.captchaExecution); 21233 var hcaptchaParameters = { 21234 'sitekey' : model.siteKey, 21235 'theme' : model.theme || 'light', 21236 'size' : model.size, 21237 }; 21238 guidelib.util.CaptchaUtil.renderCaptcha(captchaInvisibleElement, model, 21239 model.clientJsUrl, 'h-captcha-response', hcaptchaParameters); 21240 } else { 21241 captchaInvisibleElement.attr({ 21242 "data-externaldomain" : captchaElement.attr("data-externaldomain") 21243 }); 21244 captchaInvisibleElement.on("recaptchaExecution", guidelib.util.RecaptchaUtil.recaptchaExecution); 21245 guidelib.util.RecaptchaUtil.renderRecaptcha(captchaInvisibleElement, model); 21246 } 21247 }); 21248 21249 try { 21250 var evnt = document.createEvent("CustomEvent"); 21251 evnt.initCustomEvent("bridgeInitializeStart", true, true, {"guideBridge" : window.guideBridge}); 21252 window.dispatchEvent(evnt); 21253 } catch (exception) { 21254 // written for env rhino to execute(for server side validation) 21255 // todo: once env rhino implements CustomEvent and initCustomEvent remove this 21256 // this._guide.logger().log(exception); 21257 } 21258 21259 if (!window.guideBridge.userConfig["postExternalMessageConfig"]) { 21260 if (window !== window.parent) { 21261 try { 21262 window.parent.document.getElementById(window.name); 21263 //We are here means no cross domain issue. So if user has not defined custom postExternalMessageConfig and 21264 // then we'll create one which would just send event on parent. 21265 window.guideBridge.registerConfig("postExternalMessageConfig", { 21266 "postExternalHandler" : function (message) { 21267 try { 21268 var tmpEvent = document.createEvent("CustomEvent"); 21269 tmpEvent.initCustomEvent(message.name, true, true, message.data); 21270 window.parent.dispatchEvent(tmpEvent); 21271 } catch (exception) { 21272 // written for env rhino to execute 21273 //this._guide.logger().log(exception); 21274 } 21275 } 21276 }); 21277 } catch (e) { 21278 //ignore the error 21279 } 21280 } 21281 } 21282 21283 window.guideBridge._postExternalMessage({ 21284 name : "bridgeInitializeStart", 21285 data : { 21286 "guideBridge" : window.guideBridge 21287 } 21288 }); 21289})($, _); 21290 21291/** 21292 * @package guidelib.model.DataNode 21293 * @version 0.0.1 21294 */ 21295 21296(function ($, _, guideBridge, guidelib, formBridge, xfalib) { 21297 21298 var LiveDataUtils = guidelib.model.LiveDataUtils = xfalib.ut.Class.extend({ 21299 21300 constants : { 21301 SKELETON_XML : '<afData><afUnboundData><data/></afUnboundData><afBoundData><data xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/"/></afBoundData></afData>', 21302 SKELETON_JSON : '{"afData":{"afUnboundData":{"data":{}},"afBoundData":{"data":{}}}}', 21303 UNBOUND_SKELETON : '<unBound></unBound>', 21304 UNBOUND_JSON_SKELETON : '{"afUnboundData":{}}', 21305 INDEXED_XPATH_PAT : new RegExp(/\/[^\/]+\[\d+\]/), 21306 INDEXED_XPATH_PAT_JSON : new RegExp(/\/[^\/]+\/\d+/), 21307 XFA_DATA_NODE_ATTR_NAME : "xfa:dataNode", 21308 XFA_DATA_NODE_ATTR_VALUE : "dataGroup", 21309 UNKNOWN_XSD_ROOT_ELEMENT : "?", 21310 AF_ROOT_TAG : "afData", 21311 BOUND_TAG : "afBoundData", 21312 UNBOUND_TAG : "afUnboundData", 21313 XFA_TAG : "xfa", 21314 DATA_TAG : "data", 21315 BOUND_DATA_XPATH : "afBoundData/data", 21316 UNBOUND_DATA_XPATH : "afUnboundData/data", 21317 AF_DRAFT_TAG : "afSubmissionInfo/afDraft" 21318 }, 21319 21320 initialize : function () { 21321 LiveDataUtils._super.initialize.call(this); 21322 this._boundDataRoot = null; 21323 this._unboundDataRoot = null; 21324 this._xfaDataRoot = null; 21325 this._fetchingClientSideData = false; // this state indicates that we are fetching client side data, its not use-case to fetch lazy data 21326 this.lazyAttachmentMap = {}; 21327 this.attachments = []; 21328 }, 21329 21330 /** 21331 * This function updates the lazy attachment Map from 21332 * the map passed 21333 * @param fileAttachmentMap 21334 * @private 21335 */ 21336 _updateLazyAttachmentMap : function(fileAttachmentMap) { 21337 _.each(fileAttachmentMap, function (value, key) { 21338 this.lazyAttachmentMap[key] = {}; 21339 this.lazyAttachmentMap[key].fileList = value.split("\n"); 21340 this.lazyAttachmentMap[key].value = value; 21341 }, this); 21342 }, 21343 21344 /** 21345 * This function updates the lazy attachment Map from the model. 21346 * It gets the value and fileList from the model and updates the map. 21347 * If the fileUpload component is not in a lazy panel then it removes 21348 * its entry form the map(if the entry is already there). 21349 * @param model 21350 * @private 21351 */ 21352 _updateLazyAttachmentMapFromModel : function (model) { 21353 // add the component in the map only when its in a lazy panel 21354 // add the entry in map only when its not not empty 21355 if (model.parent._selfOrAncestorIsLazyReference && model.value && model.fileList && !this._fetchingClientSideData) { 21356 this.lazyAttachmentMap[model.somExpression] = { 21357 value : model.value, 21358 fileList : model.fileList, 21359 bindRef : model._getEffectiveBindRef(), 21360 fileNames : model._getFileAttachmentNames() 21361 }; 21362 } else { 21363 if (this.lazyAttachmentMap[model.somExpression]) { 21364 delete this.lazyAttachmentMap[model.somExpression]; 21365 } 21366 } 21367 }, 21368 21369 /** 21370 * This function returns the value in the lazy attachment map for the model. 21371 * It removes the entry from the map as well. This is required so that the map gets 21372 * updated with the new values when the panel unloads. 21373 * @param model 21374 * @returns {*} 21375 * @private 21376 */ 21377 _getAttachmentDataForModel : function (model) { 21378 var effectiveBindRef = model._getEffectiveBindRef(); 21379 if (model.somExpression && !_.isEmpty(this.lazyAttachmentMap)) { 21380 var data = this.lazyAttachmentMap[model.somExpression]; 21381 delete this.lazyAttachmentMap[model.somExpression]; 21382 return data; 21383 } 21384 if (effectiveBindRef && !_.isEmpty(this.attachments)) { 21385 var data = model._getCurrentFileAttachmentWrapper(this.attachments); 21386 return data; 21387 } 21388 }, 21389 21390 _getLazyAttachmentMap : function () { 21391 return this.lazyAttachmentMap; 21392 }, 21393 21394 dropXfaXml : function () { 21395 this._xfaDataRoot = null; 21396 }, 21397 21398 // only called from test framework 21399 destroy : function () { 21400 this._liveDataDoc = null; 21401 this._boundDataRoot = null; 21402 this._unboundDataRoot = null; 21403 this._xfaDataRoot = null; 21404 }, 21405 21406 initLiveData : function (prefillDataStr, xfaPrefillDataStr, isXdp, isXsd, xsdRootElement, attachments) { 21407 this.attachments = attachments; 21408 }, 21409 21410 isLiveDataInitialized : function () { 21411 }, 21412 21413 getLiveDataStr : function () { 21414 }, 21415 21416 getLiveDataDoc : function () { 21417 return this._liveDataDoc; 21418 }, 21419 21420 _isNonNaked : function () { 21421 }, 21422 21423 _getNameAndIndex : function (xpathPart) { 21424 }, 21425 21426 isIndexedPath : function (xpath) { 21427 }, 21428 21429 _createElements : function (contextNode, xpathParts) { 21430 }, 21431 21432 _createRepeatedElements : function (contextNode, xpathParts) { 21433 }, 21434 21435 _createChildElement : function (parentElement, elemName) { 21436 }, 21437 21438 _createAttributeNode : function (parentElement, attrName) { 21439 }, 21440 21441 getContextNode : function (schemaPath, dataSection, createMissingNodes, lastNodeValue) { 21442 }, 21443 21444 addIndexToPath : function (path, index) { 21445 }, 21446 21447 _getElement : function (node, xpath, options) {}, 21448 21449 hasChildNodes : function (node) { 21450 }, 21451 21452 /** 21453 * Removes a child node from its parent 21454 * @param parentNode {Node} Parent Node from which to remove the child node 21455 * @param targetNode {String} Node name of the child to remove 21456 * @param index Index of the child node to remove 21457 */ 21458 removeChild : function (parentNode, targetNodeName, index) { 21459 }, 21460 21461 insertNode : function (parentNode, childNodeName, index) { 21462 }, 21463 21464 _getDataContext : function (model, bound_indexedXpathSoFar, unBound_indexedXpathSoFar) { 21465 var bindRef = model.bindRef, 21466 liveDataUtils = this, 21467 xmlSec, 21468 indexedXpath; 21469 21470 if (model._isXfaNode()) { 21471 xmlSec = liveDataUtils.constants.XFA_TAG; 21472 indexedXpath = xfalib.ut.XMLUtils.dataSom2xpath(model.dataSom); 21473 } else if (_.isEmpty(bindRef)) { 21474 xmlSec = liveDataUtils.constants.UNBOUND_TAG; 21475 indexedXpath = unBound_indexedXpathSoFar + '/' + model.getAttribute("name").replace(/\s+/g, ''); 21476 // use attr 'name' here, as schema might have an elem called 'name' 21477 } else { 21478 xmlSec = liveDataUtils.constants.BOUND_TAG; 21479 21480 var xpathMatch = liveDataUtils.getMatchingXpathHierarchy(bou
21480nd_indexedXpathSoFar, bindRef); 21481 if (xpathMatch.isCrossHierarchy) { 21482 indexedXpath = bindRef; 21483 } else { 21484 indexedXpath = bound_indexedXpathSoFar; 21485 if (!_.isEmpty(xpathMatch.suffixParts)) { 21486 indexedXpath += '/' + xpathMatch.suffixParts.join('/'); 21487 } 21488 } 21489 } 21490 21491 return { 21492 'xmlSec' : xmlSec, 21493 'indexedXpath' : indexedXpath 21494 }; 21495 }, 21496 21497 /** 21498 * return true if both xpath parts have same element name and indices 21499 * absence of index in the templateName is ignored 21500 * @param indexedName 21501 * @param templateName 21502 * @returns {boolean} 21503 * @private 21504 * @memberof LiveDataUtils 21505 */ 21506 _cmpXpathParts : function (indexedName, templateName) { 21507 }, 21508 21509 /** 21510 * get a partition of the matching xpath part hierarchy 21511 * the matching parts have same element names and agreeable indices 21512 * @param parentXpath 21513 * @param currentXpath 21514 * @returns {{prefixParts: Array, suffixParts: (*|Array.<T>|list), isCrossHierarchy: boolean}} 21515 * @memberof LiveDataUtils 21516 */ 21517 getMatchingXpathHierarchy : function (parentXpath, currentXpath) { 21518 var isCrossHierarchy = false, 21519 prefixParts = [], 21520 suffixParts = this._sanitizedXpathParts(currentXpath); 21521 21522 _.find(this._sanitizedXpathParts(parentXpath), function (parentPart) { 21523 if (this._cmpXpathParts(parentPart, suffixParts[0])) { 21524 prefixParts.push(parentPart); 21525 suffixParts.shift(); 21526 } else { 21527 isCrossHierarchy = true; 21528 return true; 21529 } 21530 }, this); 21531 21532 return { 21533 'prefixParts' : prefixParts, 21534 'suffixParts' : suffixParts, 21535 'isCrossHierarchy' : isCrossHierarchy 21536 }; 21537 }, 21538 21539 _getXpathContext : function (targetPanel) { 21540 var boundXpath = '', 21541 unBoundXpath = '', 21542 ancestors = [], 21543 panel = targetPanel.parent; 21544 21545 while (panel instanceof guidelib.model.GuidePanel) { 21546 if (panel._preserveLazyValue()) { 21547 ancestors.unshift(panel); 21548 } 21549 panel = panel.parent; 21550 } 21551 21552 _.each(ancestors, function (ancestor) { 21553 var xmlContext = ancestor._syncModelAndData(boundXpath, unBoundXpath); 21554 boundXpath = xmlContext.bound; 21555 unBoundXpath = xmlContext.unBound; 21556 }); 21557 21558 return { 21559 'bound' : boundXpath, 21560 'unBound' : unBoundXpath 21561 }; 21562 }, 21563 21564 _applyOnLiveData : function (action, targetPanel) { 21565 if (_.isString(targetPanel)) { 21566 targetPanel = guideBridge.resolveNode(targetPanel); 21567 } 21568 21569 if (targetPanel instanceof guidelib.model.GuidePanel) { 21570 var indexedXpathsFromRoot = targetPanel._guide().internal.liveDataUtils._getXpathContext(targetPanel); 21571 targetPanel[action](indexedXpathsFromRoot.bound, indexedXpathsFromRoot.unBound); 21572 } else { 21573 guideBridge._guide.rootPanel[action]('', ''); 21574 } 21575 }, 21576 21577 /** 21578 * will capture the currently loaded model hierarchy in a xml doc to be referred to later by lazily loaded panels 21579 * @private 21580 * @memberof LiveDataUtils 21581 */ 21582 updateLiveData : function (targetPanel, fetchingClientSideData) { 21583 this._fetchingClientSideData = !_.isUndefined(fetchingClientSideData); 21584 this._applyOnLiveData('_updateLiveData', targetPanel); 21585 this._fetchingClientSideData = false; 21586 }, 21587 21588 /** 21589 * will replay the model hierarchy from the live xml, for the supplied panel 21590 * @param targetPanel 21591 * @private 21592 * @memberof LiveDataUtils 21593 */ 21594 playLiveData : function (targetPanel) { 21595 this._applyOnLiveData('_playLiveData', targetPanel); 21596 }, 21597 21598 getListOfDirtyPanels : function (dataString) { 21599 return []; 21600 }, 21601 21602 addDataNodeInfo : function (contextNode) { 21603 }, 21604 21605 /** 21606 * Set the value of the node referred by xpath in the bounded/unbounded 21607 * section as specified by section. This optionally creates the data nodes 21608 * if they are not present 21609 * @param xpath 21610 * @param section 21611 * @param createMissingNodes 21612 * @param value 21613 */ 21614 setDataValue : function (xpath, section, createMissingNodes, value) { 21615 }, 21616 21617 /** 21618 * Set the rich text(html) value of the node referred by xpath in the bounded/unbounded 21619 * section as specified by section. This optionally creates the data nodes 21620 * if they are not present 21621 * @param xpath 21622 * @param xmlSection 21623 * @param createMissingNodes 21624 * @param value 21625 */ 21626 setRichTextValue : function (xpath, xmlSection, createMissingNodes, value) { 21627 this.setDataValue(xpath, xmlSection, createMissingNodes, value); 21628 }, 21629 21630 /** 21631 * Returns the value of the node referred by xpath in the bounded/unbounded 21632 * section as specified by section. It returns undefined if the node doesn't 21633 * exist 21634 * @param xpath 21635 * @param section 21636 */ 21637 getDataValue : function (xpath, section) { 21638 }, 21639 21640 _convertModelIndexToDataIndex : function (index) { 21641 }, 21642 21643 getParentRef : function (path) { 21644 }, 21645 21646 /** 21647 * returns the parent data node for the context specified by dataNodeContext 21648 * @param dataNodeContext {object} containing xpath and section 21649 * @param createIfMissing 21650 * @returns {*} 21651 * @param parentNodeValue 21652 */ 21653 getParentDataNode : function (dataNodeContext, createIfMissing, parentNodeValue) {
21654 var parentRef = this.getParentRef(dataNodeContext.indexedXpath), 21655 parentNode; 21656 if (_.isEmpty(parentRef)) { 21657 parentNode = this.getContextNode("", dataNodeContext.xmlSec, false); 21658 } else { 21659 parentNode = this.getContextNode(parentRef, dataNodeContext.xmlSec, createIfMissing, parentNodeValue); 21660 } 21661 return parentNode; 21662 }, 21663 21664 21665 /** 21666 * Insert submission Info in the data 21667 * @param submissionInfo {object} object containing the properties to be added as submission info in data 21668 */ 21669 insertSubmissionInfo : function (submissionInfo) { 21670 21671 } 21672 21673 }); 21674 21675}($, _, window.guideBridge, window.guidelib, window.formBridge, window.xfalib)); 21676 21677/** 21678 * @package guidelib.model.DataNode 21679 * @version 0.0.1 21680 */ 21681 21682(function ($, _, guideBridge, guidelib, formBridge, xfalib) { 21683 var getOrElse = xfalib.ut.XfaUtil.prototype.getOrElse; 21684 21685 var LiveJsonUtils = guidelib.model.LiveJsonUtils = guidelib.model.LiveDataUtils.extend({ 21686 21687 initialize : function () { 21688 LiveJsonUtils._super.initialize.call(this); 21689 this._liveDataDoc = null; 21690 }, 21691 21692 initLiveData : function (prefillDataStr, guideContext) { 21693 LiveJsonUtils._super.initLiveData.apply(this, arguments); 21694 prefillDataStr = prefillDataStr || getOrElse(guideContext, "guidePrefillJson", null); 21695 21696 if (_.isString(prefillDataStr) && prefillDataStr.length > 0) { 21697 var prefillDataDoc = JSON.parse(prefillDataStr); 21698 21699 if (this._isNonNaked(prefillDataDoc)) { 21700 // non naked json, assuming full hierarchy afdata/afbounddata/data 21701 this._liveDataDoc = prefillDataDoc; 21702 this._boundDataRoot = this._getElement(this._liveDataDoc.afData, this.constants.BOUND_DATA_XPATH); 21703 this._unboundDataRoot = this._getElement(this._liveDataDoc.afData, this.constants.UNBOUND_DATA_XPATH); 21704 21705 } else { 21706 // naked json start from prefill data root 21707 this._boundDataRoot = prefillDataDoc; 21708 this._unboundDataRoot = JSON.parse(this.constants.UNBOUND_JSON_SKELETON)[this.constants.UNBOUND_TAG]; // need this for unbound data fill across lazy 21709 this._liveDataDoc = prefillDataDoc; 21710 } 21711 } else { 21712 // init default skeleton for no prefill cases 21713 this._liveDataDoc = JSON.parse(this.constants.SKELETON_JSON); 21714 this._boundDataRoot = this._getElement(this._liveDataDoc.afData, this.constants.BOUND_DATA_XPATH); 21715 this._unboundDataRoot = this._getElement(this._liveDataDoc.afData, this.constants.UNBOUND_DATA_XPATH); 21716 } 21717 if (this._boundDataRoot == null && this._isNonNaked(prefillDataDoc)) { 21718 this._liveDataDoc.afData.afBoundData = this._liveDataDoc.afData.afBoundData || {}; 21719 this._liveDataDoc.afData.afBoundData.data = this._liveDataDoc.afData.afBoundData.data || {}; 21720 this._boundDataRoot = this._liveDataDoc.afData.afBoundData.data; 21721 } 21722 }, 21723 21724 /* 21725 * This API gets the element w.r.t to the node. 21726 * Eg - path is a/b/c, then it converts the path to a.b.c and then searches for c. 21727 */ 21728 _getElement : function (node, path, options) { 21729 if (!(node instanceof Object)) { 21730 return null; 21731 } 21732 21733 if (_.isEmpty(path) || !_.isString(path)) { 21734 return node; 21735 } 21736 options = options || {}; 21737 var index = options.index; 21738 var convertedPath = path.split('/').join('.'); 21739 if (!(_.isUndefined(index) || _.isNull(index))) { 21740 convertedPath = convertedPath + "." + index; 21741 } 21742 return getOrElse(node, convertedPath, null); 21743 }, 21744 21745 /** 21746 * This function checks if the data contains naked or non naked json 21747 * @returns {boolean} returns true if there exists a afData node inside data 21748 * @private 21749 * @memberof LiveJsonUtils 21750 * @param prefillData 21751 */ 21752 _isNonNaked : function (prefillData) { 21753 prefillData = prefillData || this.getLiveDataDoc(); 21754 if (prefillData) { 21755 return prefillData.hasOwnProperty("afData"); 21756 } else { 21757 return false;
21758 } 21759 }, 21760 21761 isLiveDataInitialized : function () { 21762 return (this.getLiveDataDoc() instanceof Object); 21763 }, 21764 21765 getLiveDataStr : function () { 21766 if (this.isLiveDataInitialized()) { 21767 return JSON.stringify(this.getLiveDataDoc()); 21768 } else { 21769 return ''; 21770 } 21771 }, 21772 21773 /* 21774 * This API will remove the spaces,"\" from the path. 21775 * It will return an array after splitting the path. 21776 * Eg - for a/0/b/c, it will return ["a/0","b","c"] 21777 */ 21778 _sanitizedXpathParts : function (path) { 21779 var pathParts = (path || '').replace(/^\//, '').replace(/\s+/g, ''); 21780 pathParts = this._splitForIndex(pathParts); 21781 21782 return _.filter(pathParts, function (xpathPart) { 21783 return this._getNameAndIndex(xpathPart) !== null; 21784 }, this); 21785 }, 21786 21787 _splitForIndex : function (path) { 21788 var pathArray = []; 21789 var pathParts = path.split('/'); 21790 for (var i = 0; i < pathParts.length; i++) { 21791 var str = pathParts[i]; 21792 if ((i + 1) < pathParts.length && !isNaN(pathParts[i + 1]) && !_.isEmpty(pathParts[i + 1])) {
21793 str = str + "/" + pathParts[i + 1]; 21794 i = i + 1; 21795 } 21796 pathArray.push(str); 21797 } 21798 return pathArray; 21799 }, 21800 21801 /** 21802 * Returns the index associated with the pathPart. 21803 * Eg - if pathPart is 'a/1', then it returns {name : a, index : 1} 21804 * @param pathPart 21805 * @returns {*} 21806 * @private 21807 */ 21808 _getNameAndIndex : function (pathPart) { 21809 if (pathPart) { 21810 var elName = pathPart.match(/^([^\s\/]+)(?:\/(\d+))?$/); // match the whole string 21811 if (elName !== null) { 21812 return { 21813 name : elName[1], 21814 index : elName[2] ? parseInt(elName[2]) : -1 21815 // -1 index for depicting non repeatable element 21816 }; 21817 } 21818 } 21819 return null; 21820 }, 21821 21822 _cmpXpathParts : function (indexedName, templateName) { 21823 if (indexedName && templateName) { 21824 var match1 = this._getNameAndIndex(indexedName), 21825 match2 = this._getNameAndIndex(templateName); 21826 return !_.isEmpty(match1 && match2) 21827 && match1.name === match2.name 21828 && (match2.index === -1 || match1.index === match2.index); 21829 } 21830 return false; 21831 }, 21832 21833 /** 21834 * This function gets or creates the node if its not there. The node can be any valid JSON Value 21835 * null, string, object, array, number, boolean. 21836 * @param schemaPath 21837 * @param dataSection 21838 * @param createMissingNodes 21839 * @param lastNodeValue 21840 * @returns {*} 21841 */ 21842 getContextNode : function (schemaPath, dataSection, createMissingNodes, lastNodeValue) { 21843 var contextNode, 21844 baseContextNode, 21845 basePath = "", 21846 pathParts = this._sanitizedXpathParts(schemaPath); 21847 if (dataSection == this.constants.BOUND_TAG) { 21848 baseContextNode = this._boundDataRoot; 21849 if (this._isNonNaked(this._liveDataDoc)) { 21850 basePath = "afData/" + this.constants.BOUND_DATA_XPATH + "/"; 21851 } 21852 } else if (dataSection === this.constants.UNBOUND_TAG) { 21853 baseContextNode = this._unboundDataRoot; 21854 if (this._isNonNaked(this._liveDataDoc)) { 21855 basePath = "afData/" + this.constants.UNBOUND_DATA_XPATH + "/"; 21856 } 21857 } 21858 if (!_.isEmpty(pathParts)) { 21859 var path = (basePath + pathParts.join('/')); 21860 21861 // return baseContextNode for naked json. path can be "" only for naked json. 21862 if (path == "" && !this._isNonNaked(this._liveDataDoc)) { 21863 return baseContextNode; 21864 } 21865 21866 contextNode = this._getElement(this._liveDataDoc, path); 21867 if (!contextNode && createMissingNodes) { 21868 contextNode = this._createElements(baseContextNode, pathParts, lastNodeValue); 21869 } 21870 } else { 21871 contextNode = baseContextNode; 21872 } 21873 return contextNode; 21874 }, 21875 21876 /** 21877 * This function creates the node at the path. 21878 * 21879 * @param contextNode 21880 * @param pathParts 21881 * @returns {*} 21882 * @private 21883 * @param lastNodeValue 21884 */ 21885 _createElements : function (contextNode, pathParts, lastNodeValue) { 21886 if (!(contextNode instanceof Object)) { 21887 return null; 21888 } 21889 21890 if (_.isEmpty(pathParts)) { 21891 return contextNode; 21892 } 21893 21894 // recurse and create one level of tags at a time 21895 contextNode = this._createRepeatedElements(contextNode, pathParts, lastNodeValue); 21896 return contextNode; 21897 }, 21898 21899 // it will always return the parent node after checking the last token 21900 _createRepeatedElements : function (contextNode, pathParts, lastNodeValue) { 21901 var childContextNode = contextNode, 21902 xpathPart = this._getNameAndIndex(pathParts[0]), 21903 elemName = xpathPart.name, 21904 index = xpathPart.index || 0, 21905 i, 21906 isLastToken = (pathParts.length == 1), 21907 elementNode = contextNode[elemName]; 21908 // -1 signifies non repeating element 21909 if (index === -1) { 21910 if (elementNode == null) { 21911 childContextNode = this._createChildElement(contextNode, elemName, isLastToken, lastNodeValue); 21912 } else { 21913 childContextNode = elementNode; 21914 } 21915 // if its the last token, then stop recursion here and return the created node 21916 if (isLastToken) { 21917 return childContextNode; 21918 } 21919 } else { 21920 if (elementNode != null) { 21921 var numOfChildren = elementNode.length; 21922 if (numOfChildren < index + 1) { 21923 // create immediate 'extra' children 21924 for (i = numOfChildren; i < index + 1; ++i) { 21925 childContextNode = {}; 21926 contextNode[elemName].push(childContextNode); 21927 } 21928 } else { 21929 childContextNode = elementNode[index]; 21930 } 21931 } else { 21932 contextNode[elemName] = []; 21933 for (i = 0; i < index + 1; ++i) { 21934 childContextNode = {}; 21935 contextNode[elemName].push(childContextNode); 21936 } 21937 } 21938 } 21939 // recursively create descendants 21940 return this._createElements(childContextNode, pathParts.slice(1), lastNodeValue); 21941 }, 21942 21943 _createChildElement : function (parentElement, elemName, isLastToken, nodeValue) { 21944 if (parentElement instanceof Object) { 21945 if (isLastToken) { 21946 parentElement[elemName] = nodeValue; 21947 } else { 21948 parentElement[elemName] = {}; 21949 } 21950 return parentElement[elemName]; 21951 } 21952 }, 21953 21954 isIndexedPath : function (xpath) { 21955 return (xpath || "").match(this.constants.INDEXED_XPATH_PAT_JSON) !== null; 21956 }, 21957 21958 /** 21959 * This function sets the value of the field in the live data document. 21960 * @param xpath 21961 * @param xmlSection 21962 * @private 21963 * @param createMissingNodes 21964 * @param value 21965 */ 21966 setDataValue : function (xpath, xmlSection, createMissingNodes, value) { 21967 var lastSlash = xpath.lastIndexOf("/"), 21968 parentPath = xpath.substring(0, lastSlash), 21969 name = xpath.substring(lastSlash + 1), 21970 parent = this.getContextNode(parentPath, xmlSection, createMissingNodes, {}); 21971 if (parent instanceof Object) { 21972 if (createMissingNodes || parent.hasOwnProperty(name)) { 21973 parent[name] = value; 21974 } 21975 } 21976 }, 21977 21978 /** 21979 * This function sets the value in the model from the live data document. 21980 * @param node 21981 * @param field 21982 * @private 21983 */ 21984 getDataValue : function (xpath, xmlSection) { 21985 var lastSlash = xpath.lastIndexOf("/"), 21986 parentPath = xpath.substring(0, lastSlash), 21987 name = xpath.substring(lastSlash + 1), 21988 parent = this.getContextNode(parentPath, xmlSection, false); 21989 if (parent instanceof Object) { 21990 return parent[name] === undefined ? null : parent[name]; 21991 } 21992 return null; 21993 }, 21994 21995 getRichTextValue : function (xpath, xmlSection) { 21996 return this.getDataValue(xpath, xmlSection); 21997 }, 21998 21999 addIndexToPath : function (path, index) { 22000 if (path.match(/\/\d+$/) === null) { // only add repeat index if it doesn't already end in one 22001 path += '/' + (index); 22002 } else { 22003 this.logger().debug("AF", "Tried to add index to already indexed JSON path :" + path); 22004 } 22005 return path; 22006 }, 22007 22008 hasChildNodes : function (node) { 22009 return !_.isEmpty(node); 22010 }, 22011 22012 removeChild : function (parentNode, targetNodeName, index) { 22013 parentNode[targetNodeName].splice(index, 1); 22014 }, 22015 22016 insertNode : function (parentNode, childNodeName, index) { 22017 if (parentNode[childNodeName] == null) { 22018 parentNode[childNodeName] = []; 22019 } 22020 for (var i = 0; i < index; i++) { 22021 if (parentNode[childNodeName][i] == null) { 22022 parentNode[childNodeName][i] = {}; 22023 } 22024 } 22025 parentNode[childNodeName].splice(index, 0, {}); 22026 return parentNode[childNodeName][index]; 22027 }, 22028 22029 getDataInstances : function (dataContext, dataNodeName) { 22030 return this.getContextNode(dataContext.indexedXpath, dataContext.xmlSec); 22031 }, 22032 22033 _convertModelIndexToDataIndex : function (index) { 22034 if (index < 0) { 22035 return 0; 22036 } 22037 return index; 22038 }, 22039 22040 getParentRef : function (path) { 22041 return path.replace(/\/[^\/]+(?:\/\d+)?$/, ""); 22042 }, 22043 22044 insertSubmissionInfo : function (submissionInfo, rootNode) { 22045 if (this._isNonNaked()) { 22046 var node = rootNode, 22047 self = this, 22048 finalValue, insert, keyNode; 22049 if (node == null) { 22050 node = this._liveDataDoc.afData.afSubmissionInfo; 22051 } 22052 if (node == null && this._liveDataDoc.afData.afSubmissionInfo == null) { 22053 node = {}; 22054 this._liveDataDoc.afData.afSubmissionInfo = node; 22055 } 22056 _.each(submissionInfo, function (value, key) { 22057 if (value instanceof Array) { 22058 // we only support string items in json array 22059 finalValue = []; 22060 insert = true; 22061 _.each(value, function (arrItem, index) { 22062 if (typeof arrItem === "string") { 22063 finalValue.push(arrItem); 22064 } else { 22065 //ignore this. we currently do not support anything other than string 22066 } 22067 }); 22068 if (insert) { 22069 node[key] = finalValue.join(','); 22070 } 22071 } else if (typeof (value) === "object" && value != null) { 22072 keyNode = node[key]; 22073 if (keyNode == null) { 22074 keyNode = {}; 22075 node[key] = keyNode; 22076 } 22077 self.insertSubmissionInfo(value, keyNode); 22078 } else { 22079 node[key] = value; 22080 } 22081 }); 22082 } 22083 } 22084 22085 }); 22086 22087}($, _, window.guideBridge, window.guidelib, window.formBridge, window.xfalib)); 22088 22089/** 22090 * @package guidelib.model.DataNode 22091 * @version 0.0.1 22092 */ 22093 22094(function ($, _, guideBridge, guidelib, formBridge, xfalib) { 22095 var isXdp, isXsd, isNone; 22096 22097 var LiveXmlUtils = guidelib.model.LiveXmlUtils = guidelib.model.LiveDataUtils.extend({ 22098 22099 initialize : function () { 22100 LiveXmlUtils._super.initialize.call(this); 22101 22102 if (_.isUndefined(document.evaluate)) { 22103 wgxpath.install(); 22104 } 22105 this._liveDataDoc = null; 22106 }, 22107 22108 initLiveData : function (prefillXmlStr, xfaPrefillXmlStr, isXdp, isXsd, xsdRootElement) { 22109 LiveXmlUtils._super.initLiveData.apply(this, arguments); 22110 isXdp = isXdp || false; 22111 isXsd = isXsd || false; 22112 isNone = !(isXdp || isXsd); 22113 this.xsdRootElement = xsdRootElement; 22114 // init default skeleton for no pefill cases 22115 this._liveDataDoc = $.parseXML(this.constants.SKELETON_XML); 22116 this._boundDataRoot = this._getElement(this._liveDataDoc.documentElement, this.constants.BOUND_DATA_XPATH); 22117 this._unboundDataRoot = this._getElement(this._liveDataDoc.documentElement, this.constants.UNBOUND_DATA_XPATH); 22118 22119 if (_.isString(prefillXmlStr) && prefillXmlStr.length > 0) { 22120 var prefillXmlDoc = $.parseXML(prefillXmlStr); 22121 22122 // find data root 22123 if (this._isNonNaked(prefillXmlDoc)) { 22124 // non naked xml, assuming full hierarchy afdata/afbounddata/data 22125 22126 var prefillBoundDataRoot, 22127 prefillUnBoundDataRoot, 22128 newDataNode; 22129 22130 if (!isXdp) { //capture bound data from prefill, for both none(may contain bound form/frag) and xsd 22131 prefillBoundDataRoot = this._getElement(prefillXmlDoc.documentElement, this.constants.BOUND_DATA_XPATH); 22132 if (null == prefillBoundDataRoot) { 22133 prefillBoundDataRoot = this._getElement(prefillXmlDoc.documentElement, this.constants.BOUND_TAG + 22134 "/" + guideBridge._guide.jsonModel.xsdRootElement); 22135 } 22136 if (prefillBoundDataRoot) { 22137 newDataNode = this._liveDataDoc.importNode(prefillBoundDataRoot, true); 22138 this._boundDataRoot.parentNode.replaceChild(newDataNode, this._boundDataRoot); 22139 this._boundDataRoot = newDataNode; 22140 } 22141 } 22142 22143 prefillUnBoundDataRoot = this._getElement(prefillXmlDoc.documentElement, this.constants.UNBOUND_DATA_XPATH); 22144 if (prefillUnBoundDataRoot) { 22145 newDataNode = this._liveDataDoc.importNode(prefillUnBoundDataRoot, true); 22146 this._unboundDataRoot.parentNode.replaceChild(newDataNode, this._unboundDataRoot); 22147 this._unboundDataRoot = newDataNode; 22148 } 22149 22150 } else { 22151 // naked xml start from prefill data root 22152 22153 if (isNone) { 22154 this._unboundDataRoot = prefillXmlDoc.documentElement; 22155 this._boundDataRoot = null; 22156 } else { 22157 if (isXsd) { 22158 this._boundDataRoot = prefillXmlDoc.documentElement; 22159 } 22160 22161 var unBoundXmlDoc = $.parseXML(this.constants.UNBOUND_SKELETON); 22162 this._unboundDataRoot = unBoundXmlDoc.documentElement; // need this for unbound data fill across lazy 22163 } 22164 this._liveDataDoc = prefillXmlDoc; 22165 } 22166 } 22167 22168 if (isXdp) { // don't need the bound data sec, model is always loaded & server will fill during submission 22169 if (_.isString(xfaPrefillXmlStr) && xfaPrefillXmlStr.length > 0) { 22170 this._xfaDataRoot = xfalib.ut.XMLUtils.getXFARootFormElementFromXML($.parseXML(xfaPrefillXmlStr)); 22171 } 22172 this._boundDataRoot.parentNode.parentNode.removeChild(this._boundDataRoot.parentNode); 22173 this._boundDataRoot = null; 22174 } 22175 }, 22176 22177 isLiveDataInitialized : function () { 22178 return (this.getLiveDataDoc() instanceof Node); 22179 }, 22180 22181 getLiveDataStr : function () { 22182 if (this.isLiveDataInitialized()) { 22183 return (new XMLSerializer()).serializeToString(this.getLiveDataDoc()); 22184 } else { 22185 return ''; 22186 } 22187 }, 22188 22189 _ignoreXpathRoot : function (xpathRoot) { 22190 return this.xsdRootElement === this.cons
22190tants.UNKNOWN_XSD_ROOT_ELEMENT 22191 || this.xsdRootElement === xpathRoot; 22192 }, 22193 22194 /** 22195 * will return the apt node, in the AF xml, based on the xml context passed in. 22196 * Will create nodes if it doesn't exist and createMissingNodes is passed as true 22197 * @param schemaPath 22198 * @param dataSection 22199 * @param createMissingNodes 22200 * @returns {*} 22201 * @memberof LiveXmlUtils 22202 */ 22203 getContextNode : function (schemaPath, dataSection, createMissingNodes) { 22204 var contextNode, 22205 baseContextNode, 22206 xpathParts = this._sanitizedXpathParts(schemaPath); 22207 if (dataSection === this.constants.BOUND_TAG) { 22208 baseContextNode = this._boundDataRoot; 22209 } else if (dataSection === this.constants.UNBOUND_TAG) { 22210 baseContextNode = this._unboundDataRoot; 22211 } else if (dataSection === this.constants.XFA_TAG) { 22212 baseContextNode = this._xfaDataRoot; 22213 } 22214 if (!_.isEmpty(xpathParts)) { 22215 if (dataSection === this.constants.BOUND_TAG) { 22216 if (this._ignoreXpathRoot(xpathParts[0])) { 22217 xpathParts = xpathParts.slice(1); // discard xsd schema root 22218 if (xpathParts.length === 0) { 22219 return baseContextNode; 22220 } 22221 } 22222 } 22223 22224 contextNode = this._getElement(baseContextNode, xpathParts.join('/')); 22225 22226 if (!contextNode && createMissingNodes) { 22227 contextNode = this._createElements(baseContextNode, xpathParts); 22228 } 22229 } else if (_.isEmpty(schemaPath)) { 22230 contextNode = baseContextNode; 22231 } 22232 return contextNode; 22233 }, 22234 22235 addIndexToPath : function (path, index) { 22236 if (path.match(/\[\d+\]$/) === null) { // only add repeat index if it doesn't already end in one 22237 path += '[' + (index + 1) + ']'; // indices in xpath 1 based} 22238 } else { 22239 this.logger().debug("AF", "Tried to add index to already indexed xpath :" + path); 22240 } 22241 return path; 22242 }, 22243 22244 getDataInstances : function (dataContext, dataNodeName) { 22245 var node = this.getContextNode(dataContext.indexedXpath, dataContext.xmlSec); 22246 if (node != null) { 22247 return _.filter(node.parentNode.childNodes, function (child) { 22248 return (child instanceof Element) && child.nodeName === dataNodeName; 22249 }, this); 22250 } 22251 return null; 22252 }, 22253 22254 _findLastDataNode : function (parentContextNode, dataNodeName) { 22255 var xmlUtils = xfalib.ut.XMLUtils, 22256 iterator = xmlUtils.evaluateXPath(dataNodeName, parentContextNode, null, null, null), 22257 result = xmlUtils.iteratorToArray(iterator); 22258 if (result.length > 0) { 22259 return result[result.length - 1]; 22260 } 22261 return null; 22262 }, 22263 22264 hasChildNodes : function (node) { 22265 return node.hasChildNodes(); 22266 }, 22267 22268 removeChild : function (parentNode, targetNodeName, index) { 22269 var childNode = this._getElement(parentNode, targetNodeName + "[" + (index + 1) + "]", null); 22270 if (childNode) { 22271 parentNode.removeChild(childNode); 22272 } 22273 }, 22274 22275 insertNode : function (parentNode, childNodeName, index) { 22276 var childNode = this._getElement(parentNode, childNodeName + "[" + (index + 1) + "]", null), 22277 node = parentNode.ownerDocument.createElement(childNodeName); 22278 if (childNode) { 22279 parentNode.insertBefore(node, childNode); 22280 } else { 22281 var lastNode = this._findLastDataNode(parentNode, childNodeName); 22282 if (lastNode && lastNode.nextSibling) { 22283 parentNode.insertBefore(node, lastNode.nextSibling); 22284 } else if (lastNode && !lastNode.nextSibling) { 22285 // for the case when the last node is there but there is no next sibling. 22286 // we don't need to create all the nodes for this scenario. 22287 parentNode.appendChild(node); 22288 } else { 22289 // we need to create all the nodes till the count reaches the index. 22290 for (var i = 0; i <= index; i++) { 22291 var newNode = parentNode.ownerDocument.createElement(childNodeName); 22292 parentNode.appendChild(newNode); 22293 } 22294 } 22295 } 22296 return node; 22297 }, 22298 22299 /** 22300 * Form an xpath part returns the index as well as the tagName. 22301 * Index returned is 0 if not present 22302 * @param xpathName 22303 * @returns {*} 22304 * @private 22305 * @memberof LiveXmlUtils 22306 */ 22307 _getNameAndIndex : function (xpathPart) { 22308 if (xpathPart) { 22309 var elName = xpathPart.match(/^([^[\s\/]+)(?:\[(\d+)\])?$/); // match the whole string 22310 if (elName !== null) { 22311 return { 22312 name : elName[1], 22313 index : elName[2] ? parseInt(elName[2]) : 0 22314 }; 22315 } 22316 } 22317 return null; 22318 }, 22319 22320 _cmpXpathParts : function (indexedName, templateName) { 22321 if (indexedName && templateName) { 22322 var match1 = this._getNameAndIndex(indexedName), 22323 match2 = this._getNameAndIndex(templateName); 22324 return !_.isEmpty(match1 && match2) 22325 && match1.name === match2.name 22326 && (match2.index === 0 || match1.index === match2.index); 22327 } 22328 return false;
22329 }, 22330 22331 /** 22332 * Will split an xpath string into an array containing one xml element/node per part 22333 * This expects only the simple xpath syntax allowed in bindRefs of xsd bound fields 22334 * of the form /a/b/c/@d 22335 * @param xpath 22336 * @returns {*|Array.<T>|list} 22337 * @private 22338 * @memberof LiveXmlUtils 22339 */ 22340 _sanitizedXpathParts : function (xpath) { 22341 var xpathParts = (xpath || '').replace(/^\//, '').replace(/\s+/g, '').split('/'); 22342 22343 if (_.last(xpathParts) === "text()") { // ignore "/text()" appended to bindRef for SimpleType schema element 22344 xpathParts.splice(-1, 1); // drop last element 22345 } 22346 22347 return _.filter(xpathParts, function (xpathPart) { 22348 return this._getNameAndIndex(xpathPart) !== null; 22349 }, this); 22350 }, 22351 22352 /** 22353 * returns true if the xpath uses indices 22354 * @param xpath 22355 * @returns {boolean} 22356 * @memberof LiveXmlUtils 22357 */ 22358 isIndexedPath : function (xpath) { 22359 return (xpath || "").match(this.constants.INDEXED_XPATH_PAT) !== null; 22360 }, 22361 22362 _createElements : function (contextNode, xpathParts) { 22363 if (!(contextNode instanceof Node)) { 22364 return null; 22365 } 22366 22367 if (_.isEmpty(xpathParts)) { 22368 return contextNode; 22369 } 22370 22371 if (xpathParts[0][0] === '@') { // xpath parts having '@' as 1st char must be and attr 22372 var attrName = xpathParts[0].slice(1); 22373 // in bindrefs attributes are the last xpath part, so no need to recurse 22374 contextNode = this._createAttributeNode(contextNode, attrName); 22375 } else { 22376 // recurse and create one level of tags at a time 22377 contextNode = this._createRepeatedElements(contextNode, xpathParts); 22378 } 22379 22380 return contextNode; 22381 }, 22382 22383 /** 22384 * This will update the xml with the required tags, 22385 * and return the context node matching the xpath query. 22386 * Further if xml has lesser number of tags than the index in each part, 22387 * it'll fill those gaps with empty tags. 22388 * @param contextNode node beneath which tags are to be created 22389 * @param xpathParts 22390 * @returns {*} 22391 * @private 22392 * @memberof LiveXmlUtils 22393 */ 22394 _createRepeatedElements : function (contextNode, xpathParts) { 22395 var childContextNode = contextNode, 22396 xpathPart = this._getNameAndIndex(xpathParts[0]), 22397 elemName = xpathPart.name, 22398 index = xpathPart.index || 1, 22399 i, 22400 children = _.filter(contextNode.childNodes, function (child) { 22401 return (child instanceof Element) && child.nodeName === elemName; 22402 }); 22403 22404 if (children.length < index) { 22405 // create immediate 'extra' children 22406 for (i = children.length; i < index; ++i) { 22407 childContextNode = this._createChildElement(contextNode, elemName); 22408 } 22409 } else { 22410 childContextNode = children[index - 1]; // indices are 1 based in xml 22411 } 22412 // recursively create descendants 22413 return this._createElements(childContextNode, xpathParts.slice(1)); 22414 }, 22415 22416 _createChildElement : function (parentElement, elemName) { 22417 if (parentElement instanceof Element) { 22418 var childElem = parentElement.ownerDocument.createElement(elemName); 22419 parentElement.appendChild(childElem); 22420 return childElem; 22421 } 22422 }, 22423 22424 _createAttributeNode : function (parentElement, attrName) { 22425 if (parentElement instanceof Element) { 22426 var attrNode = parentElement.ownerDocument.createAttribute(attrName); 22427 parentElement.setAttributeNode(attrNode); 22428 return attrNode; 22429 } 22430 }, 22431 22432 /** 22433 * finds xml node/element based on current context node and xpath 22434 * @param node 22435 * @param xpath 22436 * @param options 22437 * @returns {*} 22438 * @private 22439 * @memberof LiveXmlUtils 22440 */ 22441 _getElement : function (node, xpath, options) { 22442 if (!(node instanceof Node)) { 22443 return null; 22444 } 22445 22446 if (_.isEmpty(xpath) || !_.isString(xpath)) { 22447 return node; 22448 } 22449 options = options || {}; 22450 var nsResolver = options.nsResolver; 22451 var index = options.index; 22452 // in IE singleNodeValue maybe null for attribute queries, 22453 // so find parent element of attribute, and then explicitly check for attribute node's presence 22454 22455 var xpathParts = xpath.split('/@'), 22456 checkAttr = false, 22457 attributeName; 22458 22459 if (xpathParts.length > 2) { // more than 1 attr unsupported 22460 xfalib.ut.XfaUtil.prototype.getLogger().error("BindRefs must be Xpaths ending in atmost one attribute"); // TODO localize 22461 return null; 22462 } else if (xpathParts.length === 2) { 22463 xpath = xpathParts[0]; // find parent el and seek attribute there 22464 attributeName = xpathParts[1]; // attr can only be in the last part 22465 checkAttr = true; 22466 } 22467 if (!(_.isUndefined(index) || _.isNull(index))) { 22468 xpath = xpath + "[" + index + "]"; 22469 } 22470 if (!window.XPathResult) { 22471 document.evaluate = undefined; 22472 wgxpath.install(window, true); 22473 } 22474 var result = xfalib.ut.XMLUtils.evaluateXPath(xpath, node, nsResolver, XPathResult.FIRST_ORDERED_NODE_TYPE, null), 22475 el; 22476 22477 if (result && result.resultType === XPathResult.FIRST_ORDERED_NODE_TYPE) { 22478 el = result.singleNodeValue; 22479 if (el instanceof Node) { 22480 if (!checkAttr) { 22481 return el; 22482 } else if (el.hasAttribute(attributeName)) { 22483 el = el.getAttributeNode(attributeName); 22484 if (el instanceof Node) { 22485 return el; 22486 } 22487 } 22488 } 22489 } 22490 }, 22491 22492 /** 22493 * This function checks if the document was naked or non naked xml 22494 * @param doc 22495 * @returns {boolean} returns true if there exists a afData node inside data false otherwise 22496 * @private 22497 * @memberof LiveXmlUtils 22498 */ 22499 _isNonNaked : function (doc) { 22500 doc = doc || this.getLiveDataDoc(); 22501 if (doc) { 22502 return doc.documentElement.tagName === this.constants.AF_ROOT_TAG; 22503 } else { 22504 return false;
22505 } 22506 }, 22507 22508 /** 22509 * Returns list of panels touched by the end user before saving the draft 22510 * @param dataString 22511 */ 22512 getListOfDirtyPanels : function (dataString) { 22513 if (dataString == null || dataString === "") { 22514 return []; 22515 } 22516 var livePrefillXmlDoc = $.parseXML(dataString), 22517 draftDoc = this._getElement(livePrefillXmlDoc.documentElement, this.constants.AF_DRAFT_TAG); 22518 if (_.isUndefined(draftDoc) || draftDoc.childNodes.length === 0) { 22519 return []; 22520 } 22521 var draftStr = draftDoc.firstChild.textContent.replace(/\"/g, ""), 22522 retVal = []; 22523 // not using filter here explicitly, due to ES4 syntax 22524 if (draftStr) { 22525 retVal = draftStr.split(","); 22526 } 22527 return retVal; 22528 }, 22529 22530 /** 22531 * This function sets the rich text value of the field in the live data. 22532 * @param xpath 22533 * @param xmlSection 22534 * @param createMissingNodes 22535 * @param value 22536 * @private 22537 */ 22538 setRichTextValue : function (xpath, xmlSection, createMissingNodes, value) { 22539 var node = this.getContextNode(xpath, xmlSection, createMissingNodes); 22540 if (node instanceof Node) { 22541 var richTextNode = $.parseXML(value); 22542 // clear the text content before appending child 22543 node.textContent = ""; 22544 node.appendChild(richTextNode.documentElement); 22545 } 22546 }, 22547 22548 setDataValue : function (xpath, xmlSection, createMissingNodes, value) { 22549 var node = this.getContextNode(xpath, xmlSection, createMissingNodes); 22550 if (node instanceof Node) { 22551 node.textContent = value; 22552 } 22553 }, 22554 22555 getDataValue : function (xpath, xmlSection) { 22556 var node = this.getContextNode(xpath, xmlSection, false); 22557 if (node instanceof Node) { 22558 return node.textContent || null; 22559 } 22560 return undefined; 22561 }, 22562 22563 getRichTextValue : function (xpath, xmlSection) { 22564 var node = this.getContextNode(xpath, xmlSection, false); 22565 if (node instanceof Node) { 22566 return node.innerHTML.trim(); 22567 } 22568 return undefined; 22569 }, 22570 22571 _convertModelIndexToDataIndex : function (index) { 22572 if (index < 0) { 22573 return 1; 22574 } 22575 return index + 1; 22576 }, 22577 22578 getParentRef : function (path) { 22579 return path.substring(0, path.lastIndexOf("/")); 22580 }, 22581 22582 insertSubmissionInfo : function (submissionInfo, rootNode) { 22583 if (this._isNonNaked()) { 22584 var xmlutils = xfalib.ut.XMLUtils, 22585 node = rootNode === undefined 22586 ? xmlutils.findOrCreateElement("afSubmissionInfo", this._liveDataDoc.documentElement) 22587 : rootNode, 22588 self = this; 22589 _.each(submissionInfo, function (value, key) { 22590 var keyNode; 22591 if (value instanceof Array) { 22592 // we only support string items in json array 22593 var finalValue = [], insert = true; 22594 _.each(value, function (arrItem, index) { 22595 if (typeof arrItem === "string") { 22596 finalValue.push(arrItem); 22597 } else if (arrItem instanceof Object && arrItem != null) { 22598 insert = false; 22599 var el = node.ownerDocument.createElement(key); 22600 node.appendChild(el); 22601 self.insertSubmissionInfo(arrItem, el); 22602 } 22603 }); 22604 if (insert) { 22605 keyNode = xmlutils.findOrCreateElement(key, node); 22606 keyNode.textContent = finalValue.join(','); 22607 node.appendChild(keyNode); 22608 } 22609 } else if (typeof (value) === "object" && value != null) { 22610 keyNode = xmlutils.findOrCreateElement(key, node); 22611 self.insertSubmissionInfo(value, keyNode); 22612 if (keyNode) { 22613 node.appendChild(keyNode); 22614 } 22615 } else { 22616 keyNode = xmlutils.findOrCreateElement(key, node); 22617 if (keyNode) { 22618 keyNode.textContent = value; 22619 node.appendChild(keyNode); 22620 } 22621 } 22622 }); 22623 } 22624 } 22625 }); 22626 22627}($, _, window.guideBridge, window.guidelib, window.formBridge, window.xfalib)); 22628 22629/* 22630 * *********************************************************************** 22631 * ADOBE CONFIDENTIAL 22632 * __________________ 22633 * 22634 * Copyright 2015 Adobe Systems Incorporated 22635 * All Rights Reserved. 22636 *
22637 * NOTICE: All information contained herein is, and remains 22638 * the property of Adobe Systems Incorporated and its suppliers, 22639 * if any. The intellectual and technical concepts contained 22640 * herein are proprietary to Adobe Systems Incorporated and its 22641 * suppliers and may be covered by U.S. and Foreign Patents, 22642 * patents in process, and are protected by trade secret or copyright law. 22643 * Dissemination of this information or reproduction of this material 22644 * is strictly forbidden unless prior written permission is obtained 22645 * from Adobe Systems Incorporated. 22646 * *********************************************************************** 22647 */ 22648 22649/** 22650 * @package guidelib.model.LiveModel 22651 * @version 0.0.1 22652 */ 22653 22654(function ($, _, guideBridge, guidelib) { 22655 var LiveModel = guidelib.model.LiveModel = xfalib.ut.Class.extend({ 22656 initialize : function () { 22657 LiveModel._super.initialize.call(this); 22658 this._crossFragmentFields = {}; // 2 level map: name => { bindRef => abstract model } 22659 this._dataNodes = {}; 22660 }, 22661 22662 // only called from test framework 22663 destroy : function () { 22664 this._crossFragmentFields = {}; 22665 this._dataNodes = {}; 22666 }, 22667 22668 getCrossFragmentFields : function () { 22669 return this._crossFragmentFields; 22670 }, 22671 22672 add : function (key, model) { 22673 if (key) { 22674 var dn = this._dataNodes[key] || new guidelib.model.DataNode(); 22675 dn.addField(model); 22676 this._dataNodes[key] = dn; 22677 } 22678 }, 22679 22680 isLive : function (key) { 22681 return _.isString(key) && _.has(this._dataNodes, key); 22682 }, 22683 22684 remove : function (key, model) { 22685 if (this.isLive(key)) { 22686 var dn = this._dataNodes[key]; 22687 dn.removeField(model); 22688 } 22689 }, 22690 22691 getAllFieldModels : function (keys) { 22692 return _.flatten(_.map(keys, function (key) { 22693 var result, 22694 dataNode = this._dataNodes[key]; 22695 if (dataNode) { 22696 result = dataNode.getFieldModels(); 22697 } 22698 return result; 22699 }, this)); 22700 }, 22701 22702 getAllAbstractFieldModels : function (keys) { 22703 return _.flatten(_.map(keys, function (key) { 22704 return this._dataNodes[key].getAbstractFieldModels(); 22705 }, this)); 22706 }, 22707 22708 resetData : function () { 22709 // all loaded models in data nodes dataNodes will be reset by the respective fields 22710 // just need to reset the abstract cross frag fields 22711 _.each(this._crossFragmentFields, function (fields) { 22712 _.each(fields, function (abstractField) { 22713 abstractField.resetData(); 22714 }); 22715 }); 22716 }, 22717 22718 createDataNodes : function (duplicateBindRefs) { 22719 _.each(duplicateBindRefs, function (bindRef) { 22720 this.add(bindRef); 22721 }, this); 22722 }, 22723 22724 createCrossFragFields : function (crossFragFields, guide) { 22725 _.each(crossFragFields, function (field) { 22726 var effectiveBindRef = field.bindRef || field.name, 22727 value = field._value || null,// default value, keep null because js is quirky with operations on undefined 22728 absModel = new guidelib.model.AbstractField({ 22729 'name' : field.name, 22730 'className' : field.guideNodeClass, 22731 'bindRef' : field.bindRef, 22732 'dataSom' : field.dataSom, 22733 'afDataSom' : field.afDataSom, 22734 'jsonModel' : { 22735 '_value' : value, 22736 "{default}" : value 22737 }, 22738 '_guideContainer' : guide 22739 }); 22740 22741 if (_.isEmpty(this._crossFragmentFields[field.name])) { 22742 this._crossFragmentFields[field.name] = {}; 22743 } 22744 this._crossFragmentFields[field.name][effectiveBindRef] = absMo
22744del; 22745 22746 this.add(effectiveBindRef, absModel); // unbound globals with same name linked together 22747 22748 }, this); 22749 }, 22750 22751 prefillCrossFragFields : function (guide) { 22752 var dataUtils = guide.internal.liveDataUtils; 22753 if (dataUtils.isLiveDataInitialized()) { 22754 _.each(this._crossFragmentFields, function (fields, name) { 22755 _.each(fields, function (absModel, bindRef) { 22756 var dataContext = dataUtils._getDataContext(absModel, '', ''); 22757 // fill value from prefill data or saved lazy live data 22758 absModel.value = dataUtils.getDataValue(dataContext.indexedXpath, dataContext.xmlSec); 22759 }, this); 22760 }, this); 22761 } 22762 } 22763 }); 22764}($, _, window.guideBridge, window.guidelib)); 22765 22766/** 22767 * @package guidelib.model.FormData 22768 * @version 0.0.1 22769 */ 22770 22771(function ($, _, guidelib) { 22772 22773 /** 22774 * JavaScript class to represent form data 22775 * @class FormData 22776 * @since Forms As A Cloud service (FaaCS) 22777 */ 22778 var AfFormData = guidelib.model.FormData = xfalib.ut.Class.extend({ 22779 22780 initialize : function () { 22781 AfFormData._super.initialize.call(this); 22782 }, 22783 22784 toJsObject : function() { 22785 return { 22786 "data" : this.data, 22787 "contentType" : this.contentType, 22788 "attachments" : this.attachments 22789 } 22790 }, 22791 22792 /** 22793 * This returns the html form data representation of adaptive form data. This could be used to submit the adaptive form data to 22794 * external end point from the client. The HTML form data contains the following the key / value pairs: 22795 * 1. data -> contains form data represented as string 22796 * 2. contentType -> contains content type of form data (it would be application/xml or application/json) 22797 * 2. fileAttachments -> list of blobs containing the file (in case of fileUrl's the type of blob would be application/json) 22798 * 3. fileAttachmentBindRefs -> list of string containing file bindRef's, this has one to one mapping with fileAttachments 22799 * @returns {*} 22800 */ 22801 toHTMLFormData : function() { 22802 // using native formData class 22803 var formData = new FormData(); 22804 // appending data of adaptive form in data key 22805 // data could be JSON or XML 22806 if (this.contentType) { 22807 formData.append("contentType", this.contentType); 22808 } 22809 formData.append("data", this.data); 22810 for (var index = 0; index < this.attachments.length; index++) { 22811 var fileAttachmentWrapper = this.attachments[index]; 22812 // 2nd parameter should be of blob type, hence adding an explicit check here 22813 // we could have created dataURL for all the files in the client, but this would cause the browser 22814 // to slow down since it would serialize the binary, hence following the below approach 22815 if (fileAttachmentWrapper.isFile()) { 22816 formData.append("fileAttachments", fileAttachmentWrapper.data, fileAttachmentWrapper.name); 22817 } else { 22818 // blob is supported on all major browsers 22819 var urlBlob = new Blob([ 22820 JSON.stringify({ 22821 "data" : fileAttachmentWrapper.data, 22822 "name" : fileAttachmentWrapper.name, 22823 "contentType" : fileAttachmentWrapper.contentType 22824 }) 22825 ], { type: 'application/json' }); 22826 formData.append("fileAttachments", urlBlob); 22827 } 22828 formData.append("fileAttachmentBindRefs", fileAttachmentWrapper.bindRef); 22829 } 22830 return formData; 22831 } 22832 }); 22833 22834 AfFormData.defineProps({ 22835 /** 22836 * Actual form data (could be JSON or xml) 22837 */ 22838 data : { 22839 get : function () { 22840 return this.options.data; 22841 } 22842 }, 22843 22844 /** 22845 * List of {FileAttachmentWrapper} {@link FileAttachmentWrapper} 22846 */ 22847 attachments : { 22848 get : function () { 22849 return this.options.attachments; 22850 } 22851 }, 22852 22853 /** 22854 * Content type of form data (it could be application/xml or application/json) 22855 */ 22856 contentType : { 22857 get : function () { 22858 return this.options.contentType; 22859 } 22860 } 22861 }); 22862 22863 22864}($, _, window.guidelib)); 22865 22866/** 22867 * @package guidelib.model.FileAttachmentWrapper 22868 * @version 0.0.1 22869 */ 22870 22871(function ($, _, guidelib) { 22872 22873 /** 22874 * JavaScript class to represent the each file data present in the form. 22875 * Data could be URI (URI could be a file URL or dataURL) 22876 * @class FileAttachmentWrapper 22877 * @since Forms As A Cloud service (FaaCS) 22878 */ 22879 var FileAttachmentWrapper = guidelib.model.FileAttachmentWrapper = xfalib.ut.Class.extend({ 22880 22881 initialize : function () { 22882 FileAttachmentWrapper._super.initialize.call(this); 22883 }, 22884 22885 /** 22886 * Converts file attachment wrapper to a javascript object
22887 * @returns {{name: *, contentType: *, bindRef: *, data: *}} 22888 */ 22889 toJsObject : function () { 22890 return { 22891 name : this.name, 22892 contentType : this.contentType, 22893 bindRef : this.bindRef, 22894 data : this.data 22895 } 22896 }, 22897 22898 /** 22899 * Checks if the file data is native JS File object 22900 * @returns {boolean} 22901 */ 22902 isFile : function() { 22903 return this.data instanceof File; 22904 }, 22905 22906 22907 /** 22908 * Returns blob for the data URL present in data 22909 * @returns {*} 22910 */ 22911 dataURLtoBlob : function() { 22912 var dataurl = this.data, // data should be a data url 22913 arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1], 22914 bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); 22915 while(n--){ 22916 u8arr[n] = bstr.charCodeAt(n); 22917 } 22918 return new Blob([u8arr], {type: mime}); 22919 } 22920 }); 22921 22922 FileAttachmentWrapper.defineProps({ 22923 /** 22924 * Actual name of the file associated with data 22925 */ 22926 name : { 22927 get : function () { 22928 return this.options.name; 22929 } 22930 }, 22931 22932 /** 22933 * Content type of file 22934 */ 22935 contentType : { 22936 get : function () { 22937 return this.options.contentType; 22938 } 22939 }, 22940 22941 /** 22942 * This would be effective bindRef meaning bindRef in case of data model or component name in case of unbound data 22943 */ 22944 bindRef : { 22945 get : function () { 22946 return this.options.bindRef; 22947 } 22948 }, 22949 22950 /** 22951 * This would represent the name of the form element to which the file binary is associated. 22952 * In case of unbound form, bindRef and component name would be the same 22953 */ 22954 formElementName : { 22955 get : function () { 22956 return this.options.formElementName || this.options.bindRef; 22957 } 22958 }, 22959 22960 /** 22961 * Data could be URI (URI could be file URL or dataURL) or native JavaScript File object 22962 */ 22963 data : { 22964 get : function () { 22965 return this.options.data; 22966 } 22967 } 22968 }); 22969 22970 22971}($, _, window.guidelib)); 22972 22973/************************************************************************* 22974 * 22975 * ADOBE CONFIDENTIAL 22976 * __________________ 22977 * 22978 * Copyright 2014 Adobe Systems Incorporated 22979 * All Rights Reserved. 22980 *
22981 * NOTICE: All information contained herein is, and remains 22982 * the property of Adobe Systems Incorporated and its suppliers, 22983 * if any. The intellectual and technical concepts contained 22984 * herein are proprietary to Adobe Systems Incorporated and its 22985 * suppliers and may be covered by U.S. and Foreign Patents, 22986 * patents in process, and are protected by trade secret or copyright law. 22987 * Dissemination of this information or reproduction of this material 22988 * is strictly forbidden unless prior written permission is obtained 22989 * from Adobe Systems Incorporated. 22990 **************************************************************************/ 22991 22992 22993(function (_, $) { 22994 "use strict"; 22995 22996 22997 var isBrowserIE = xfalib.ut.XfaUtil.prototype.detectIE(); 22998 22999 var _defaults = { 23000 'showLink' : false, 23001 'scrollMode' : 'vertical', 23002 textAreaClass : ".guide-tnc-content", 23003 checkBoxClass : ".guide-tnc-checkbox", 23004 checkBoxDisableClass : ".guide-tnc-checkbox-disabled", 23005 checkBoxReviewedClass : ".guide-tnc-checkbox-reviewed", 23006 linkClass : ".guide-tnc-link", 23007 documentVisitedClass : ".guide-tnc-document-visited", 23008 documentUnVisitedClass : ".guide-tnc-document-unvisited" 23009 }; 23010 23011 var _reviewStatusMap = { 23012 REVIEWED : "reviewed", 23013 UNREVIEWD : "unreviewed", 23014 AGREE : "agree" 23015 }; 23016 23017 var AfTnc = function (element, options) { 23018 this.options = options; 23019 this.$element = $(element); 23020 23021 23022 this.enters = this.leaves = 0; 23023 this.inside = false;
23024 23025 23026 this.reviewdoc = this.status = _reviewStatusMap.UNREVIEWD; 23027 23028 23029 this.$elementCheckBox = this.$element.find(this.options.checkBoxClass || _defaults.checkBoxClass); 23030 23031 this.$elementTextArea = $(this.textArea()); 23032 23033 this.$elementLink = $(this.link()); 23034 23035 this.isTextContentVisible = false; 23036 23037 if (this.options.showLink) { 23038 23039 this.$elementLink.find('a').click($.proxy(this.handleReviewStatusChange, this)); 23040 } else { 23041 var setCheckBoxState = function () { 23042 if (this.hasScrollBar(this.$elementTextArea.parent().get(0))) { 23043 23044 23045 this.$elementTextArea.parent().scroll($.proxy(this.handleReviewStatusChange, this)); 23046 } else { 23047 23048 if (this.$elementTextArea.css('display') !== 'none') { 23049 this.status = _reviewStatusMap.REVIEWED; 23050 this.isTextContentVisible = true; 23051 23052 if (!this.options.showAsPopUp) { 23053 this.enableCheckBox(); 23054 } 23055 this.reviewDoc = this.$elementTextArea.text(); 23056 } 23057 } 23058 }; 23059 23060 23061 if (document.readyState === "complete") { 23062 setCheckBoxState.call(this); 23063 } else { 23064 23065 23066 $($.proxy(setCheckBoxState, this)); 23067 } 23068 } 23069 23070 23071 if (this.options.showAsPopUp) { 23072 var unvisitedClass = this.options.documentUnVisitedClass || _defaults.documentUnVisitedClass, 23073 visitedClass = this.options.documentVisitedClass || _defaults.documentVisitedClass; 23074 var _self = this, 23075 dialogId = this.$elementCheckBox.find('a') 23076 .keydown(function (e) { 23077 if (e.keyCode === 13 || e.which == 13 || e.charCode === 32) { 23078 $(this).click(); 23079 return false; 23080 } 23081 }) 23082 .click(function (event) { 23083 if ($(this).hasClass(unvisitedClass.substring(1))) { 23084 $(this).toggleClass(visitedClass.substring(1) + " " + unvisitedClass.substring(1)); 23085 } 23086 23087 23088 if (isBrowserIE || _self.isTextContentVisible) { 23089 _self.enableCheckBox(); 23090 } 23091 }).attr("href"); 23092 23093 $(dialogId).on('hidden.bs.modal', function (e) { 23094 _self.$elementCheckBox.find('input').focus(); 23095 }); 23096 } else { 23097 23098 this._updateScreenReaderText(); 23099 } 23100 23101 23102 this.$elementCheckBox.find('input').change($.proxy(this.handleCheckBoxChange, this)); 23103 }; 23104 23105 AfTnc.prototype = { 23106 23107 clear : function () { 23108 this.$element.val(''); 23109 }, 23110 23111 destroy : function () { 23112 this.$element.val(''); 23113 this.$element.empty(); 23114 }, 23115 23116 _updateScreenReaderText : function () { 23117 if (!this.options.showAsPopUp) { 23118 var _self = this; 23119 23120 this.$element.find(".guide-tnc-sr-only").each(function (i, obj) { 23121 $(this).html(_self.options.screenReaderText); 23122 }); 23123 } 23124 }, 23125 23126 _restoreClickState : function (value) { 23127 if (this.options.showLink) { 23128 var arr = value.split("\n"), 23129 linkState = []; 23130 23131 _.each(arr, function (linkText, index) { 23132 23133 linkState.push(_.last(linkText.split('='))); 23134 }); 23135 var unvisitedClass = this.options.documentUnVisitedClass || _defaults.documentUnVisitedClass, 23136 visitedClass = this.options.documentVisitedClass || _defaults.documentVisitedClass; 23137 this.$elementLink.find('a').each(function (index) { 23138 $(this).data("clicked", linkState[index]); 23139 if (linkState[index] === "1") { 23140 $(this).addClass(visitedClass.substring(1)); 23141 } else { 23142 $(this).addClass(unvisitedClass.substring(1)); 23143 } 23144 }); 23145 } 23146 }, 23147 23148 value : function (value) { 23149 if (value) { 23150 23151 if (this.options.showLink) { 23152 this._restoreClickState(value); 23153 } 23154 this.reviewDoc = value; 23155 } else { 23156 return this.reviewDoc; 23157 } 23158 23159 }, 23160 23161 reviewStatus : function (value) { 23162 var val = this.getClickState(); 23163 if (!_.isUndefined(value)) { 23164 if (value == "true") { 23165 this.enableCheckBox(); 23166 this.$elementCheckBox.find('input').attr("checked", "checked"); 23167 this.$elementCheckBox.find('input').prop("checked", true); 23168 } else if (value == null || value == "false") { 23169 23170 this.$elementCheckBox.find('input').removeAttr("checked"); 23171 this.$elementCheckBox.find('input').removeProp("checked"); 23172 } 23173 this.approvalStatus = value; 23174 } else { 23175 if (this.status == _reviewStatusMap.REVIEWED || this.status == _reviewStatusMap.UNREVIEWD) { 23176 return null; 23177 } else if (this.status == _reviewStatusMap.AGREE) { 23178 return true; 23179 } 23180 } 23181 }, 23182 23183 clickStatus : function (value) { 23184 if (value) { 23185 if (value === _reviewStatusMap.REVIEWED) { 23186 var arr = this.getClickState(); 23187 if (_.isArray(arr) && arr.length > 0) { 23188 arr = arr.join("\n"); 23189 this._restoreClickState(arr); 23190 } 23191 this.enableCheckBox(); 23192 } 23193 this.status = value; 23194 } else { 23195 return this.status; 23196 } 23197 }, 23198 23199 showLink : function (value) { 23200 if (value !== undefined) { 23201 this.options.showLink = value; 23202 } else { 23203 return this.options.showLink; 23204 } 23205 }, 23206 23207 access : function (value) { 23208 this.accessOption = value; 23209 if (value == "readOnly") { 23210 this.disableCheckBox(); 23211 if (this.options.showLink) { 23212 this.$elementLink.find('a').each(function (index, elem) {
23213 $(elem).css('pointer-events', 'none'); 23214 23215 $(elem).attr('disabled', 'disabled'); 23216 }); 23217 } 23218 } else if (value == "open") { 23219 23220 23221 if ((this.status == _reviewStatusMap.REVIEWED || this.status == _reviewStatusMap.AGREE) && !this.options.showAsPopUp) { 23222 this.enableCheckBox(); 23223 } 23224 if (this.options.showLink) { 23225 this.$element.find('a').each(function (index, elem) { 23226 $(elem).css('pointer-events', ''); 23227 $(elem).removeAttr('disabled'); 23228 }); 23229 } 23230 } 23231 }, 23232 23233 link : function () { 23234 return this.$element.find(this.options.linkClass || _defaults.linkClass); 23235 }, 23236 23237 textArea : function () { 23238 return this.$element.find(this.options.textAreaClass || _defaults.textAreaClass); 23239 }, 23240 23241 getClickState : function () { 23242 if (this.options.showLink) { 23243 var arr = []; 23244 this.$elementLink.find('a').each(function (index) { 23245 arr.push({ 23246 'displayText' : $(this).text(), 23247 'linkText' : $(this).attr('href'), 23248 'clicked' : $(this).data("clicked") 23249 }); 23250 }); 23251 return arr; 23252 } 23253 }, 23254 23255 enableCheckBox : function () { 23256 if (this.accessOption !== "readOnly") { 23257 this.$elementCheckBox.find('input').removeAttr("disabled"); 23258 this.$elementCheckBox.removeClass(this.options.checkBoxDisableClass.substring(1)); 23259 } 23260 }, 23261 23262 disableCheckBox : function () { 23263 this.$elementCheckBox.find('input').attr('disabled', 'disabled'); 23264 this.$elementCheckBox.addClass(this.options.checkBoxDisableClass.substring(1)); 23265 }, 23266 23267 handleReviewStatusChange : function (event) { 23268 var arr = [], 23269 visitedClass = this.options.documentVisitedClass || _defaults.documentVisitedClass; 23270 if (this.options.showLink) { 23271 this.status = _reviewStatusMap.REVIEWED; 23272 23273 $(event.target).data("clicked", 1); 23274 $(event.target).addClass(visitedClass.substring(1)); 23275 this.linkStateMap = this.getClickState(); 23276 _.each(this.linkStateMap, function (element, index) { 23277 if (!element.clicked) { 23278 this.status = _reviewStatusMap.UNREVIEWD; 23279 } 23280 23281 arr.push(element.displayText + "=" + element.linkText + "=" + (_.isUndefined(element.clicked) ? "0" : "1")); 23282 }, this); 23283 if (arr.length > 0) { 23284 this.reviewDoc = arr.join("\n"); 23285 } 23286 23287 if (this.status == _reviewStatusMap.REVIEWED) { 23288 this.enableCheckBox(); 23289 } 23290 23291 23292 this.$element.trigger('reviewComplete.tnc'); 23293 23294 } else { 23295 23296 var position = this.getScroll(this.$elementTextArea.parent().get(0)), 23297 xy = position[this.options.scrollMode == 'vertical' ? 'y' : 'x']; 23298 var isScrolledToEnd = this.getScrollSize(this.$elementTextArea.parent().get(0)).y <= (this.getSize(this.$elementTextArea.parent().get(0)).y + xy); 23299 23300 this.reviewDoc = this.$elementTextArea.text(); 23301 23302 23303 if (isScrolledToEnd) { 23304 23305 if (!this.inside) { 23306 23307 this.inside = true; 23308 this.enters++; 23309 23310 this.status = _reviewStatusMap.REVIEWED; 23311 if (!this.approvalStatus) { 23312 this.enableCheckBox(); 23313 23314 this.$element.trigger('reviewComplete.tnc', [position,this.enters,event]); 23315 } 23316 } 23317 } 23318 23319 else if (this.inside) { 23320 this.inside = false;
23321 this.leaves++; 23322 23323 } 23324 } 23325 23326 }, 23327 23328 handleCheckBoxChange : function (event) { 23329 if ($(event.target).is(':checked')) { 23330 this.status = _reviewStatusMap.AGREE; 23331 this.$elementCheckBox.addClass(this.options.checkBoxReviewedClass.substring(1)); 23332 } else { 23333 this.status = _reviewStatusMap.UNREVIEWD; 23334 this.$elementCheckBox.removeClass(this.options.checkBoxReviewedClass.substring(1)); 23335 } 23336 this.$element.trigger('checkboxStateChange.tnc'); 23337 }, 23338 23339 getScrollSize : function (elem) { 23340 return {x : elem.scrollWidth, y : elem.scrollHeight}; 23341 }, 23342 23343 getScroll : function (elem) { 23344 return {x : elem.scrollLeft, y : elem.scrollTop}; 23345 }, 23346 23347 getSize : function (elem) { 23348 return {x : elem.offsetWidth, y : elem.offsetHeight}; 23349 }, 23350 23351 hasScrollBar : function (container) { 23352 23353 if (isBrowserIE) { 23354 23355 return ((container.scrollHeight - 2) > container.clientHeight) || ((container.scrollWidth - 2) > container.clientWidth); 23356 } else { 23357 return container.scrollHeight > container.clientHeight || container.scrollWidth > container.clientWidth; 23358 } 23359 } 23360 }; 23361 23362 $.fn.afTnc = function (option, value) { 23363 var get = '', 23364 element = this.each(function () { 23365 23366 var $this = $(this), 23367 data = $this.data('AfTnc'), 23368 options = $.extend({}, _defaults, typeof option === 'object' && option); 23369 23370 23371 if (!data) { 23372 $this.data('AfTnc', (data = new AfTnc(this, options))); 23373 } 23374 23375 23376 if (typeof option === 'string') { 23377 get = data[option](value); 23378 } 23379 }); 23380 23381 if (typeof get !== undefined) { 23382 return get; 23383 } else { 23384 return element; 23385 } 23386 }; 23387 23388})(_, $); 23389(function ($) { 23390 var xfaUtil = xfalib.ut.XfaUtil.prototype; 23391 $.widget("xfaWidget.tnc", $.xfaWidget.abstractWidget, { 23392 23393 _widgetName : "tnc", 23394 _superPrototype : $.xfaWidget.abstractWidget.prototype, 23395 getOptionsMap : function () { 23396 var parentOptionsMap = this._superPrototype.getOptionsMap.apply(this, arguments), 23397 newMap = $.extend({}, parentOptionsMap, $.extend({}, this.options, { 23398 "value" : function (value) { 23399 this.$userControl.afTnc("value", value); 23400 }, 23401 "reviewStatus" : function (value) { 23402 this.$userControl.afTnc("reviewStatus", value); 23403 }, 23404 23405 "clickStatus" : function (value) { 23406 this.$userControl.afTnc("clickStatus", value); 23407 }, 23408 23409 "access" : function (value) { 23410 this.$userControl.afTnc("access", value); 23411 } 23412 })); 23413 return newMap; 23414 }, 23415 23416 _getReviewStatus : function () { 23417 return $(this.element).afTnc("reviewStatus"); 23418 }, 23419 23420 _getClickStatus : function () { 23421 return $(this.element).afTnc("clickStatus"); 23422 }, 23423 23424 getEventMap : function () { 23425 var parentEventMap = this._superPrototype.getEventMap.apply(this, arguments), 23426 newMap = $.extend({}, parentEventMap, 23427 { 23428 "change" : null, 23429 "reviewComplete.tnc" : xfaUtil.XFA_CHANGE_EVENT, 23430 "checkboxStateChange.tnc" : xfaUtil.XFA_CHANGE_EVENT 23431 }); 23432 return newMap; 23433 }, 23434 render : function () { 23435 this._superPrototype.render.apply(this, arguments); 23436 $(this.element).afTnc(this.getOptionsMap()); 23437 return $(this.element); 23438 }, 23439 showDisplayValue : function () { 23440 23441 }, 23442 showValue : function () { 23443 23444 }, 23445 getCommitValue : function () { 23446 this.options.reviewStatus = this._getReviewStatus(); 23447 this.options.clickStatus = this._getClickStatus(); 23448 return $(this.element).afTnc("value"); 23449 } 23450 }); 23451})($); 23452 23453(function (_, guidelib) { 23454 var orderGetAttribute = { 23455 "Guide" : "XFA", 23456 "XFA" : "Guide" 23457 }, 23458 23459 newlyAddedProperties = ["enabled", "visible"]; 23460 23461 var GuideNode = guidelib.model.GuideNode = xfalib.ut.EventClass.extend({ 23462 msClassName : "guideNode", 23463 guideUtil : guidelib.util.GuideUtil, 23464 23465 initialize : function () { 23466 23467 23468 this.className = this.jsonModel.guideNodeClass || this.msClassName; 23469 this.parent = null; 23470 this._isItem = false;
23471 this._index = 0; 23472 }, 23473 23474 _postInitialize : function () { 23475 23476 }, 23477 23478 _triggerOnBridge : function (eventName, target, property, oldVal, newVal) { 23479 if (window.guideBridge) { 23480 window.guideBridge.trigger(eventName, 23481 guidelib.event.GuideModelEvent.createEvent(eventName, target, property, 23482 oldVal, newVal)); 23483 } 23484 }, 23485 23486 _getEffectiveBindRef : function() { 23487 return this.bindRef || this.getAttribute("name"); 23488 }, 23489 23490 validate : function (errorList) { 23491 23492 }, 23493 23494 23495 23496 _getXFAOptionStringFromGuideItems : function (guideItems) { 23497 var optionsStr = "", indexOfSeparator = 0; 23498 if (!_.isEmpty(guideItems) && !_.isArray(guideItems)) { 23499 guideItems = [guideItems]; 23500 } 23501 _.each(guideItems, function (item, index, list) { 23502 if(item.indexOf(",") > -1){ 23503 item = item.replace(/,/g, "\\,"); 23504 } 23505 indexOfSeparator = item.indexOf('='); 23506 23507 23508 if (indexOfSeparator > -1) { 23509 optionsStr += item.substring(indexOfSeparator + 1) + "," + item.substring(0, indexOfSeparator); 23510 } else { 23511 optionsStr += item + "," + item; 23512 } 23513 if (index < guideItems.length - 1) { 23514 optionsStr += ","; 23515 } 23516 }); 23517 return optionsStr; 23518 }, 23519 23520 _compareXFAItemsWithGuideItems : function (xfaItems, guideItems) { 23521 var match = true; 23522 if (xfaItems.length !== guideItems.length) { 23523 match = false; 23524 } 23525 if (match) { 23526 var bndNode = this.bindNode; 23527 _.each(guideItems, function (item, index, list) { 23528 if (item.indexOf('=') > -1) { 23529 if ((bndNode.getSaveItem(index) + "=" + bndNode.getDisplayItem(index)) == item) { 23530 match = false; 23531 } 23532 } else { 23533 if ((bndNode.getSaveItem(index) + "=" + bndNode.getDisplayItem(index)) == (item + "=" + item)) { 23534 match = false; 23535 } 23536 } 23537 }); 23538 } 23539 return match; 23540 }, 23541 23542 23543 syncXFAProps : function () { 23544 if (this.bindNode) { 23545 _.each(this._guide()._guideSchema.getAttributes(this.className), 23546 function (attr, attrName) { 23547 var xfaProp = attr.xfaProp, 23548 propChain = (xfaProp || "").split("."), 23549 xfaAttr = propChain.length > 0 ? propChain[propChain.length - 1] 23550 : undefined; 23551 23552 23553 23554 23555 23556 23557 if (!xfaAttr || (newlyAddedProperties.indexOf(attrName) != -1 && _.isUndefined(this.jsonModel[attrName]))) { 23558 return; 23559 } 23560 var objChain = propChain.splice(0, propChain.length - 1), 23561 obj = _.reduce(objChain, 23562 function (obj, prop) { 23563 if (_.isObject(obj)) { 23564 return obj[prop]; 23565 } 23566 return undefined; 23567 }, this.bindNode), 23568 val = this.getGuideProp(attrName, attr), 23569 convertor = this._guide()._guideSchema.getConvertor(attrName), 23570 cVal = convertor ? convertor.guideToXfa.apply(this, [val]) : val, 23571 xfaVal; 23572 try { 23573 if (obj) { 23574 xfaVal = obj[xfaAttr]; 23575 if (cVal !== undefined) { 23576 if (xfaAttr === "items") { 23577 var match = this._compareXFAItemsWithGuideItems(obj, cVal); 23578 var SET_ITEMS_INSERT_MODE_PAIR = 2; 23579 if (!match) { 23580 var optionsStr = this._getXFAOptionStringFromGuideItems(cVal); 23581 if (optionsStr !== "") { 23582 obj.setItems(optionsStr, SET_ITEMS_INSERT_MODE_PAIR); 23583 } else { 23584 obj.clearItems(); 23585 } 23586 } 23587 } else if (cVal !== xfaVal) { 23588 obj[xfaAttr] = cVal; 23589 } 23590 } 23591 } 23592 } catch (e) { 23593 this.logger().error("AF", "setting {0}(guide {1}) for {2} is not supported in xfa", 23594 [xfaProp, attrName, this.bindNode.somExpression]); 23595 if (e.stack) { 23596 this.logger().error("AF", e.stack); 23597 } 23598 } 23599 }, this); 23600 } 23601 }, 23602 23603 23604 prepare : function () { 23605 23606 }, 23607 23608 23609 nakedChildReferences : function (nIndex, obj) { 23610 return; 23611 }, 23612 23613 23614 getNaked : function (nIndex, container, scope) { 23615 var nodeName = this.getAttribute("name"), 23616 oldReference = container._private["_" + nodeName + "_"],
23617 canOverride = (container._isOverriden && !container._isOverriden["_" + nodeName + "_"]), 23618 isGlobalFieldRef = this.isGlobal && (container === guidelib.__runtime__ || container === this._guide().runtime) 23619 && (container[nodeName] instanceof guidelib.model.AbstractField); 23620 23621 if ((scope && scope._nameArray[nodeName] === 1) || (nIndex === this.index)) { 23622 if (oldReference === null || oldReference === undefined || canOverride || isGlobalFieldRef) { 23623 guidelib.util.GuideUtil._createGetterSetter(container, nodeName, this); 23624 if (canOverride === true) { 23625 container._isOverriden["_" + nodeName + "_"] = true; 23626 } 23627 } 23628 } 23629 }, 23630 23631 _getReducedJSON : function () { 23632 var whitelistedProperties = ["name", "templateId", "_value", "guideNodeClass"], 23633 reducedJsonObject = {}; 23634 guidelib.model.util.CommonUtils.returnMinimalJSON(whitelistedProperties, reducedJsonObject, this); 23635 return reducedJsonObject; 23636 }, 23637 23638 _getNakedThis : function () { 23639 return this; 23640 }, 23641 23642 _xfa : function () { 23643 if (window.xfalib) { 23644 return window.xfalib.runtime.xfa; 23645 } 23646 return null; 23647 }, 23648 23649 _guide : function () { 23650 return this.options._guideContainer; 23651 }, 23652 23653 23654 playJson : function (pJsonModel) { 23655 23656 }, 23657 23658 23659 23660 visit : function (callback, context) { 23661 callback.apply(context, [this]); 23662 }, 23663 23664 _collectValues : function (keyValue) { 23665 23666 }, 23667 23668 _setParentAccess : function (value) { 23669 23670 }, 23671 23672 _unloadModel : function () { 23673 this.trigger(guidelib.event.GuideModelEvent.OBJECT_DESTROYED, 23674 guidelib.event.GuideModelEvent.createEvent( 23675 guidelib.event.GuideModelEvent.OBJECT_DESTROYED, 23676 this, 23677 "destroy", 23678 null, 23679 this 23680 ) 23681 ); 23682 this._guide()._modelTemplateCacheStore.removeModel(this.id); 23683 this.off(); 23684 23685 if (_.isObject(guidelib.__runtime__[this.name]) && (guidelib.__runtime__[this.name] === this || guidelib.__runtime__[this.name].somExpression === this.somExpression)) { 23686 guidelib.__runtime__[this.name] = undefined; 23687 if (_.isObject(guidelib.__runtime__._private['_' + this.name + '_'])) { 23688 guidelib.__runtime__._private['_' + this.name + '_'] = undefined; 23689 } 23690 } 23691 23692 if (_.isObject(this._guide().runtime[this.name]) && (this._guide().runtime[this.name] === this || this._guide().runtime[this.name].somExpression === this.somExpression)) { 23693 this._guide().runtime[this.name] = undefined; 23694 if (_.isObject(this._guide().runtime._private['_' + this.name + '_'])) { 23695 this._guide().runtime._private['_' + this.name + '_'] = undefined; 23696 } 23697 } 23698 }, 23699 23700 _triggerEvent : function (event, propName, prevText, newText) { 23701 this.trigger(event, 23702 guidelib.event.GuideModelEvent.createEvent(event, this, propName, 23703 prevText, newText)); 23704 }, 23705 23706 23707 dispatchEvent : function (eventName, payload) { 23708 this._triggerEvent(eventName, payload); 23709 if(this.parent !== null){ 23710 this.parent.dispatchEvent(eventName, payload); 23711 } 23712 }, 23713 23714 23715 setAttribute : function (value, attrName) { 23716 if (this.jsonModel[attrName] !== value) { 23717 var oldValue = this.jsonModel[attrName]; 23718 this.jsonModel[attrName] = value; 23719 this._triggerEvent(guidelib.event.GuideModelEvent.MODEL_CHANGED, attrName, oldValue, value); 23720 } 23721 }, 23722 23723 _getSomExpression : function () { 23724 if (this.parent == null) { 23725 return "guide[0]." + this._escapeQualifiedName(); 23726 } else { 23727 return this.parent.somExpression + "." + this._escapeQualifiedName(); 23728 } 23729 }, 23730 23731 _escapeQualifiedName : function () { 23732 var name = this.getAttribute("name"); 23733 var index = this._index; 23734 var qname = name + "[" + index + "]"; 23735 return qname.replace(/\./, "\\."); 23736 }, 23737 23738 23739 getGuideProp : function (attrName, attr) { 23740 var val = this.getOrElse(this.jsonModel, attrName, attr["default"]); 23741 if (val === undefined) { 23742 return undefined; 23743 } 23744 return guidelib.model.GuideSchema.prototype.getTypedValue(attr.type, val); 23745 23746 }, 23747 23748 23749 getXFAProp : function (attrName, attr) { 23750 var xfaName = attr.xfaProp, 23751 convertor = guidelib.model.GuideSchema.prototype.getConvertor(attrName), 23752 val; 23753 if (this.bindNode && xfaName !== undefined) { 23754 val = this.bindNode.getOrElse(this.bindNode, xfaName, undefined); 23755 if (convertor) { 23756 val = convertor.xfaToGuide.apply(this, [val]); 23757 } 23758 if (val !== undefined) { 23759 return val; 23760 } 23761 } 23762 return undefined; 23763 }, 23764 23765 23766 getAttribute : function (attrName) { 23767 var attr = guidelib.model.GuideSchema.prototype.getAttributeProps(this.className, attrName), 23768 priority = attr.priority || (attr.xfaProp !== undefined ? "XFA" : "Guide"), 23769 23770 val = this["get" + priority + "Prop"].apply(this, [attrName, attr]); 23771 23772 if (val === undefined) { 23773 23774 val = this["get" + orderGetAttribute[priority] + "Prop"].apply(this, [attrName, attr]); 23775 } 23776 return val; 23777 }, 23778 23779 23780 resetData : function () { 23781 23782 } 23783 }); 23784 23785 GuideNode.defineProps({ 23786 23787 23788 "name" : { 23789 get : function () { 23790 return (this.getAttribute("name") || "").replace(/\s+/g, ''); 23791 } 23792 }, 23793 23794 "templateId" : { 23795 get : function () { 23796 return this.getAttribute("templateId"); 23797 } 23798 }, 23799 23800 23801 "id" : { 23802 get : function () { 23803 return this.getAttribute("id") || this.templateId; 23804 } 23805 }, 23806 23807 23808 somExpression : { 23809 get : function () { 23810 return this._getSomExpression(); 23811 } 23812 }, 23813 23814 23815 "title" : { 23816 get : function () { 23817 return this.getAttribute("jcr:title"); 23818 } 23819 }, 23820 23821 23822 "nonLocalizedTitle" : { 23823 get : function () { 23824 return this.getAttribute("nonLocalizedTitle"); 23825 } 23826 }, 23827 23828 23829 panel : { 23830 get : function () { 23831 return this.parent.panel; 23832 } 23833 }, 23834 23835 viewVisited : { 23836 get : function () { 23837 return this.getAttribute("viewVisited"); 23838 }, 23839 set : function (visit) { 23840 this.setAttribute(visit, "viewVisited"); 23841 } 23842 }, 23843 23844 23845 index : { 23846 get : function () { 23847 return this._index; 23848 } 23849 }, 23850 23851 23852 visible : { 23853 get : function () { 23854 return true; 23855 }, 23856 set : function (value) { 23857 23858 } 23859 }, 23860 23861 23862 enabled : { 23863 get : function () { 23864 return true; 23865 }, 23866 set : function (value) { 23867 23868 } 23869 }, 23870 23871 23872 cssClassName : { 23873 get : function () { 23874 return this.getAttribute("css"); 23875 } 23876 }, 23877 23878 enableLayoutOptimization : { 23879 get : function () { 23880 return false;
23881 } 23882 }, 23883 23884 jcrPath : { 23885 get : function () { 23886 return this.jsonModel["jcr:path"]; 23887 } 23888 }, 23889 23890 23891 targetVersion : { 23892 get : function () { 23893 return this.getAttribute("fd:targetVersion"); 23894 } 23895 } 23896 }); 23897}(_, guidelib)); 23898(function (_, guidelib, $) { 23899 var Verify = guidelib.model.Verify = guidelib.model.GuideNode.extend({ 23900 msClassName : "verify", 23901 23902 initialize : function () { 23903 Verify._super.initialize.call(this); 23904 this.validationStatus = true; 23905 }, 23906 23907 validate : function (errorList) { 23908 23909 23910 var iframeFormBridge = null, validationStatus = true; 23911 23912 if (this.jsonModel.interactive !== undefined && this.jsonModel.interactive === "true") { 23913 23914 23915 23916 23917 23918 if (guideBridge.hostName === "client") { 23919 iframeFormBridge = $('#verifiable_form').get(0).contentWindow.formBridge; 23920 } 23921 23922 23923 if (iframeFormBridge !== undefined && iframeFormBridge !== null) { 23924 validationStatus = iframeFormBridge.validateForm(); 23925 if (!validationStatus) { 23926 errorList.push({som : this.somExpression, errorText : "XFA validation errors."}); 23927 } 23928 this.validationStatus = validationStatus; 23929 } 23930 } 23931 23932 return validationStatus; 23933 } 23934 }); 23935 Verify.defineProps({ 23936 forceElementFocusChange : { 23937 get : function () { 23938 return true; 23939 } 23940 } 23941 }); 23942})(_, guidelib, $); 23943(function (_, guidelib) { 23944 var Esign = guidelib.model.Esign = guidelib.model.GuideNode.extend({ 23945 msClassName : "esign", 23946 23947 initialize : function () { 23948 Esign._super.initialize.call(this); 23949 this.validationStatus = true; 23950 }, 23951 23952 validate : function (errorList) { 23953 23954 23955 var validationStatus = true; 23956 if (!_.isUndefined(FD) && 23957 !_.isUndefined(FD.AFaddon) && 23958 FD.AFaddon.Signing) { 23959 validationStatus = FD.AFaddon.Signing.isDocumentSigned(this.jsonModel.signingService); 23960 if (!validationStatus) { 23961 errorList.push({som : this.somExpression, errorText : "Signing not complete."}); 23962 } 23963 } 23964 this.validationStatus = validationStatus; 23965 return validationStatus; 23966 } 23967 }); 23968 Esign.defineProps({ 23969 forceElementFocusChange : { 23970 get : function () { 23971 return true; 23972 } 23973 } 23974 }); 23975})(_, guidelib); 23976(function (_, xfalib, guidelib) { 23977 23978 var expressionContent = "with(this) {" + 23979 "\n\t with(guidelib.__runtime__) {" + 23980 "\n\t with(this._guide().runtime) {" + 23981 "\n\t\t var _guide_result = this[${affectedProp}] = eval(\"${expression}\");" + 23982 "\n\t\t return _guide_result ;" + 23983 "\n\t }" + 23984 "\n}};", 23985 scriptContent = "with(this) {" + 23986 "\n\t with(guidelib.__runtime__) {" + 23987 "\n\t with(this._guide().runtime) {" + 23988 "\n\t var result = eval(\"${expression}\");" + 23989 "\n\t\t return result; " + 23990 "\n\t }" + 23991 "\n}}"; 23992 23993 var Scriptable = guidelib.model.Scriptable = guidelib.model.GuideNode.extend({ 23994 msClassName : "scriptable", 23995 23996 initialize : function () { 23997 Scriptable._super.initialize.call(this); 23998 23999 this.className = this.jsonModel.guideNodeClass || this.msClassName; 24000 this._compiledExpressions = {}; 24001 this._compiledScripts = {}; 24002 this.mActiveEvents = []; 24003 this.dependants = []; 24004 24005 if (this.initScript) { 24006 this._isInitScriptExecuted = false;
24007 } 24008 this._collectExpressions(); 24009 }, 24010 24011 _postInitialize : function () { 24012 24013 if (this._isXfaNode()) { 24014 this.bindNode = this.options.bindNode || this._getBindNode(); 24015 if (this.bindNode) { 24016 this.bindNode.on(xfalib.script.XfaModelEvent.FORM_MODEL_CHANGED, this); 24017 } 24018 } 24019 24020 this._parentAccess = this.getOrElse(this, "parent.enabled", true); 24021 }, 24022 24023 _unloadModel : function () { 24024 if (this._isXfaNode && this._isXfaNode()) { 24025 if (this.bindNode) { 24026 this.bindNode.off(xfalib.script.XfaModelEvent.FORM_MODEL_CHANGED, this); 24027 } 24028 } 24029 24030 Scriptable._super._unloadModel.call(this); 24031 }, 24032 24033 _collectExpressions : function () { 24034 if (this.visibleExp) { 24035 this._compiledExpressions["visibleExp"] = this._compileExpression(this.visibleExp, "visible"); 24036 } 24037 if (this.enabledExp) { 24038 this._compiledExpressions["enabledExp"] = this._compileExpression(this.enabledExp, "enabled"); 24039 } 24040 24041 if (this.initScript) { 24042 this._compiledScripts.initScript = this._compileExpression(this.initScript, null); 24043 } 24044 }, 24045 24046 _compileExpression : function (expression, affectedProp) { 24047 if (expression) { 24048 try { 24049 24050 var content = affectedProp ? expressionContent.replace(/\${affectedProp}/g, '"' + affectedProp + '"') 24051 .replace(/\${expression}/g, expression.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/(?:\r\n|\r|\n)/g, " ")) 24052 : scriptContent.replace(/\${expression}/g, 24053 expression.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/(?:\r\n|\r|\n)/g, " ")); 24054 24055 return new Function(content); 24056 } catch (exception) { 24057 this.logger().error("AF", "Error in compiling expression:" + expression); 24058 } 24059 } 24060 return null; 24061 }, 24062 24063 _isXfaNode : function () { 24064 return (this._xfa() && this.getOrElse(this, "jsonModel.bindRef", "").indexOf("xfa[0].form[0].") === 0); 24065 }, 24066 24067 _xfa : function () { 24068 return this.getOrElse(window, "xfalib.runtime.xfa", null); 24069 }, 24070 24071 prepare : function () { 24072 Scriptable._super.prepare.apply(this); 24073 24074 24075 24076 24077 24078 if (this.initScript && !this._isInitScriptExecuted) { 24079 this.executeExpression("initScript"); 24080 this._isInitScriptExecuted = true; 24081 } 24082 var expressionTypes = _.keys(this._compiledExpressions); 24083 this._guide().queueExpressions(this, expressionTypes); 24084 }, 24085 24086 24087 handleEvent : function (evnt) { 24088 if (evnt instanceof xfalib.script.XfaModelEvent) { 24089 switch (evnt.name) { 24090 case xfalib.script.XfaModelEvent.FORM_MODEL_CHANGED: 24091 this._handleXfaModelChanged(evnt); 24092 break; 24093 default: 24094 24095 } 24096 } else if (evnt instanceof guidelib.event.GuideModelEvent) { 24097 this.handleGuideEvent(evnt); 24098 } 24099 }, 24100 24101 handleGuideEvent : function (evnt) { 24102 }, 24103 24104 24105 executeExpression : function (eventName, detail) { 24106 var guideContainerNode = this._guide(); 24107 if (this._isXfaNode() && this.bindNode instanceof xfalib.script.EventContainerNode) { 24108 if (guidelib.util.GuideUtil.xfaExprMap[eventName] !== null) { 24109 this.bindNode.execEvent(guidelib.util.GuideUtil.xfaExprMap[eventName] || eventName, detail); 24110 } 24111 } 24112 if (_.isUndefined(this._compiledExpressions[eventName]) && _.isUndefined(this._compiledScripts[eventName])) { 24113 if (!guideContainerNode._currentContext) { 24114 guideContainerNode.runPendingExpressions(); 24115 } else { 24116 this.logger().log("AF", "executeExpression called withing from another executeExpression. Should NEVER happen "); 24117 } 24118 return true; 24119 } 24120 24121 if (this.mActiveEvents[eventName]) { 24122 return; 24123 } 24124 this.mActiveEvents[eventName] = true; 24125 var managedExp = this._compiledExpressions[eventName] ? true : false, 24126 oldContext = guideContainerNode._currentContext; 24127 24128 guideContainerNode._currentContext = {contextNode: this, expression: eventName, managedExp: managedExp}; 24129 this._setExpressionContext(this, this.index); 24130 var $event = { 24131 name: eventName, 24132 target: this, 24133 data: detail 24134 }; 24135 guideContainerNode.runtime.$event = $event;
24136 var expResult = this._expressionHandler(eventName); 24137 this.mActiveEvents[eventName] = false; 24138 24139 24140 guideContainerNode._currentContext = oldContext; 24141 if (oldContext && oldContext.contextNode) { 24142 oldContext.contextNode._setExpressionContext(oldContext.contextNode, oldContext.contextNode.index); 24143 } 24144 guideContainerNode.runtime.$event = null; 24145 guideContainerNode.runPendingExpressions(); 24146 return expResult; 24147 }, 24148 24149 _setExpressionContext : function (startNode, currentIndex) { 24150 24151 var currentSom = this.somExpression; 24152 function somCommonPrefixLen(field) { 24153 return guidelib.util.GuideUtil.commonPrefixLen(currentSom, field.somExpression); 24154 } 24155 24156 if (this._guide().internal.liveModel) { 24157 _.each(this._guide().internal.liveModel.getCrossFragmentFields(), function (fields, name) { 24158 var loadedFields, 24159 nearestField; 24160 24161 24162 loadedFields = this._guide().internal.liveModel.getAllFieldModels(_.keys(fields)); 24163 24164 24165 if (!_.isEmpty(loadedFields)) { 24166 nearestField = _.max(loadedFields, somCommonPrefixLen); 24167 } 24168 24169 24170 24171 24172 24173 guidelib.util.GuideUtil._createGetterSetter(guidelib.__runtime__, name, nearestField || fields[_.keys(fields)[0]]); 24174 guidelib.util.GuideUtil._createGetterSetter(this._guide().runtime, name, nearestField || fields[_.keys(fields)[0]]); 24175 }, this); 24176 } 24177 24178 24179 this._guide().runtime._isOverriden = {}; 24180 guidelib.__runtime__._isOverriden = {}; 24181 while (startNode) { 24182 24183 startNode.nakedChildReferences(currentIndex, guidelib.__runtime__); 24184 startNode.nakedChildReferences(currentIndex, this._guide().runtime); 24185 currentIndex = startNode.index; 24186 startNode = startNode.parent; 24187 } 24188 }, 24189
24190 _expressionHandler : function (expressionName) { 24191 var expFn, returnValue; 24192 if (this._compiledExpressions[expressionName]) { 24193 expFn = this._compiledExpressions[expressionName]; 24194 try { 24195 returnValue = expFn.apply(this); 24196 } catch (exception) { 24197 24198 this.logger().error("AF", "Error in compiling expression:" + this.name + ":" + expressionName + ":" + exception.stack); 24199 } 24200 } else if (this._compiledScripts[expressionName]) { 24201 expFn = this._compiledScripts[expressionName]; 24202 try { 24203 return expFn.apply(this); 24204 } catch (scriptException) { 24205 24206 this.logger().error("AF", "Error in compiling expression:" + this.name + ":" + expressionName + ":" + scriptException.stack); 24207 } 24208 } 24209 return returnValue; 24210 }, 24211 24212 _handleXfaModelChanged : function (event) { 24213 if (event._property == "presence") { 24214 24215 var newText = !(event.newText != "visible"); 24216 this._triggerEvent(guidelib.event.GuideModelEvent.MODEL_CHANGED, "visible", event.prevText, newText); 24217 } else if (event._property == "access") { 24218 this.trigger(guidelib.event.GuideModelEvent.MODEL_CHANGED, 24219 guidelib.event.GuideModelEvent.createEvent( 24220 guidelib.event.GuideModelEvent.MODEL_CHANGED, 24221 this, 24222 "enabled", 24223 event.prevText == "open", 24224 event.newText == "open" 24225 ) 24226 ); 24227 } 24228 }, 24229 24230 _getScreenReaderText : function (index) { 24231 var screenReaderText, assistPriority = this._getAssistPriority(); 24232 if (assistPriority == "custom") { 24233 screenReaderText = this._getCustomAssist(index) || this._getToolTip(index) || this._getCaption(index) || this._getName(index); 24234 } else if (assistPriority == "shortDescription") { 24235 screenReaderText = this._getToolTip(index) || this._getCaption(index) || this._getName(index); 24236 } else if (assistPriority == "label") { 24237 screenReaderText = this._getCaption(index) || this._getName(index); 24238 } else if (assistPriority == "name") { 24239 screenReaderText = this._getName(index); 24240 } 24241 return screenReaderText; 24242 }, 24243 24244 _getAssistPriority : function () { 24245 24246 return this.getAttribute("assistPriority") || "custom"; 24247 }, 24248 24249 _getCustomAssist : function () { 24250 var customAssist; 24251 if (this.bindNode && this.bindNode.assist && this.bindNode.assist.speak && this.bindNode.assist.speak.value) { 24252 customAssist = this.bindNode.assist.speak.value; 24253 } else if (this.jsonModel.custom) { 24254 customAssist = this.jsonModel.custom; 24255 } 24256 return customAssist; 24257 }, 24258 24259 _getToolTip : function () { 24260 return this.shortDescription; 24261 }, 24262 24263 _getCaption : function () { 24264 return this.getAttribute("jcr:title"); 24265 }, 24266 24267 _getName : function (index) { 24268 return this.getAttribute("name"); 24269 }, 24270 24271 _getBindNode : function () { 24272 var bindRef = this.getAttribute("bindRef"); 24273 if (!bindRef) { 24274 return null; 24275 } 24276 var bindNode = null; 24277 var bindParent = this.parent ? this.parent._bindParent() : null; 24278 if (bindParent) { 24279 var bindParentRef = bindParent.getAttribute("bindRef"); 24280 if (bindRef.substring(0, bindParentRef.length) == bindParentRef) { 24281 24282 24283 var relativeBindRef = bindRef.substring(bindParentRef.length + 1);
24284 bindNode = bindParent.bindNode.resolveNode(relativeBindRef); 24285 } 24286 } 24287 if (!bindNode && this._isXfaNode()) { 24288 bindNode = this._xfa().resolveNode(bindRef); 24289 } 24290 return bindNode; 24291 }, 24292 24293 _bindParent : function () { 24294 if (this.bindNode) { 24295 return this; 24296 } else if (this.parent) { 24297 return this.parent._bindParent(); 24298 } 24299 return null; 24300 }, 24301 24302 24303 _getEnabled : function () { 24304 if (this.bindNode) { 24305 return this.bindNode.access == "open"; 24306 } else { 24307 return this.getAttribute("enabled") && this._parentAccess; 24308 } 24309 }, 24310 24311 24312 _setEnabled : function (value) { 24313 if (!this.bindNode) { 24314 if (this.getAttribute("enabled") !== value) { 24315 var oldEnabled = this.getAttribute("enabled"); 24316 this.setAttribute(value, "enabled"); 24317 this.trigger(guidelib.event.GuideModelEvent.MODEL_CHANGED, 24318 guidelib.event.GuideModelEvent.createEvent( 24319 guidelib.event.GuideModelEvent.MODEL_CHANGED, 24320 this, 24321 "enabled", 24322 oldEnabled, 24323 this.jsonModel.enabled 24324 ) 24325 ); 24326 this._triggerOnBridge("elementEnableChanged", this, "enablement", oldEnabled, this.jsonModel.enabled); 24327 } 24328 24329 } else { 24330 var convertor = this._guide()._guideSchema.getConvertor("enabled"); 24331 if (convertor) { 24332 this.bindNode.access = convertor.guideToXfa.apply(this, [value]); 24333 } 24334 } 24335 }, 24336 24337 24338 _setParentAccess : function (value) { 24339 var oldValue = this._parentAccess; 24340 this._parentAccess = value; 24341 this.trigger(guidelib.event.GuideModelEvent.MODEL_CHANGED, 24342 guidelib.event.GuideModelEvent.createEvent( 24343 guidelib.event.GuideModelEvent.MODEL_CHANGED, 24344 this, 24345 "enabled", 24346 oldValue, 24347 this.enabled 24348 ) 24349 ); 24350 }, 24351 24352 24353 _addStateOverride : function (key, values) { 24354 if (key !== null && _.isString(key) && values !== null) { 24355 var somExpr = this.somExpression; 24356 somExpr = somExpr.substring(this._guide().somExpression.length + 1); 24357 this.jsonModel.stateOverrides = this.jsonModel.stateOverrides || {"somExpr" : somExpr}; 24358 this.jsonModel.stateOverrides[key] = values; 24359 this._guide()._addToStateOverrideMap(this.id + this.name, this.jsonModel.stateOverrides); 24360 } 24361 } 24362 }); 24363 24364 Scriptable.defineProps({ 24365 24366 shortDescription : { 24367 get : function () { 24368 return this.getAttribute("shortDescription"); 24369 } 24370 }, 24371 24372 24373 longDescription : { 24374 get : function () { 24375 return this.getAttribute("longDescription"); 24376 } 24377 }, 24378 24379 visibleExp : { 24380 get : function () { 24381 return this.getAttribute("visibleExp"); 24382 } 24383 }, 24384 24385 initScript : { 24386 get : function () { 24387 return this.jsonModel.initScript; 24388 } 24389 }, 24390 24391 enabledExp : { 24392 get : function () { 24393 return this.getAttribute("enabledExp"); 24394 } 24395 }, 24396 24397 24398 visible : { 24399 get : function () { 24400 return this.getAttribute("visible"); 24401 }, 24402 24403 set : function (value) { 24404 if (!this.bindNode) { 24405 if (this.getAttribute("visible") !== value) { 24406 var oldVisible = this.getAttribute("visible"), 24407 dorExclusionFlag; 24408 this.setAttribute(value, "visible"); 24409 24410 24411 24412 if (this.getAttribute("dorExclusion") !== null) { 24413 if ((this._guide().getAttribute("excludeFromDoRIfHidden") === "true") 24414 || (this._guide().print 24415 && this._guide().print["excludeFromDoRIfHidden"] === "true")) { 24416 dorExclusionFlag = !value; 24417 24418 24419 this.dorExclusion = dorExclusionFlag; 24420 } 24421 } 24422 this.trigger(guidelib.event.GuideModelEvent.MODEL_CHANGED, 24423 guidelib.event.GuideModelEvent.createEvent( 24424 guidelib.event.GuideModelEvent.MODEL_CHANGED, 24425 this, 24426 "visible", 24427 oldVisible, 24428 this.jsonModel.visible 24429 ) 24430 ); 24431 this._triggerOnBridge("elementVisibleChanged", this, "visible", oldVisible, this.jsonModel.visible); 24432 } 24433 } else { 24434 if (value == true) { 24435 this.bindNode.presence = "visible"; 24436 } else { 24437 this.bindNode.presence = "hidden"; 24438 } 24439 } 24440 } 24441 }, 24442 24443 24444 dorExclusion : { 24445 get : function () { 24446 24447 if (this.jsonModel.dorExclusion != null) { 24448 if (_.isString(this.jsonModel.dorExclusion)) { 24449 24450 return this.jsonModel.dorExclusion === "true"; 24451 } else { 24452 return this.jsonModel.dorExclusion; 24453 } 24454 } 24455 24456 else if ((this._guide().getAttribute("excludeFromDoRIfHidden") === "true") 24457 || (this._guide().print 24458 && this._guide().print["excludeFromDoRIfHidden"] === "true")) { 24459 return !this.visible; 24460 } else { 24461 24462 return false;
24463 } 24464 }, 24465 24466 set : function (value) { 24467 24468 24469 24470 var somExpr = this.somExpression; 24471 somExpr = somExpr.substring(this._guide().somExpression.length + 1); 24472 this._guide()._addToExcludeFromDorMap(somExpr, value); 24473 this.jsonModel.dorExclusion = value; 24474 } 24475 }, 24476 24477 24478 stateOverrides : { 24479 get : function () { 24480 return this.jsonModel.stateOverrides; 24481 } 24482 }, 24483 24484 24485 enabled : { 24486 get : function () { 24487 return this._getEnabled(); 24488 }, 24489 24490 set : function (value) { 24491 24492 this._setEnabled(!!value); 24493 } 24494 }, 24495 24496 24497 bindRef : { 24498 get : function () { 24499 return (this.getAttribute("bindRef") || "").replace(/\s+/g, ''); 24500 } 24501 }, 24502 24503 24504 isXsd : { 24505 24506 get : function () { 24507 return _.isString(guideBridge._guide.xsdRef) && !_.isEmpty(this.bindRef) && this.bindRef[0] === '/'; 24508 } 24509 } 24510 }); 24511})(_, window.xfalib, guidelib); 24512(function (_, guidelib) { 24513 var GuideImage = guidelib.model.GuideImage = guidelib.model.Scriptable.extend({ 24514 msClassName : "guideImage" 24515 }); 24516 24517 GuideImage.defineProps({ 24518 value : { 24519 get : function () { 24520 if (this.bindNode) { 24521 return this.bindNode.rawValue; 24522 } else { 24523 return null; 24524 } 24525 } 24526 } 24527 }); 24528})(_, guidelib); 24529(function (_, guidelib) { 24530 var GuideAdModule = guidelib.model.GuideAdModule = guidelib.model.Scriptable.extend({ 24531 msClassName : "guideAdModule", 24532 24533 initialize : function () { 24534 GuideAdModule._super.initialize.call(this); 24535 this.jsonModel["{default}"] = this.getOrElse(this.jsonModel, "{default}", this.jsonModel._value); 24536 this.layoutConfigs = []; 24537 24538 if (typeof this.jsonModel.layoutConfig === "string") { 24539 this.layoutConfigs.push(JSON.parse(this.jsonModel.layoutConfig)); 24540 } else { 24541 _.each(this.jsonModel.layoutConfig, function (layoutConfig) { 24542 this.layoutConfigs.push(JSON.parse(layoutConfig)); 24543 }, this); 24544 } 24545 }, 24546 24547 _getTypedValue : function (value) { 24548 if (_.isUndefined(value) || value === null || value === "") { 24549 return null; 24550 } 24551 return value + ""; 24552 }, 24553 24554 playJson : function (pJsonModel) { 24555 var olval = this.jsonModel._value; 24556 this.jsonModel._value = pJsonModel._value; 24557 this._triggerOnBridge("elementValueChanged", this, "value", olval, this.jsonModel._value); 24558 } 24559 }); 24560 24561 GuideAdModule.defineProps({ 24562 24563 value : { 24564 get : function () { 24565 return this._getTypedValue(this.jsonModel._value); 24566 }, 24567 set : function (newValue) { 24568 var oldValue = this._getTypedValue(this.jsonModel._value), 24569 newTypedValue = this._getTypedValue(newValue); 24570 24571 if (newTypedValue !== undefined && (newTypedValue !== oldValue)) { 24572 if (this.jsonModel._value !== newValue) { 24573 this.jsonModel._value = newTypedValue || ""; 24574 } 24575 this._triggerOnBridge("elementValueChanged", this, "value", oldValue, newTypedValue); 24576 } 24577 } 24578 } 24579 }); 24580}(_, guidelib)); 24581(function (_, $) { 24582 24583 var Responsive = { 24584 breakpoints : [], 24585 controlRowDefaults : {} 24586 }, 24587 isPad = navigator.userAgent.match(/iPad/i) !== null, 24588 isIphone = (navigator.userAgent.match(/iPhone/i) !== null) || (navigator.userAgent.match(/iPod/i) !== null), 24589 isIphoneOrIpad = isPad || isIphone; 24590 24591 Responsive.breakpoints = [ 24592 { 24593 name : 'desktop', 24594 width : Infinity 24595 }, 24596 { 24597 name : 'tablet-landscape', 24598 width : 1024 24599 }, 24600 { 24601 name : 'tablet-potrait', 24602 width : 768 24603 }, 24604 { 24605 name : 'mobile-landscape', 24606 width : 480 24607 }, 24608 { 24609 name : 'mobile-potrait', 24610 width : 320 24611 } 24612 ]; 24613 24614 24615 Responsive.controlRowDefaults = { 24616 24617 breakpoints : Responsive.breakpoints, 24618 24619
24620 controlRowDetails : { 24621 renderer : function (tablePlugin, row) { 24622 var cells = null; 24623 if (tablePlugin.options.bControlRowHiddenCells) { 24624 cells = row.$tableRowElement.find("td:hidden"); 24625 } else { 24626 cells = row.$tableRowElement.find("td"); 24627 24628 if (tablePlugin.options.bDisableControlRowCells) { 24629 24630 row.$tableRowElement.find("input, select, textarea, button").attr("disabled", "disabled"); 24631 } 24632 } 24633 var data = cells.map(function (index, cell) { 24634 var $cell = $(cell), 24635 header = tablePlugin.header($cell), 24636 $clickedTableRow = row.$tableRowElement, 24637 cellIdx = null, 24638 cellData = null; 24639 cellIdx = { 24640 24641 row : $clickedTableRow.index(), 24642 column : $cell.index() 24643 }; 24644 24645 cellData = tablePlugin._getCellData(cellIdx); 24646 return $("<li></li>").attr("data-rtp-index", cellIdx.column).addClass("clearfix").append( 24647 $("<div></div>").addClass("rtp-title").text($.trim(header.text())) 24648 ).append( 24649 $("<div></div>").addClass("rtp-data").append(cellData) 24650 ); 24651 }); 24652 24653 return $('<ul data-rtp-index="' + row.index + '"></ul>').append(data.get()); 24654 }, 24655 24656 target : 0, 24657 24658 type : 'inline' 24659 } 24660 }; 24661 24662 var ResponsiveTablePlugin = function (element, options) { 24663 this.options = options; 24664 this.$element = $(element); 24665 this.columns = []; 24666 }; 24667 24668 24669 var TableColumn = function ($tableElement, colIdx, bIsResize) { 24670 var $colHeaderElement = $tableElement.find("th").eq(colIdx); 24671 24672 this.minWidth = (bIsResize ? (parseInt($colHeaderElement.css("min-width"), 10)) : $colHeaderElement.outerWidth()); 24673 this.header = $colHeaderElement; 24674 this.colIndex = colIdx; 24675 this.$tableElement = $tableElement; 24676 }; 24677 24678 24679 TableColumn.prototype = { 24680 24681 cells : function () { 24682 24683 var headerValue = this.header.attr("id"); 24684 return this.$tableElement.find("tr td").filter(function () { 24685 var id = $(this).attr("headers"); 24686 if (id) { 24687 if (id.indexOf(headerValue) > -1) { 24688 return $(this); 24689 } 24690 } 24691 }); 24692 }, 24693 24694 visible : function (bFlag) { 24695 var cells = this.cells(); 24696 this.isVisible = bFlag; 24697 if (bFlag === true) { 24698 cells.show(); 24699 this.header.show(); 24700 } else { 24701 this.header.hide(); 24702 24703 var headers = this.header.prevAll().filter(":visible"), 24704 headerLen = headers.length; 24705 24706 $.each(cells, function () { 24707 if (!$(this).data("shown")) { 24708 $(this).hide(); 24709 } 24710 var colSpan = $(this).data("colspan") || $(this).attr("colspan"); 24711 24712 if (colSpan > 1) { 24713 var totalColSpan = 0; 24714 $(this).prevAll().each(function () { 24715 totalColSpan += (+($(this).data("colspan") || $(this).attr("colspan"))); 24716 }); 24717 24718 if (totalColSpan == 0) { 24719 $(this).show(); 24720 $(this).data("shown", true); 24721 24722 if ($(this).data("colspan") == null) { 24723 $(this).data("colspan", $(this).attr("colspan")); 24724 } 24725 $(this).attr("colspan", headerLen); 24726 } 24727 24728 else if (totalColSpan < headerLen) { 24729 $(this).show(); 24730 $(this).data("shown", true);
24731 if ($(this).data("colspan") == null) { 24732 $(this).data("colspan", $(this).attr("colspan")); 24733 } 24734 $(this).attr("colspan", (headerLen - totalColSpan)); 24735 } 24736 } 24737 }); 24738 } 24739 } 24740 }; 24741 24742 24743 var TableRow = function ($tableRowElement) { 24744 this.$tableRowElement = $tableRowElement; 24745 this.index = $tableRowElement.index(); 24746 24747 this.child = { 24748 $element : null, 24749 isShown : false 24750 }; 24751 $tableRowElement.data("tableRow", this); 24752 }; 24753 24754 TableRow.prototype = { 24755 24756 updateChild : function (info, colSpan) { 24757 24758 if (this.child.$element && this.child.$element.length > 0) { 24759 this.child.$element.empty(); 24760 this.child.$element.append($("<td></td>").addClass(ResponsiveTablePlugin.prototype.defaults.CONTROL_ROW_CLASS).attr("colspan", colSpan).append($(info))); 24761 } else if (this.$tableRowElement.next(ResponsiveTablePlugin.prototype.defaults.CONTROL_ROW_SELECTOR).length > 0) { 24762 this.child.$element = this.$tableRowElement.next(); 24763 this.child.$element.append($("<td></td>").addClass(ResponsiveTablePlugin.prototype.defaults.CONTROL_ROW_CLASS).attr("colspan", colSpan).append($(info))); 24764 } else { 24765 24766 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))); 24767 24768 this.$tableRowElement.after(this.child.$element); 24769 } 24770 24771 }, 24772 24773 showChild : function () { 24774 24775 this.child.$element.get(0).style.display = ""; 24776 this.child.isShown = true; 24777 }, 24778 24779 hideChild : function () { 24780 this.child.$element.hide(); 24781 this.child.isShown = false; 24782 } 24783 }; 24784 24785 ResponsiveTablePlugin.prototype = { 24786 24787 _getCellData : function (index) { 24788 24789 var tableRow = this.$element.find("tbody tr").eq(index.row), 24790 tableCell = tableRow.find("td").eq(index.column); 24791 24792 if (this.options.viewCallback) { 24793 24794 var id = tableCell.find(ResponsiveTablePlugin.prototype.defaults.GUIDE_ID_SELECTOR).attr("id"); 24795 24796 return this.options.viewCallback(id); 24797 } else { 24798 return tableCell.html(); 24799 } 24800 }, 24801 24802 24803 header : function (cell) { 24804 24805 24806 var id = cell.attr("headers").split(" ")[0]; 24807 24808 return this.$element.find("#" + id); 24809 }, 24810 24811 initializeColumns : function (bIsResize) { 24812 var columns = []; 24813 24814 24815 24816 this.colLength = this.$element.find("th").length; 24817 for (var colIdx = 0; colIdx < this.colLength; colIdx++) { 24818 24819 24820 columns.push(new TableColumn(this.$element, colIdx, bIsResize)); 24821 } 24822 return columns; 24823 }, 24824 24825 24826 _initializeColumnWidth : function () { 24827 24828 24829 24830 var display = this._getColumnsVisibility(), 24831 24832 visibleColumns = _.filter(display, function (item) { 24833 return item == true; 24834 }).length, 24835 $allTableHeaders = this.$element.find("th"), 24836 $tableHeader = null, 24837 width = null, 24838 sum = 0; 24839 if (!this.options.bAutoWidth) { 24840 24841 24842 for (var i = 0; i < visibleColumns; i++) { 24843 sum += parseInt(this.options.aWidth[i], 10); 24844 } 24845 } else { 24846 sum = visibleColumns; 24847 } 24848 24849 if (display.length == this.colLength) { 24850 for (var i = 0; i < visibleColumns; i++) { 24851 if (this.options.aWidth) { 24852 24853 width = ((Math.floor((this.options.aWidth[i] * 100) / sum)) + "%"); 24854 } else { 24855 width = ((Math.floor((1 * 100) / sum)) + "%"); 24856 } 24857 $tableHeader = $allTableHeaders.eq(i); 24858 24859 24860 $tableHeader[0].style.width = width; 24861 } 24862 } 24863 }, 24864 24865 _constructor : function () { 24866 var that = this; 24867 24868 this.controlRow = $.extend(true, {}, Responsive.controlRowDefaults); 24869 this.columns = this.initializeColumns(); 24870 24871 $(window).on("resize orientationchange", function (event) { 24872 that._initializeColumnVisibility(event); 24873 }); 24874 24875 24876 24877 this.controlRow.breakpoints.sort(function (a, b) { 24878 return a.width < b.width ? 1 : 24879 a.width > b.width ? -1 : 0; 24880 }); 24881 this._initializeColumnVisibility(); 24882 24883 this._controlRowInitialization(); 24884 }, 24885 24886 _initializeColumnVisibility : function (event) { 24887 var that = this; 24888 24889 if (event) { 24890 24891 24892 this.$element.find("td").each(function () { 24893 $(this).removeData("shown"); 24894
24895 if ($(this).data("colspan") != null) { 24896 24897 $(this).attr("colspan", $(this).data("colspan")); 24898 } 24899 }); 24900 24901 24902 24903 this.columns = this.initializeColumns(event); 24904 } 24905 24906 24907 24908 24909 this._initializeColumnWidth(); 24910 this.display = this._resize(); 24911 24912 24913 this.$element.find("tbody tr:not(.child)").each(function () { 24914 if ($(this).next(ResponsiveTablePlugin.prototype.defaults.CONTROL_ROW_SELECTOR).length == 0) { 24915 $(this).after($("<tr></tr>").addClass(ResponsiveTablePlugin.prototype.defaults.CONTROL_ROW_CLASS).hide()); 24916 } 24917 }); 24918 24919 24920 var details = this.controlRow.controlRowDetails; 24921 24922 if (details.type) { 24923 24924 this._controlRowVisibility(event); 24925 24926 24927 this.$element.on(ResponsiveTablePlugin.prototype.defaults.EVENT_COLUMN_VISIBILITY, function () { 24928 that._controlRowVisibility(); 24929 }); 24930 24931 this.$element.addClass('rtp-' + details.type); 24932 } 24933 24934 if (this.options.fixTableControls) { 24935 24936 24937 24938 if (_.isUndefined(event) || event.type === "orientationchange" || (event.type === "resize" && !isIphoneOrIpad)) { 24939 24940 this.options.fixTableControls(event); 24941 } 24942 } 24943 }, 24944 24945 24946 _fixControlRows : function () { 24947 this.$element.find(ResponsiveTablePlugin.prototype.defaults.CONTROL_ROW_SELECTOR).remove(); 24948 }, 24949 24950 24951 isColumnHidden : function () { 24952 return this.bColumnHidden || false; 24953 }, 24954 24955 24956 _rearrangeTableRuntimeControls : function (lastVisibleColumn, event) { 24957 24958 24959 var $runtimeAddControls = this.$element.find(".guideTableRuntimeControls .guideTableRuntimeAddControl"), 24960 runtimeControlIndex = 0, 24961 that = this, 24962 index = null; 24963 $runtimeAddControls.each(function () { 24964 24965 if ($(this).is(":visible")) { 24966 runtimeControlIndex = $(this).closest("td").index(); 24967 return false; 24968 } 24969 }); 24970 24971 if ((runtimeControlIndex <= lastVisibleColumn)) { 24972 24973 24974 $runtimeAddControls.each(function () { 24975 24976 24977 var $runtimeControl = $(this).closest(".guideTableRuntimeControls"), 24978 $runtimeControlTableRow = $(this).closest("tr"); 24979 if ($runtimeControl.hasClass("guideTableRuntimeRightControls")) { 24980 24981 $runtimeControl.appendTo($runtimeControlTableRow.find("td").eq(lastVisibleColumn)); 24982 if (runtimeControlIndex !== lastVisibleColumn) { 24983 var $component = $runtimeControl.prev(); 24984 $component.css("display", "block"); 24985 $component.css("float", "none"); 24986 } 24987 } 24988 24989 }); 24990 } 24991 }, 24992 24993 24994 _controlRowVisibility : function (event) { 24995 var that = this, 24996 24997 hiddenColumns = _.filter(this.columns, function (element) { 24998 return (element.isVisible) !== true; 24999 }), 25000 lastVisibleColumn = this.columns.length - hiddenColumns.length; 25001 25002 25003 this._rearrangeTableRuntimeControls(lastVisibleColumn - 1, event); 25004 25005 if (hiddenColumns && hiddenColumns.length > 0) { 25006 25007 this.$element.addClass('collapsed'); 25008 25009 this.bColumnHidden = true; } else { 25010 25011 this.$element.removeClass('collapsed'); 25012 25013 this.bColumnHidden = false;
25014 } 25015 }, 25016 25017 25018 _controlRowInitialization : function () { 25019 var that = this; 25020 var details = this.controlRow.controlRowDetails; 25021 25022 25023 if (details.type === 'inline') { 25024 25025 details.target = ("." + (this.options.tableRuntimeEditControlClass || "tableRuntimeEditControl")); 25026 } 25027 25028 25029 25030 25031 var target = details.target; 25032 var selector = typeof target === 'string' ? target : 'td'; 25033 25034 25035 this.$element.on('click keypress', selector, function (e) { 25036 25037 25038 if ((e.type == "keypress" && e.keyCode == 13) || e.type == "click") { 25039 25040 if (!that.$element.hasClass('collapsed')) { 25041 return; 25042 } 25043 25044 var $row = $(this).closest('tr'), 25045 rowData = $row.data("tableRow"), 25046 row = rowData; 25047 25048 25049 25050 if (row == null || row.child.$element.parent().length === 0) { 25051 row = new TableRow($row); 25052 $row.data("tableRow", row); 25053 } 25054 if (row.child.isShown) { 25055 row.hideChild(); 25056 row.$tableRowElement.removeClass('parent'); 25057 } else { 25058 var info = that.controlRow.controlRowDetails.renderer(that, row); 25059 row.updateChild(info, that.colLength); 25060 row.showChild(); 25061 row.$tableRowElement.addClass('parent'); 25062 25063 row.child.$element.find("input, select, textarea, button").eq(0).focus(); 25064 } 25065 } 25066 }); 25067 }, 25068 25069 25070 _resize : function () { 25071 var width = $(window).width(); 25072 var breakpoints = this.controlRow.breakpoints; 25073 var breakpoint = breakpoints[0].name; 25074 25075 25076 for (var i = breakpoints.length - 1 ; i >= 0 ; i--) { 25077 if (width <= breakpoints[i].width) { 25078 breakpoint = breakpoints[i].name; 25079 break; 25080 } 25081 } 25082 25083 25084 var display = this._getColumnsVisibility(breakpoint); 25085 25086 _.each(this.columns, function (item, index) { 25087 item.visible(display[index]); 25088 }); 25089 25090 return display; 25091 }, 25092 25093 25094 _getColumnsVisibility : function (breakpoint) { 25095 var columns = this.columns, 25096 i, 25097 len = this.$element.find("th"), 25098 display = []; 25099 25100 25101 var widthAvailable = this.$element.parent().outerWidth(); 25102 var usedWidth = widthAvailable; 25103 25104 25105 25106 display = _.map(columns, function (item) { 25107 usedWidth -= item.minWidth; 25108 return ((usedWidth < 0) ? false : true); 25109 }); 25110 25111 25112 display[0] = true; 25113 return display; 25114 } 25115 25116 }; 25117 25118 $.fn.responsiveTablePlugin = function (option, value) { 25119 var get = '', 25120 element = this.each(function () { 25121 25122 if ($(this).is('table') === true) { 25123 var $this = $(this), 25124 data = $this.data('responsiveTablePlugin'), 25125 options = $.extend({}, ResponsiveTablePlugin.prototype.defaults, typeof option === 'object' && option); 25126 25127 25128 if (!data) { 25129 $this.data('responsiveTablePlugin', (data = new ResponsiveTablePlugin(this, options))); 25130 data._constructor(); 25131 } 25132 25133 25134 if (typeof option === 'string') { 25135 get = data[option](value); 25136 } 25137 } 25138 }); 25139 25140 if (get != "") { 25141 return get; 25142 } else { 25143 return element; 25144 } 25145 }; 25146 25147 ResponsiveTablePlugin.prototype.defaults = { 25148 25149 EVENT_COLUMN_VISIBILITY : "responsiveTablePlugin.columnVisibility", 25150 GUIDE_ID_SELECTOR : "div[data-guide-view-bind]", 25151 CONTROL_ROW_CLASS : "child", 25152 CONTROL_ROW_SELECTOR : "tr.child" 25153 }; 25154 25155})(_, $); 25156(function ($, _, guidelib) { 25157 25158 25159 var getPanelsWithNumericFields = function (panels, fieldName) { 25160 if (_.isUndefined(panels) || panels === null) { 25161 return []; 25162 } 25163 if (!_.isArray(panels)) { 25164 panels = [panels]; 25165 } 25166 return _.filter(panels, function (panel) { 25167 return panel instanceof guidelib.model.GuidePanel 25168 && panel[fieldName] instanceof guidelib.model.GuideNumericBox; 25169 }); 25170 }, 25171 25172 sum = function (numPanels, fieldName) { 25173 return _.reduce(numPanels, 25174 function (memo, currentItem) { 25175 var curValue = parseFloat(currentItem.getOrElse(currentItem, fieldName + ".value", 0)); 25176 if (isNaN(curValue)) { 25177 curValue = 0; 25178 } 25179 return memo + curValue; 25180 }, 0); 25181 }; 25182 25183 25184 guidelib.__runtime__.af.sum = function (panels, fieldName) { 25185 return sum(getPanelsWithNumericFields(panels, fieldName), fieldName); 25186 }; 25187 25188 25189 guidelib.__runtime__.af.avg = function (panels, fieldName) { 25190 var n_panels = getPanelsWithNumericFields(panels, fieldName), 25191 total = sum(n_panels, fieldName); 25192 if (n_panels.length === 0) { 25193 return 0; 25194 } 25195 return total / n_panels.length; 25196 }; 25197 25198 25199 guidelib.__runtime__.af.max = function (panels, fieldName) { 25200 var panel = _.max(getPanelsWithNumericFields(panels, fieldName), function (panel) { 25201 return panel.getOrElse(panel, fieldName + ".value", Number.NEGATIVE_INFINITY); 25202 }); 25203 if (panel instanceof guidelib.model.GuidePanel) { 25204 return panel[fieldName]; 25205 } 25206 return null; 25207 }; 25208 25209 25210 guidelib.__runtime__.af.min = function (panels, fieldName) { 25211 var panel = _.min(getPanelsWithNumericFields(panels, fieldName), function (panel) { 25212 return panel.getOrElse(panel, fieldName + ".value", Number.POSITIVE_INFINITY); 25213 }); 25214 if (panel instanceof guidelib.model.GuidePanel) { 25215 return panel[fieldName]; 25216 } 25217 return null; 25218 }; 25219 25220}($, _, guidelib)); 25221(function ($, _, guidelib) { 25222 25223 25224 25225 guidelib.__runtime__.af.reduce = function (panels, fieldName, iterator, memo, context) { 25226 if (!_.isArray(panels)) { 25227 panels = [panels]; 25228 } 25229 return _.reduce(panels, function (memo, panel) { 25230 if (panel instanceof guidelib.model.GuidePanel && !_.isUndefined(panel[fieldName])) { 25231 if (_.isFunction(iterator)) { 25232 return iterator.apply(context, [memo, panel, panel[fieldName]]); 25233 } 25234 } 25235 return memo; 25236 }, memo); 25237 }; 25238 25239 25240 25241 guidelib.__runtime__.af.filter = function (panels, fieldName, predicate, context) { 25242 if (!_.isArray(panels)) { 25243 panels = [panels]; 25244 } 25245 return _.map( 25246 _.filter(panels, function (panel) { 25247 if (panel instanceof guidelib.model.GuidePanel && !_.isUndefined(panel[fieldName])) { 25248 if (_.isFunction(predicate)) { 25249 return predicate.apply(context, [panel, panel[fieldName]]); 25250 } 25251 return false;
25252 } 25253 }), 25254 function (panel) { 25255 return panel[fieldName]; 25256 } 25257 ); 25258 }; 25259 25260 guidelib.__runtime__.af.formatDateToISOString = function (dateObject) { 25261 var day, month, year; 25262 if (!_.isUndefined(dateObject) && _.isObject(dateObject)) { 25263 day = dateObject.getDate().toString(); 25264 25265 month = (dateObject.getMonth() + 1).toString(); 25266 year = dateObject.getFullYear().toString(); 25267 if (month.length === 1) { 25268 month = "0" + month.toString(); 25269 } 25270 25271 return year + "-" + month + "-" + day; 25272 25273 } 25274 }; 25275}($, _, guidelib)); 25276(function (_, guidelib) { 25277 25278 var GuideNavigationContext = guidelib.model.util.GuideNavigationContext = xfalib.ut.Class.extend({ 25279 msClassName : "guideNavigationContext", 25280 initialize : function () { 25281 GuideNavigationContext._super.initialize.call(this); 25282 this._currentItem = this.options.currentItem; 25283 this._parentPanel = this.options.parentPanel; 25284 this.guideUtil = guidelib.util.GuideUtil; 25285 }, 25286 25287 getQualifiedNamedItem : function (qName) { 25288 var navItems = this._getNavigableItems(); 25289 var qItem = _.find(navItems, function (item) { 25290 return (item._escapeQualifiedName() == qName); 25291 }, this); 25292 return qItem; 25293 }, 25294 25295 getItemForNav : function (navToken) { 25296 if (navToken == "prevItem" || navToken == "nextItem" || navToken == "firstItem" || navToken == "lastItem") { 25297 return this[navToken]; 25298 } else { 25299 return this.getQualifiedNamedItem(navToken); 25300 } 25301 }, 25302 25303 25304 _isNavigableItem : function (item) { 25305 return item.visible; 25306 }, 25307 25308 25309 _isNavigablePanel : function (item) { 25310 if (item && item instanceof guidelib.model.GuidePanel) { 25311 return item.visible && item.isNavigable; 25312 } 25313 }, 25314 25315 _getNavigableItems : function () { 25316 var navItems = _.filter(this._parentPanel.items, function (item) { 25317 return this._isNavigableItem(item); 25318 }, this); 25319 return navItems; 25320 }, 25321 25322 _getNavigableDescendant : function (navigableAncestor) { 25323 25324 25325 if (navigableAncestor && navigableAncestor != this._parentPanel) { 25326 var currentItem = navigableAncestor.parent._navigationContext.currentItem, 25327 deepItem = null; 25328 while (currentItem instanceof guidelib.model.GuidePanel) { 25329 deepItem = currentItem; 25330 currentItem = currentItem._navigationContext.currentItem; 25331 } 25332 return deepItem; 25333 } 25334 return null; 25335 }, 25336 25337 25338 _getSomOnNavigableAncestor : function (somExpression) { 25339 if (_.isEmpty(somExpression)) { 25340 return null; 25341 } 25342 25343 var index = somExpression.lastIndexOf("."), 25344 parentModel, 25345 parentSom, 25346 isNavigable, 25347 guideModel = this._parentPanel._guide(); 25348 25349 if (index !== -1) { 25350 parentSom = somExpression.substring(0, index); 25351 parentModel = guideModel.resolveNode(parentSom); 25352 if (parentModel) { 25353 isNavigable = this._isNavigablePanel(parentModel); 25354 } 25355 if (isNavigable) { 25356 return somExpression; 25357 } 25358 return this._getSomOnNavigableAncestor(parentSom); 25359 } 25360 25361 return guideModel.rootPanel.somExpression; 25362 }, 25363 25364 25365 _getNavigableAncestor : function (navOrder) { 25366 25367 25368 25369 var guideModel = this._parentPanel._guide(), 25370 navigableAncestorSom = this._getSomOnNavigableAncestor(guideModel._currentNavigablePanelSom), 25371 navigableAncestorItem = guideModel.resolveNode(navigableAncestorSom); 25372 25373 while (navigableAncestorItem 25374 && navigableAncestorItem != this._parentPanel && !navigableAncestorItem.parent._navigationContext[navOrder] 25375 && this.guideUtil.isChildPartOfContainer(this._parentPanel, navigableAncestorItem)) { 25376 25377 var navigableParentItemSom = this._getSomOnNavigableAncestor(navigableAncestorItem.parent.somExpression); 25378 navigableAncestorItem = guideModel.resolveNode(navigableParentItemSom); 25379 } 25380 return navigableAncestorItem; 25381 }, 25382 25383 _getNakedThis : function () { 25384 return this; 25385 } 25386 }); 25387 25388 GuideNavigationContext.defineProps({ 25389 25390 currentItem : { 25391 get : function () { 25392 if (this._currentItem) { 25393 return this._currentItem; 25394 } else { 25395 return this.firstItem; 25396 } 25397 }, 25398 set : function (value) { 25399 this._currentItem = value; 25400 } 25401 }, 25402 25403 prevItem : { 25404 get : function () { 25405 var navItems = this._getNavigableItems(); 25406 var item = this.currentItem; 25407 if (navItems.indexOf(item) > 0) { 25408 return navItems[navItems.indexOf(item) - 1]; 25409 } else { 25410 return null; 25411 } 25412 } 25413 }, 25414 25415 nextItem : { 25416 get : function () { 25417 var navItems = this._getNavigableItems(); 25418 var item = this.currentItem; 25419 if (navItems.indexOf(item) < (navItems.length - 1)) { 25420 return navItems[navItems.indexOf(item) + 1]; 25421 } else { 25422 return null; 25423 } 25424 } 25425 }, 25426 25427 nextNavigablePanel : { 25428 get : function () { 25429 var navigableAncestor = this._getNavigableAncestor("nextItem"), 25430 25431 navigableDescendant = this._getNavigableDescendant(navigableAncestor); 25432 return navigableDescendant; 25433 } 25434 }, 25435 25436 25437 prevNavigablePanel : { 25438 get : function () { 25439 var navigableAncestor = this._getNavigableAncestor("prevItem"), 25440 25441 navigableDescendant = this._getNavigableDescendant(navigableAncestor); 25442 return navigableDescendant; 25443 } 25444 }, 25445 25446 25447 firstItem : { 25448 get : function () { 25449 var navItems = this._getNavigableItems(); 25450 return navItems[0] || null; 25451 } 25452 }, 25453 25454 lastItem : { 25455 get : function () { 25456 var navItems = this._getNavigableItems(); 25457 if (navItems.length) { 25458 return navItems[navItems.length - 1]; 25459 } else { 25460 return null; 25461 } 25462 } 25463 }, 25464 25465 hasNextItem : { 25466 get : function () { 25467 return this.nextItem != null; 25468 } 25469 }, 25470 25471 hasPrevItem : { 25472 get : function () { 25473 return this.prevItem != null; 25474 } 25475 }, 25476 25477 25478 hasNextNavigablePanel : { 25479 get : function () { 25480 return this.nextNavigablePanel != null; 25481 } 25482 }, 25483 25484 25485 hasPrevNavigablePanel : { 25486 get : function () { 25487 return this.prevNavigablePanel != null; 25488 } 25489 }, 25490 25491 25492 isFirstItem : { 25493 get : function () { 25494 return this.currentItem == this.firstItem; 25495 } 25496 }, 25497 25498 isLastItem : { 25499 get : function () { 25500 return this.currentItem == this.lastItem; 25501 } 25502 } 25503 }); 25504 25505})(_, guidelib); 25506(function (_, guidelib) { 25507 25508 25509 var GuideModelEvent = guidelib.event.GuideModelEvent = xfalib.ut.Class.extend({ 25510 msClassName : "guideModelEvent" 25511 }); 25512 25513 GuideModelEvent.defineProps({ 25514 25515 "prevText" : { 25516 get : function () { 25517 return this.jsonModel.prevText; 25518 } 25519 }, 25520 25521 "newText" : { 25522 get : function () { 25523 return this.jsonModel.newText; 25524 } 25525 }, 25526 25527 "name" : { 25528 get : function () { 25529 return this.jsonModel.name; 25530 } 25531 }, 25532 "keyDown" : { 25533 get : function () { 25534 return this.jsonModel.keyDown; 25535 } 25536 }, 25537 "modifier" : { 25538 get : function () { 25539 return this.jsonModel.modifier; 25540 } 25541 }, 25542 25543 "target" : { 25544 get : function () { 25545 return this.jsonModel.target; 25546 } 25547 }, 25548 "shift" : { 25549 get : function () { 25550 return this.jsonModel.shift; 25551 } 25552 }, 25553 "change" : { 25554 get : function () { 25555 return this.jsonModel.change; 25556 }, 25557 set : function (value) { 25558 this.jsonModel.change = value; 25559 } 25560 }, 25561 25562 "_property" : { 25563 get : function () { 25564 return this.jsonModel._property; 25565 } 25566 } 25567 }); 25568 25569 GuideModelEvent.createEvent = function (nm, tgt, prop, oldVal, newVal) { 25570 var evnt = { 25571 name : nm, 25572 target : tgt, 25573 _property : prop, 25574 prevText : oldVal, 25575 newText : newVal 25576 }; 25577 return new GuideModelEvent({"jsonModel" : evnt}); 25578 }; 25579 25580 GuideModelEvent.MODEL_REFRESH = "guide.modelRefresh"; 25581 GuideModelEvent.CHILD_CHANGED = "guide.childChanged"; 25582 GuideModelEvent.MULTIPLE_CHILD_ADDED = "guide.multipleChildAdded"; 25583 GuideModelEvent.MODEL_CHANGED = "guide.modelChanged"; 25584 GuideModelEvent.VALUE_CHANGED = "guide.valueChanged"; 25585 GuideModelEvent.ERROR_CHANGED = "guide.errorChanged"; 25586 GuideModelEvent.ERROR_RESET = "guide.errorReset"; 25587 GuideModelEvent.VISIBLE_CHANGED = "guide.visibleChanged"; 25588 GuideModelEvent.ENABLED_CHANGED = "guide.enabledChanged"; 25589 GuideModelEvent.ITEMS_CHANGED = "guide.itemsChanged"; 25590 GuideModelEvent.OBJECT_DESTROYED = "guide.objectDestroyed"; 25591 GuideModelEvent.NAVIGATE_SECTION = "guide.navigateSection";
25592 GuideModelEvent.LAZY_LOADED = "guide.lazyLoaded"; 25593}(_, guidelib)); 25594(function ($, _, guidelib) { 25595 var GuideViewRegistry = guidelib.view.GuideViewRegistry = xfalib.ut.Class.extend({ 25596 25597 25598 _findWidget : function (config, name, className) { 25599 var result = _.find(config, function (widgetName, identifier) { 25600 return name === identifier; 25601 }); 25602 if (result === undefined) { 25603 result = _.find(config, function (widgetName, identifier) { 25604 return className === identifier; 25605 }); 25606 } 25607 return result; 25608 }, 25609 25610 25611 _findWidgetNameFromCSS : function (cssClasses) { 25612 var result = null; 25613 if (_.isString(cssClasses)) { 25614 _.find(cssClasses.split(" "), 25615 function (cssClass, index) { 25616 var match = cssClass.match(/^widget_([\w\W]+)$/); 25617 if (match && match.length === 2) { 25618 result = match[1]; 25619 return true; 25620 } 25621 return false; 25622 }); 25623 } 25624 return result; 25625 }, 25626 25627 createView : function (element, parentView) { 25628 var $element = $(element); 25629 var options = { 25630 'element' : $element.get(0), 25631 'widgetName' : $element.data("guideViewWidget"), 25632 'parentView' : parentView 25633 }; 25634 var guideViewBind = $element.data("guideViewBind"); 25635 var model = window.guideBridge._resolveId(guideViewBind); 25636 25637 25638 if (model) { 25639 options.model = model; 25640 var clsName = model.className; 25641 var nodeClass = clsName.charAt(0).toUpperCase() + clsName.substr(1) + "View"; 25642 var viewClass = guidelib.view[nodeClass], 25643 widgetConfig = window.guideBridge.userConfig.widgetConfig; 25644 if (model instanceof guidelib.model.Field || model instanceof guidelib.model.GuideCompositeField) { 25645 options.widgetName = this._findWidgetNameFromCSS(model.cssClassName) 25646 || this._findWidget(widgetConfig, model.name, model.className); 25647 } 25648 if (!viewClass && model instanceof guidelib.model.GuideContainerNode) { 25649 viewClass = guidelib.view.GuideContainerView; 25650 } 25651 if (!viewClass && model instanceof guidelib.model.Field) { 25652 viewClass = guidelib.view.GuideFieldView; 25653 } 25654 if (!viewClass && model instanceof guidelib.model.GuidePanel) { 25655 viewClass = guidelib.view.GuidePanelView; 25656 } 25657 if (!viewClass && model instanceof guidelib.model.GuideItemsContainer) { 25658 viewClass = guidelib.view.GuideItemsView; 25659 } 25660 if (!viewClass) { 25661 viewClass = guidelib.view.GuideBaseView; 25662 } 25663 25664 var bindView = new viewClass(options); 25665 return bindView; 25666 } 25667 } 25668 }); 25669 25670})($, _, guidelib); 25671(function (_, guidelib, xfalib) { 25672 var DataNode = guidelib.model.DataNode = xfalib.ut.Class.extend({ 25673 initialize : function () { 25674 this.linkedFields = []; 25675 this.isUpdateInProgress = false; 25676 }, 25677 25678 addField : function (model) { 25679 if (!_.isEmpty(model) && !_.contains(this.linkedFields, model)) { 25680 this.linkedFields.push(model); 25681 model.on(guidelib.event.GuideModelEvent.VALUE_CHANGED, this); 25682 } 25683 }, 25684 25685 removeField : function (model) { 25686 if (!_.isEmpty(model)) { 25687 model.off(guidelib.event.GuideModelEvent.VALUE_CHANGED, this); 25688 this.linkedFields = _.without(this.linkedFields, model); 25689 } 25690 }, 25691 25692 getFieldModels : function () { 25693 return _.filter(this.linkedFields, function (field) { 25694 return (field instanceof guidelib.model.Field); 25695 }); 25696 }, 25697 25698 getAbstractFieldModels : function () { 25699 return _.filter(this.linkedFields, function (field) { 25700 return (field instanceof guidelib.model.AbstractField); 25701 }); 25702 }, 25703 25704 handleEvent : function (event) { 25705 switch (event.name) { 25706 case guidelib.event.GuideModelEvent.VALUE_CHANGED: 25707 if (!_.contains(['guideButton', 'guideTextDraw', 'guideAdobeSignBlock'], event.target.className)) { 25708 this.updateLinkedFieldsValue(event); 25709 } 25710 break; 25711 default: 25712 event.target.logger().warn("AF", "Unexpected Event type on Data Node", event); 25713 } 25714 }, 25715 25716 updateLinkedFieldsValue : function (event) { 25717 if (this.isUpdateInProgress) { 25718 return; 25719 } 25720 25721 this.isUpdateInProgress = true; 25722 var newValue = event.target._getValue(); 25723 25724 try { 25725 _.each(this.linkedFields, function (field) { 25726 if (field !== event.target) { 25727 field.value = newValue; 25728 } 25729 }, this); 25730 } catch (ex) { 25731 event.target.logger().error("AF", "Unable to set Linked Field value" + ex); 25732 } finally { 25733 this.isUpdateInProgress = false;
25734 } 25735 } 25736 }); 25737 25738}(_, guidelib, xfalib)); 25739 25740 25741(function (guidelib, $) { 25742 25743 var VERSION_AEM_61 = "AEM6.1", 25744 VERSION_AEM_62 = "AEM6.2", 25745 VERSION_AEM_63 = "AEM6.3", 25746 VERSION_AEM_65 = "AEM6.5", 25747 flagsStatus = {}, 25748 getMinorMajor = function (version) { 25749 var match = version.match(/AEM(\d+)(?:\.(\d+))?/); 25750 if (match == null) { 25751 return null; 25752 } 25753 return { 25754 major : match[1], 25755 minor : match[2] === undefined ? "0" : match[2] 25756 }; 25757 }, 25758 compareNumbers = function (num1, num2) { 25759 return (num1 - num2); 25760 }, 25761 compareVersions = function (version1, version2) { 25762 if (typeof version1 !== "string" || typeof version2 !== "string") { 25763 throw "Comparing Invalid Versions"; 25764 } 25765 var v1 = getMinorMajor(version1), 25766 v2 = getMinorMajor(version2); 25767 if (v1 == null || v2 == null) { 25768 throw "Comparing Invalid Versions"; 25769 } 25770 var c = compareNumbers(+v1.major, +v2.major); 25771 return c !== 0 ? c : compareNumbers(+v1.minor, +v2.minor); 25772 }, 25773 Version = guidelib.util.Version = xfalib.ut.Class.extend({ 25774 initialize : function (options) { 25775 flagsStatus = {}; 25776 var compat = options.scriptingBehaviourVersion; 25777 if (compat === "None") { 25778 compat = this.current(); 25779 } 25780 this.scriptingBehaviourVersion = compat || VERSION_AEM_65; 25781 var majorMinor = getMinorMajor(this.scriptingBehaviourVersion); 25782 if (majorMinor == null) { 25783 throw "Invalid Version number"; 25784 } 25785 this.major = majorMinor.major; 25786 this.minor = majorMinor.minor; 25787 }, 25788 25789 current : function () { 25790 return VERSION_AEM_65; 25791 }, 25792 25793 compatibleVersion : function () { 25794 return this.scriptingBehaviourVersion; 25795 }, 25796 25797 isPrevious : function (version) { 25798 return compareVersions(this.scriptingBehaviourVersion, version) < 0; 25799 }, 25800 25801 isPreviousOrSame : function (version) { 25802 var c = compareVersions(this.scriptingBehaviourVersion, version); 25803 return c < 0 || c == 0; 25804 }, 25805 25806 isAfter : function (version) { 25807 return compareVersions(this.scriptingBehaviourVersion, version) > 0; 25808 }, 25809 25810 isAfterOrSame : function (version) { 25811 var c = compareVersions(this.scriptingBehaviourVersion, version); 25812 return c > 0 || c == 0; 25813 }, 25814 25815 isSame : function (version) { 25816 return compareVersions(this.scriptingBehaviourVersion, version) == 0; 25817 }, 25818 25819 isOn : function (flag) { 25820 switch (flag) { 25821 case this.Flags.RUN_VALUE_COMMMIT_ON_SCRIPT_CHANGE: 25822 if (flagsStatus[flag] == undefined) { 25823 flagsStatus[flag] = this.isAfter(this.AEM_61); 25824 } 25825 return flagsStatus[flag]; 25826 case this.Flags.RUN_VALUE_COMMMIT_ON_PREFILL: 25827 if (flagsStatus[flag] == undefined) { 25828 flagsStatus[flag] = this.isAfter(this.AEM_63); 25829 } 25830 return flagsStatus[flag]; 25831 } 25832 throw "Invalid Flag"; 25833 } 25834 }); 25835 25836 Version.prototype.Flags = {}; 25837 Object.defineProperties(Version.prototype.Flags, { 25838 RUN_VALUE_COMMMIT_ON_SCRIPT_CHANGE : { 25839 value : "manageValueCommit", 25840 writable : false 25841 }, 25842 RUN_VALUE_COMMMIT_ON_PREFILL : { 25843 value : "manageValueCommitOnPrefill", 25844 writable : false 25845 } 25846 }); 25847 Version.defineProps({ 25848 AEM_61 : { 25849 value : VERSION_AEM_61, 25850 writable : false 25851 }, 25852 25853 AEM_62 : { 25854 value : VERSION_AEM_62, 25855 writable : false 25856 }, 25857 25858 AEM_63 : { 25859 value : VERSION_AEM_63, 25860 writable : false 25861 }, 25862 25863 AEM_65 : { 25864 value : VERSION_AEM_65, 25865 writable : false 25866 } 25867 }); 25868}(guidelib, $)); 25869(function ($, guidelib, _) { 25870 var GuideBaseView = guidelib.view.GuideBaseView = xfalib.ut.Class.extend({ 25871 guideUtil : guidelib.util.GuideUtil, 25872 _triggerOnBridge : function (eventName, target, property, oldVal, newVal) { 25873 var evnt = guidelib.event.GuideModelEvent.createEvent(eventName, target, 25874 property, oldVal, newVal); 25875 window.guideBridge.trigger(eventName, evnt); 25876 }, 25877 25878 initialize : function () { 25879 GuideBaseView._super.initialize.call(this); 25880 this.$element = $(this.options.element); 25881 this.id = this.$element.attr("id"); 25882 this._model = this.options.model; 25883 this.parentView = this.options.parentView; 25884 this.$element.data("guideView", this); 25885 this._$item = null; 25886 this._$itemNav = null; 25887 if (this._model && this._model != null) { 25888 this._model.on(guidelib.event.GuideModelEvent.MODEL_CHANGED, this.handleModelChanged, this); 25889 } 25890 this._syncPending = true; 25891 this._visibleHelpElement = "none"; 25892 this._polyfills(); 25893 }, 25894
25895 _polyfills: function () { 25896 var IEpolyfillForObjectDotEntries = function() { 25897 if(!Object.entries) { 25898 Object.entries = function (obj) { 25899 var ownProps = Object.keys(obj), 25900 i = ownProps.length, 25901 resArray = new Array(i); 25902 while (i--) 25903 resArray[i] = [ownProps[i], obj[ownProps[i]]]; 25904 25905 return resArray; 25906 }; 25907 } 25908 }; 25909 25910 var polyfills = [IEpolyfillForObjectDotEntries]; 25911 25912 for (var i = 0; i < polyfills.length; ++i) { 25913 polyfills[i](); 25914 } 25915 }, 25916 25917 postInitialize : function () { 25918 }, 25919 25920 _unloadView : function () { 25921 25922 this._model.off(guidelib.event.GuideModelEvent.MODEL_CHANGED, this.handleModelChanged, this); 25923 25924 this.$element = null; 25925 this.$widget = null; 25926 this._model = null; 25927 this._$item = null; 25928 this._$itemNav = null; 25929 this.parentView = null; 25930 }, 25931 25932 handleVisibleChanged : function (event) { 25933 25934 25935 if (!event.newText) { 25936 this.$item.addClass("hidden"); 25937 this.$itemNav.addClass("hidden"); 25938 if (this.parentView.currentActiveItemView == this) { 25939 this.parentView.setActive("nextItem"); 25940 } 25941 if (event.prevText) { 25942 this.announceVisibilityChanged("HIDDEN"); 25943 } 25944 } else { 25945 25946 this.$item.removeClass("hidden"); 25947 this.$itemNav.removeClass("hidden"); 25948 if (!event.prevText) { 25949 this.announceVisibilityChanged("VISIBLE"); 25950 } 25951 } 25952 }, 25953 25954 announceVisibilityChanged : function (visible) { 25955 var $statusAnnounceElement = this.parentView.$element.find('.guideGridFluidLayout2ContainerStatus'); 25956 var $elementLabel = this.$item.find('.guideFieldLabel label'); 25957 if ($statusAnnounceElement && $elementLabel) { 25958 var newStatus = visible === "VISIBLE" ? 25959 this.guideUtil.getLocalizedMessage("", guidelib.i18n.strings.showingField, [$elementLabel.text()]) 25960 : 25961 this.guideUtil.getLocalizedMessage("", guidelib.i18n.strings.hidingField, [$elementLabel.text()]); 25962 $statusAnnounceElement.attr('aria-label', newStatus); 25963 } 25964 }, 25965 25966 handleModelChanged : function (event) { 25967 switch (event._property) { 25968 case "viewVisited": 25969 if (event.newText) { 25970 this.$item.addClass("stepped"); 25971 this.$itemNav.addClass("stepped"); 25972 }else { 25973 this.$item.removeClass("stepped"); 25974 this.$itemNav.removeClass("stepped"); 25975 } 25976 break; 25977 25978 case "visible": 25979 25980 this.handleVisibleChanged(event); 25981 break; 25982 } 25983 }, 25984 25985 setActive : function (activeItemToken, focus, muteScripts) { 25986 if (focus && (this._model.className === "guideNode" || this._model.forceElementFocusChange)) { 25987 if (this.$element !== null && typeof this.$element.focus === "function" && !this._guideView.skipFieldFocus) { 25988 25989 this.$element.focus(); 25990 25991 this._guideView.currentFocusItemSom = this._model.somExpression; 25992 } 25993 25994 } 25995 return true; 25996 }, 25997 25998 focusable : function () { 25999 return this._model.visible; 26000 }, 26001 26002 _find : function (selector) { 26003 return this._guideView.$element.find(selector); 26004 }, 26005 26006 _syncGuideNodeToHtml : function (deepSync) { 26007 this._syncPending = false;
26008 26009 26010 this.handleVisibleChanged(guidelib.event.GuideModelEvent.createEvent( 26011 guidelib.event.GuideModelEvent.MODEL_CHANGED, 26012 this, 26013 "visible", 26014 this._model.visible, 26015 this._model.visible 26016 ), {skipLazyAutoLoad: true}); 26017 }, 26018 26019 _updateIds : function ($el, oldId, newId) { 26020 if (oldId == newId) { 26021 return; 26022 } 26023 26024 var idSelector = "#" + oldId, 26025 modelBindSelector = this.guideUtil.modelElSelector(oldId), 26026 attrSelector = '[id^="' + oldId + '"]', 26027 longDescriptionSelector = '[data-guide-longDescription^="' + oldId + '"]', 26028 labelSelector = 'label[for^="' + oldId + '"]', 26029 targetIdSelector = "[data-guide-id^='" + oldId + "']", 26030 $elById = $el.find(idSelector).addBack(idSelector), 26031 selectorAttrObject = { 26032 "id" : attrSelector , 26033 "for" : labelSelector, 26034 "data-guide-longDescription" : longDescriptionSelector, 26035 "data-guide-id" : targetIdSelector 26036 }; 26037 26038 26039 26040 if ($elById.attr(guidelib.util.GuideUtil.DATA_GUIDE_ITEM_CONTAINER) !== undefined) { 26041 $elById.attr(guidelib.util.GuideUtil.DATA_GUIDE_ITEM_CONTAINER, newId + guidelib.util.GuideUtil.GUIDE_ITEM_CONTAINER_SUFFIX); 26042 } 26043 26044 if ($elById.attr(guidelib.util.GuideUtil.DATA_GUIDE_ITEM) !== undefined) { 26045 $elById.attr(guidelib.util.GuideUtil.DATA_GUIDE_ITEM, newId + guidelib.util.GuideUtil.GUIDE_ITEM_SUFFIX); 26046 } 26047 $elById.attr("id", newId); 26048 $el.find(modelBindSelector).addBack(modelBindSelector).attr(this.guideUtil.GUIDE_VIEW_BIND_ATTR, newId); 26049 26050 _.each(_.keys(selectorAttrObject), function (item, index) { 26051 var selector = selectorAttrObject[item]; 26052 $el.find(selector).addBack(selector).each(function () { 26053 26054 var $this = $(this), 26055 prevId = $this.attr(item), 26056 nextId = newId + prevId.substring(oldId.length); 26057 $this.attr(item, nextId); 26058 }); 26059 }, this); 26060 }, 26061 26062 getSiblingItemView : function (siblingType) { 26063 if (this.parentView instanceof guidelib.view.GuidePanelView) { 26064 var siblingItem = this.parentView._model.navigationContext.getItemForNav(siblingType); 26065 if (siblingItem) { 26066 return this.parentView.getQualifiedNamedView(siblingItem._escapeQualifiedName()); 26067 } 26068 } 26069 return null; 26070 } 26071 }); 26072 26073 GuideBaseView.defineProps({ 26074 _guideView : { 26075 get : function () { 26076 return window.guideBridge._guideView; 26077 } 26078 }, 26079 26080 _guide : { 26081 get : function () { 26082 return window.guideBridge._guide; 26083 } 26084 }, 26085 26086 $item : { 26087 get : function () { 26088 if (!this._$item || this._$item.length == 0) { 26089 var itemSelector = this.guideUtil.itemSelector(this._model.id, this._model); 26090 this._$item = this._find(itemSelector); 26091 26092 26093 if (this._$item && this._$item.length == 0) { 26094 return this.$element; 26095 } 26096 } 26097 return this._$item; 26098 } 26099 }, 26100 26101 $itemNav : { 26102 get : function () { 26103 if (!this._$itemNav) { 26104 var itemNavSelector = this.guideUtil.itemNavSelector(this._model.id); 26105 this._$itemNav = this._find(itemNavSelector); 26106 } 26107 return this._$itemNav; 26108 } 26109 }, 26110 visibleHelpElement : { 26111 get : function () { 26112 return this._visibleHelpElement; 26113 }, 26114 set : function (helpType) { 26115 this._visibleHelpElement = helpType; 26116 } 26117 }, 26118 26119 26120 isItem : { 26121 get : function () { 26122 return this._model._isItem; 26123 } 26124 }, 26125 26126 qualifiedName : { 26127 get : function () { 26128 return this._model._escapeQualifiedName(); 26129 } 26130 } 26131 26132 }); 26133}($, guidelib, _)); 26134(function ($, guidelib, _) { 26135 26136 var xfaUtil = xfalib.ut.XfaUtil.prototype, 26137 GuideFieldView = guidelib.view.GuideFieldView = guidelib.view.GuideBaseView.extend({
26138 _defaultWidgetName : "defaultWidget", 26139 26140 26141 autofillFieldKeywordToName : { 26142 "name" : "name", 26143 "given-name" : "fname", 26144 "additional-name" : "mname", 26145 "family-name" : "lname", 26146 "email" : "email", 26147 "street-address" : "address", 26148 "address-line1" : "address", 26149 "address-line2" : "address", 26150 "address-level1" : "state", 26151 "address-level2" : "city", 26152 "postal-code" : "zip", 26153 "country" : "country", 26154 "tel" : "phone", 26155 "cc-name" : "ccname", 26156 "cc-number" : "cardnumber", 26157 "cc-csc" : "cvc", 26158 "cc-exp-month" : "ccmonth", 26159 "cc-exp-year" : "ccyear", 26160 "cc-exp" : "exp-date", 26161 "cc-type" : "card-type" 26162 }, 26163 26164 initialize : function () { 26165 GuideFieldView._super.initialize.call(this); 26166 this._initializeWidget(); 26167 this._defineModelEvents(); 26168 this._markMandatory(); 26169 this._updateEmptyStatus(); 26170 this.oldValue = null; 26171 }, 26172 26173 postInitialize : function () { 26174 this._syncGuideNodeToHtml(true); 26175 }, 26176 26177 createWidgetOptions : function () { 26178 return { 26179 name : this._model.getAttribute("autocomplete") ? this.autofillFieldKeywordToName[this._model.getAttribute("autofillFieldKeyword")] : this._model.id + "_jqName", 26180 value : this._model.value, 26181 displayValue : this._model.formattedValue, 26182 commitEvent : this.getCommitEvent(), 26183 access : this._model.enabled ? "open" : "readOnly", 26184 screenReaderText : this._model._getScreenReaderText(), 26185 mandatory : this._model.mandatory 26186 }; 26187 }, 26188 26189 getCommitEvent : function () { 26190 return xfalib.ut.XfaUtil.prototype.XFA_EXIT_EVENT; 26191 }, 26192 26193 getWidgetName : function () { 26194 var widgetName; 26195 if (this.$widget) { 26196 var $elem = this.$widget.find('[data-af-widgetname]').addBack('[data-af-widgetname]'); 26197 26198 if ($elem && $elem.length > 0) { 26199 widgetName = $elem.attr("data-af-widgetname"); 26200 } 26201 } 26202 if (!widgetName) { 26203 this.logger().warn("AF", "widget name is not specified for field " + this._model.somExpression + 26204 ", falling back to other widget"); 26205 } 26206 return widgetName || this.options.widgetName || this._defaultWidgetName; 26207 }, 26208 26209 _unloadView : function () { 26210 if (this._model) { 26211 this._model.off(guidelib.event.GuideModelEvent.VALUE_CHANGED, this.handleValueChanged, this); 26212 this._model.off(guidelib.event.GuideModelEvent.ERROR_CHANGED, this.handleErrorChanged, this); 26213 this._model.off(guidelib.event.GuideModelEvent.ERROR_RESET, this.handleErrorReset, this); 26214 } 26215 26216 this.jqwidget = null; 26217 GuideFieldView._super._unloadView.apply(this, arguments); 26218 }, 26219 26220 _initializeWidget : function () { 26221 if (this.$element.find('div.guideFieldWidget').length) { 26222 this.$widget = this.$element.find('div.guideFieldWidget'); 26223 } else { 26224 this.$widget = null; 26225 } 26226 26227 26228 if (this.$widget) { 26229 $(this.$widget).on(this.getCommitEvent(), $.proxy(this.handleCommit, this)) 26230 .on(xfaUtil.XFA_CLICK_EVENT, $.proxy(this.handleClick, this)) 26231 .on(xfaUtil.XFA_EXIT_EVENT, $.proxy(this.handleFocusOut, this)) 26232 .on(xfaUtil.XFA_ENTER_EVENT, $.proxy(this.handleEnter, this)); 26233 } 26234 }, 26235 26236 _defineModelEvents : function () { 26237 if (this._model) { 26238 26239 26240 this._model.on(guidelib.event.GuideModelEvent.VALUE_CHANGED, this.handleValueChanged, this); 26241 26242 this._model.on(guidelib.event.GuideModelEvent.ERROR_CHANGED, this.handleErrorChanged, this); 26243 this._model.on(guidelib.event.GuideModelEvent.ERROR_RESET, this.handleErrorReset, this); 26244 26245 } 26246 }, 26247 26248 _syncGuideNodeToHtml : function (deepSync) { 26249 GuideFieldView._super._syncGuideNodeToHtml.apply(this, arguments); 26250 if (this._model) { 26251 var propsToSync = { 26252 "visible" : this._model.visible, 26253 "jcr:title" : this._model.title 26254 }; 26255 _.each(propsToSync, function (value, key, list) { 26256 this.handleModelChanged(guidelib.event.GuideModelEvent.createEvent( 26257 guidelib.event.GuideModelEvent.MODEL_CHANGED, this, key, value, value 26258 )); 26259 }, this); 26260 this.$element.attr("data-disabled", !this._model.enabled + ""); 26261 } 26262 if (this.$widget) { 26263 var widgetOptions = this.createWidgetOptions(); 26264 if (!this.jqwidget) {
26265 this.createWidget(this.getWidgetName(), widgetOptions); 26266 } else { 26267 this.setWidgetOptions(widgetOptions); 26268 } 26269 } 26270 26271 if (this._model.forceErrorShow && this._model._errorText) { 26272 this.handleErrorChanged({prevText : this._model.validationState, newText : this._model._errorText}); 26273 } 26274 26275 26276 26277 26278 26279 if (this._guide.jsonModel.textReplacementMap) { 26280 var footnoteArr = Object.entries(this._guide.jsonModel.textReplacementMap); 26281 var tempArray = []; 26282 for (var i = 0; i < footnoteArr.length; i++) { 26283 26284 26285 26286 if(!tempArray[footnoteArr[i][1]]){ 26287 tempArray[footnoteArr[i][1]] = footnoteArr[i][0]; 26288 } 26289 var selector = $("span[data-af-footnote-id=" + "\"" + footnoteArr[i][0] + "\"]"); 26290 for (var j = 0; j < $(selector).length; j++) { 26291 var supTag = document.createElement("sup"); 26292 var anchorTag = document.createElement("a"); 26293 anchorTag.setAttribute("href", "#" + tempArray[footnoteArr[i][1]] + "_ftn"); 26294 anchorTag.setAttribute("data-footnote-id", tempArray[footnoteArr[i][1]]); 26295 anchorTag.setAttribute("title", $('#' + tempArray[footnoteArr[i][1]]).text()); 26296 anchorTag.innerHTML = footnoteArr[i][1]; 26297 supTag.appendChild(anchorTag); 26298 $($(selector)[j]).html(supTag.outerHTML); 26299 } 26300 } 26301 } 26302 }, 26303 26304 setWidgetOptions : function (widgetOptions) { 26305 this.jqwidget.option(widgetOptions); 26306 26307 }, 26308 26309 26310 _markMandatory : function (value) { 26311 if (this._model.mandatory && this.$element) { 26312 this.$element.attr("data-mandatory", "true"); 26313 } else { 26314 this.$element.removeAttr("data-mandatory"); 26315 26316 if (this._model._failedTest === this.guideUtil.MANDATORY_TEST) { 26317 this._model._guide().runtime.errorManager.unMarkError(this.$element, this._model.somExpression); 26318 } 26319 } 26320 if (this.jqwidget) { 26321 this.setWidgetOptions({ 26322 "mandatory" : value 26323 }); 26324 } 26325 }, 26326 26327 26328 _updateEmptyStatus : function (event) { 26329 var val = event ? event.newText : this._model.value; 26330 if (val == null || typeof val === 'string' && val.length == 0) { 26331 this.$element.removeClass("af-field-filled").addClass("af-field-empty"); 26332 } else { 26333 this.$element.removeClass("af-field-empty").addClass("af-field-filled"); 26334 } 26335 }, 26336 26337 handleValueChanged : function (event) { 26338 switch (event._property) { 26339 case "value": 26340 this.jqwidget.option("value", event.prevText); 26341 this.jqwidget.option("displayValue", event.newText); 26342 break; 26343 } 26344 this._updateEmptyStatus(event); 26345 }, 26346 26347 handleErrorChanged : function (event) { 26348 var value = event.prevText, 26349 errorMessage = event.newText; 26350 if (value === true) { 26351 this._model._guide().runtime.errorManager.unMarkError(this.$element, this._model.somExpression); 26352 this.$element.addClass("validation-success").removeClass("validation-failure"); 26353 this.updateWidgetOption("isValid", true); 26354 } else { 26355 this._model._guide().runtime.errorManager.markError(errorMessage, this.$element, this._model.somExpression, 26356 guideBridge.getValidationContext());
26357 this.$element.addClass("validation-failure").removeClass("validation-success"); 26358 this.updateWidgetOption("isValid", false); 26359 } 26360 }, 26361 26362 handleErrorReset : function (event) { 26363 this._model._guide().runtime.errorManager.unMarkError(this.$element, this._model.somExpression); 26364 this.$element.removeClass("validation-failure").removeClass("validation-success"); 26365 this.updateWidgetOption("isValid", undefined); 26366 }, 26367 26368 handleCommit : function () { 26369 if (this._model.enabled) { 26370 this.commitValue(this.jqwidget.option("value")); 26371 } 26372 }, 26373 26374 handleClick : function (event) { 26375 window.guideBridge.clickedOnWindow = false; 26376 }, 26377 26378 handleFocusOut : function (event) { 26379 var gb = window.guideBridge; 26380 26381 if (this.getCommitEvent() !== xfaUtil.XFA_EXIT_EVENT) { 26382 this._model.executeExpression("exit"); 26383 } 26384 if (gb && gb.clickedOnWindow) { 26385 this._guideView.currentFocusItemSom = null; 26386 } 26387 gb.clickedOnWindow = false; 26388 if (!(this._model.className === 'guideRadioButton' || this._model.className === 'guideCheckBox' || this._model.className === 'guideButton')) { 26389 this._triggerOnBridge("elementFocusOut", "", "", "", ""); 26390 } 26391 26392 if ((this.oldValue !== this._model.value) && this._model._errorText) { 26393 this.handleErrorChanged({prevText : this._model.validationState, newText : this._model._errorText}); 26394 } 26395 this.$element.removeClass('guideActiveField'); 26396 }, 26397 26398 handleModelChanged : function (event) { 26399 switch (event._property) { 26400 case "enabled": 26401 26402 26403 var prop = event.newText ? "open" : "readOnly"; 26404 if (this.jqwidget) { 26405 this.jqwidget.option("access", prop); 26406 } 26407 this.$element.attr("data-disabled", !event.newText + ""); 26408 break; 26409 case "mandatory": 26410 26411 this._markMandatory(this._model.mandatory); 26412 break; 26413 case "validateExpMessage": 26414 var newText = event.jsonModel.newText; 26415 this._changeValidationMessage(newText); 26416 break; 26417 case "jcr:title": 26418 26419 var newText = event.jsonModel.newText; 26420 this._changeTitle(newText); 26421 break; 26422 default: 26423 GuideFieldView._super.handleModelChanged.apply(this, arguments); 26424 } 26425 }, 26426 26427 26428 _changeTitle : function (newText) { 26429 var $field = $("#" + this.id), 26430 $guideFieldLabelDiv = $field.children(".guideFieldLabel"), 26431 $labelDiv = $guideFieldLabelDiv.children("label"); 26432 if ($labelDiv) { 26433 newText = DOMPurify.sanitize(newText); 26434 $labelDiv.html(newText); 26435 } 26436 }, 26437 26438 26439 _changeValidationMessage : function (newText) { 26440 var $fieldNode = $("#" + this.id), 26441 $errorDiv = $fieldNode.children(".guideFieldError"); 26442 $errorDiv.html(newText); 26443 }, 26444 26445 26446 commitValue : function (value) { 26447 this._model.value = value; 26448 var _version = this._model._guide().version; 26449 if (!(_version.isOn(_version.Flags.RUN_VALUE_COMMMIT_ON_SCRIPT_CHANGE))) { 26450 this._model.executeExpression("valueCommitScript"); 26451 } 26452 26453 26454 if (this.getCommitEvent() === xfaUtil.XFA_CHANGE_EVENT) { 26455 this._model.executeExpression("change"); 26456 } else { 26457 this._model.executeExpression("exit"); 26458 } 26459 }, 26460 26461 26462 tempXfaFixes : function () { 26463 26464 26465 26466 if (this.$element) { 26467 this.$element.find("input").css("position", "relative"); 26468 } 26469 this.handleAccessibility(); 26470 }, 26471 26472 handleAccessibility : function () { 26473 26474 if (this._model.mandatory) { 26475 this.$widget.find("input,textarea,select,button").attr("aria-required", true); 26476 } 26477 if(this._model._getToolTip()) { 26478 this.$element.find("input,textarea,select,button").attr("aria-labelledby",this._model.id + "_widget" + " " + this._model.id + "_guideFieldShortDescription"); 26479 } 26480 if (this._model._getScreenReaderText() === this._model._getToolTip()) { 26481 this.$element.find("input,textarea,select,button").removeAttr("aria-label"); 26482 this.$element.find("input,textarea,select,button").attr("aria-labelledby",this._model.id + "_guideFieldShortDescription"); 26483 } 26484 }, 26485 26486 26487 _getWidgetInitialOptions : function ($widget) { 26488 var $elem = $widget.find('[data-af-widgetname]').addBack('[data-af-widgetname]'); 26489 if ($elem.length > 0) { 26490 this.logger().info("AF", "Getting widget options for " + this._model.somExpression); 26491 var optionsMap = $elem.data('af-widgetoptions') || {}; 26492 _.each($elem[0].attributes, function (attr) { 26493 var nm = attr.name.match(/data-af-widgetoption-([^-]+)$/); 26494 if (nm != null && nm.length > 1) { 26495 this.logger().info("AF", "adding option " + nm[1] + " with value " + " "); 26496 optionsMap[nm[1]] = attr.value; 26497 } 26498 }, this); 26499 return optionsMap; 26500 } 26501 return {}; 26502 }, 26503 26504 _newWidget : function (widgetname, options, $widgetElem) { 26505 var jqwidget = null, 26506 fixesRequired = widgetname == this._defaultWidget
26506Name; 26507 try { 26508 26509 $widgetElem[widgetname](options); 26510 26511 26512 jqwidget = $widgetElem.data(widgetname) || $widgetElem.data('xfaWidget-' + widgetname); 26513 } catch (e) { 26514 this.logger().error("AF", "widget " + widgetname + " doesn't exists. Falling back to default widget"); 26515 fixesRequired = true; 26516 jqwidget = $widgetElem[this._defaultWidgetName](options).data('xfaWidget-' + widgetname); 26517 } 26518 26519 if (fixesRequired) { 26520 this.tempXfaFixes(); 26521 } 26522 return jqwidget; 26523 }, 26524 26525 createWidget : function (widgetname, options) { 26526 var initialOptions = this._getWidgetInitialOptions(this.$widget); 26527 var _options = $.extend({}, options, initialOptions); 26528 this.jqwidget = this._newWidget(widgetname, _options, this.$widget); 26529 }, 26530 26531 handleEnter : function () { 26532 this._guideView.currentFocusItemSom = this._model.somExpression; 26533 var gb = window.guideBridge; 26534 if (gb) { 26535 gb.clickedOnWindow = false; 26536 } 26537 if (!(this._model.className === 'guideRadioButton' || this._model.className === 'guideCheckBox' || this._model.className === 'guideButton')) { 26538 this._triggerOnBridge("elementFocus", "", "", "", ""); 26539 } 26540 this.oldValue = this._model.value; 26541 this.$element.addClass('guideActiveField'); 26542 }, 26543 26544 handleChange : function () { 26545 26546 }, 26547
26548 setActive : function (activeItemToken, focus, muteScripts) { 26549 GuideFieldView._super.setActive.call(this, activeItemToken, focus, muteScripts); 26550 if (focus) { 26551 26552 if (!this._guideView.skipFieldFocus && this.jqwidget && this.jqwidget.focus) { 26553 this.jqwidget.focus(); 26554 this._guideView.currentFocusItemSom = this._model.somExpression; 26555 } 26556 26557 } 26558 return true; 26559 }, 26560 26561 updateWidgetOption : function (optionName, optionValue) { 26562 26563 if (this.jqwidget) { 26564 this.jqwidget.option(optionName, optionValue); 26565 } 26566 } 26567 26568 }); 26569}($, guidelib, _)); 26570(function ($, guidelib) { 26571 var GuideCaptchaView = guidelib.view.GuideCaptchaView = guidelib.view.GuideFieldView.extend({ 26572 26573 _defaultWidgetName : "afcaptcha", 26574 26575 syncGuideNodeToHtml : true, 26576 26577 initialize : function () { 26578 26579 if (this.options.model.isWidgetRecaptcha) { 26580 if ((this.options.model.captchaEnterprise && !this.options.model.checkBoxkey) || 26581 (this.options.model.captchaInvisible && this.options.model.mandatory)) { 26582 this._model = this.options.model; 26583 this.syncGuideNodeToHtml = false; 26584 return; 26585 } else if (this.options.model.captchaInvisible) { 26586 this.options.element.classList.add("af-hideRecaptchaView"); 26587 this.options.model.captchaValidate = false; 26588 } 26589 } else if ((this.options.model.isWidgetTurnstile || this.options.model.isWidgetHcaptcha) && this.options.model.captchaInvisible) { 26590 this._model = this.options.model; 26591 this.syncGuideNodeToHtml = false; 26592 return; 26593 } 26594 GuideCaptchaView._super.initialize.apply(this, arguments); 26595 if (this._model.captchaWidget) { 26596 26597 this._defaultWidgetName = this._model.captchaWidget; 26598 } 26599 }, 26600 26601 _initializeWidget : function () { 26602 GuideCaptchaView._super._initializeWidget.apply(this, arguments); 26603 if (this.$widget.length > 0) { 26604 this.$widget.on("tokenChange.captcha", $.proxy(this.handleTokenChange, this)); 26605 } 26606 }, 26607 26608 _syncGuideNodeToHtml : function (deepSync) { 26609 if(!this.syncGuideNodeToHtml) 26610 return; 26611 GuideCaptchaView._super._syncGuideNodeToHtml.call(this, deepSync); 26612 }, 26613 26614 handleTokenChange : function (event) { 26615 this._model.value = event.token; 26616 }, 26617 26618 createWidgetOptions : function () { 26619 var options = GuideCaptchaView._super.createWidgetOptions.apply(this, arguments); 26620 return $.extend({}, options, { 26621 "captchaConfigData" : this.options.model.jsonModel 26622 }); 26623 }, 26624 26625 handleErrorChanged : function (event) { 26626 var value = event.prevText, 26627 errorMessage = event.newText; 26628 if (value === false) { 26629 this._model._guide().runtime.errorManager.markError(errorMessage, this.$element, this._model.somExpression, 26630 guideBridge.getValidationContext()); 26631 this.$element.addClass("validation-failure").removeClass("validation-success"); 26632 } else { 26633 this.$element.addClass("validation-success").removeClass("validation-failure"); 26634 } 26635 } 26636 }); 26637}($, guidelib)); 26638(function ($, guidelib, _) { 26639 var xfaUtil = xfalib.ut.XfaUtil.prototype, 26640 GuideCompositeFieldView = guidelib.view.GuideCompositeFieldView = guidelib.view.GuideFieldView.extend({ 26641 _defaultWidgetName : "defaultField", 26642 26643 26644 getModelNameOptionsMap : function () { 26645 return {}; 26646 }, 26647 26648 initialize : function () { 26649 GuideCompositeFieldView._super.initialize.call(this); 26650 this._defineChildModelEvents(); 26651 }, 26652 26653 postInitialize : function () { 26654 GuideCompositeFieldView._super.postInitialize.call(this); 26655 var _self = this; 26656 if (this.getModelNameOptionsMap()) { 26657 _.each(this.getModelNameOptionsMap(), function (value, modelName) { 26658 var childModel = _self._model[modelName]; 26659 if (childModel._errorText) { 26660 childModel._triggerEvent(guidelib.event.GuideModelEvent.ERROR_CHANGED, 26661 "validationStatus", childModel.validationState, childModel._errorText); 26662 } 26663 }); 26664 } 26665 }, 26666 26667 _unloadView : function () { 26668 var _self = this; 26669 if (this.getModelNameOptionsMap()) { 26670 _.each(this.getModelNameOptionsMap(), function (value, modelName) { 26671 var obj = _self._model[modelName]; 26672 26673 obj.off(guidelib.event.GuideModelEvent.VALUE_CHANGED, _self.handleValueChanged, _self);
26674 if (obj.mandatory || obj.validateExp) { 26675 obj.off(guidelib.event.GuideModelEvent.ERROR_CHANGED, _self.handleErrorChanged, _self); 26676 obj.off(guidelib.event.GuideModelEvent.ERROR_RESET, _self.handleErrorReset, _self); 26677 } 26678 }); 26679 26680 } 26681 GuideCompositeFieldView._super._unloadView.call(_self); 26682 }, 26683 26684 _defineChildModelEvents : function () { 26685 var _self = this; 26686 if (this.getModelNameOptionsMap()) { 26687 _.each(this.getModelNameOptionsMap(), function (value, modelName) { 26688 var obj = _self._model[modelName]; 26689 26690 obj.on(guidelib.event.GuideModelEvent.VALUE_CHANGED, _self.handleValueChanged, _self); 26691 26692 26693 if (obj.mandatory || obj.validateExp) { 26694 obj.on(guidelib.event.GuideModelEvent.ERROR_CHANGED, _self.handleErrorChanged, _self); 26695 obj.on(guidelib.event.GuideModelEvent.ERROR_RESET, _self.handleErrorReset, _self); 26696 } 26697 }); 26698 26699 } 26700 }, 26701 26702 handleCommit : function () { 26703 var _self = this; 26704 if (!_.isEmpty(this.getModelNameOptionsMap())) { 26705 _.each(this.getModelNameOptionsMap(), function (value, modelName) { 26706 var obj = _self._model[modelName]; 26707 if (!_.isUndefined(obj)) { 26708 var val = _self.jqwidget.option(value); 26709 if (_.isArray(val)) { 26710 val = val.join("\n"); 26711 } 26712 obj.value = val; 26713 } 26714 }); 26715 } else { 26716 this._model.value = this.jqwidget.option("value"); 26717 } 26718 this._model.executeExpression("valueCommitScript"); 26719 this.execCommitExpression(); 26720 }, 26721 26722 handleValueChanged : function (event) { 26723 26724 26725 switch (event._property) { 26726 case "value": 26727 var map = this.getModelNameOptionsMap(); 26728 this.jqwidget.option(map[event.target.name], event.prevText); 26729 break; 26730 } 26731 }, 26732 26733 execCommitExpression : function () { 26734 26735 if (this.getCommitEvent() == xfaUtil.XFA_CHANGE_EVENT) { 26736 this._model.executeExpression("change"); 26737 } else { 26738 this._model.executeExpression("exit"); 26739 } 26740 } 26741 }); 26742}($, guidelib, _)); 26743(function ($, guidelib) { 26744 var GuideFileUploadView = guidelib.view.GuideFileUploadView = guidelib.view.GuideCompositeFieldView.extend({ 26745 _defaultWidgetName : "fileUpload", 26746 26747 initialize : function () { 26748 GuideFileUploadView._super.initialize.call(this); 26749 26750 this._blockDoubleExtensions = this._readDoubleExtensionConfig(); 26751 }, 26752 26753 26754 _readDoubleExtensionConfig: function () { 26755 var $widget = this.$element.hasClass('afFileUpload') ? this.$element : this.$element.find('.afFileUpload'); 26756 var disableDoubleExtension = $widget.data('disableDoubleExtensionFiles'); 26757 return disableDoubleExtension === true || disableDoubleExtension === "true"; 26758 }, 26759 26760 getModelNameOptionsMap : function () { 26761 var map = GuideFileUploadView._super.getModelNameOptionsMap.apply(this, arguments); 26762 return $.extend({}, map, { 26763 "fileAttachment" : "value", 26764 "comment" : "comment" 26765 }); 26766 }, 26767 26768 createWidgetOptions : function () { 26769 var options = GuideFileUploadView._super.createWidgetOptions.apply(this, arguments), 26770 fileNamesStr = this._model._getFileAttachmentNames(), 26771 fileNamesArr = []; 26772 if (fileNamesStr) { 26773 fileNamesArr = fileNamesStr.split("\n"); 26774 } 26775 return $.extend({}, options, { 26776 fileList : this._model.fileList, 26777 buttonText : this._model.buttonText, 26778 multiSelect : this._model.multiSelection, 26779 fileSizeLimit : this._model.fileSizeLimit, 26780 mimeType : this._model.getOrElse(this._model.jsonModel, "mimeType", ""), 26781 buttonClass : "button.guide-fu-attach-button", 26782 fileItemListClass : "ul.guide-fu-fileItemList",
26783 iframeContainer : "div.guideContainerWrapperNode", 26784 showComment : this._model.showComment, 26785 value : this._model.fileAttachment.value, 26786 fileNames : fileNamesArr, 26787 comment : this._model.comment.value, 26788 _uuidGenerator : function () { return guideBridge._getUUID.apply(this); }, 26789 _filePath : "/tmp/fd/af", 26790 _getUrl : guideBridge._getUrl(""), 26791 disablePreview : false, 26792 uploaderPluginName : guideBridge.userConfig.uploaderPluginName || "adobeFileUploader" 26793 }); 26794 }, 26795 26796 handleCommit : function () { 26797 26798 26799 26800 if (!this._blockDoubleExtensions) { 26801 this._model.fileList = this.jqwidget.option("fileList"); 26802 GuideFileUploadView._super.handleCommit.apply(this, arguments); 26803 } else { 26804 var fileList = this.jqwidget.option("fileList") || []; 26805 var filtered = this._filterFileList(fileList); 26806 var validFiles = filtered.validFiles; 26807 var invalidFiles = filtered.invalidFiles; 26808 26809 if (invalidFiles.length > 0) { 26810 alert("Files with multiple extensions are not allowed:\n" + invalidFiles.join("\n")); 26811 } 26812 this._updateFileList(validFiles); 26813 26814 this._model.fileAttachment.value = (this._model.fileList || []) 26815 .map(this._extractFileName.bind(this)) 26816 .filter(Boolean) 26817 .join("\n"); 26818 } 26819 }, 26820 26821 26822 _extractFileName: function (fileItem) { 26823 if (typeof fileItem === "string") { 26824 return fileItem; 26825 } else if (fileItem && fileItem.name) { 26826 return fileItem.name; 26827 } else if (fileItem && fileItem[0] && fileItem[0].files && fileItem[0].files.length > 0) { 26828 return fileItem[0].files[0].name; 26829 } 26830 return ""; 26831 }, 26832 26833 26834 _renderFileListUI: function () { 26835 var self = this; 26836 var $ul = this.$element.find("ul.guide-fu-fileItemList"); 26837 $ul.empty(); 26838 26839 (this._model.fileList || []).forEach(function(fileItem) { 26840 var name = self._extractFileName(fileItem); 26841 if (name) { 26842 $ul.append("<li class='guide-fu-fileItem'>" + name + "</li>"); 26843 } 26844 }); 26845 }, 26846 26847 26848 _updateFileList: function (fileList) { 26849 this._model.fileList = fileList; 26850 this.jqwidget.option("fileList", fileList); 26851 this._renderFileListUI(); 26852 }, 26853 26854 26855 _filterFileList: function (fileList) { 26856 var self = this; 26857 var invalidFiles = []; 26858 var validFiles = []; 26859 26860 if (!fileList || !fileList.length) return { invalidFiles: invalidFiles, validFiles: validFiles }; 26861 26862 for (var i = 0; i < fileList.length; i++) { 26863 var fileItem = fileList[i]; 26864 26865 if (fileItem && fileItem[0] && fileItem[0].files) { 26866 var hasInvalidFile = false; 26867 for (var j = 0; j < fileItem[0].files.length; j++) { 26868 var file = fileItem[0].files[j]; 26869 if (this._hasDoubleExtension(file.name)) { 26870 invalidFiles.push(file.name); 26871 hasInvalidFile = true; 26872 } 26873 } 26874 if (!hasInvalidFile) { 26875 validFiles.push(fileItem); 26876 } 26877 } else { 26878 26879 var fileName = this._extractFileName(fileItem); 26880 if (fileName) { 26881 if (this._hasDoubleExtension(fileName)) { 26882 invalidFiles.push(fileName); 26883 } else { 26884 validFiles.push(fileItem); 26885 } 26886 } 26887 } 26888 }
26889 return { invalidFiles: invalidFiles, validFiles: validFiles }; 26890 }, 26891 26892 26893 _hasDoubleExtension: function (fileName) { 26894 return fileName && fileName.split('.').length > 2; 26895 }, 26896 26897 handleModelChanged : function (event) { 26898 switch (event._property) { 26899 case "fileList": 26900 if (this._blockDoubleExtensions) { 26901 this.jqwidget.option("fileList", this._model.fileList || []); 26902 this._renderFileListUI(); 26903 } else { 26904 this.jqwidget.option("fileList", event.prevText); 26905 } 26906 break; 26907 default: 26908 GuideFileUploadView._super.handleModelChanged.apply(this, arguments); 26909 break; 26910 } 26911 }, 26912 26913 handleAccessibility : function () { 26914 26915 26916 var isBrowserIE9OrIE10 = ($.browser.msie && ($.browser.version === '9.0' || $.browser.version === '10.0')); 26917 if (isBrowserIE9OrIE10) { 26918 if (this._model.mandatory) { 26919 this.$widget.attr("aria-required", true); 26920 } 26921 if (this._model._getScreenReaderText() === this._model._getToolTip()) { 26922 this.$widget.removeAttr("aria-label"); 26923 this.$widget.attr("aria-labelledby", this._model.id + "_guideFieldShortDescription"); 26924 } 26925 } else { 26926 GuideFileUploadView._super.handleAccessibility.apply(this, arguments); 26927 } 26928 }, 26929 26930 setActive : function (activeItemToken, focus, muteScripts) { 26931 guidelib.view.GuideFieldView._super.setActive.call(this, activeItemToken, focus, muteScripts); 26932 if (focus) { 26933 this._guideView.currentFocusItemSom = this._model.somExpression; 26934 this.$element.find("button").focus(); 26935 } 26936 return true; 26937 }, 26938 26939 26940 26941 tempXfaFixes : function () { 26942 26943 this.handleAccessibility(); 26944 }, 26945 26946 getCommitEvent : function () { 26947 return xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT; 26948 } 26949 }); 26950}($, guidelib)); 26951(function ($, guidelib) { 26952 var GuideTermsAndConditionsView = guidelib.view.GuideTermsAndConditionsView = guidelib.view.GuideCompositeFieldView.extend({ 26953 _defaultWidgetName : "tnc", 26954 26955 getModelNameOptionsMap : function () { 26956 var map = GuideTermsAndConditionsView._super.getModelNameOptionsMap.apply(this, arguments); 26957 return $.extend({}, map, { 26958 "reviewDocument" : "value", 26959 "reviewStatus" : "reviewStatus" 26960 }); 26961 }, 26962 26963 createWidgetOptions : function () { 26964 var options = GuideTermsAndConditionsView._super.createWidgetOptions.apply(this, arguments); 26965 return $.extend({}, options, { 26966 textAreaClass : ".guide-tnc-content", 26967 checkBoxClass : ".guide-tnc-checkbox", 26968 linkClass : ".guide-tnc-link", 26969 checkBoxDisableClass : ".guide-tnc-checkbox-disabled", 26970 checkBoxReviewedClass : ".guide-tnc-checkbox-reviewed", 26971 showLink : this._model.showLink, 26972 showAsPopUp : this._model.showAsPopUp, 26973 value : this._model.reviewDocument.value, 26974 reviewStatus : this._model.reviewStatus.value, 26975 clickStatus : this._model.clickStatus 26976 }); 26977 }, 26978 26979 26980 tempXfaFixes : function () { 26981 26982 26983 26984 if (this.$widget) { 26985 this.$widget.css("position", "relative"); 26986 } 26987 26988 }, 26989 26990 handleCommit : function (event) { 26991 26992 this._model.clickStatus = this.jqwidget.option("clickStatus"); 26993 26994 GuideTermsAndConditionsView._super.handleCommit.apply(this, arguments); 26995 }, 26996 26997 handleModelChanged : function (event) { 26998 26999 27000 switch (event._property) { 27001 case "clickStatus": 27002 this.jqwidget.option("clickStatus", event.prevText); 27003 break; 27004 default: 27005 GuideTermsAndConditionsView._super.handleModelChanged.apply(this, arguments); 27006 break; 27007 } 27008 }, 27009 27010 getCommitEvent : function () { 27011 return xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT; 27012 } 27013 }); 27014}($, guidelib)); 27015(function ($, guidelib) { 27016 var GuideTelephoneView = guidelib.view.GuideTelephoneView = guidelib.view.GuideFieldView.extend({ 27017
27018 _defaultWidgetName : "telephoneWidget", 27019 27020 createWidgetOptions : function () { 27021 var options = GuideTelephoneView._super.createWidgetOptions.apply(this, arguments); 27022 return $.extend({}, options, { 27023 placeholder : this._model.placeholderText 27024 }); 27025 } 27026 27027 }); 27028}($, guidelib)); 27029 27030(function ($, guidelib) { 27031 var GuideTextDrawView = guidelib.view.GuideTextDrawView = guidelib.view.GuideFieldView.extend({ 27032 _defaultWidgetName : "abstractWidget", 27033 27034 initialize : function () { 27035 GuideTextDrawView._super.initialize.call(this); 27036 if (this.$element && this.$element.length > 0) { 27037 $(this.$element) 27038 .on("focus.guideTextDraw", $.proxy(this.handleEnter, this)) 27039 .on("click.guideTextDraw", $.proxy(this.handleClick, this)); 27040 } 27041 }, 27042 27043 _syncGuideNodeToHtml : function (deepSync) { 27044 GuideTextDrawView._super._syncGuideNodeToHtml.call(this, deepSync); 27045 27046 27047 var isFloatingField = this._model._isFloatingField(); 27048 var isParentLazy = guidelib.util.GuideUtil._checkIfAncestorIsALazyReference(this); 27049 if (!isParentLazy && this._model.value === this._model.jsonModel._value && this.$element.html() !== this._model.value && !isFloatingField) { 27050 27051 27052 } else { 27053 this.handleValueChanged({ 27054 _property : "value", 27055 newText : this._model.value ? this._model.value : "" 27056 }); 27057 } 27058 }, 27059 27060 handleValueChanged : function (event) { 27061 switch (event._property) { 27062 case "value": 27063 this.$element.html(event.newText); 27064 break; 27065 } 27066 }, 27067 27068 setActive : function (activeItemToken, focus, muteScripts) { 27069 guidelib.view.GuideFieldView._super.setActive.call(this, activeItemToken, focus, muteScripts); 27070 if (focus && !this._guideView.skipFieldFocus) { 27071 if (this.$element) { 27072 this.$element.focus(); 27073 } 27074 this._guideView.currentFocusItemSom = this._model.somExpression; 27075 } 27076 return true; 27077 } 27078 }); 27079}($, guidelib)); 27080 27081 27082(function ($, guidelib) { 27083 var GuideAdobeSignBlockView = guidelib.view.GuideAdobeSignBlockView = guidelib.view.GuideTextDrawView.extend({ 27084 }); 27085}($, guidelib)); 27086(function ($, guidelib) { 27087 var GuideButtonView = guidelib.view.GuideButtonView = guidelib.view.GuideFieldView.extend({ 27088 _defaultWidgetName : "xfaButton", 27089 27090 handleClick : function (event) { 27091 this._triggerOnBridge("elementButtonClicked", this._model, "click", "", ""); 27092 this._model.executeExpression("clickExp"); 27093 GuideButtonView._super.handleClick.call(this); 27094 }, 27095 27096 _changeTitle : function (newText) { 27097 var $fieldTitleSpan = $("#" + this.id + "_widget"); 27098 var $buttonLabel = $fieldTitleSpan.children("[data-guide-button-label]"); 27099 newText = DOMPurify.sanitize(xfalib.ut.XfaUtil.prototype.encodeScriptableTags(newText)); 27100 $buttonLabel.html(newText); 27101 }, 27102 27103 tempXfaFixes : function () { 27104 27105 27106 27107 if (this.$element) { 27108 this.$element.find("button").css("position", "relative"); 27109 } 27110 this.handleAccessibility(); 27111 } 27112 27113 }); 27114}($, guidelib)); 27115(function ($, guidelib, _) { 27116 var fileInputIdCounter = 0; 27117 var GuideListFileAttachmentButtonView = guidelib.view.GuideListFileAttachmentButtonView = guidelib.view.GuideButtonView.extend({ 27118 27119 _clearFileListing : function () { 27120 $('#fileAttachment .modal-list', window.document).children().remove(); 27121 _.each(this._fileListViews, function (childView) { 27122 childView._unloadView(); 27123 }, this); 27124 this._fileListViews = []; 27125 fileInputIdCounter = 0; 27126 }, 27127 _updateFileListing : function (fileAttachmentModel) { 27128 if (fileAttachmentModel.className == "guideFileUpload") { 27129 var $htmlTemplate = this._guideView.$element.find("#" + fileAttachmentModel.id), 27130 inputFileSelector = "#" + fileAttachmentModel.id + "_widget", 27131 27132 27133 27134 27135 27136 $cloneHtmlTemplate = $htmlTemplate.clone(); 27137 27138 $cloneHtmlTemplate.find(inputFileSelector).attr("id", fileAttachmentModel.id + "_widget" + (++fileInputIdCounter)); 27139 this._addSuffixToHelpIds($cloneHtmlTemplate, fileInputIdCounter); 27140 var $fluidDesign = $('<div></div>').addClass("row").append('<div class="col-md-12"></div>');
27141 $('#fileAttachment .modal-list', window.document).append($cloneHtmlTemplate.appendTo($fluidDesign)); 27142 var view = guidelib.view.GuideViewRegistry.prototype.createView($cloneHtmlTemplate, this); 27143 this._fileListViews.push(view); 27144 view.postInitialize(); 27145 27146 } 27147 }, 27148 _addSuffixToHelpIds : function ($html, suffix) { 27149 var $questionMarkElement = $html.find("[data-guide-longDescription]"), 27150 $shortHelpElement; 27151 if ($questionMarkElement.length > 0) { 27152 var idForLongHelp = $questionMarkElement.attr("data-guide-longDescription"), 27153 $longHelpElement = $(".guideFieldDescription.long", $html); 27154 idForLongHelp = idForLongHelp + suffix; 27155 $longHelpElement.attr("id", idForLongHelp); 27156 $questionMarkElement.attr("data-guide-longDescription", idForLongHelp); 27157 } 27158 27159 27160 }, 27161 27162 27163 _markFileListing : function () { 27164 if (this.$element) { 27165 this.$element.find("button").attr("data-guide-fileListing", true); 27166 } 27167 }, 27168 27169 initialize : function () { 27170 GuideListFileAttachmentButtonView._super.initialize.apply(this, arguments); 27171 this._markFileListing(); 27172 27173 27174 this._fileListViews = []; 27175 } 27176 }); 27177}($, guidelib, _)); 27178(function ($, guidelib, _) { 27179 var xfaUtil = xfalib.ut.XfaUtil.prototype, 27180 GuideDropDownListView = guidelib.view.GuideDropDownListView = guidelib.view.GuideFieldView.extend({ 27181 27182 _defaultWidgetName : "dropDownList", 27183 27184 initialize : function () { 27185 GuideDropDownListView._super.initialize.apply(this, arguments); 27186 if (this._model.multiSelect) { 27187 this._defaultWidgetName = "listBox"; 27188 } 27189 }, 27190 27191 _valueToArray : function (value) { 27192 var valueArray; 27193 if (value !== null && !_.isUndefined(value)) { 27194 if (_.isString(value)) { 27195 valueArray = value.split("\n"); 27196 } else if (_.isNumber(value)) { 27197 valueArray = [value.toString()]; 27198 } 27199 } else { 27200 valueArray = [null]; 27201 } 27202 return valueArray; 27203 }, 27204 27205 createWidgetOptions : function () { 27206 var options = GuideDropDownListView._super.createWidgetOptions.apply(this, arguments); 27207 27208 27209 return $.extend({}, options, { 27210 multiSelect : this._model.multiSelect, 27211 editable : false, 27212 items : this._model._getOptionsArray("save", "display"), 27213 value : this._valueToArray(this._model.value), 27214 placeholder : this._model.placeholderText 27215 }); 27216 }, 27217 27218 27219 handleCommit : function () { 27220 var val = this.jqwidget.option("value"); 27221 if (_.isArray(val)) { 27222 val = val.join("\n"); 27223 } 27224 27225 this.commitValue(val); 27226 }, 27227 27228 27229 commitValue : function (value) { 27230 var oldValue = this._model.value; 27231 this._model.value = value; 27232 27233 27234 27235 var _version = this._model._guide().version; 27236 if (!(_version.isOn(_version.Flags.RUN_VALUE_COMMMIT_ON_SCRIPT_CHANGE))) { 27237 this._model.executeExpression("valueCommitScript"); 27238 } 27239 if (this.getCommitEvent() === xfaUtil.XFA_CHANGE_EVENT) { 27240 27241 27242 27243 27244 27245 this._model.executeExpression("change", { 27246 "prevText" : oldValue, 27247 "newText" : this._model.value 27248 }); 27249 } else { 27250 27251 this._model.executeExpression("exit"); 27252 } 27253 }, 27254 27255 handleValueChanged : function (event) { 27256 this.jqwidget.option("value", this._valueToArray(event.prevText)); 27257 this.jqwidget.option("displayValue", this._valueToArray(event.
27257newText)); 27258 this._updateEmptyStatus(event); 27259 }, 27260 27261 getCommitEvent : function () { 27262 return xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT; 27263 }, 27264 27265 handleModelChanged : function (event) { 27266 if (event._property === "addItem") { 27267 this._handleAddItem(event); 27268 } 27269 if (event._property === "clearItems") { 27270 this._handleClearItems(event); 27271 } 27272 if (event._property === "deleteItem") { 27273 this._handleDeleteItem(event); 27274 } else { 27275 GuideDropDownListView._super.handleModelChanged.apply(this, arguments); 27276 } 27277 }, 27278 27279 _handleAddItem : function (event) { 27280 var itemValues = { 27281 sDisplayVal : event.newText, 27282 sSaveVal : event.prevText 27283 }; 27284 this.jqwidget.addItem(itemValues); 27285 }, 27286 27287 _handleClearItems : function (event) { 27288 this.jqwidget.clearItems(); 27289 }, 27290 27291 _handleDeleteItem : function (event) { 27292 this.jqwidget.deleteItem(event.newText); 27293 }, 27294 27295 handleItemsChanged : function (event) { 27296 var items = this._model._getOptionsArray("save", "display"); 27297 this.jqwidget.option("items", items); 27298 this.jqwidget.option("value", this._valueToArray(this._model.jsonModel._value)); 27299 this.jqwidget.option("displayValue", this._valueToArray(this._model.formattedValue)); 27300 }, 27301 27302 _defineModelEvents : function () { 27303 GuideDropDownListView._super._defineModelEvents.apply(this, arguments); 27304 if (this._model) { 27305 27306 this._model.on(guidelib.event.GuideModelEvent.ITEMS_CHANGED, this.handleItemsChanged, this); 27307 } 27308 }, 27309 27310 27311 tempXfaFixes : function () { 27312 27313 27314 if (this.$element) { 27315 if (!this._model.multiSelect) { 27316 this.$element.find("select") 27317 .css("position", "relative") 27318 .attr("id", this._model.id + "_widget") 27319 .attr("aria-describedby", this._model.id + "_widget_desc"); 27320 } else { 27321 27322 if (this._model.height) { 27323 this.$element.find("ol").css("max-height", "none"); 27324 } 27325 this.$element.find("ol") 27326 .css("position", "relative") 27327 .attr("id", this._model.id + "_widget"); 27328 } 27329 } 27330 this.handleAccessibility(); 27331 } 27332 }); 27333 27334}($, guidelib, _)); 27335(function ($, guidelib, _) { 27336 var GuideCheckBoxView = guidelib.view.GuideCheckBoxView = guidelib.view.GuideFieldView.extend({ 27337 _defaultWidgetName : "XfaCheckBox", 27338 initialize : function () { 27339 GuideCheckBoxView._super.initialize.apply(this, arguments); 27340 this._setListenersForLabelClick(); 27341 this._setListenersForRadioButtonKeyPress(); 27342 }, 27343 27344 _setListenersForLabelClick : function () { 27345 var self = this; 27346 this.$element 27347 .find(".guideWidgetLabel") 27348 .each(function (index, item) { 27349 $(item).click( 27350 (function (index) { 27351 return function () { 27352 27353 if (self._model.enabled) { 27354 self.jqwidget[self.getJQWidgetIdentifier(index)].click(); 27355 } 27356 }; 27357 }(index)) 27358 ); 27359 }); 27360 }, 27361 27362 _setListenersForRadioButtonKeyPress : function () { 27363 var self = this; 27364 this.$element 27365 .find(".guideRadioButtonItem") 27366 .each(function (index, item) { 27367 $(item).keypress(function (e){ 27368 if(e.keyCode == "13" || e.keyCode == "32"){ 27369 e.preventDefault(); 27370 if (self._model.enabled) { 27371 self.jqwidget[self.getJQWidgetIdentifier(index)].click(); 27372 } 27373 } 27374 }); 27375 }); 27376 }, 27377 _syncGuideNodeToHtml : function (deepSync) { 27378 if (this._model._isStateOverridden("options")) { 27379 this._replaceGroupItemsWithNewOptions(this._model._getOptionsArray(), this._model.getAttribute("alignment")); 27380 27381 27382 27383 27384 this.jqwidget = null; 27385 27386 } 27387 GuideCheckBoxView._super._syncGuideNodeToHtml.apply(this, arguments); 27388 }, 27389 getJQWidgetIdentifier : function (index) { 27390 return index; 27391 }, 27392 27393 createWidgetOptions : function () { 27394 var options = GuideCheckBoxView._super.createWidgetOptions.apply(this, arguments); 27395 27396 return $.extend({}, options, { 27397 states : 2 27398 }); 27399 }, 27400 27401 getCommitEvent : function () { 27402 return xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT; 27403 }, 27404 27405 getStateFromValue : function (value, items) { 27406 if (value === null) { 27407 return 1; 27408 } 27409 var valuesArray = null; 27410 if (value && value.indexOf && value.indexOf("\\,") > -1) { 27411 valuesArray = this.splitOnNonEscapedCommas(value); 27412 } else { 27413 valuesArray = (value + "").split(","); 27414 } 27415 if (valuesArray && valuesArray.indexOf(items[0] + "") !== -1) { 27416 return 0; 27417 } 27418 return 1; 27419 }, 27420 27421 getOnOffValueFromModelValue : function (val, items) {
27422 return items[this.getStateFromValue(val, items)]; 27423 }, 27424 27425 splitOnNonEscapedCommas : function (string) { 27426 var splitArray = []; 27427 var currentSubstring = ''; 27428 var escaped = false; 27429 27430 for (var i = 0; i < string.length; i++) { 27431 var char = string[i]; 27432 27433 if (char === ',' && !escaped) { 27434 splitArray.push(currentSubstring.trim()); 27435 currentSubstring = ''; 27436 } else { 27437 currentSubstring += char; 27438 escaped = (char === '\\' && !escaped); 27439 } 27440 } 27441 splitArray.push(currentSubstring.trim()); 27442 return splitArray; 27443 }, 27444 27445 handleValueChanged : function (event) { 27446 _.each(this.jqwidget, function (jqwidget) { 27447 var setVal = this.getOnOffValueFromModelValue(event.prevText, this._escapeCommas(jqwidget.option("values"))); 27448 setVal = this._unescapeCommas(setVal); 27449 jqwidget.option("value", setVal); 27450 jqwidget.option("displayValue", setVal); 27451 }, this); 27452 this.$widget.find("[checked!=checked]").parents(".guideCheckBoxItem").removeClass('guideItemSelected'); 27453 this.$widget.find("[checked=checked]").parents(".guideCheckBoxItem").addClass('guideItemSelected'); 27454 }, 27455 27456 _escapeCommas : function (items) { 27457 var temp = _.clone(items); 27458 if(temp[0] && temp[0].indexOf && temp[0].indexOf(',') > -1 && temp[0].indexOf('\\,') === -1) { 27459 temp[0] = temp[0].replace(/,/g, "\\,"); 27460 } 27461 return temp; 27462 }, 27463 27464 _unescapeCommas : function (value) { 27465 if(value && value.indexOf && value.indexOf('\\,') > -1) { 27466 value = value.replace(/\\,/g, ','); 27467 } 27468 return value; 27469 }, 27470 27471 handleCommit : function () { 27472 var temp = ""; 27473 _.each(this.jqwidget, function (jqwidget, index) { 27474 var items = this._escapeCommas(jqwidget.option("values")); 27475 if (jqwidget.option("state") === 0) { 27476 27477 temp = temp + items[0] + ","; 27478 } 27479 }, this); 27480 temp = temp.substring(0, temp.length - 1); 27481 this.commitValue(this._unescapeCommas(temp)); 27482 }, 27483 27484 handleEnabledChanged : function (event) { 27485 27486 if (!this.$element.hasClass("dontSyncEnabled")) { 27487 var prop = event.newText ? "open" : "readOnly"; 27488 _.each(this.jqwidget, function (jqwidget) { 27489 jqwidget.option("access", prop); 27490 }); 27491 } 27492 27493 this.$element.attr("data-disabled", !this._model.enabled); 27494 }, 27495 27496 handleModelChanged : function (evnt) { 27497 switch (evnt._property) { 27498 case "enabled": 27499 this.handleEnabledChanged(evnt); 27500 break; 27501 default: 27502 GuideCheckBoxView._super.handleModelChanged.apply(this, arguments); 27503 } 27504 }, 27505 27506 handleItemsChanged : function (event) { 27507 this._replaceGroupItemsWithNewOptions(this._model._getOptionsArray(), this._model.jsonModel.alignment); 27508 this.createWidget(this.getWidgetName(), this.createWidgetOptions()); 27509 }, 27510 27511 _getGroupItemIdentifier : function () { 27512 return '.guideCheckBoxGroupItems'; 27513 }, 27514 27515 _getWidgetType : function () { 27516 return 'checkbox'; 27517 }, 27518 27519 _getItemName : function () { 27520 return "CheckBoxItem"; 27521 }, 27522 27523 _getItemSkeleton : function () { 27524 var guideWidgetItemName = "guide" + this._getItemName(); 27525 var afWidgetItemName = "af" + this._getItemName(); 27526 return '<div class="' + guideWidgetItemName + ' ' + afWidgetItemName + ' {NAME_PLACEHOLDER} {CSS_PLACEHOLDER}" data-original-title="" title="">\n' + 27527 ' <div class="guideFieldWidget left XfaCheckBox" data-id="{COUNTER_PLACEHOLDER}" data-original-title="" title="">\n' + 27528 ' <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' + 27529 ' </div>\n' + 27530 ' <div class="guideWidgetLabel right">\n' + 27531 ' <label>{LABEL_PLACEHOLDER}</label>\n' + 27532 ' </div>\n' + 27533 ' </div>'; 27534 }, 27535 27536 _renderGroupItem : function (options) { 27537 var itemSkeleton = this._getItemSkeleton(), 27538 namePlaceHolder = "{NAME_PLACEHOLDER}", 27539 cssPlaceHolder = "{CSS_PLACEHOLDER}", 27540 counterPlaceHolder = "{COUNTER_PLACEHOLDER}" , 27541 templateIDPlaceHolder = "{TEMPLATE_ID_PLACEHOLDER}", 27542 labelPlaceHolder = "{LABEL_PLACEHOLDER}", 27543 guideUtil = guidelib.util.GuideUtil; 27544 itemSkeleton = guideUtil.replaceAll(itemSkeleton, namePlaceHolder, options.modelName); 27545 itemSkeleton = guideUtil.replaceAll(itemSkeleton, templateIDPlaceHolder, options.modelTemplateId); 27546 itemSkeleton = guideUtil.replaceAll(itemSkeleton, cssPlaceHolder, options.cssValue);
27547 itemSkeleton = guideUtil.replaceAll(itemSkeleton, counterPlaceHolder, options.itemIndex); 27548 itemSkeleton = guideUtil.replaceAll(itemSkeleton, labelPlaceHolder, options.displayValue); 27549 return itemSkeleton; 27550 }, 27551 27552 _replaceGroupItemsWithNewOptions : function (items, cssValue) { 27553 var groupItem = this.$element.find(this._getGroupItemIdentifier()), 27554 options = {}, 27555 widgetName = this.getWidgetName(), 27556 self = this; 27557 27558 27559 groupItem.empty(); 27560 options.widgetType = this._getWidgetType(); 27561 options.modelName = this._model.name; 27562 options.modelTemplateId = this._model.id; 27563 27564 if (this._model.css !== null && !_.isUndefined(this._model.css)) { 27565 cssValue += " " + this._model.css; 27566 } 27567 options.cssValue = cssValue; 27568 27569 _.each(items, function (value, index) { 27570 options.itemIndex = index; 27571 options.displayValue = value.displayValue; 27572 options.saveValue = value.saveValue; 27573 groupItem.append(self._renderGroupItem(options)); 27574 }); 27575 this._initializeWidget(); 27576 this._setListenersForLabelClick(); 27577 }, 27578 27579 _replaceAll : function (stringToReplaceIn, textToReplace, replacementString) { 27580 return stringToReplaceIn.split(textToReplace).join(replacementString); 27581 }, 27582 27583 _defineModelEvents : function () { 27584 GuideCheckBoxView._super._defineModelEvents.apply(this, arguments); 27585 if (this._model) { 27586 27587 this._model.on(guidelib.event.GuideModelEvent.ITEMS_CHANGED, this.handleItemsChanged, this); 27588 } 27589 }, 27590 27591 setWidgetOptions : function (options) { 27592 var index = 0; 27593 _.each(this.jqwidget, function (jqwidget, id) { 27594 this._initOrUpdateWidget(id, this._getOptions(options, index++)); 27595 }, this); 27596 }, 27597 27598 _getOptions : function (options, index) { 27599 var items = this._model.getOnOffValues(index), 27600 val = this.getOnOffValueFromModelValue(this._model.value, items), 27601 optionsCopy = _.extend(options, { 27602 value : val, 27603 displayValue : val, 27604 values : items, 27605 state : this.getStateFromValue(this._model.value, items), 27606 screenReaderText : this._model._getScreenReaderText(index) 27607 }); 27608 return optionsCopy; 27609 }, 27610 27611 _initOrUpdateWidget : function (id, options, widgetname, $widget, initialOptions) { 27612 if (this.jqwidget[id]) { 27613 this.jqwidget[id].option(options); 27614 } else { 27615 var _options = $.extend({}, options, initialOptions); 27616 this.jqwidget[id] = this._newWidget(widgetname, _options, $widget); 27617 } 27618 this.$widget.find("[checked!=checked]").parents(".guideCheckBoxItem").removeClass('guideItemSelected'); 27619 this.$widget.find("[checked=checked]").parents(".guideCheckBoxItem").addClass('guideItemSelected'); 27620 }, 27621 27622 initializeJqWidget : function () { 27623 this.jqwidget = []; 27624 }, 27625 27626 createWidget : function (widgetname, options) { 27627 var self = this; 27628 this.initializeJqWidget(); 27629 if (this.$widget) { 27630 this.$widget.each(function (index, widget) { 27631 self._initOrUpdateWidget(self.getJQWidgetIdentifier(index), 27632 self._getOptions(options, index), 27633 widgetname, 27634 $(widget), 27635 self._getWidgetInitialOptions($(widget))); 27636 }); 27637 this.tempXfaFixes(); 27638 } 27639 }, 27640 27641 setActive : function (activeItemToken, focus, muteScripts) { 27642 guidelib.view.GuideFieldView._super.setActive.call(this, activeItemToken, focus, muteScripts); 27643 if (focus && !this._guideView.skipFieldFocus) { 27644 if (this.jqwidget && this.jqwidget[this.getJQWidgetIdentifier(0)]) { 27645 this.jqwidget[this.getJQWidgetIdentifier(0)].focus(); 27646 } 27647 this._guideView.currentFocusItemSom = this._model.somExpression; 27648 } 27649 return true; 27650 }, 27651 27652 updateWidgetOption : function (optionName, optionValue) { 27653 _.each(this.jqwidget, function (jqwidget, index) { 27654 if (optionName == "isValid") { 27655 jqwidget.option(optionName, optionValue); 27656 } 27657 }, this); 27658 }, 27659 27660 handleAccessibility : function () { 27661 GuideCheckBoxView._super.handleAccessibility.apply(this, arguments); 27662 this.$element.attr("role", "group"); 27663 if (this._model.jsonModel.assistPriority && this._model.jsonModel.custom && this._model.jsonModel.assistPriority === "custom"){ 27664 this.$element.attr("aria-label", this._model.jsonModel.custom[0]); 27665 } else { 27666 var $label = this.$element.find(".guideFieldLabel label"), 27667 label = $label.get(0); 27668 if (label && label.id) { 27669 this.$element.attr("aria-labelledby", label.id); 27670 } 27671 } 27672 } 27673 27674 }); 27675}($, guidelib, window._)); 27676 27677(function ($, guidelib, _) { 27678 var GuideRadioButtonView = guidelib.view.GuideRadioButtonView = guidelib.view.GuideCheckBoxView.extend({ 27679
27680 _defaultWidgetName : "XfaCheckBox", 27681 27682 _prevOnWidget : null, 27683 27684 _getWidgetType : function () { 27685 return 'radio'; 27686 }, 27687 27688 _getItemName : function () { 27689 return "RadioButtonItem"; 27690 }, 27691 27692 _getGroupItemIdentifier : function () { 27693 return '.guideRadioButtonGroupItems'; 27694 }, 27695 27696 getJQWidgetIdentifier : function (index) { 27697 return this._model.getItemIdentifier(index); 27698 }, 27699 27700 handleValueChanged : function (event) { 27701 var somExpression = event.prevText; 27702 if (this.jqwidget[somExpression]) { 27703 this.jqwidget[somExpression].option("value", event.newText); 27704 this.jqwidget[somExpression].option("displayValue", event.newText); 27705 if (event.newText === null) { 27706 this._prevOnWidget = null; 27707 } else { 27708 this._prevOnWidget = this.jqwidget[somExpression]; 27709 } 27710 } 27711 this.$widget.find("[checked!=checked]").parents(".guideRadioButtonItem").removeClass('guideItemSelected').attr("aria-checked", false); 27712 this.$widget.find("[checked=checked]").parents(".guideRadioButtonItem").addClass('guideItemSelected').attr("aria-checked", true); 27713 this._updateEmptyStatus(); 27714 }, 27715 27716 handleCommit : function () { 27717 var jqwidgettochange = _.find(this.jqwidget, function (jqwidget) { 27718 return jqwidget.option("state") === 0 && jqwidget !== this._prevOnWidget; 27719 }, this); 27720 this.commitValue(jqwidgettochange.option("value")); 27721 this._prevOnWidget = jqwidgettochange; 27722 }, 27723 27724 _initOrUpdateWidget : function (id, options, widgetname, widget) { 27725 GuideRadioButtonView._super._initOrUpdateWidget.apply(this, arguments); 27726 if (options.state === 0) { 27727 this._prevOnWidget = this.jqwidget[id]; 27728 } 27729 this.$widget.find("[checked!=checked]").parents(".guideRadioButtonItem").removeClass('guideItemSelected'); 27730 this.$widget.find("[checked=checked]").parents(".guideRadioButtonItem").addClass('guideItemSelected'); 27731 }, 27732 27733 initializeJqWidget : function () { 27734 this.jqwidget = {}; 27735 27736 27737 27738 this.$widget.find("[checked]").removeAttr("checked"); 27739 this.$widget.find("[checked=checked]").removeAttr("checked"); 27740 27741 }, 27742 27743 handleAccessibility : function () { 27744 GuideRadioButtonView._super.handleAccessibility.apply(this, arguments); 27745 this.$element.attr("role", "radiogroup"); 27746 } 27747 }); 27748}($, guidelib, _)); 27749(function ($, guidelib, _) { 27750 var GuideSwitchView = guidelib.view.GuideSwitchView = guidelib.view.GuideCheckBoxView.extend({ 27751 _defaultWidgetName : "guideSwitch", 27752 27753 createWidgetOptions : function () { 27754 var options = GuideSwitchView._super.createWidgetOptions.apply(this, arguments), 27755 items = this._model.jsonModel.options, checkedLabel, uncheckedLabel; 27756 27757 if (Array.isArray(items) && items.length > 0) { 27758 checkedLabel = items[0]; 27759 } else if (!_.isUndefined(items) && items.length > 0) { 27760 checkedLabel = items; 27761 } else { 27762 checkedLabel = " "; 27763 } 27764 if (Array.isArray(items) && items.length > 1) { 27765 uncheckedLabel = items[1]; 27766 } else { 27767 uncheckedLabel = " "; 27768 } 27769 return $.extend({}, options, { 27770 checkedLabel : checkedLabel.substring(checkedLabel.indexOf("=") + 1), 27771 uncheckedLabel : uncheckedLabel.substring(uncheckedLabel.indexOf("=") + 1) 27772 }); 27773 }, 27774 27775 handleValueChanged : function (event) { 27776 27777 var jqwidget = this.jqwidget[0], 27778 jqwidgetOptions = jqwidget.options; 27779 var setVal = this.getOnOffValueFromModelValue(event.prevText, jqwidget.option("values")); 27780 if (jqwidgetOptions.value !== setVal) { 27781 jqwidget.option("value", setVal); 27782 27783 var userControl = jqwidget.$userControl; 27784 var checked = jqwidgetOptions.value === jqwidgetOptions.values[0]; 27785 userControl.prop("checked", checked); 27786 userControl.parent().toggleClass('ui-state-active', checked); 27787 userControl.change(); 27788 } 27789 }, 27790 27791 handleCommit : function () { 27792 var jqwidget = this.jqwidget[0], 27793 items = jqwidget.option("values"), 27794 state = jqwidget.option("state"); 27795 this.commitValue(items[state]); 27796 } 27797 }); 27798}($, guidelib, _)); 27799 27800(function ($, guidelib) { 27801 var GuideNumericBoxView = guidelib.view.GuideNumericBoxView = guidelib.view.GuideFieldView.extend({
27802 _defaultWidgetName : "numericInput", 27803 createWidgetOptions : function () { 27804 var options = GuideNumericBoxView._super.createWidgetOptions.apply(this, arguments); 27805 return $.extend({}, options, { 27806 dataType : this._model.dataType, 27807 leadDigits : this._model.leadDigits, 27808 fracDigits : this._model.fracDigits, 27809 27810 zero : guidelib.i18n.numberSymbols.zero, 27811 decimal : guidelib.i18n.numberSymbols.decimal, 27812 commitEvent : this.getCommitEvent(), 27813 placeholder : this._model.placeholderText 27814 }); 27815 } 27816 }); 27817 27818}($, guidelib)); 27819(function ($, guidelib) { 27820 var GuidePasswordBoxView = guidelib.view.GuidePasswordBoxView = guidelib.view.GuideFieldView.extend({ 27821 _defaultWidgetName : "defaultWidget", 27822 27823 createWidgetOptions : function () { 27824 var options = GuidePasswordBoxView._super.createWidgetOptions.apply(this, arguments); 27825 27826 return $.extend({}, options, { 27827 placeholder : this._model.placeholderText 27828 }); 27829 } 27830 }); 27831}($, guidelib)); 27832(function ($, guidelib) { 27833 var GuideDatePickerView = guidelib.view.GuideDatePickerView = guidelib.view.GuideFieldView.extend({ 27834 _defaultWidgetName : "dateTimeEdit", 27835 27836 createWidgetOptions : function () { 27837 var options = GuideDatePickerView._super.createWidgetOptions.apply(this, arguments), 27838 useNativeWidget = (this._model.displayPictureClause === null && this._model.editPictureClause == null); 27839 27840 return $.extend({}, options, { 27841 days : guidelib.i18n.calendarSymbols.abbrdayNames, 27842 months : guidelib.i18n.calendarSymbols.monthNames, 27843 zero : guidelib.i18n.numberSymbols.zero, 27844 clearText : xfalib.locale.Strings.clearText, 27845 useNativeWidget : useNativeWidget, 27846 showCalendarIcon : true, 27847 editPattern : this._model.editPictureClause, 27848 placeholder : this._model.placeholderText, 27849 minValidDate : this._model.minimum, 27850 maxValidDate : this._model.maximum, 27851 exclMaxDate : this._model.exclusiveMaximum, 27852 exclMinDate : this._model.exclusiveMinimum, 27853 allowNonIsoValue : true 27854 }); 27855 }, 27856 27857 27858 tempXfaFixes : function () { 27859 GuideDatePickerView._super.tempXfaFixes.apply(this, arguments); 27860 27861 if (this.$widget) { 27862 this.$widget.children("not:input[type=date]").height("100%"); 27863 } 27864 }, 27865 27866 handleAccessibility : function () { 27867 GuideDatePickerView._super.handleAccessibility.apply(this, arguments); 27868 this.$widget.children("div[tabIndex]").removeAttr("tabIndex"); 27869 if (this.$widget) { 27870 var $icon = this.$widget.find('.datepicker-calendar-icon'); 27871 if ($icon && $icon.length) { 27872 var localizedLabel = (guidelib && guidelib.i18n && guidelib.i18n.strings && guidelib.i18n.strings.showDatePicker) 27873 ? guidelib.i18n.strings.showDatePicker 27874 : 'Show date picker'; 27875 $icon.attr('role', 'button') 27876 .attr('tabindex', '0') 27877 .attr('aria-haspopup', 'dialog') 27878 .attr('aria-label', localizedLabel) 27879 .attr('title', localizedLabel); 27880 } 27881 } 27882 } 27883 }); 27884}($, guidelib)); 27885 27886 (function ($, guidelib) { 27887 var GuideFootnotePlaceHolderView = guidelib.view.GuideFootnotePlaceHolderView = guidelib.view.GuideTextDrawView.extend({ 27888 _defaultWidgetName : "abstractWidget", 27889 27890 initialize : function () { 27891 GuideFootnotePlaceHolderView._super.initialize.call(this); 27892 var that = this; 27893 $(function () { 27894 that._renderFootnotes(); 27895 }) 27896 guideBridge.on("elementNavigationChanged", function(event, payload) { 27897 that._renderFootnotes(); 27898 }) 27899 $(window.document).on('click.guidetab.data-api', '[data-guide-toggle$="accordion-tab"]', 27900 function(e) { 27901 that._renderFootnotes(); 27902 }) 27903 27904 }, 27905 27906 _renderFootnotes: function () { 27907 27908 27909 if(!this.$element.is(":visible")) { 27910 this._model.value = ""; 27911 return; 27912 } 27913 27914 var footnoteMap = this._model.footnoteMap; 27915 var footnoteArr = Object.entries(footnoteMap); 27916 if (footnoteArr.length > 0) { 27917 var value = '<div>'; 27918 var nodes = new Map(); 27919 for (footnoteID in footnoteMap) { 27920 var selector = "a[data-footnote-id=\"" + footnoteID + "\"]"; 27921 var mapKey = $(selector)[0].innerHTML; 27922 if (!nodes.has(mapKey)) { 27923 nodes.set(mapKey, footnoteMap[footnoteID]); 27924 } 27925 }; 27926 var tupleArray = [];
27927 nodes.forEach(function(value, key) { 27928 tupleArray.push([key, value]); 27929 }); 27930 tupleArray.sort(function(a, b) { 27931 return a[0] - b[0]; 27932 }); 27933 tupleArray.forEach(function(el) { 27934 value += el[1]; 27935 }); 27936 value += '</div>'; 27937 this._model.value = value; 27938 } 27939 }, 27940 27941 setActive: function () { 27942 this._renderFootnotes(); 27943 } 27944 }); 27945}($, guidelib)); 27946 27947 27948 27949 27950(function ($, guidelib) { 27951 var GuideScribbleView = guidelib.view.GuideScribbleView = guidelib.view.GuideFieldView.extend({ 27952 _defaultWidgetName : "ScribbleImageField", 27953 27954 createWidgetOptions : function () { 27955 var options = GuideScribbleView._super.createWidgetOptions.apply(this, arguments); 27956 return $.extend({}, options, { 27957 commitProperty : "src", 27958 geoLocMandatoryOnIpad : "false", 27959 aspectRatio : this._valueOfAspectRatioToBeUsed() 27960 }); 27961 }, 27962 27963 _valueOfAspectRatioToBeUsed : function () { 27964 var aspectRatio ; 27965 if (this._model.jsonModel.aspectRatio) { 27966 aspectRatio = this._model.jsonModel.aspectRatio; 27967 } else { 27968 27969 if (!this._presenceOfHeight()) { 27970 aspectRatio = "6.8888"; 27971 } 27972 } 27973 return aspectRatio ; 27974 }, 27975 27976 _presenceOfHeight : function () { 27977 return (this._model.jsonModel.hasOwnProperty('height') && this._model.jsonModel.height.toString().length > 0); 27978 }, 27979 27980 postInitialize : function () { 27981 GuideScribbleView._super.postInitialize.call(this); 27982 var that = this; 27983 27984 if (!this._presenceOfHeight()) { 27985 setTimeout(function () {guidelib.util.GuideUtil._computeHeightAndWidthForScribble(that.$widget);}, guidelib.util.GuideUtil.SCRIBBLE_RESIZE_TIME_INTERVAL); 27986 $(window).off("resize", guidelib.util.GuideUtil._resizeScribbleField); 27987 $(window).on("resize", guidelib.util.GuideUtil._resizeScribbleField); 27988 } 27989 }, 27990 27991 handleAccessibility : function () { 27992 27993 if (this._model.mandatory) { 27994 this.$widget.find("img").attr("aria-required", true); 27995 } 27996 if (this._model._getScreenReaderText() === this._model._getToolTip()) { 27997 this.$element.find("img").removeAttr("aria-label"); 27998 this.$element.find("img").attr("aria-labelledby", this._model.id + "_guideFieldShortDescription"); 27999 } else if (this._model._getAssistPriority() === "none") { 28000 this.$element.find("img").attr("aria-label", " "); 28001 } 28002 }, 28003 28004 28005 tempXfaFixes : function () { 28006 if (this.$widget) { 28007 this.$widget.css("position", "relative").find("img").css("position", "relative"); 28008 } 28009 this.handleAccessibility(); 28010 } 28011 }); 28012}($, guidelib)); 28013(function ($, guidelib) { 28014 var GuideTextBoxView = guidelib.view.GuideTextBoxView = guidelib.view.GuideFieldView.extend({ 28015 _defaultWidgetName : "textField", 28016 28017 initialize : function () { 28018 GuideTextBoxView._super.initialize.apply(this, arguments); 28019 if (this._model.allowRichText) { 28020 this._defaultWidgetName = "richTextField"; 28021 } 28022 }, 28023 28024 createWidgetOptions : function () { 28025 var options = GuideTextBoxView._super.createWidgetOptions.apply(this, arguments), 28026 html5Type = this._model.getAttribute("html5Type"); 28027 return $.extend({}, options, { 28028 multiLine : this._model.multiLine, 28029 minLength : this._model.allowRichText ? null : this._model.minLength, 28030 length : this._model.allowRichText ? null : this._model.length, 28031 maxChars : this._model.allowRichText ? null : this._model.maxChars, 28032 required : this._model.mandatory, 28033 28034 html5Type : html5Type ? html5Type : "", 28035 totalLengthMessage : this.guideUtil.getLocalizedMessage("", guidelib.i18n.strings.totalLengthMessage, [this._model.length]), 28036 minimumLengthMessage : this.guideUtil.getLocalizedMessage("", guidelib.i18n.strings.minimumLengthMessage, [this._model.minLength]), 28037 allowRichText : this._model.allowRichText, 28038 placeholder : this._model.placeholderText 28039 }); 28040 }, 28041 28042 28043 28044 28045 tempXfaFixes : function () { 28046 if (this._model.jsonModel.multiLine) { 28047 this.$element.find("textarea").css("position", "relative"); 28048 this.handleAccessibility(); 28049 } else { 28050 GuideTextBoxView._super.tempXfaFixes.apply(this); 28051 } 28052 }, 28053 28054 handleAccessibility : function () { 28055 GuideTextBoxView._super.handleAccessibility.apply(this); 28056 if (this._model.jsonModel.multiLine) { 28057 this.$element.find("textarea").attr("aria-multiLine", true); 28058 } 28059 } 28060 }); 28061}($, guidelib)); 28062(function ($, guidelib) { 28063 var xfaUtil = xfalib.ut.XfaUtil.prototype, 28064 GuideImageView = guidelib.view.GuideImageView = guidelib.view.GuideBaseView.extend({ 28065 initialize : function () { 28066 GuideImageView._super.initialize.call(this); 28067 if (this._model.value != null) { 28068 var srcString = "data:image/*;base64," + this._model.value; 28069 this.$element.children('img').attr('src', srcString); 28070 } 28071 }, 28072 28073 postInitialize : function () { 28074 this._syncGuideNodeToHtml(); 28075 }, 28076
28077 setActive : function (activeItemToken, focus, muteScripts) { 28078 guidelib.view.GuideFieldView._super.setActive.call(this, activeItemToken, focus, muteScripts); 28079 if (focus && !this._guideView.skipFieldFocus) { 28080 if (this.$element) { 28081 this.$element.focus(); 28082 } 28083 this._guideView.currentFocusItemSom = this._model.somExpression; 28084 } 28085 return true; 28086 } 28087 28088 }); 28089}($, guidelib)); 28090 28091(function ($, guidelib) { 28092 var GuideChartView = guidelib.view.GuideChartView = guidelib.view.GuideBaseView.extend({ 28093 28094 initialize : function () { 28095 GuideChartView._super.initialize.call(this); 28096 var chartView = this; 28097 $(window).on("resize orientationchange", function () { 28098 chartView.renderChart.apply(chartView); 28099 }); 28100 }, 28101 28102 postInitialize : function () { 28103 this._syncGuideNodeToHtml(true); 28104 }, 28105 28106 handleModelChanged : function (event) { 28107 switch (event._property) { 28108 case "data": 28109 case "chartType": 28110 this.renderChart(); 28111 break; 28112 28113 case "visible": 28114 this.handleVisibleChanged(event); 28115 break; 28116 } 28117 }, 28118 28119 handleVisibleChanged : function (event) { 28120 28121 28122 if (!event.newText) { 28123 28124 this.$element.addClass("hidden"); 28125 if (this.parentView.currentActiveItemView == this) { 28126 this.parentView.setActive("nextItem"); 28127 } 28128 } else { 28129 28130 this.$element.removeClass("hidden"); 28131 } 28132 }, 28133 28134 _generateChart : function () { 28135 var $chartElement = this.$element, chartModel = this._model, isChartVisible, chart; 28136 28137 var plottedChartSelector = chartModel.jsonModel.isInteractiveCommunicationChartResource ? '.highcharts-container' 28138 : '.dv-chart-container'; 28139 var $plottedChart = $chartElement 28140 .find(plottedChartSelector); 28141 isChartVisible = ($chartElement.parent().width() > 0) 28142 && ($chartElement.width() > 0) ? true : false; 28143 28144 28145 28146 28147 if ((isChartVisible || $plottedChart.length == 0) 28148 && chartModel.repeatableItem) { 28149 try { 28150 28151 $plottedChart.remove(); 28152 if (chartModel.jsonModel.isInteractiveCommunicationChartResource) { 28153 chart = new fd.chart.ChartInstanceGenerator() 28154 .generate(chartModel.jsonModel, 28155 chartModel.jsonModel.data); 28156 Highcharts.chart($chartElement.attr('id'), 28157 chart); 28158 } else { 28159 chart = guidelib.chartUtils.constructChart( 28160 chartModel, $chartElement); 28161 if (chart) { 28162 chart.render(); 28163 } 28164 } 28165 } catch (exception) { 28166 this.logger().error("AF Chart view", 28167 "Error while rendering chart " + exception); 28168 } 28169 } 28170 }, 28171 28172 renderChart : function () { 28173 if (this._model.data) { 28174 var chartView = this; 28175 window.requestAnimationFrame(function () { 28176 chartView._generateChart.apply(chartView); 28177 }); 28178 } 28179 }, 28180 28181 _syncGuideNodeToHtml : function (deepSync) { 28182 this.renderChart(); 28183 guidelib.view.GuideChartView._super._syncGuideNodeToHtml.call(this, deepSync); 28184 }, 28185 28186 setActive : function (activeItemToken, focus, muteScripts) { 28187 guidelib.view.GuideChartView._super.setActive.call(this, activeItemToken, focus, muteScripts); 28188 if (focus && !this._guideView.skipFieldFocus) { 28189 if (this.$element) { 28190 this.$element.focus(); 28191 } 28192 this._guideView.currentFocusItemSom = this._model.somExpression; 28193 } 28194 return true; 28195 } 28196 }); 28197}($, guidelib)); 28198(function ($, guidelib) { 28199 var GuideAdModuleView = guidelib.view.GuideAdModuleView = guidelib.view.GuideBaseView.extend({ 28200 28201 initialize : function () { 28202 GuideAdModuleView._super.initialize.call(this); 28203 if (this._model) { 28204 28205 this._model.on(guidelib.event.GuideModelEvent.VALUE_CHANGED, this.handleValueChanged, this); 28206 } 28207 this.oldValue = null; 28208 }, 28209 28210 postInitialize : function () { 28211 this._syncGuideNodeToHtml(true); 28212 }, 28213 28214 handleValueChanged : function (event) { 28215 switch (event._property) { 28216 case "value": 28217 this.$element.html(event.newText); 28218 break; 28219 } 28220 }, 28221 28222 handleVisibleChanged : function (event) { 28223 28224 28225 if (!event.newText) { 28226 28227 this.$element.addClass("hidden"); 28228 if (this.parentView.currentActiveItemView == this) {
28229 this.parentView.setActive("nextItem"); 28230 } 28231 } else { 28232 28233 this.$element.removeClass("hidden"); 28234 } 28235 }, 28236 28237 handleModelChanged : function (event) { 28238 GuideAdModuleView._super.handleModelChanged.apply(this, arguments); 28239 }, 28240 _syncGuideNodeToHtml : function (deepSync) { 28241 if (this._model.value) { 28242 this.$element 28243 .html(this._model.value) 28244 .find('img') 28245 .attr('src', function (idx, val) { 28246 return Granite.HTTP.externalize(val); 28247 }); 28248 } 28249 28250 if (this._model.layoutConfigs) { 28251 var options = { 28252 $element : this.$element, 28253 layoutConfigs : this._model.layoutConfigs 28254 }; 28255 guidelib.util.AdUtil.applyLayouts(options); 28256 } 28257 if (this._model) { 28258 this.handleModelChanged(guidelib.event.GuideModelEvent.createEvent( 28259 guidelib.event.GuideModelEvent.MODEL_CHANGED, 28260 this, 28261 "visible", 28262 this._model.visible, 28263 this._model.visible 28264 )); 28265 } 28266 }, 28267 28268 setActive : function (activeItemToken, focus, muteScripts) { 28269 guidelib.view.GuideFieldView._super.setActive.call(this, activeItemToken, focus, muteScripts); 28270 if (focus) { 28271 if (this.$element) { 28272 this.$element.focus(); 28273 } 28274 this._guideView.currentFocusItemSom = this._model.somExpression; 28275 } 28276 return true; 28277 } 28278 }); 28279}($, guidelib)); 28280(function ($, _, guidelib) { 28281 var GuideItemsView = guidelib.view.GuideItemsView = guidelib.view.GuideBaseView.extend({ 28282 initialize : function () { 28283 GuideItemsView._super.initialize.call(this); 28284 this.childViews = []; 28285 }, 28286 28287 28288 _unloadView : function () { 28289 if (this._model._selfOrAncestorIsLazyReference) { 28290 var fragmentPlaceHolderSelector = "#" + this.id, 28291 ind; 28292 28293 $(fragmentPlaceHolderSelector).children().remove(); 28294 28295 var queueForLazyItems = this._guideView._queueViewForLazyItems; 28296 28297 if ((ind = _.indexOf(queueForLazyItems, this)) !== -1) { 28298 queueForLazyItems[ind] = undefined; 28299 } 28300 _.each(this.childViews, function (view) { 28301 28302 view._unloadView(); 28303 }, this); 28304 28305 this.childViews = []; 28306 28307 this._currentActiveItemView = null; 28308 28309 this._guideView._domTemplateCacheStore.removeDomElement("#" + this._model.templateId); 28310 28311 this._guideView._reInitializeGuideContainerDom(); 28312 } 28313 }, 28314 postInitialize : function () { 28315 this.childViews = _.reduce(this._model.children, function (childViews, childModel) { 28316 var childView = this._createNonRepeatChildView(childModel); 28317 if (childView) { 28318 childViews.push(childView); 28319 } 28320 return childViews; 28321 }, [], this); 28322 28323 this._syncGuideNodeToHtml(false); 28324 }, 28325 28326 _createNonRepeatChildView : function (childModel) { 28327 28328 28329 28330 28331 var childElSelector = this.guideUtil.modelElSelector(childModel.id); 28332 var $childEl = this.$element.find(childElSelector); 28333 if (!$childEl.length) { 28334 $childEl = this.$element.find(this.guideUtil.modelElSelector(childModel.templateId)); 28335 this._updateIds($childEl, childModel.templateId, childModel.id); 28336 } 28337 if ($childEl.length) { 28338 var childView = guidelib.view.GuideViewRegistry.prototype.createView($childEl, this); 28339 childView.postInitialize(); 28340 return childView; 28341 } 28342 return null; 28343 }, 28344 28345 _syncGuideNodeToHtml : function (deepSync) { 28346 if (deepSync) { 28347 _.each(this.childViews, function (childView) { 28348 childView._syncGuideNodeToHtml(true); 28349 }, this); 28350 } 28351 GuideItemsView._super._syncGuideNodeToHtml.call(this, deepSync); 28352 }, 28353 28354 _findChildView : function (childModel) { 28355 var view = _.find(this.childViews, function (childView) { 28356 return childView._model == childModel; 28357 }, this); 28358 return view; 28359 } 28360 }); 28361 28362 GuideItemsView.defineProps({ 28363 itemsView : { 28364 get : function () { 28365 var views = _.filter(this.childViews, function (childView) { 28366 return childView.isItem; 28367 }, this); 28368 return views; 28369 } 28370 } 28371 }); 28372}($, _, guidelib)); 28373 28374(function ($, guidelib) { 28375 var GuideAdModuleGroupView = guidelib.view.GuideAdModuleGroupView = guidelib.view.GuideItemsView.extend({ 28376 initialize : function () { 28377 GuideAdModuleGroupView._super.initialize.call(this); 28378 if (this._model) { 28379 28380 this._model.on(guidelib.event.GuideModelEvent.VALUE_CHANGED, this.handleValueChanged, this); 28381 } 28382 }, 28383 28384 postInitialize : function () { 28385 if (this._model.value || this._model.value === "") { 28386 this._syncGuideNodeToHtml(true); 28387 } else { 28388 GuideAdModuleGroupView._super.postInitialize.call(this); 28389 } 28390 }, 28391 28392 handleValueChanged : function (event) { 28393 switch (event._property) { 28394 case "value": 28395 this.$element.html(event.newText); 28396 break; 28397 } 28398 }, 28399 28400 _syncGuideNodeToHtml : function (deepSync) { 28401 if (this._model.value || this._model.value === "") { 28402 this.$element 28403 .html(this._model.value) 28404 .find('img') 28405 .attr('src', function (idx, val) { 28406 return Granite.HTTP.externalize(val); 28407 }); 28408 } else { 28409 GuideAdModuleGroupView._super._syncGuideNodeToHtml.call(this, deepSync); 28410 } 28411 }, 28412
28413 setActive : function (activeItemToken, focus, muteScripts) { 28414 guidelib.view.GuideAdModuleGroupView._super.setActive.call(this, activeItemToken, focus, muteScripts); 28415 if (focus) { 28416 if (this.$element) { 28417 this.$element.focus(); 28418 } 28419 this._guideView.currentFocusItemSom = this._model.somExpression; 28420 } 28421 return true; 28422 } 28423 28424 }); 28425}($, guidelib)); 28426(function ($, _, guidelib) { 28427 28428 var GuidePanelView = guidelib.view.GuidePanelView = guidelib.view.GuideItemsView.extend({ 28429 initialize : function () { 28430 GuidePanelView._super.initialize.call(this); 28431 this._currentActiveItemView = null; 28432 this._$itemsContainer = null; 28433 this._$itemsNavContainer = null; 28434 this._$summary = null; 28435 this._$title = null; 28436 28437 this._childInitializeWaiting = true; 28438 28439 this._model.on(guidelib.event.GuideModelEvent.CHILD_CHANGED, this.handleChildChanged, this); 28440 this._model.on(guidelib.event.GuideModelEvent.MULTIPLE_CHILD_ADDED, this.multipleChildAdded, this); 28441 this._summarySelector = this.guideUtil.summarySelector(this._model.id); 28442 this._titleSelector = this.guideUtil.propSelector("title", this._model.id); 28443 }, 28444 28445 addRemoveTemplateMarker : function () { 28446 var featureToggle = FD.isToggleEnabled(guidelib.util.FeatureToggleConstants.FT_VALID_NAV_UL_CHILDREN) ? true : false; 28447 28448 _.each(this._model.children, function (childModel) { 28449 if (childModel instanceof guidelib.model.GuideInstanceManager) { 28450 28451 var imId = childModel.id, 28452 instanceId = (childModel._instances[0] || {}).id || childModel.instanceTemplateId, 28453 gTemplateMarkerPanel = '<div id="' + imId + 'panel" style="display: none" data-guide-template-marker="true"></div>', 28454 gTemplateMarkerNav = '<'+ (featureToggle ? 'li' : 'div') +' id="' + imId + 'nav" style="display: none" data-guide-template-marker="true"></' + (featureToggle ? 'li' : 'div') + '>', 28455 instanceItem = this.guideUtil.itemSelector(instanceId, childModel), 28456 navItem = this.guideUtil.itemNavSelector(instanceId); 28457 this.$itemsContainer.find(instanceItem).before(gTemplateMarkerPanel); 28458 this.$itemsNavContainer.find(navItem).before(gTemplateMarkerNav); 28459 if (childModel._instances && childModel._instances.length === 0) { 28460 $(navItem, this.$element).remove(); 28461 $(instanceItem, this.$element).remove(); 28462 } 28463 } 28464 }, this); 28465 28466 }, 28467 28468 postInitialize : function () { 28469 28470 28471 28472 28473 this.handleSummaryChanged(); 28474 this.handleTitleChanged(); 28475 if (this._model.repeatable) { 28476 this._toggleAddRemoveButtons(); 28477 } 28478 if (!this.parentView._model.enableLayoutOptimization) { 28479 28480 this._postInitializeChildren(); 28481 } else { 28482 28483 28484 28485 28486 28487 28488 this.handleVisibleChanged(guidelib.event.GuideModelEvent.createEvent( 28489 guidelib.event.GuideModelEvent.MODEL_CHANGED, 28490 this, 28491 "visible", 28492 this._model.visible, 28493 this._model.visible 28494 ), {skipLazyAutoLoad: true}); 28495 } 28496 28497 28498 28499 28500 28501 this.addRemoveTemplateMarker(); 28502 }, 28503 28504 handleVisibleChanged : function (event, options) { 28505 GuidePanelView._super.handleVisibleChanged.apply(this, arguments); 28506 28507 28508 28509 28510 28511 28512 28513 options = options || {}; 28514 if (event.newText === true && 28515 this._model._lazyReference && 28516 !this._model._itemsLoaded && 28517 this._model.getAttribute('autoLoad') === false && 28518 options.skipLazyAutoLoad !== true && 28519 this._model._guide().getGuideState() === guidelib.model.GuideSchema.prototype.GuideStateConstants.GUIDE_STATE_MODEL_COMPLETE) { 28520 28521 28522 this._loadLazyFragment({ preserveLazy: true }); 28523 } 28524 }, 28525 28526 _postInitializeChildren : function () { 28527 this._childInitializeWaiting = false;
28528 this._syncGuideNodeToHtml(true); 28529 this.handleAccessibility(); 28530 28531 28532 28533 if (this.parentView.$itemsNavContainer && this.parentView.$itemsNavContainer.filter(":not(.tab-navigators-mobile)").length === 0) { 28534 this.setActive("firstItem", false, true); 28535 } 28536 }, 28537 28538 _syncGuideNodeToHtml : function (deepSync, currentAddedChildIndex) { 28539 if (this._childInitializeWaiting) { 28540 return; 28541 } 28542 28543 28544 28545 28546 28547 28548 28549 28550 var that = this; 28551 var htmlTemplateCache = this._guideView._domTemplateCacheStore; 28552 var oldItems = {}; 28553 var oldNonItems = {}; 28554 var newChildren = {}; 28555 28556 28557 _.each(this.childViews, function (childView) { 28558 if (childView.isItem) { 28559 oldItems[childView.id] = childView; 28560 } else { 28561 oldNonItems[childView.id] = childView; 28562 } 28563 }, this); 28564 28565 28566 28567 28568 28569 28570 28571 28572 _.each(this._model.items, function (childModel) { 28573 var cTemplateId = childModel.templateId; 28574 var childId = childModel.id, 28575 $childItem = null, 28576 $childItemNav = null; 28577 28578 28579 $childItem = this._find(this.guideUtil.itemSelector(childId, childModel)); 28580 $childItemNav = this._find(this.guideUtil.itemNavSelector(childId)); 28581 28582 28583 28584 if (!$childItem.length && !newChildren[cTemplateId] && currentAddedChildIndex !== 0) { 28585 28586 28587 $childItem = this.$itemsContainer.find(this.guideUtil.itemSelector(cTemplateId, childModel)); 28588 $childItemNav = this.$itemsNavContainer.find(this.guideUtil.itemNavSelector(cTemplateId)); 28589 } 28590 if (!$childItem.length) { 28591 28592 $childItem = htmlTemplateCache.cloneDomElement(this.guideUtil.itemSelector(cTemplateId, childModel)); 28593 $childItemNav = htmlTemplateCache.cloneDomElement(this.guideUtil.itemNavSelector(cTemplateId)); 28594 if (!$childItem.length) { 28595 this.logger().error("AF", "Html template could not be found. cTemplateId:" + cTemplateId + ", som:" + childModel.somExpression); 28596 return; 28597 } 28598 } 28599 this._updateIds($childItem, cTemplateId, childId); 28600 this._updateIds($childItemNav, cTemplateId, childId); 28601 28602 28603 $childItem.attr("data-guide-parent-id", this._model.id); 28604 $childItemNav.attr("data-guide-parent-id", this._model.id); 28605 var view = null; 28606 if (oldItems.hasOwnProperty(childId)) { 28607 view = oldItems[childId]; 28608 if (view instanceof guidelib.view.GuidePanelView && view._model.instanceManager.repeatable && !_.isUndefined(that._model.bindNode)) { 28609 28610 this._fixChildDom(view); 28611 } 28612 if (deepSync) { 28613 view._syncGuideNodeToHtml(deepSync); 28614 } 28615 } else { 28616 var $childEl = this._find("#" + childId); 28617 if ($childEl.length) { 28618 view = this._createChild($childEl); 28619 } else { 28620 $childEl = $childItem.find("#" + childId).addBack("#" + childId); 28621 if ($childEl.length) { 28622 view = this._createChild($childEl, $childItem, $childItemNav); 28623 } else { 28624 this.logger().debug("AF", "Skip creating view. could not find el for id:" + childId
28624); 28625 } 28626 } 28627 if (this._model.repeatable) { 28628 guidelib.util.GuideUtil._initializeShortDescription($childEl); 28629 } 28630 } 28631 if (view) { 28632 newChildren[childId] = view; 28633 } 28634 }, this 28635 ); 28636 28637 28638 this.$itemsContainer.find('[data-guide-parent-id="' + that._model.id + '"]').each(function () { 28639 var $this = $(this); 28640 var thisId = $this.attr("id"); 28641 28642 if (thisId.indexOf(that.guideUtil.GUIDE_ITEM_SUFFIX) === -1) { 28643 thisId = $this.attr(that.guideUtil.DATA_GUIDE_ITEM); 28644 } 28645 var childId = thisId.substring(0, thisId.length - that.guideUtil.GUIDE_ITEM_SUFFIX.length); 28646 if (!newChildren.hasOwnProperty(childId) && !window.guideBridge._resolveId(childId)) { 28647 that.logger().log("guideView", 5, "removing element as no corresponding form dom node found. id:" + thisId + ", parent id:" + that.id); 28648 $this.remove(); 28649 that._find(that.guideUtil.itemNavSelector(childId)).remove(); 28650 } 28651 }); 28652 28653 this.childViews = []; 28654 _.each(this._model.children, function (childModel) { 28655 var childIsItem = childModel._isItem; 28656 var childId = childModel.id; 28657 if (childIsItem && newChildren.hasOwnProperty(childId)) { 28658 28659 this.childViews.push(newChildren[childId]); 28660 } else if (!childIsItem) { 28661 var nonItemChildView = null; 28662 if (oldNonItems.hasOwnProperty(childId)) { 28663 nonItemChildView = oldNonItems[childId]; 28664 } else { 28665 nonItemChildView = this._createNonRepeatChildView(childModel); 28666 } 28667 if (nonItemChildView) { 28668 if (deepSync) { 28669 nonItemChildView._syncGuideNodeToHtml(deepSync); 28670 } 28671 this.childViews.push(nonItemChildView); 28672 } 28673 } 28674 }, this); 28675 28676 guidelib.view.GuideBaseView.prototype._syncGuideNodeToHtml.apply(this, arguments); 28677 }, 28678 28679 _createChild : function ($childEl, $item, $itemNav) { 28680 var guideViewBind = $childEl.data("guideViewBind"); 28681 var model = window.guideBridge._resolveId(guideViewBind); 28682 if (model && model.getAttribute('skipViewCreation') !== 'true') { 28683 var view = guidelib.view.GuideViewRegistry.prototype.createView($childEl, this); 28684 this._fixChildDom(view, $item, $itemNav); 28685 view.postInitialize(); 28686 return view; 28687 } 28688 }, 28689 28690 _fixChildDom : function (view, $item, $itemNav) { 28691 28692 28693 28694 var newChild = view._model; 28695 if (!(newChild instanceof guidelib.model.GuidePanel) || !newChild.repeatable) { 28696 return; 28697 } 28698 var $childItem = $item || view.$item; 28699 var $childItemNav = $itemNav || view.$itemNav; 28700 var children = this._model.children; 28701 var insertAfterId = (newChild.instanceIndex > 0) ? children[children.indexOf(newChild) - 1].id : null; 28702 28703 var insertAfterItemSelector = insertAfterId ? this.guideUtil.itemSelector(insertAfterId, newChild) : "#" + newChild.instanceManager.id + "panel"; 28704 var insertAfterNavSelector = insertAfterId ? this.guideUtil.itemNavSelector(insertAfterId) : "#" + newChild.instanceManager.id + "nav"; 28705 28706 28707 this.$itemsContainer.each(function (index) { 28708 var insertEl = $childItem.get(index) || $childItem.get(0), 28709 $insertAfterItem = $(this).find(insertAfterItemSelector); 28710 28711 if ($insertAfterItem.length == 0) { 28712 insertAfterItemSelector = "[data-guide-template-marker=" + newChild.instanceManager.id + "]"; 28713 $insertAfterItem = $(this).find(insertAfterItemSelector); 28714 28715 if (newChild.instanceIndex === 0 && $insertAfterItem.length > 0) { 28716 $insertAfterItem.removeAttr("data-guide-template-marker"); 28717 $(insertEl).attr("data-guide-template-marker", newChild.instanceManager.id); 28718 } 28719 } 28720 28721 if ($insertAfterItem.get(0) !== insertEl) { 28722 28723 $insertAfterItem.after($(insertEl)); 28724 } 28725 }); 28726 28727 28728 28729 this.$itemsNavContainer.each(function (index) { 28730 var insertNavEl = $childItemNav.get(index) || $childItemNav.get(0); 28731 $(this).find(insertAfterNavSelector).after($(insertNavEl)); 28732 }); 28733 }, 28734 28735 multipleChildAdded : function (event) { 28736 if (event.jsonModel.newText && event.jsonModel.newText.length > 0) { 28737 this._syncGuideNodeToHtml(true); 28738 this.childViews.forEach(function (childView) { 28739 if (childView._model.repeatable) { 28740 childView._toggleAddRemoveButtons(); 28741 } 28742 }); 28743 } 28744 }, 28745
28746 handleChildChanged : function (event) { 28747 var newlyCreatedInstance = null, 28748 currentAddedInstanceIndex = -1; 28749 if (event._property == "childRemoved") { 28750 var $elementRemoved = this.$element.find("#" + event.prevText.id), 28751 index = $elementRemoved.index(); 28752 } 28753 if (event._property == "childAdded") { 28754 newlyCreatedInstance = event.newText; 28755 currentAddedInstanceIndex = newlyCreatedInstance.instanceIndex; 28756 } 28757 28758 this._syncGuideNodeToHtml(true, currentAddedInstanceIndex); 28759 this.childViews.forEach(function (childView) { 28760 if (childView._model.repeatable) { 28761 childView._toggleAddRemoveButtons(); 28762 } 28763 }); 28764 if (event._property == "childRemoved") { 28765 28766 28767 this.$element.trigger("panelRemoved.af", [$elementRemoved, index]); 28768 if (this.currentActiveItemView && event.prevText == this.currentActiveItemView._model) { 28769 28770 this._currentActiveItemView = null; 28771 this.setActive("nextItem"); 28772 } 28773 } 28774 if (newlyCreatedInstance != null) { 28775 28776 28777 this.$element.trigger("panelAdded.af", [this.$element.find("#" + newlyCreatedInstance.id)]); 28778 } 28779 }, 28780 28781 handleSummaryChanged : function () { 28782 if (this.$summary.length > 0) { 28783 if (this._model.summary) { 28784 this.$summary.text(this._model.summary); 28785 } else { 28786 var title = this._model.title; 28787 if (this._model.instanceIndex && this._model.repeatable) { 28788 title += " " + this._model.instanceIndex; 28789 } 28790 this.$summary.text(title); 28791 } 28792 } 28793 }, 28794 28795 handleTitleChanged : function () { 28796 if (this.$title.length > 0) { 28797 this.$title.text(this._model.title); 28798 } 28799 28800 var isPanelActive = $("#" + this.id + "_guide-item").hasClass("active"); 28801 if (isPanelActive) { 28802 $("[data-target-guide-content]").text(this._model.title); 28803 } 28804 }, 28805 28806 handleModelChanged : function (event) { 28807 switch (event._property) { 28808 case "summary": 28809 this.handleSummaryChanged(); 28810 break; 28811 case "title": 28812 this.handleTitleChanged(); 28813 break; 28814 default: 28815 GuidePanelView._super.handleModelChanged.apply(this, arguments); 28816 } 28817 }, 28818 28819 _createReferredView : function () { 28820 28821 this._postInitializeChildren(); 28822 }, 28823 28824 _loadLazyFragment : function (options) { 28825 28826 28827 28828 28829 28830 28831 var that = this; 28832 options = options || {}; 28833 28834 this._model._guide().internal.liveDataUtils.updateLiveData(); 28835 28836 28837 28838 28839 var preserveLazy = options.preserveLazy === true; 28840 if (!preserveLazy) { 28841 this._guideView._clearInactiveLazyViews(this); 28842 } 28843 28844 28845 this._viewCreationInProgress = true; 28846 28847 28848 var guide = this._model._guide(); 28849 var callbacks = guide._lazyLoadCallbacks || {}; 28850 28851 this._model._loadLazyFragment({ 28852 "preFetch" : callbacks.preFetch || function () { 28853 $("#loadingPage").addClass("guideLoading"); 28854 }, 28855 "postFetch" : callbacks.postFetch || function () { 28856 $("#loadingPage").removeClass("guideLoading"); 28857 }, 28858 "success" : function () { 28859 28860 that._createReferredView(); 28861 28862 28863 that._viewCreationInProgress = undefined; 28864 that._itemsLoaded = true; 28865 } 28866 }); 28867 28868 28869 }, 28870 28871
28872 setActive : function (activeItemToken, focus, muteScripts) { 28873 28874 28875 28876 if (this._model._lazyReference && this._model.getAttribute('autoLoad') !== false) { 28877 28878 28879 28880 28881 28882 if (_.isUndefined(this._viewCreationInProgress) && _.isUndefined(this._itemsLoaded) 28883 && this._guideView._currentActiveItemView !== this) { 28884 this._loadLazyFragment(); 28885 } 28886 } 28887 28888 var currentActiveItemQName = this.getOrElse(this.currentActiveItemView, "qualifiedName", null); 28889 28890 activeItemToken = activeItemToken || currentActiveItemQName || "firstItem"; 28891 if (activeItemToken != currentActiveItemQName) { 28892 var newActiveItemModel = this._model.navigationContext.getItemForNav(activeItemToken); 28893 if (!newActiveItemModel) { 28894 this.logger().log("AF", "activeItemToken not found:" + activeItemToken + ",currentActiveItem:" + 28895 currentActiveItemQName + ":" + this._model.somExpression); 28896 return false; 28897 } 28898 var newActiveItemView = this.getQualifiedNamedView(newActiveItemModel._escapeQualifiedName()); 28899 if (!muteScripts && this._model.completionExpReq && this.currentActiveItemView && this.currentActiveItemView.focusable() && (this.childViews.indexOf(newActiveItemView) > this.childViews.indexOf(this.currentActiveItemView))) { 28900 var completed = true; 28901 if (this._model.getAttribute("validateOnStepCompletion")) { 28902 completed = window.guideBridge.validate([], this._model.panel.navigationContext.currentItem.somExpression); 28903 } 28904 28905 completed = completed && this._model.executeExpression("completionExp"); 28906 if (!completed) { 28907 return false; 28908 } else if (this.currentActiveItemView) { 28909 this.currentActiveItemView.$item.addClass("completed"); 28910 this.currentActiveItemView.$itemNav.addClass("completed"); 28911 } 28912 } 28913 this.currentActiveItemView = newActiveItemView; 28914 28915 28916 28917 28918 28919 } 28920 if (this.currentActiveItemView) {
28921 this.currentActiveItemView.setActive(null, focus, muteScripts); 28922 } 28923 return true; 28924 }, 28925 28926 _clearInactiveLazyViews : function (that) { 28927 _.each(this.childViews, function (item) { 28928 if (item && item._model.className === "guidePanel" && item._ancestorHasNavigableLayout) { 28929 if (item._model._itemsLoaded && !that._isSelfOrAncestor(item) && !item._hasEffectiveActiveClass() 28930 && item._model._lazyReference) { 28931 28932 item._model._unloadLazyReferenceModel(); 28933 28934 item._model._itemsLoaded = undefined; 28935 28936 item._unloadView(); 28937 28938 item._itemsLoaded = undefined; 28939 } else { 28940 28941 item._clearInactiveLazyViews(that); 28942 } 28943 } 28944 }, this); 28945 }, 28946 28947 _isSelfOrAncestor : function (panelView) { 28948 28949 var selfOrParentView = this; 28950 while (!_.isUndefined(selfOrParentView) && selfOrParentView._model.className !== "rootPanelNode") { 28951 if (panelView === selfOrParentView) { 28952 return true; 28953 } 28954 selfOrParentView = selfOrParentView.parentView; 28955 } 28956 return false; 28957 }, 28958 28959 _hasEffectiveActiveClass : function () { 28960 var hierarchy = this; 28961 while (!_.isUndefined(hierarchy) && this._model.className !== "rootPanelNode") { 28962 if (hierarchy.$item.hasClass("active")) { 28963 hierarchy = hierarchy.parentView; 28964 } else { 28965 return false; 28966 } 28967 } 28968 return true; 28969 }, 28970 28971 handleAccessibility : function () { 28972 var role, screenReaderText; 28973 screenReaderText = this._model._getScreenReaderText(); 28974 role = this._model._getRole(); 28975 if (screenReaderText) { 28976 this.$itemNav.attr("aria-label", screenReaderText); 28977 } 28978 this.$itemNav.find('a').attr("tabindex", function (index, currentValue) { 28979 return (currentValue == -1 ? currentValue : 0); 28980 }); 28981 }, 28982 28983 getQualifiedNamedView : function (qName) { 28984 var view = _.find(this.childViews, function (childView) { 28985 return (childView._model._escapeQualifiedName() == qName); 28986 }, this); 28987 return view; 28988 }, 28989 28990 _toggleAddRemoveButtons : function () { 28991 var panelModel = this._model, 28992 instanceManager = panelModel.instanceManager; 28993 $('[data-guide-id="' + panelModel.id + '"][data-guide-addremove="remove"]').toggleClass("hidden", instanceManager.instanceCount == instanceManager.minOccur); 28994 $('[data-guide-id="' + panelModel.id + '"][data-guide-addremove="add"]').toggleClass("hidden", instanceManager.instanceCount == instanceManager.maxOccur); 28995 } 28996 }); 28997 28998 GuidePanelView.defineProps({ 28999 hasNavigableLayout : { 29000 get : function () { 29001 return this.$itemsNavContainer.length > 0; 29002 } 29003 }, 29004 $itemsContainer : { 29005 get : function () { 29006 29007 if (this._model._selfOrAncestorIsLazyReference || !this._$itemsContainer || this._$itemsContainer.length === 0) { 29008 this._$itemsContainer = this._find(this.guideUtil.itemContainerSelector(this._model.id)); 29009 29010 if (this._$itemsContainer.length === 0) { 29011 this._$itemsContainer = this._find(this.guideUtil.alternateItemContainerSelector(this._model.id)); 29012 } 29013 } 29014 return this._$itemsContainer; 29015 } 29016 }, 29017 $itemsNavContainer : { 29018 get : function () { 29019 if (this._model._selfOrAncestorIsLazyReference || !this._$itemsNavContainer || this._$itemsNavContainer.length === 0) { 29020 this._$itemsNavContainer = this._find(this.guideUtil.itemNavContainerSelector(this._model.id)); 29021 } 29022 return this._$itemsNavContainer; 29023 } 29024 }, 29025 $summary : { 29026 get : function () { 29027 if (!this._$summary) { 29028 this._$summary = this._find(this._summarySelector); 29029 } 29030 return this._$summary; 29031 } 29032 }, 29033 $title : { 29034 get : function () { 29035 if (!this._$title) { 29036 this._$title = this._find(this._titleSelector); 29037 } 29038 return this._$title; 29039 } 29040 }, 29041 currentActiveItemView : { 29042 get : function () { 29043 return this._currentActiveItemView; 29044 }, 29045 set : function (value) { 29046 if (value != this._currentActiveItemView) { 29047 if (this._currentActiveItemView) { 29048 29049 this._currentActiveItemView._model.viewVisited = true; 29050 } 29051 if (!value) { 29052 var itemModel = this._model.navigationContext.firstItem; 29053 if (itemModel) { 29054 value = this.getQualifiedNamedView(itemModel._escapeQualifiedName()); 29055 } 29056 } 29057 this._currentActiveItemView = value; 29058 29059 this._model.navigationContext.currentItem = (this._currentActiveItemView || {})._model; 29060 _.each(this.childViews, function (childView) { 29061 if (childView == this._currentActiveItemView) { 29062 childView.$item.addClass("active"); 29063 childView.$itemNav.addClass("active"); 29064 childView.$itemNav.attr("aria-selected", true); 29065 childView.$itemNav.attr("aria-disabled", false); 29066 childView.$itemNav.removeClass("wizard-tab-disabled"); 29067 } else { 29068 childView.$item.removeClass("active"); 29069 childView.$itemNav.removeClass("active"); 29070 childView.$itemNav.attr("aria-selected", false); 29071 } 29072 }, this); 29073 29074 29075 29076 29077 if (this._currentActiveItemView instanceof guidelib.view.GuidePanel
29077View && this._currentActiveItemView._childInitializeWaiting) { 29078 this._currentActiveItemView._postInitializeChildren(); 29079 } 29080 29081 if (true && _.isUndefined(this._model._ajaxCallDone)) { 29082 29083 29084 var model = this._model; 29085 29086 while (model && !(model instanceof guidelib.model.RootPanelNode)) { 29087 if (model.toolbar) { 29088 model.toolbar.execNavigationChangeExpression(); 29089 } 29090 model = model.parent; 29091 } 29092 29093 if (model && model.toolbar && model instanceof guidelib.model.RootPanelNode) { 29094 model.toolbar.execNavigationChangeExpression(); 29095 } 29096 } 29097 } 29098 } 29099 }, 29100 29101 _ancestorHasNavigableLayout : { 29102 get : function () { 29103 var parentView = this.parentView; 29104 while (parentView) { 29105 if (parentView.$itemsNavContainer && parentView.$itemsNavContainer.length > 0) { 29106 return true; 29107 } 29108 parentView = parentView.parentView; 29109 } 29110 return false; 29111 } 29112 } 29113 }); 29114}($, _, guidelib)); 29115(function ($, _, guidelib) { 29116 29117 var cloneCounter = 0; 29118 29119 var tableMobileLayoutConstants = { 29120 COLLAPSIBLE_COLUMNS : "collapsibleColumns", 29121 HEADERS_LEFT : "headersLeft", 29122 COLLAPSIBLE_COLUMNS_CONTROL_ROW_SELECTOR : "tr.child", 29123 RUNTIME_TABLE_CONTROL : "guideTableRuntimeControls", 29124 RUNTIME_TABLE_RIGHT_CONTROL : "guideTableRuntimeRightControls", 29125 RUNTIME_TABLE_LEFT_CONTROL : "guideTableRuntimeLeftControls", 29126 RUNTIME_TABLE_ADD_CONTROL : "guideTableRuntimeAddControl", 29127 RUNTIME_TABLE_DELETE_CONTROL : "guideTableRuntimeDeleteControl", 29128 RUNTIME_TABLE_EDIT_CONTROL : "guideTableRuntimeEditControl" 29129 }; 29130 29131 var tableSortingComponents = { 29132 GUIDE_INSTANCE_MANAGER : "guideInstanceManager", 29133 WEB_CHANNEL_HEADER_COMPONENT : "fd/ccm/web-channel/components/tableHeader/v1/tableHeader", 29134 AF_TABLE_HEADER_COMPONENT : "fd/af/components/tableHeader", 29135 SORTING_ENABLED : "sortingEnabled" 29136 }; 29137 29138 var GuideTableView = guidelib.view.GuideTableView = guidelib.view.GuidePanelView.extend({ 29139 29140 29141 TABLE_WIDTH_BUFFER : 23, 29142 29143 _getPluginOptions : function () { 29144 var defaultOptions = { 29145 "bAutoWidth" : this.bAutoWidth 29146 }, columnWidthArray = null, 29147 sum = 0, 29148 sWidthArray = null, 29149 numOfTableCol = this.$tableElement.find("th").length; 29150 29151 if (this.bAutoWidth === false) { 29152 columnWidthArray = this._model.columnWidth.split(","); 29153 if (columnWidthArray.length === numOfTableCol) { 29154 29155 _.each(columnWidthArray, function (item) { 29156 sum += parseInt(item, 10); 29157 }); 29158 29159 sWidthArray = _.map(columnWidthArray, function (item) { 29160 return { 29161 "pWidth" : Math.floor((item * 100) / sum) 29162 }; 29163 }); 29164 } 29165 29166 defaultOptions = _.extend({}, defaultOptions, { 29167 aWidthPercentage : sWidthArray, 29168 aWidth : columnWidthArray 29169 }); 29170 } 29171 return defaultOptions; 29172 29173 }, 29174 29175 29176 setAutoWidth : function () { 29177 if (this._model.columnWidth && this._model.columnWidth.length > 0) { 29178 this.bAutoWidth = false; 29179 } else { 29180 this.bAutoWidth = true; 29181 } 29182 }, 29183 29184 29185 createView : function (id) { 29186 var $htmlTemplate = this._guideView._domTemplateCacheStore.cloneDomElement("#" + id), 29187 formElemSelector = "#" + id + "_widget", 29188 counter = ++cloneCounter; 29189 if ($htmlTemplate.length == 0) { 29190 29191 $htmlTemplate = this.$element.find("#" + id).clone(); 29192 } 29193 29194 $htmlTemplate.find(formElemSelector).attr("id", id + "_widget" + counter); 29195 29196 var view = guidelib.view.GuideViewRegistry.prototype.createView($htmlTemplate, this); 29197 view.postInitialize(); 29198 return $htmlTemplate; 29199 }, 29200 29201 initializeTableColumnWidth : function (pluginOptions) { 29202 29203 if (this.bAutoWidth == false && this._model.mobileLayout === tableMobileLayoutConstants.HEADERS_LEFT) { 29204 29205 29206 this.$tableElement.css("table-layout", "fixed"); 29207 var widthArray = pluginOptions["aWidthPercentage"], 29208 numOfTableCol = this.$tableElement.find("th").length; 29209 if (widthArray && widthArray.length == numOfTableCol) { 29210 29211 this.$tableElement.find("th").each(function (index) { 29212 $(this).css("width", widthArray[index]["pWidth"] + "%"); 29213 }); 29214 } 29215 } 29216 }, 29217 29218 _checkIfTableSortingEnabled : function () { 29219 var jsonModel = this._model.jsonModel; 29220 return (jsonModel[tableSortingComponents.SORTING_ENABLED] === "true"); 29221 }, 29222 29223
29224 handleParentVisibleChanged : function (event) { 29225 switch (event._property) { 29226 case "visible": 29227 this.handleTableShown(); 29228 break; 29229 } 29230 }, 29231 29232 29233 _checkParentModelChanged : function() { 29234 var currentParent = this.parentView; 29235 while(currentParent != null) { 29236 currentParent._model.on(guidelib.event.GuideModelEvent.MODEL_CHANGED, this.handleParentVisibleChanged, this); 29237 currentParent = currentParent.parentView; 29238 } 29239 }, 29240 29241 29242 initialize : function () { 29243 GuideTableView._super.initialize.apply(this, arguments); 29244 29245 this._checkParentModelChanged(); 29246 29247 this.$tableElement = this.$element.find("> table"); 29248 29249 this.setAutoWidth(); 29250 29251 var widgetOptions = this._getPluginOptions(), 29252 that = this; 29253 29254 this.initializeTableColumnWidth(widgetOptions); 29255 this._fixTableControls(true); 29256 if (this._model.mobileLayout === tableMobileLayoutConstants.COLLAPSIBLE_COLUMNS) { 29257 widgetOptions = _.extend({}, widgetOptions, { 29258 29259 bControlRowHiddenCells : false, 29260 29261 29262 bDisableControlRowCells : true, 29263 29264 viewCallback : $.proxy(this.createView, this), 29265 29266 tableRuntimeEditControlClass : tableMobileLayoutConstants.RUNTIME_TABLE_EDIT_CONTROL, 29267 29268 fixTableControls : $.proxy(this._fixTableControls, this) 29269 }); 29270 29271 this.jqwidget = this.$tableElement.responsiveTablePlugin(widgetOptions).data("responsiveTablePlugin"); 29272 } else { 29273 29274 $(window).on("resize orientationchange", function (event) { 29275 that._fixTableControls(event); 29276 }); 29277 } 29278 29279 if (this._checkIfTableSortingEnabled()) { 29280 this.$tableElement.tableSorting = this.guideTableSorter.initialize; 29281 this.$tableElement.tableSorting({ 29282 model : this._model, 29283 tableContext : this 29284 }); 29285 } 29286 }, 29287 29288 handleVisibleChanged : function (event) { 29289 GuideTableView._super.handleVisibleChanged.apply(this, arguments); 29290 29291 this.handleTableShown(); 29292 this._resetTableCellWidth(); 29293 }, 29294 29295 handleTableShown : function () { 29296 if (this._model.mobileLayout === tableMobileLayoutConstants.COLLAPSIBLE_COLUMNS) { 29297 29298 this.jqwidget._initializeColumnVisibility(); 29299 29300 if (this.jqwidget.isColumnHidden()) { 29301 29302 this.$tableElement.find(".guideFieldNode").addClass("dontSyncEnabled"); 29303 29304 this.$tableElement.find("input, select, textarea, button").attr("disabled", "disabled"); 29305 } 29306 } 29307 }, 29308 29309 _resetTableCellWidth : function () { 29310 var that = this, 29311 tableWidthBuffer = this.TABLE_WIDTH_BUFFER; 29312 29313 this.$tableElement.find("." + tableMobileLayoutConstants.RUNTIME_TABLE_CONTROL).each(function () { 29314 var element = this; 29315 setTimeout(function () { 29316 that._resetTableCell($(element), tableWidthBuffer); 29317 }, 1); 29318 }); 29319 }, 29320 29321 _resetTableCell : function ($element, tableWidthBuffer) { 29322 var componentWidth; 29323 29324 if ($element.hasClass(tableMobileLayoutConstants.RUNTIME_TABLE_RIGHT_CONTROL)) { 29325 var $component = $element.prev(), 29326 $td = $element.parent(); 29327 29328 29329 if ($element.is(":visible")) { 29330 29331 $component.css("display", "inline-block"); 29332 $component.css("float", "left"); 29333 componentWidth = $td.width() - $element.outerWidth() - tableWidthBuffer; 29334 var percentage = ((componentWidth / $td.width()) * 100); 29335 29336 29337 $component.width(percentage + "%"); 29338 } else { 29339 29340 29341 $component.css("display", "block"); 29342 $component.css("float", "none"); 29343 $component.width($td.width()); 29344 } 29345 } else if ($element.hasClass(tableMobileLayoutConstants.RUNTIME_TABLE_LEFT_CONTROL)) { 29346 29347 if ($element.is(":visible")) { 29348 $element.next().css("display", "inline-block"); 29349 componentWidth = $element.parent().width() - $element.outerWidth() - tableWidthBuffer; 29350 var percentage = ((componentWidth / $element.parent().width()) * 100); 29351 $element.next().width(percentage + "%"); 29352 } else { 29353 29354 $element.next().css("display", "block"); 29355 } 29356 } 29357 }, 29358 29359 _fixTableControls : function (event) { 29360 29361 29362 29363 if ((this._model.mobileLayout === tableMobileLayoutConstants.COLLAPSIBLE_COLUMNS) && (this.jqwidget)) { 29364 29365 if (this.jqwidget.isColumnHidden()) { 29366 29367 this.$tableElement.find("tr:not(.child)").find(".guideFieldNode").addClass("dontSyncEnabled"); 29368 29369 this.$tableElement.find("tr:not(.child)").find("input, select, textarea, button").attr("disabled", "disabled"); 29370 } else { 29371 29372 this.$tableElement.find(".guideFieldNode").removeClass("dontSyncEnabled"); 29373 29374 this.$tableElement.find("input, select, textarea, button").removeAttr("disabled"); 29375 } 29376 } 29377 29378 29379 if (event) { 29380 this._resetTableCellWidth(); 29381 } 29382 }, 29383 29384 29385 _fixChildDom : function (view, $item, $itemNav) { 29386 GuideTableView._super._fixChildDom.apply(this, arguments); 29387 29388 29389 if (this._model.mobileLayout === tableMobileLayoutConstants.COLLAPSIBLE_COLUMNS) { 29390 29391 this.jqwidget._fixControlRows(); 29392 } 29393 29394 this._fixTableControls(); 29395 29396 this._resetTableCellWidth(); 29397 }, 29398 29399 _postInitializeChildren : function () { 29400 29401 GuideTableView._super._postInitializeChildren.call(this); 29402 29403 29404 29405 29406 29407 if (this._model.mobileLayout === tableMobileLayoutConstants.COLLAPSIBLE_COLUMNS) { 29408 29409 this.handleTableShown(); 29410 } 29411 29412 29413 else if (this._model.mobileLayout === tableMobileLayoutConstants.HEADERS_LEFT) { 29414 this._fixTableCellForHeaderLeftLayout(); 29415 } 29416 this._resetTableCellWidth(); 29417 }, 29418 29419 _fixTableCellForHeaderLeftLayout : function () { 29420 var that = this, 29421 guideUtil = guidelib.util.GuideUtil; 29422 this.$tableElement.find("tr td").each(function () { 29423 guideUtil._setGuideDataHeader($(this), that.$tableElement); 29424 }); 29425 }, 29426 29427
29428 handleChildChanged : function (event) { 29429 GuideTableView._super.handleChildChanged.apply(this, arguments); 29430 29431 29432 if (this._model.mobileLayout === tableMobileLayoutConstants.HEADERS_LEFT) { 29433 this._fixTableCellForHeaderLeftLayout(); 29434 } 29435 if (event._property == "childAdded") { 29436 this._resetTableCellWidth(); 29437 } 29438 }, 29439 29440 addRemoveTemplateMarker : function () { 29441 29442 _.each(this._model.children, function (childModel) { 29443 if (childModel instanceof guidelib.model.GuideInstanceManager) { 29444 29445 var imId = childModel.id, 29446 instanceId = (childModel._instances[0] || {}).id || childModel.instanceTemplateId, 29447 gTemplateMarker = null, 29448 29449 instanceItem = this.guideUtil.itemSelector(instanceId, childModel._instances[0]), 29450 navItem = this.guideUtil.itemNavSelector(instanceId), 29451 $instanceItem = this.$itemsContainer.find(instanceItem); 29452 if ($instanceItem.is("tr")) { 29453 $instanceItem.attr("data-guide-template-marker", imId); 29454 } 29455 29456 29457 29458 29459 29460 } 29461 }, this); 29462 }, 29463 29464 tableSortComparator : { 29465 DATE : function (tableModelDataRows, sortList, tableContext) { 29466 return tableModelDataRows.sort(function (a, b) { 29467 var currColumn = sortList[0][0], currOrder = sortList[0][1], 29468 guideTableSorter = tableContext.guideTableSorter, 29469 value_a = guideTableSorter.formatDateValue(guideTableSorter.getValueFromJsonModel(a, currColumn)), 29470 value_b = guideTableSorter.formatDateValue(guideTableSorter.getValueFromJsonModel(b, currColumn)); 29471 return guideTableSorter.ComparedOrder(value_a, value_b, currOrder); 29472 }); 29473 }, 29474 NUMBER : function (tableModelDataRows, sortList, tableContext) { 29475 return tableModelDataRows.sort(function (a, b) { 29476 var currColumn = sortList[0][0], currOrder = sortList[0][1], 29477 guideTableSorter = tableContext.guideTableSorter, 29478 value_a = guideTableSorter.formatRegexFloatData(guideTableSorter.getValueFromJsonModel(a, currColumn)), 29479 value_b = guideTableSorter.formatRegexFloatData(guideTableSorter.getValueFromJsonModel(b, currColumn)); 29480 return guideTableSorter.ComparedOrder(value_a, value_b, currOrder); 29481 }); 29482 29483 }, 29484 STRING : function (tableModelDataRows, sortList, tableContext) { 29485 return tableModelDataRows.sort(function (a, b) { 29486 var currColumn = sortList[0][0], currOrder = sortList[0][1], 29487 guideTableSorter = tableContext.guideTableSorter, 29488 value_a = guideTableSorter.formatRichTextString(guideTableSorter.getValueFromJsonModel(a, currColumn, true)), 29489 value_b = guideTableSorter.formatRichTextString(guideTableSorter.getValueFromJsonModel(b, currColumn, true)); 29490 return guideTableSorter.ComparedOrder(value_a, value_b, currOrder); 29491 }); 29492 } 29493 }, 29494 29495 29496 guideTableSorter : new function () { 29497 this.initialize = function (tableSortingConfig) { 29498 return this.each(function () { 29499 this.tableConfig = {}; 29500 var defaultSortingConfig = {sortList : [], selectorsHeaders : 'thead th', 29501 headerCss : {asc : "asc", desc : "desc", random : "random"} 29502 }; 29503 if (!this.tHead || !this.tBodies) {return;} 29504 var table = $(this), tableConfig = {}; 29505 tableConfig = $.extend(this.tableConfig, defaultSortingConfig, tableSortingConfig); 29506 var tableHeaderModel, tableModel = tableConfig.model; 29507 for (var index = 0 ; index < tableModel.children.length ; index++) { 29508 if (isTableHeaderRow(tableModel.children[index])) { 29509 tableHeaderModel = tableModel.children[index]; 29510 tableConfig.tableHeader = tableHeaderModel; 29511 break; 29512 } 29513 } 29514 var $tableHeaders = filterSortableHeaders(tableConfig, this); 29515 $tableHeaders.click(function () { 29516 if (this.sortingAllowed) { 29517 sortCurrentColumn(this, table, tableConfig, $tableHeaders); 29518 } 29519 }); 29520 29521 $tableHeaders.each(function (index) { 29522 if (this.sortingAllowed) {
29523 sortOnFirstColumn(this, tableModel); 29524 return false; 29525 } 29526 }); 29527 }); 29528 }; 29529 29530 29531 function sortOnFirstColumn(firstColumn, tableModel) { 29532 if (typeof tableModel._guide !== "undefined" && tableModel._guide()) { 29533 var isSubmittedData = guidelib.util.GuideUtil._fetchJSONNodeValue(tableModel._guide().runtime.guideContext.guidePrefillJson, "afSubmissionInfo"); 29534 isSubmittedData = isSubmittedData || guidelib.util.GuideUtil.fetchXMLNodeValue(tableModel._guide().runtime.guideContext.guidePrefillXml, "afSubmissionInfo"); 29535 if (!isSubmittedData) { 29536 $(firstColumn).trigger("click"); 29537 } 29538 } 29539 } 29540 29541 29542 function filterSortableHeaders(tableConfig, tableDom) { 29543 var $tableHeaders = $(tableConfig.selectorsHeaders, tableDom).each(function (index) { 29544 this.column = index; 29545 this.order = 1; 29546 }); 29547 for (var column = 0 ; column < tableConfig.tableHeader.children.length ; column++) { 29548 var currColumnModel = tableConfig.tableHeader.children[column]; 29549 $tableHeaders[column].sortingAllowed = true; 29550 var sortDataType = currColumnModel.jsonModel["sortingDataType"]; 29551 sortDataType = !sortDataType ? "STRING" : sortDataType; 29552 currColumnModel.jsonModel.sortingDataType = sortDataType; 29553 if (!tableConfig.tableHeader.visible || sortDataType === "noSort") { 29554 $tableHeaders[column].sortingAllowed = false; 29555 $($tableHeaders[column]).removeClass("sortEnabled"); 29556 var $sortingButton = $($tableHeaders[column]).find(".sortingButton").remove(); 29557 } 29558 } 29559 return $tableHeaders; 29560 } 29561 29562 29563 function sortCurrentColumn(currentHeader, table, tableConfig, $tableHeaders) { 29564 var tableRows = (table[0].tBodies[0] && table[0].tBodies[0].rows.length) || 0; 29565 if (tableRows > 0) { 29566 currentHeader.order = (++(currentHeader.order) % 2); 29567 tableConfig.sortList = []; 29568 tableConfig.sortList.push([currentHeader.column, currentHeader.order]); 29569 setTimeout(function () { 29570 updateTableHeaderStyles($tableHeaders, tableConfig.sortList, tableConfig); 29571 sortGuideTableDataModel(tableConfig, tableConfig.sortList, tableConfig.model); 29572 }, 1); 29573 } 29574 } 29575 29576 29577 function updateTableHeaderStyles($headers, sortingList, tableConfig) { 29578 var order, headerCSS = [tableConfig.headerCss.asc, tableConfig.headerCss.desc, tableConfig.headerCss.random]; 29579 $headers.each(function (index) { 29580 var $sortingButton = $(this).find(".sortingButton"); 29581 $sortingButton.removeClass(headerCSS[0]).removeClass(headerCSS[1]).removeClass(headerCSS[2]); 29582 if ($headers[index].sortingAllowed) { 29583 if (index === sortingList[0][0]) { 29584 order = sortingList[0][1]; 29585 $sortingButton.addClass(headerCSS[order]); 29586 } else { 29587 $sortingButton.addClass(tableConfig.headerCss.random); 29588 } 29589 } 29590 }); 29591 } 29592 29593 29594 function sortGuideTableDataModel(tableConfig, sortList, tableModel) { 29595 var i,j = 0,tableModelChildren = tableModel.children, tableDataRows = [], prevTableModel = tableModel, 29596 modifiedGuideTableModel = [], tableContext = tableConfig.tableContext; 29597 29598 for (i = 0; i < tableModelChildren.length; i++) { 29599 if (tableModelChildren[i].className !== tableSortingComponents.GUIDE_INSTANCE_MANAGER) { 29600 if (isTableRowsWithData(tableModelChildren[i])) { 29601 tableDataRows.push(tableModelChildren[i]); 29602 } 29603 } 29604 } 29605 var dataType = tableConfig.tableHeader.children[[sortList[0][0]]].jsonModel.sortingDataType; 29606 tableDataRows = tableContext.tableSortComparator[dataType].call(tableConfig, tableDataRows, sortList, tableContext); 29607 for (i = 0; i < tableModel.children.length; i++) { 29608 if (isTableRowsWithData(tableModel.children[i])) { 29609 modifiedGuideTableModel.push(tableDataRows[j]); 29610 j++; 29611 } else { 29612 modifiedGuideTableModel.push(tableModel.children[i]); 29613 } 29614 } 29615 tableModel.children = modifiedGuideTableModel; 29616 tableModel._triggerEvent(guidelib.event.GuideModelEvent.MODEL_CHANGED, "tableModelSorted", prevTableModel, tableModel); 29617 syncNewModelToHTML(tableConfig.tableContext, tableModel); 29618 } 29619 29620 29621 function isTableRowsWithData(tableModelChildElement) { 29622 var resourceType = tableModelChildElement.options.jsonModel["sling:resourceType"], 29623 childElementClassName = tableModelChildElement.className; 29624 return !((childElementClassName === tableSortingComponents.GUIDE_INSTANCE_MANAGER) || (resourceType === tableSortingComponents.AF_TABLE_HEADER_COMPONENT) || (resourceType === tableSortingComponents.WEB_CHANNEL_HEADER_COMPONENT)); 29625 } 29626 29627 function isTableHeaderRow(tableModelChildElement) { 29628 var resourceType = tableModelChildElement.options.jsonModel["sling:resourceType"]; 29629 return ((resourceType === tableSortingComponents.AF_TABLE_HEADER_COMPONENT) || (resourceType === tableSortingComponents.WEB_CHANNEL_HEADER_COMPONENT)); 29630 } 29631 29632 this.formatRegexFloatData = function (data) { 29633 return (isNaN(parseFloat(data))) ? 0 : parseFloat(data); 29634 }; 29635 29636 this.formatDateValue = function (data) { 29637 return (isNaN(new Date(data).getTime())) ? 0 : new Date(data).getTime(); 29638 }; 29639 29640 this.formatRichTextString = function (data) { 29641 data = "<div>" + data + "</div>"; 29642 return $(data).text().trim(); 29643 }; 29644 29645 this.ComparedOrder = function (value_a, value_b, currOrder) { 29646 if (value_a > value_b) { 29647 return (currOrder === 0) ? 1 : -1; 29648 } else if (value_a < value_b) { 29649 return (currOrder === 0) ? -1 : 1; 29650 } else { 29651 return -1; 29652 } 29653 }; 29654 29655 this.getValueFromJsonModel = function (tableRow, currColumn, isString) { 29656 var jsonModel = tableRow.children[getValidCurrentColumn(tableRow.children, currColumn)].jsonModel, value = null; 29657 if (!isString && jsonModel.defaultValue && jsonModel.defaultValue.length === 1) { 29658 value = jsonModel.defaultValue[0]; 29659 } 29660 if (!value) { 29661 value = jsonModel._value; 29662 } 29663 return value === null ? "" : this.formatRichTextString(value); 29664 }; 29665 29666 29667 function getValidCurrentColumn(tableRowModel, currColumn) {
29668 var validCurrColumn = currColumn, index = 0 ; 29669 while (currColumn > 0) { 29670 if (tableRowModel[index].jsonModel.guideNodeClass === tableSortingComponents.GUIDE_INSTANCE_MANAGER) { 29671 validCurrColumn++; 29672 } else { 29673 currColumn--; 29674 } 29675 index++; 29676 } 29677 return validCurrColumn; 29678 } 29679 29680 29681 function syncNewModelToHTML(tableContext, tableModel) { 29682 var tableItemsViews = {}, childView, index; 29683 29684 for (index = 0; index < tableContext.childViews.length; index++) { 29685 childView = tableContext.childViews[index]; 29686 if (childView.isItem) { 29687 tableItemsViews[childView.id] = childView; 29688 } 29689 } 29690 for (index = 1; index < tableContext._model.items.length; index++) { 29691 var childModel = tableContext._model.items[index], childId = childModel.id, view = tableItemsViews[childId],newChild = view._model, 29692 $childItem = view.$item, $childItemNav = view.$itemNav, insertBeforeId, insertAfterId; 29693 if (index === 1) { 29694 if (tableModel.items.length > 2) { 29695 insertBeforeId = tableModel.items[index + 1].id; 29696 } 29697 } else { 29698 insertAfterId = tableModel.items[index - 1].id; 29699 } 29700 var insertAfterItemSelector = insertAfterId ? tableContext.guideUtil.itemSelector(insertAfterId, newChild) : "#" + newChild.instanceManager.id, 29701 insertBeforeItemSelector = insertBeforeId ? tableContext.guideUtil.itemSelector(insertBeforeId, newChild) : "#" + newChild.instanceManager.id; 29702 tableContext.$itemsContainer.each(function (index) { 29703 var insertEl = $childItem.get(index) || $childItem.get(0), 29704 $insertBeforeItem, 29705 $insertAfterItem = $(this).find(insertAfterItemSelector); 29706 if ($insertAfterItem.get(0) !== insertEl) { 29707 $insertAfterItem.after($(insertEl)); 29708 } else { 29709 $insertBeforeItem = $(this).find(insertBeforeItemSelector); 29710 $insertBeforeItem.before($(insertEl)); 29711 } 29712 }); 29713 } 29714 } 29715 } 29716 }); 29717}($, _, guidelib)); 29718 29719(function ($, guidelib) { 29720 var GuideTableRowView = guidelib.view.GuideTableRowView = guidelib.view.GuidePanelView.extend({ 29721 29722 handleChildChanged : function (event) { 29723 29724 } 29725 29726 }); 29727}($, guidelib)); 29728(function ($, guidelib, _) { 29729 var GuideContainerView = guidelib.view.GuideContainerView = guidelib.view.GuideItemsView.extend({ 29730 initialize : function () { 29731 this._queueViewForLazyItems = []; 29732 29733 window.guideBridge._guideView = this; 29734 var $htmlTemplateDom = $(this.options.element).clone(); 29735 this._domTemplateCacheStore = 29736 new guidelib.view.util.DomTemplateCacheStore({$htmlTemplateDom : $htmlTemplateDom}); 29737 this._lastFocussedPanelForNonActionFields = null; 29738 GuideContainerView._super.initialize.call(this); 29739 this._currentFocusItemSom = null; 29740 29741 29742 this._previousFocusItemSom = "FIRST_TIME"; 29743 $(window).on("keydown.guides", $.proxy(this.hotKeys, this)); 29744 this.postInitialize(); 29745 this._model.on(guidelib.event.GuideModelEvent.MODEL_REFRESH, function (evnt) { 29746 switch (evnt._property) { 29747 case "jsonModel": 29748 this._syncGuideNodeToHtml(true); 29749 break; 29750 default: 29751 this._model.logger().error("unexpected event property " + evnt._property); 29752 } 29753 }, this); 29754 }, 29755 29756 _reInitializeGuideContainerDom : function () { 29757 var $guideContainerDom = $('div.guideContainerWrapperNode'); 29758 this.$element = $guideContainerDom; 29759 }, 29760 29761 setFocus : function (somExp, focusOpt, runNavScr) { 29762 var options, 29763 focusOption, 29764 runNavScript, 29765 somExpression, 29766 muteScripts; 29767 if (_.isObject(somExp)) { 29768 options = somExp; 29769 somExpression = options.somExpression; 29770 focusOption = options.focusOption; 29771 runNavScript = options.runCompletionScript; 29772 } else { 29773 somExpression = somExp; 29774 focusOption = focusOpt; 29775 runNavScript = runNavScr; 29776 } 29777 muteScripts = !runNavScript; 29778 if (focusOption == "nextItemDeep" || focusOption == "prevItemDeep") { 29779 29780 if (somExpression) { 29781 this.logger().warn("AF", "somExpression is currently not supported for deepNavigation:" + somExpression + ":" + focusOption); 29782 return false;
29783 } 29784 var existingFocusNavItem = this.getSomOnNavigableAncestor(this._lastFocussedPanelForNonActionFields); 29785 var existingNavView = this.getView(existingFocusNavItem); 29786 var siblingNavName = (focusOption == "nextItemDeep") ? "nextItem" : "prevItem"; 29787 29788 while (existingNavView && (existingNavView.parentView != this) && !existingNavView.getSiblingItemView(siblingNavName)) { 29789 var navigableParentItem = this.getSomOnNavigableAncestor(existingNavView.parentView._model.somExpression); 29790 existingNavView = this.getView(navigableParentItem); 29791 } 29792 if (existingNavView && existingNavView.parentView != this && existingNavView.getSiblingItemView(siblingNavName)) { 29793 var madeActive = existingNavView.parentView.setActive(siblingNavName, false, muteScripts); 29794 if (!madeActive) { 29795 this.logger().log("AF", "could not setActive for the deepNav:" + existingNavView._model.somExpression); 29796 return false; 29797 } 29798 29799 var deepChildNav = (siblingNavName == "nextItem") ? "firstItem" : "lastItem"; 29800 var currentActiveChildView = existingNavView.parentView.currentActiveItemView; 29801 while (currentActiveChildView) { 29802 currentActiveChildView.setActive(deepChildNav, !currentActiveChildView.currentActiveItemView, true); 29803 currentActiveChildView = currentActiveChildView.currentActiveItemView; 29804 } 29805 return true; 29806 } else { 29807 this.logger().warn("AF", "could not locate view for given somExpression:" + somExpression + ":" + focusOption); 29808 return false; 29809 } 29810 } 29811 29812 if (!somExpression) { 29813 29814 somExpression = this.guideModel.rootPanel.somExpression; 29815 } 29816 var currentView = this.rootPanelView; 29817 29818 29819 if (currentView) { 29820 var relativeSom = this.guideUtil.relativeSom(this.guideModel.rootPanel.somExpression, somExpression); 29821 if (relativeSom) { 29822 var somTokens = relativeSom.split("."); 29823 var error = 29824 _.find(somTokens, function (qName) { 29825 currentView.setActive(qName, false, muteScripts); 29826 if (currentView instanceof guidelib.view.GuidePanelView && (currentView.currentActiveItemView == null || currentView.currentActiveItemView.qualifiedName != qName)) { 29827 this.logger().log("AF", "could not find token:" + qName + ", som:" + somExpression); 29828 return true; 29829 } else { 29830 if (currentView.currentActiveItemView != null) { 29831 currentView = currentView.currentActiveItemView; 29832 } 29833 } 29834 }, this); 29835 if (error) { 29836 return false; 29837 } 29838 } 29839 } else { 29840 29841 var $element = this._getGuideDomElement(somExpression); 29842 29843 29844 if ($element && $element.length > 0) { 29845 29846 29847 currentView = $element.data("guideView"); 29848 } 29849 } 29850 29851 if (currentView) { 29852 return currentView.setActive(focusOption, true, muteScripts); 29853 } else { 29854 return false; 29855 } 29856 }, 29857 29858 _getGuideDomElement : function (somExpression, option) { 29859 var nav = "", res, node, nodeElSelector; 29860 if (somExpression && typeof somExpression === 'string') { 29861 node = this.guideModel.resolveNode(somExpression); 29862 if (!node) { 29863 return; 29864 } 29865 nodeElSelector = "#" + node.id; 29866 if (option === "nav") { 29867 nodeElSelector = this.guideUtil.itemNavSelector(node.id); 29868 } 29869 res = this.$element.find(nodeElSelector); 29870 return res; 29871 } 29872 }, 29873 29874 getView : function (somExpression) { 29875 if (!somExpression) { 29876 return null; 29877 }
29878 var $focusEl = this._getGuideDomElement(somExpression), 29879 view = null, 29880 ancestorView = null; 29881 if ($focusEl && $focusEl.length > 0) { 29882 if (!$focusEl.data("guideView")) { 29883 var rootPanelSom = this.guideModel.rootPanel.somExpression; 29884 var relativeSom = guidelib.util.GuideUtil.relativeSom(rootPanelSom, somExpression) || ""; 29885 29886 _.reduce(relativeSom.split("."), function (currentSom, somToken) { 29887 currentSom = currentSom ? currentSom + "." + somToken : somToken; 29888 ancestorView = this.getView(currentSom); 29889 if (ancestorView instanceof guidelib.view.GuidePanelView && ancestorView._childInitializeWaiting) { 29890 ancestorView._postInitializeChildren(); 29891 } 29892 return currentSom; 29893 }, rootPanelSom, this); 29894 } 29895 view = $focusEl.data("guideView"); 29896 if (view instanceof guidelib.view.GuidePanelView && view._childInitializeWaiting) { 29897 view._postInitializeChildren(); 29898 } 29899 29900 return view; 29901 } 29902 return null; 29903 }, 29904 29905 hotKeys : function (evnt) { 29906 var handled = false, currentFocusItemSom; 29907 29908 switch (evnt.keyCode) { 29909 case 37: 29910 if (evnt.altKey) { 29911 window.guideBridge.setFocus(null, 'prevItemDeep', true); 29912 handled = true; 29913 } 29914 break; 29915 case 39: 29916 if (evnt.altKey) { 29917 window.guideBridge.setFocus(null, 'nextItemDeep', true); 29918 handled = true; 29919 } 29920 break; 29921 case 82: 29922 if (evnt.altKey) { 29923 window.guideBridge.reset(); 29924 handled = true; 29925 } 29926 break; 29927 case 83: 29928 if (evnt.altKey) { 29929 window.guideBridge.submit(); 29930 handled = true; 29931 } 29932 break; 29933 } 29934 if (handled) { 29935 evnt.preventDefault(); 29936 } 29937 }, 29938 29939 getSomOnNavigableAncestor : function (somExpression) { 29940 if (!somExpression || somExpression === "") { 29941 return null; 29942 } 29943 29944 var index, parentView, parentSom, isNavigable; 29945 index = somExpression.lastIndexOf("."); 29946 29947 if (index !== -1) { 29948 parentSom = somExpression.substring(0, index); 29949 parentView = this.getView(parentSom); 29950 if (parentView) { 29951 isNavigable = parentView.hasNavigableLayout; 29952 } 29953 if (isNavigable) { 29954 return somExpression; 29955 } 29956 return this.getSomOnNavigableAncestor(parentSom); 29957 } 29958 29959 return this.guideModel.rootPanel.somExpression; 29960 }, 29961 29962 __printSyncPending : function () { 29963 29964 _.each(this.childViews, function (childView) { 29965 if (childView._syncPending) { 29966 this.logger().error("AF", childView._model.somExpression); 29967 } else { 29968 GuideContainerView.prototype.__printSyncPending.call(childView); 29969 } 29970 }, this); 29971 }, 29972 29973 _clearInactiveLazyViews : function (that) { 29974 _.each(this.childViews, function (item) { 29975 if (item._model.className === "rootPanelNode") { 29976 item._clearInactiveLazyViews(that); 29977 } 29978 }); 29979 } 29980 29981 }); 29982 29983 GuideContainerView.defineProps({ 29984 guideModel : { 29985 get : function () { 29986 return this._model; 29987 } 29988 }, 29989 29990 rootPanelView : { 29991 get : function () { 29992 return this._findChildView(this.guideModel.rootPanel); 29993 } 29994 }, 29995 29996 currentFocusItemSom : { 29997 get : function () { 29998 return this._currentFocusItemSom; 29999 }, 30000 set : function (newSom) { 30001 if (this._currentFocusItemSom !== newSom) { 30002 var oldValue = this._currentFocusItemSom; 30003 if (oldValue) { 30004 this._previousFocusItemSom = oldValue; 30005 } 30006 this._currentFocusItemSom = newSom; 30007 30008 if (newSom != null && this._model.resolveNode(newSom).parent.className !== "guideToolbar") { 30009 this._lastFocussedPanelForNonActionFields = this.get
30009SomOnNavigableAncestor(this._currentFocusItemSom); 30010 30011 30012 this._model._currentNavigablePanelSom = this._lastFocussedPanelForNonActionFields; 30013 } 30014 if (newSom) { 30015 this._triggerOnBridge("elementFocusChanged", this._model.resolveNode(newSom), "focus", this._previousFocusItemSom, newSom); 30016 if (this._previousFocusItemSom) { 30017 var getPreviousItemNavigableSom = this.getSomOnNavigableAncestor(this._previousFocusItemSom), 30018 getCurrentItemNavigableSom = this.getSomOnNavigableAncestor(newSom); 30019 if (getCurrentItemNavigableSom !== getPreviousItemNavigableSom) { 30020 this._triggerOnBridge("elementNavigationChanged", this._model.resolveNode(getCurrentItemNavigableSom), 30021 "navigate", getPreviousItemNavigableSom, getCurrentItemNavigableSom); 30022 } 30023 } 30024 } 30025 } 30026 } 30027 }, 30028 30029 skipFieldFocus : { 30030 30031 get : function () { 30032 return this._skipFieldFocus; 30033 }, 30034 30035 set : function (newVal) { 30036 this._skipFieldFocus = newVal; 30037 } 30038 } 30039 }); 30040}($, guidelib, _)); 30041(function (_, guidelib) { 30042 guidelib.model.mixin.ValidationsDisabled = { 30043 normalProperties : { 30044 setParentValidationsDisabled : function (bParentValidationsDisabled) { 30045 var oldValidationsDisabled = this.validationsDisabled, 30046 newValidationsDisabled; 30047 this._bParentValidationsDisabled = bParentValidationsDisabled; 30048 newValidationsDisabled = this.validationsDisabled; 30049 this.handleChildValidationsDisabled(newValidationsDisabled, oldValidationsDisabled); 30050 }, 30051 30052 handleChildValidationsDisabled : function (newValidationsDisabled, oldValidationsDisabled) { 30053 if (newValidationsDisabled !== oldValidationsDisabled) { 30054 if (this instanceof guidelib.model.Field) { 30055 if (newValidationsDisabled === true) { 30056 if (this.validationState === false) { 30057 this._errorText = ""; 30058 this.validationState = true; 30059 this._triggerEvent(guidelib.event.GuideModelEvent.ERROR_CHANGED, 30060 "validationStatus", this.validationState, this._errorText); 30061 } 30062 } 30063 } 30064 _.each(this._children, function (child) { 30065 if (child instanceof guidelib.model.Field || child instanceof guidelib.model.GuideItemsContainer) { 30066 child.setParentValidationsDisabled(newValidationsDisabled); 30067 } 30068 }); 30069 } 30070 } 30071 }, 30072 propertyDescriptors : { 30073 validationsDisabled : { 30074 get : function () { 30075 return this._bParentValidationsDisabled || this._validationsDisabled; 30076 }, 30077 set : function (bValidationsDisabled) { 30078 var oldValidationsDisabled = this.validationsDisabled, 30079 newValidationsDisabled; 30080 this._validationsDisabled = bValidationsDisabled; 30081 newValidationsDisabled = this.validationsDisabled; 30082 this.handleChildValidationsDisabled(newValidationsDisabled, oldValidationsDisabled); 30083 } 30084 } 30085 } 30086 }; 30087 30088}(_, guidelib)); 30089(function (_, guidelib) { 30090 30091 30092 var GuideItemsContainer = guidelib.model.GuideItemsContainer = guidelib.model.Scriptable.extend({ 30093 msClassName : "guideItemsContainer", 30094 30095 initialize : function () { 30096 GuideItemsContainer._super.initialize.call(this); 30097 this._children = []; 30098 this._nameArray = {}; 30099 this._private = {}; 30100 this._initChildren(); 30101 this._normalizeChildren(); 30102 this._bParentValidationsDisabled = false;
30103 this._validationsDisabled = false; 30104 }, 30105 30106 _postInitialize : function () { 30107 30108 30109 GuideItemsContainer._super._postInitialize.call(this); 30110 _.each(this._children, function (childNode) { 30111 childNode._postInitialize(); 30112 }, this); 30113 }, 30114 30115 30116 validate : function (errorList) { 30117 var validationStatus = true, 30118 tempValidationStatus; 30119 30120 if (!this.visible) { 30121 return true; 30122 } 30123 if (_.isUndefined(errorList)) { 30124 errorList = []; 30125 } 30126 30127 var subContainerErrorArray = [], 30128 arrLen; 30129 _.each(this.children, function (child) { 30130 tempValidationStatus = child.validate(subContainerErrorArray); 30131 if (tempValidationStatus === false) { 30132 validationStatus = false; 30133 } 30134 }, this); 30135 30136 tempValidationStatus = GuideItemsContainer._super.validate.call(this, subContainerErrorArray); 30137 if (tempValidationStatus === false) { 30138 validationStatus = false; 30139 } 30140 arrLen = subContainerErrorArray.length; 30141 while (arrLen > 0) { 30142 errorList[errorList.length] = subContainerErrorArray[subContainerErrorArray.length - arrLen]; 30143 arrLen--; 30144 } 30145 return validationStatus; 30146 }, 30147 30148 prepare : function () { 30149 _.each(this._children, function (childNode) { 30150 childNode.prepare(); 30151 }, this); 30152 GuideItemsContainer._super.prepare.call(this); 30153 }, 30154 30155 syncXFAProps : function () { 30156 GuideItemsContainer._super.syncXFAProps.apply(this, arguments); 30157 _.each(this._children, function (childNode) { 30158 childNode.syncXFAProps(); 30159 }); 30160 }, 30161 30162 _initChildren : function (bLazyInitialization) { 30163 var panelItems = [], 30164 jsonModelItemsWithoutRepeatJson = {}, 30165 keyLengthForJsonWithoutRepeat = 0, 30166 keyLengthJsonItemsOriginal = 0; 30167 30168 30169 30170 30171 30172 _.each(this.jsonModel.items, function (item) { 30173 30174 30175 30176 if (item.templateId && item.templateId.indexOf("GUID") === -1) { 30177 jsonModelItemsWithoutRepeatJson[item.templateId] = item; 30178 } 30179 }); 30180 keyLengthForJsonWithoutRepeat = _.keys(jsonModelItemsWithoutRepeatJson).length; 30181 30182 keyLengthJsonItemsOriginal = _.keys(this.jsonModel.items || {}).length; 30183 if (keyLengthForJsonWithoutRepeat > 0 && keyLengthForJsonWithoutRepeat !== keyLengthJsonItemsOriginal) { 30184 this.jsonModel.items = jsonModelItemsWithoutRepeatJson; 30185 } 30186 _.each(this.jsonModel.items, 30187 function (item) { 30188 if (_.isObject(item)) { 30189 30190 30191 30192 30193 var options = {}; 30194 if (this.options._guideContainer) { 30195 options = _.extend({}, options, {"_guideContainer" : this.options._guideContainer}); 30196 } 30197 var panelItemModel = guidelib.model.GuideModelRegistry.prototype.createModel(item, options); 30198 panelItemModel._isItem = true; 30199 this._initializeChild(panelItemModel); 30200 panelItems.push(panelItemModel); 30201 } 30202 }, 30203 this); 30204 this._children = panelItems; 30205 }, 30206 30207 _initializeChild : function (childItem) { 30208 childItem.parent = this; 30209 }, 30210 30211 _normalizeChildren : function () { 30212 this._nameArray = {}; 30213 this._private = {}; 30214 _.each(this.children, function (child) { 30215 child._index = this._addProperty(child); 30216 30217 child.getNaked(child._index, guidelib.__runtime__, null); 30218 child.getNaked(child._index, this._guide().runtime, null); 30219 }, this); 30220 }, 30221 30222 nakedChildReferences : function (nIndex, obj) { 30223 var i, oNode; 30224 for (i = 0; i < this._children.length; i++) { 30225 oNode = this._children[i]; 30226 oNode.getNaked(nIndex, obj, this); 30227 } 30228 }, 30229 _getReducedJSON : function (isRepeatable) { 30230 var reducedJSONChildren, 30231 that = this, 30232 index = 0; 30233 30234 reducedJSONChildren = GuideItemsContainer._super._getReducedJSON.call(this); 30235 reducedJSONChildren.items = {}; 30236 30237 30238 30239 30240 _.each(this.jsonModel.items, function (childNode, key) { 30241 reducedJSONChildren.items[key] = that.items[index]._getReducedJSON(isRepeatable); 30242 index += 1; 30243 }); 30244 return reducedJSONChildren; 30245 }, 30246 30247 _addProperty : function (oValueObject) { 30248 var sName = oValueObject.getAttribute("name"), 30249 nIndex = 0; 30250 30251 30252 30253 this._nameArray[sName] = this._nameArray[sName] || nIndex; 30254 nIndex = this._nameArray[sName]++; 30255 if (nIndex === 0) { 30256 30257 30258 30259 30260 guidelib.util.GuideUtil._createGetterSetter(this, sName, oValueObject); 30261 } 30262 return nIndex; 30263 }, 30264 30265 _getTitle : function () { 30266 return this.jsonModel["jcr:title"]; 30267 }, 30268 30269 visit : function (callback, context) { 30270 GuideItemsContainer._super.visit.apply(this, arguments); 30271 _.each(this._children, function (child, index) { 30272 child.visit(callback, context); 30273 }); 30274 }, 30275 30276 playJson : function (pJsonModel) { 30277 if (pJsonModel) { 30278 var pJsonItems = _.filter(pJsonModel.items, function (item) { 30279 if (_.isObject(item)) { 30280 return true; 30281 } 30282 return false;
30283 }, this); 30284 30285 _.each(this.items, function (childNode, index) { 30286 childNode.playJson(pJsonItems[index]); 30287 }, this); 30288 GuideItemsContainer._super.playJson.call(this, pJsonModel); 30289 } 30290 30291 }, 30292 30293 _collectValues : function (keyValue) { 30294 _.each(this._children, function (childNode) { 30295 childNode._collectValues(keyValue); 30296 }, this); 30297 }, 30298 30299 getElement : function (elClassName) { 30300 var element = _.find(this._children, function (childModel) { 30301 return childModel.className === elClassName; 30302 }, this); 30303 return element; 30304 }, 30305 30306 30307 _unloadModel : function () { 30308 _.each(this.children, function (child) { 30309 child._unloadModel(); 30310 }, this); 30311 GuideItemsContainer._super._unloadModel.call(this); 30312 }, 30313 30314 _findChildren : function (oSOM, bMultiple) { 30315 var arr = [], 30316 elemFound = false; 30317 _.find(this._children, function (child) { 30318 if (oSOM === child._escapeQualifiedName()) { 30319 arr.push(child._getNakedThis()); 30320 elemFound = true; 30321 } 30322 if (elemFound && !bMultiple) { 30323 return true; 30324 } 30325 if (elemFound && oSOM.indexOf("[*]") < 0) { 30326 return true; 30327 } 30328 }, this); 30329 return arr; 30330 }, 30331 30332 30333 resetData : function () { 30334 _.each(this._children, function (childNode) { 30335 childNode.resetData(); 30336 }, this); 30337 }, 30338 30339 30340 _changeDescendantsAccess : function (value) { 30341 _.each(this.items, function (child) { 30342 child._setParentAccess(value); 30343 if (child instanceof guidelib.model.GuideItemsContainer) { 30344 child._changeDescendantsAccess(value); 30345 } 30346 }, this); 30347 }, 30348 30349 30350 _changeContainerAccess : function (value) { 30351 this._changeDescendantsAccess(value); 30352 }, 30353 30354 30355 _changeDescendantsProperty : function (value, property, leafNodesOnly) { 30356 _.each(this.items, function (child) { 30357 if (child instanceof guidelib.model.GuideItemsContainer) { 30358 if (!leafNodesOnly) { 30359 child[property] = value; 30360 } 30361 child._changeDescendantsProperty(value, property); 30362 } else { 30363 child[property] = value; 30364 } 30365 }, this); 30366 }, 30367 30368 30369 disableAllFields : function () { 30370 this.enabled = false; 30371 var property = "enabled"; 30372 this._changeDescendantsProperty(false, property, true); 30373 } 30374 30375 }); 30376 30377 GuideItemsContainer.defineProps({ 30378 children : { 30379 get : function () { 30380 return (this._children || []).slice(0); 30381 }, 30382 set : function (value) { 30383 this._children = value; 30384 } 30385 }, 30386 30387 30388 items : { 30389 get : function () { 30390 var itemChildren = _.filter(this._children, function (child) { 30391 if (child._isItem) { 30392 return true; 30393 } 30394 return false; 30395 }, this); 30396 return itemChildren; 30397 } 30398 }, 30399 30400 _selfOrAncestorIsLazyReference : { 30401 get : function () { 30402 if (this._lazyReference) { 30403 return true; 30404 } 30405 return guidelib.util.GuideUtil._checkIfAncestorIsALazyReference(this); 30406 } 30407 }, 30408 _lazyReference : { 30409 get : function () { 30410 return !_.isUndefined(this.jsonModel["fragRef"]) 30411 && !_.isUndefined(this.jsonModel["optimizeRenderPerformance"]); 30412 } 30413 } 30414 }); 30415 30416 GuideItemsContainer.addMixins([ 30417 guidelib.model.mixin.ValidationsDisabled 30418 ]); 30419 30420}(_, guidelib)); 30421 30422(function (_, guidelib) { 30423 var GuideToolbar = guidelib.model.GuideToolbar = guidelib.model.GuideItemsContainer.extend({ 30424 msClassName : "guideToolbar", 30425 30426 initialize : function () { 30427 GuideToolbar._super.initialize.call(this); 30428 }, 30429 30430 execNavigationChangeExpression : function () { 30431 _.each(this.items, function (childModel) { 30432 if (childModel.navigationChangeExp) { 30433 this._guide().queueExpressions(childModel, "navigationChangeExp"); 30434 } 30435 }, this); 30436 } 30437 30438 }); 30439 30440})(_, guidelib); 30441 30442(function (_, guidelib) { 30443 30444 30445 var GuideCompositeField = guidelib.model.GuideCompositeField = guidelib.model.GuideItemsContainer.extend({ 30446 msClassName : "guideCompositeField", 30447 initialize : function () { 30448 this._uuid = guideBridge._produceUUID(); 30449 GuideCompositeField._super.initialize.call(this); 30450 }, 30451 30452 _setGuideValue : function (value) { 30453 if (!_.isEmpty(value)) { 30454 _.each(this.items, function (item) { 30455 if (value.hasOwnProperty(item.name) && _.isFunction(item._setGuideValue)) { 30456 item._setGuideValue(value[item.name]); 30457 } 30458 }, this); 30459 } 30460 }, 30461 30462 _collectExpressions : function () { 30463 GuideCompositeField._super._collectExpressions.apply(this); 30464 if (this.valueCommitScript) { 30465 30466 this._compiledScripts.valueCommitScript = this._compileExpression(this.valueCommitScript, null); 30467 } 30468 } 30469 }); 30470 30471 GuideCompositeField.defineProps({ 30472 valueCommitScript : { 30473 get : function () { 30474 return this.getAttribute("valueCommitScript"); 30475 } 30476 }, 30477 uuid : { 30478 get : function () { 30479 return this._uuid; 30480 }, 30481 set : function (newUuid) { 30482 if (this._uuid != newUuid) { 30483 this._uuid = newUuid; 30484 } 30485 } 30486 } 30487 }); 30488 30489})(_, guidelib); 30490 30491(function (_, guidelib) { 30492 30493 var GuideTermsAndConditions = guidelib.model.GuideTermsAndConditions = guidelib.model.GuideCompositeField.extend({ 30494 msClassName : "guideTermsAndConditions", 30495 30496 playJson : function (pJsonModel) { 30497 this.jsonModel.clickStatus = pJsonModel.clickStatus; 30498 GuideTermsAndConditions._super.playJson.apply(this, arguments); 30499 }, 30500 30501 _updateLiveData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar) { 30502 this._syncModelAndData(bound_indexedXpathSoFar, unBound_indexedXpathSoFar, '_updateLiveData'); 30503 }, 30504 30505 _playLiveData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar) { 30506 this._syncModelAndData(bound_indexedXpathSoFar, unBound_indexedXpathSoFar, '_playLiveData'); 30507 if (this.reviewStatus.value === "true") { 30508 this.clickStatus = "agree"; 30509 } else { 30510 this.clickStatus = "unreviewed"; 30511 } 30512 }, 30513 30514 _syncModelAndData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar, recurse) { 30515 if (_.isString(recurse)) { 30516 var dataContext = this._guide().internal.liveDataUtils._getDataContext(this, bound_indexedXpathSoFar, unBound_indexedXpathSoFar); 30517 if (dataContext.xmlSec === this._guide().internal.liveDataUtils.constants.BOUND_TAG) { 30518 bound_indexedXpathSoFar = dataContext.indexedXpath; 30519 } else { 30520 unBound_indexedXpathSoFar = dataContext.indexedXpath; 30521 } 30522 _.each(this.items, function (item) { 30523 if (_.isFunction(item[recurse])) { 30524 item[recurse](bound_indexedXpathSoFar, unBound_indexedXpathSoFar); 30525 } 30526 }); 30527 } 30528 } 30529 }); 30530 30531 GuideTermsAndConditions.defineProps({ 30532 showLink : { 30533 get : function () { 30534 return this.getAttribute("showLink"); 30535 } 30536 }, 30537 30538 30539 clickStatus : { 30540 get : function () { 30541 return this.getAttribute("clickStatus"); 30542 }, 30543 set : function (status) { 30544 this.setAttribute(status, "clickStatus"); 30545 } 30546 }, 30547 30548 showAsPopUp : { 30549 get : function () { 30550 return this.getAttribute("showAsPopUp"); 30551 } 30552 } 30553 }); 30554 30555})(_, guidelib); 30556(function (_, guidelib) { 30557 30558 30559 var GuideFileUpload = guidelib.model.GuideFileUpload = guidelib.model.GuideCompositeField.extend({ 30560 msClassName : "guideFileUpload", 30561 30562 _getReducedJSON : function () { 30563 this._syncModelToAttachments(); 30564 var reducedJSONChildren = GuideFileUpload._super._getReducedJSON.call(this), 30565 addtionalWhitelistedProperties = ["id", "files"]; 30566 guidelib.model.util.CommonUtils.returnMinimalJSON(addtionalWhitelistedProperties, reducedJSONChildren, this); 30567 var fileAttachmentValue = reducedJSONChildren.files; 30568 reducedJSONChildren.files = this._getFileAttachmentNames(fileAttachmentValue); 30569 return reducedJSONChildren; 30570 }, 30571 30572 _getContentType : function(fileUrl) { 30573 var contentType = null, 30574 self = this; 30575 if (self._fileAttachmentWrapper) { 30576 var element = self._fileAttachmentWrapper.find(function(x) { return x.data === fileUrl}); 30577 if (element) { 30578 contentType = element.contentType; 30579 } 30580 } 30581 return contentType 30582 }, 30583 30584 30585 _getFileAttachmentNames : function (fileAttachmentValue) { 30586 var value = fileAttachmentValue || this.value; 30587 if (value) { 30588 var self = this, 30589 fileNames = _.map(value.split("\n"), function (val) { 30590 if (self._fileAttachmentWrapper) { 30591 var element = self._fileAttachmentWrapper.find(function(x) { return x.data === val}); 30592 if (element) { 30593 return element.name; 30594 } 30595 } 30596 var fName = val; 30597 30598 if (fName.lastIndexOf("/") === fName.length - 1) { 30599 fName = fName.substring(0, fName.length - 1); 30600 } 30601 return fName.substring(fName.lastIndexOf("/") + 1); 30602 }).join("\n"); 30603 return fileNames; 30604 } 30605 }, 30606 30607 _getInputFileSubmissionNames : function () { 30608 var fileNames = (this._getFileAttachmentNames() || "").split("\n"), 30609 fileList = this.fileList || [], 30610 submissionNames = [], 30611 fileNamesIndex = 0; 30612 _.each(fileList, function (inputFileDOM) { 30613 if (_.isString(inputFileDOM)) { 30614 fileNamesIndex++; 30615 return; 30616 } 30617 var files = inputFileDOM[0] && inputFileDOM[0].files; 30618 _.each(files, function () { 30619 submissionNames.push(fileNames[fileNamesIndex++]); 30620 }); 30621 }); 30622 return submissionNames; 30623 }, 30624 30625 _triggerFileListChange : function () { 30626 var currValue = this._fileList; 30627 this.trigger(guidelib.event.GuideModelEvent.MODEL_CHANGED, 30628 guidelib.event.GuideModelEvent.createEvent( 30629 guidelib.event.GuideModelEvent.MODEL_CHANGED, 30630 this, 30631 "fileList", 30632 currValue, 30633 currValue 30634 ) 30635 ); 30636 }, 30637 30638 _getCurrentFileAttachmentWrapper : function(attachments) { 30639 var currentListOfAttachments = null, 30640 effectiveBindRef = this._getEffectiveBindRef(), 30641 self = this; 30642 if (_.isArray(attachments) && attachments.length > 0) { 30643 currentListOfAttachments = attachments.filter(function(x) { 30644 return x.bindRef === effectiveBindRef; 30645 }) 30646 } 30647 return currentListOfAttachments; 30648 }, 30649 30650 _playAttachmentWrappers : function(currentAttachmentWrappers) { 30651 var currValue = this.fileAttachment.value, 30652 _guide = this._guide(); 30653 if (_.isArray(currentAttachmentWrappers) && currentAttachmentWrappers.length > 0) { 30654 this._fileAttachmentWrapper = currentAttachmentWrappers; 30655 30656 if (this.valueCommitScript && _guide.version.isOn(_guide.version.Flags.RUN_VALUE_COMMMIT_ON_PREFILL) && currValue) { 30657 30658 _guide.queueExpressions(this, ["valueCommitScript"]); 30659 } 30660 var data = currentAttachmentWrappers.map(function(x) {return x.data}); 30661 30662 var fieldValue = data.join("\n"); 30663 this.fileAttachment._setGuideValue(fieldValue); 30664 if (!_.isEmpty(fieldValue)) { 30665 this._fileList = fieldValue.split("\n"); 30666 } 30667 } 30668 }, 30669 30670 playJson : function (pJsonModel, attachments) { 30671 if (attachments) { 30672 var currentListOfAttachments = this._getCurrentFileAttachmentWrapper(attachments); 30673 this._playAttachmentWrappers(currentListOfAttachments); 30674 } else { 30675 30676 GuideFileUpload._super.playJson.call(this, pJsonModel); 30677 } 30678 }, 30679 30680 _syncModelToAttachments : function () { 30681 var files = this.fileAttachment.value || "", 30682 filesArray = files.split('\n'), 30683 uniqueNames = guideBridge._makeFileNameUnique(); 30684 var isIOS = guidelib.util.GuideUtil._isIOS(); 30685 var files = this.fileAttachment.value || "", 30686 filesArray = files.split('\n'), 30687 areNamesUnique = (new Set(filesArray)).size === filesArray.length; 30688 this.jsonModel.files = 30689 _.map(files.split('\n'), function (file, index) { 30690 if (!_.isEmpty(file)) { 30691 if ((uniqueNames || (!areNamesUnique && isIOS)) && file[0] !== '/') { 30692 file = this.uuid + "-" + (index + 1) + "__afAttachment__" + file; 30693 } 30694 } 30695 return file; 30696 }, this).join('\n'); 30697 }, 30698 30699 _updateLiveData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar) { 30700 this._syncModelAndData(bound_indexedXpathSoFar, unBound_indexedXpathSoFar, "_updateLiveData"); 30701 }, 30702 30703 _playLiveData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar) { 30704 this._syncModelAndData(bound_indexedXpathSoFar, unBound_indexedXpathSoFar, "_playLiveData"); 30705 }, 30706 30707 _handleFileAttachmentItem : function (fileAttachmentModel, bound_indexedXpathSoFar, unBound_indexedXpathSoFar, recurse) { 30708 30709 var dataUtils = this._guide().internal.liveDataUtils, 30710 dataContext = dataUtils._getDataContext(fileAttachmentModel, bound_indexedXpathSoFar, unBound_indexedXpathSoFar); 30711 if (recurse == "_updateLiveData") { 30712 dataUtils._updateLazyAttachmentMapFromModel(this); 30713 dataUtils.setDataValue(dataContext.indexedXpath, dataContext.xmlSec, 30714 !fileAttachmentModel.isEmpty(), fileAttachmentModel.isEmpty() ? "" : this._getFileAttachmentValue()); 30715 } else { 30716 var data = dataUtils._getAttachmentDataForModel(this); 30717 if (!_.isArray(data) && !_.isEmpty(data)) { 30718 this.fileList = data.fileList; 30719 var fileAttachmentValue = []; 30720 var value = data.value.split("\n"); 30721 _.each(value, function (value, index) { 30722 if (value[0] != '/')
30722 { 30723 30724 30725 var name = value.substr(value.lastIndexOf("_") + 1); 30726 fileAttachmentValue.push(name); 30727 } else { 30728 30729 fileAttachmentValue.push(value); 30730 } 30731 }); 30732 fileAttachmentModel.value = fileAttachmentValue.join("\n"); 30733 } 30734 if (_.isArray(data) && data.length > 0) { 30735 this._playAttachmentWrappers(data); 30736 } 30737 this._syncModelToAttachments(); 30738 } 30739 }, 30740 30741 _syncModelAndData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar, recurse) { 30742 if (_.isString(recurse)) { 30743 var liveDataUtils = this._guide().internal.liveDataUtils; 30744 var dataContext = liveDataUtils._getDataContext(this, bound_indexedXpathSoFar, unBound_indexedXpathSoFar); 30745 if (dataContext.xmlSec === liveDataUtils.constants.BOUND_TAG) { 30746 bound_indexedXpathSoFar = dataContext.indexedXpath; 30747 } else { 30748 unBound_indexedXpathSoFar = dataContext.indexedXpath; 30749 } 30750 _.each(this.items, function (item) { 30751 if (_.isFunction(item[recurse])) { 30752 if (item.name == "fileAttachment") { 30753 30754 30755 this._handleFileAttachmentItem(item, bound_indexedXpathSoFar, unBound_indexedXpathSoFar, recurse); 30756 } else { 30757 item[recurse](bound_indexedXpathSoFar, unBound_indexedXpathSoFar); 30758 } 30759 } 30760 }, this); 30761 } 30762 }, 30763 30764 30765 _getIndexedXpath : function (model, bound_indexedXpathSoFar, unBound_indexedXpathSoFar) { 30766 var name = model.getAttribute("name").replace(/\s+/g, ''); 30767 return unBound_indexedXpathSoFar ? unBound_indexedXpathSoFar + '/' + name : bound_indexedXpathSoFar + '/' + name; 30768 }, 30769 30770 30771 _getFileAttachmentValue : function () { 30772 30773 30774 30775 this._syncModelToAttachments(); 30776 return this._getFileAttachmentNames(this.jsonModel.files); 30777 } 30778 30779 }); 30780 30781 GuideFileUpload.defineProps({ 30782 30783 multiSelection : { 30784 get : function () { 30785 return this.getAttribute("multiSelection"); 30786 } 30787 }, 30788 30789 buttonText : { 30790 get : function () { 30791 return this.getAttribute("buttonText"); 30792 } 30793 }, 30794 30795 showComment : { 30796 get : function () { 30797 return this.getAttribute("showComment"); 30798 } 30799 }, 30800 30801 30802 fileSizeLimit : { 30803 get : function () { 30804 return this.getAttribute("fileSizeLimit"); 30805 } 30806 }, 30807 30808 fileList : { 30809 get : function () { 30810 return this._fileList; 30811 }, 30812 30813 set : function (newValue) { 30814 var oldValue = this._fileList; 30815 var newTypedValue = newValue; 30816 if (newTypedValue != oldValue) { 30817 this._fileList = newTypedValue; 30818 } 30819 30820 30821 30822 var isIOS = guidelib.util.GuideUtil._isIOS(), 30823 fileList = this._fileList, 30824 that = this; 30825 if (isIOS && fileList) { 30826 30827 this._fileAttachmentWrapperIOS = []; 30828 30829 for (var i = 0; i < fileList.length; i++) { 30830 if (!_.isString(fileList[i])) { 30831 30832 var files = fileList[i].get(0).files, 30833 _readFile = function (file) { 30834 30835 that._fileAttachmentWrapperIOS.push( 30836 new Promise(function(resolve, reject){ 30837 var reader = new FileReader(); 30838 reader.onload = function() { 30839 var faWrapper = new guidelib.model.FileAttachmentWrapper({ 30840 name: file.name, 30841 data: this.result, 30842 formElementName : that.name, 30843 contentType: file.type, 30844 bindRef: that._getEffectiveBindRef() 30845 }); 30846 resolve(faWrapper); 30847 }; 30848 reader.onerror = reject;
30849 reader.readAsDataURL(file); 30850 }) 30851 ) 30852 }; 30853 if (files) { 30854 30855 [].forEach.call(files, _readFile); 30856 } 30857 } 30858 } 30859 } 30860 this._triggerFileListChange(); 30861 } 30862 }, 30863 value : { 30864 get : function () { 30865 this._syncModelToAttachments(); 30866 return this.jsonModel.files; 30867 } 30868 } 30869 }); 30870 30871})(_, guidelib); 30872(function (_, guidelib) { 30873 var GuideAdModuleGroup = guidelib.model.GuideAdModuleGroup = guidelib.model.GuideItemsContainer.extend({ 30874 msClassName : "guideAdModuleGroup", 30875 30876 _getTypedValue : function (value) { 30877 30878 if (_.isUndefined(value) || value === null) { 30879 return null; 30880 } 30881 return value + ""; 30882 }, 30883 30884 playJson : function (pJsonModel) { 30885 var typedValue = this._getTypedValue(pJsonModel._value); 30886 30887 if (typedValue || typedValue === "") { 30888 30889 var olval = this.jsonModel._value; 30890 this.jsonModel._value = pJsonModel._value; 30891 this._triggerOnBridge("elementValueChanged", this, "value", olval, this.jsonModel._value); 30892 } else { 30893 30894 GuideAdModuleGroup._super.playJson.call(this, pJsonModel); 30895 } 30896 } 30897 }); 30898 30899 GuideAdModuleGroup.defineProps({ 30900 30901 value : { 30902 get : function () { 30903 return this._getTypedValue(this.jsonModel._value); 30904 }, 30905 set : function (newValue) { 30906 var oldValue = this._getTypedValue(this.jsonModel._value), 30907 newTypedValue = this._getTypedValue(newValue); 30908 30909 if (newTypedValue !== undefined && (newTypedValue !== oldValue)) { 30910 if (this.jsonModel._value !== newValue) { 30911 this.jsonModel._value = newTypedValue || ""; 30912 } 30913 this._triggerOnBridge("elementValueChanged", this, "value", oldValue, newTypedValue); 30914 } 30915 } 30916 } 30917 }); 30918 30919}(_, guidelib)); 30920(function (_, guidelib) { 30921 guidelib.model.mixin.AddDependencyMgmt = { 30922 normalProperties : { 30923 _addDependant : function (oNode, expressionType) { 30924 var dependantConf = this._findDependant(oNode); 30925 if (!dependantConf) { 30926 dependantConf = {dependant : oNode, events : []}; 30927 this.dependants.push(dependantConf); 30928 } 30929 30930 if (dependantConf.events.indexOf(expressionType) < 0) { 30931 dependantConf.events.push(expressionType); 30932 oNode.on(guidelib.event.GuideModelEvent.OBJECT_DESTROYED, this._handleDependentDestroyed, this); 30933 } 30934 }, 30935 30936 _notifyDependants : function () { 30937 _.each(this.dependants, function (dependantConf) { 30938 this._guide().queueExpressions(dependantConf.dependant, dependantConf.events); 30939 }, this); 30940 }, 30941 30942 _removeDependant : function (oNode) { 30943 oNode.off(guidelib.event.GuideModelEvent.OBJECT_DESTROYED, this._handleDependentDestroyed, this); 30944 var dependantConf = this._findDependant(oNode); 30945 this.dependants = _.without(this.dependants, dependantConf); 30946 }, 30947 30948 _findDependant : function (oNode) { 30949 return _.find(this.dependants, function (conf) { return (conf.dependant === oNode); }); 30950 }, 30951 30952 _handleDependentDestroyed : function (event) { 30953 this._removeDependant(event.target); 30954 } 30955 } 30956 }; 30957})(_, guidelib); 30958 30959(function (_, guidelib) { 30960 var GuideChart = guidelib.model.GuideChart = guidelib.model.Scriptable.extend({ 30961 msClassName : "guideChart", 30962 30963 _collectExpressions : function () { 30964 GuideChart._super._collectExpressions.apply(this); 30965 this._compiledExpressions["aggregateExp"] = this._compileExpression('guidelib.chartUtils.gatherAxisData(this);', "data"); 30966 } 30967 }); 30968 30969 GuideChart.defineProps({ 30970 30971 data : { 30972 get : function () { 30973 var context = this._guide()._currentContext; 30974 if (context && context.contextNode && context.expression 30975 && !(context.contextNode === this && context.expression === "aggregateExp")) { 30976 this._addDependant(context.contextNode, context.expression); 30977 } 30978 return this.jsonModel.data; 30979 }, 30980 30981 set : function (newValue) { 30982 var oldValue = this.jsonModel.data; 30983 this.jsonModel.data = newValue; 30984 30985 var valueHasChanged = !_.isEqual(oldValue, newValue); 30986 if (valueHasChanged) { 30987 30988 this._notifyDependants(); 30989 this._triggerEvent(guidelib.event.GuideModelEvent.MODEL_CHANGED, "data", oldValue, newValue); 30990 } 30991 } 30992 }, 30993 30994 30995 dataSourceType : { 30996 get : function () { 30997 return this.getAttribute("dataSourceType"); 30998 }, 30999 set : function (newValue) { 31000 var oldValue = this.jsonModel.dataSourceType; 31001 this.jsonModel.dataSourceType = newValue; 31002 this._triggerEvent(guidelib.event.GuideModelEvent.MODEL_CHANGED, "dataSourceType", oldValue, newValue); 31003 } 31004 }, 31005 31006 31007 width : { 31008 get : function () { 31009 return this.getAttribute("width"); 31010 }, 31011 31012 set : function (newValue) { 31013 this.jsonModel.width = newValue; 31014 } 31015 }, 31016 31017 height : { 31018 get : function () { 31019 return this.getAttribute("height"); 31020 }, 31021 31022 set : function (newValue) { 31023 this.jsonModel.height = newValue; 31024 } 31025 }, 31026 31027 xAxisTitle : { 31028 get : function () { 31029 return this.getAttribute("xAxisTitle"); 31030 }, 31031 set : function (newValue) { 31032 this.jsonModel.chartType = newValue; 31033 } 31034 }, 31035 31036 yAxisTitle : { 31037 get : function () { 31038 return this.getAttribute("yAxisTitle"); 31039 }, 31040 set : function (newValue) { 31041 this.jsonModel.chartType = newValue; 31042 } 31043 }, 31044 31045 chartType : { 31046 get : function () { 31047 return this.getAttribute("chartType"); 31048 }, 31049 set : function (newValue) { 31050 var oldValue = this.jsonModel.chartType; 31051 this.jsonModel.chartType = newValue; 31052 this._triggerEvent(guidelib.event.GuideModelEvent.MODEL_CHANGED, "chartType", oldValue, newValue); 31053 } 31054 }, 31055 31056 repeatableItem : { 31057 get : function () { 31058 return this.getAttribute("repeatableItem"); 31059 }, 31060 set : function (newValue) { 31061 this.jsonModel.repeatableItem = newValue; 31062 } 31063 }, 31064 31065 xExp : { 31066 get : function () { 31067 return this.getAttribute("xExp"); 31068 }, 31069 set : function (newValue) { 31070 this.jsonModel.xExp = newValue; 31071 } 31072 }, 31073 31074 reducerXFunction : { 31075 get : function () { 31076 return this.getAttribute("reducerXFunction"); 31077 }, 31078 set : function (newValue) { 31079 this.jsonModel.reducerXFunction = newValue; 31080 if (newValue !== 'none') {
31081 this.jsonModel.reducerYFunction = 'none'; 31082 } 31083 } 31084 }, 31085 31086 yExp : { 31087 get : function () { 31088 return this.getAttribute("yExp"); 31089 }, 31090 set : function (newValue) { 31091 this.jsonModel.yExp = newValue; 31092 } 31093 }, 31094 31095 reducerYFunction : { 31096 get : function () { 31097 return this.getAttribute("reducerYFunction"); 31098 }, 31099 set : function (newValue) { 31100 this.jsonModel.reducerYFunction = newValue; 31101 if (newValue !== 'none') { 31102 this.jsonModel.reducerXFunction = 'none'; 31103 } 31104 } 31105 }, 31106 31107 innerRadius : { 31108 get : function () { 31109 return this.getAttribute("innerRadius"); 31110 }, 31111 set : function (newValue) { 31112 this.jsonModel.innerRadius = newValue; 31113 } 31114 }, 31115 31116 lineColor : { 31117 get : function () { 31118 return this.getAttribute("lineColor"); 31119 }, 31120 set : function (newValue) { 31121 this.jsonModel.lineColor = newValue; 31122 } 31123 }, 31124 31125 pointColor : { 31126 get : function () { 31127 return this.getAttribute("pointColor"); 31128 }, 31129 set : function (newValue) { 31130 this.jsonModel.pointColor = newValue; 31131 } 31132 }, 31133 31134 areaColor : { 31135 get : function () { 31136 return this.getAttribute("areaColor"); 31137 }, 31138 set : function (newValue) { 31139 this.jsonModel.areaColor = newValue; 31140 } 31141 }, 31142 31143 tooltipHtml : { 31144 get : function () { 31145 return this.getAttribute("tooltipHtml"); 31146 }, 31147 set : function (newValue) { 31148 this.jsonModel.tooltipHtml = newValue; 31149 } 31150 }, 31151 31152 showLegends : { 31153 get : function () { 31154 return this.getAttribute("showLegends"); 31155 }, 31156 set : function (newValue) { 31157 this.jsonModel.showLegends = newValue; 31158 } 31159 }, 31160 31161 legendPosition : { 31162 get : function () { 31163 return this.getAttribute("legendPosition"); 31164 }, 31165 set : function (newValue) { 31166 this.jsonModel.legendPosition = newValue; 31167 } 31168 } 31169 }); 31170 31171 GuideChart.addMixins([ 31172 guidelib.model.mixin.AddDependencyMgmt 31173 ]); 31174}(_, guidelib)); 31175(function (_, guidelib) { 31176 31177 var GuideInstanceManager = guidelib.model.GuideInstanceManager = guidelib.model.GuideNode.extend({ 31178 msClassName : "guideInstanceManager", 31179 initialize : function () { 31180 GuideInstanceManager._super.initialize.call(this); 31181 this._instances = []; 31182 this.dependants = []; 31183 this.deafen = false; 31184 this._bindPending = true; 31185 }, 31186 31187 _postInitializeBinding : function () { 31188 31189 31190 31191 if (!this._bindPending) { 31192 return; 31193 } else { 31194 this._bindPending = false; 31195 } 31196 31197 31198 31199 31200 31201 31202 var instance = this._instances[this.instanceCount - 1]; 31203 if (!instance) { 31204 this.logger().log("There was no instance found for InstanceManager at postInitialize:" + this.somExpression); 31205 } 31206 if (instance.bindNode && instance.bindNode.instanceManager) { 31207 this.bindNode = instance.bindNode.instanceManager; 31208 this.bindNode.parent.on(xfalib.script.XfaModelEvent.CHILD_ADDED, this); 31209 this.bindNode.parent.on(xfalib.script.XfaModelEvent.CHILD_REMOVED, this); 31210 } 31211 }, 31212 31213 _unloadModel : function () { 31214 var instance = this._instances[this.instanceCount - 1]; 31215 31216 if (instance.bindNode && instance.bindNode.instanceManager) { 31217 this.bindNode.parent.off(xfalib.script.XfaModelEvent.CHILD_ADDED, this); 31218 this.bindNode.parent.off(xfalib.script.XfaModelEvent.CHILD_REMOVED, this); 31219 } 31220 31221 GuideInstanceManager._super._unloadModel.call(this); 31222 }, 31223 31224 31225 handleEvent : function (event) { 31226 if (!this.deafen && event instanceof xfalib.script.XfaModelEvent) { 31227 switch (event.name) { 31228 case xfalib.script.XfaModelEvent.CHILD_ADDED: 31229 var addedInstance = event.newText; 31230 if (addedInstance.instanceManager == this.bindNode) { 31231 this._insertInstance(addedInstance.instanceIndex, addedInstance); 31232 } 31233 break; 31234 case xfalib.script.XfaModelEvent.CHILD_REMOVED: 31235 var removedInstance = event.prevText; 31236 if (removedInstance.instanceManager == this.bindNode) { 31237 this._removeInstance(removedInstance.instanceIndex, false); 31238 } 31239 break; 31240 case xfalib.script.XfaModelEvent.CHILD_MOVED: 31241 this.logger().log("CHILD_REMOVED should never be dispatched. It's achieved via ad and remove child."); 31242 break; 31243 default: 31244 31245 break; 31246 } 31247 } 31248 }, 31249 31250 _instanceTemplate : function () { 31251 return this._guide()._modelTemplateCacheStore.cloneJsonTemplate(this.jsonModel.instanceTemplateId); 31252 }, 31253 31254 31255 addInstance : function (addedXfaInstance) { 31256 return this._insertInstance(undefined, addedXfaInstance); 31257 }, 31258 31259 31260 addInstances : function (instancesConfig, addedXfaInstances) { 31261 var instanceCount = instancesConfig.instanceCount, 31262 instancesToAdd, availableInstances; 31263 if (this.maxOccur == -1) { 31264 instancesToAdd = instanceCount; 31265 }else { 31266 availableInstances = this.maxOccur - this.instanceCount; 31267 31268 instancesToAdd = instanceCount > availableInstances ? availableInstances : instanceCount; 31269 } 31270 var oChildsAdded = []; 31271 for (var i = 0; i < instancesToAdd ; i++) { 31272 oChildsAdded.push(this._insertInstance(undefined, addedXfaInstances, true)); 31273 } 31274 var oParentContainer = this.parent; 31275 oParentContainer._triggerEvent(guidelib.event.GuideModelEvent.MULTIPLE_CHILD_ADDED, "multipleChildAdded", 31276 null, oChildsAdded); 31277 }, 31278 31279 _manageChild : function (oCreatedChild, nIndex) { 31280 oCreatedChild._instanceManager = this; 31281 if (nIndex === undefined) { 31282 this._instances.push(oCreatedChild); 31283 } else { 31284 this._instances.splice(nIndex, 0, oCreatedChild); 31285 } 31286 }, 31287 31288 31289 _insertInstance : function (nIndex, addedXfaInstance, muteEvent) { 31290 if ((+this.maxOccur >= 0) && (+this.maxOccur == this.instanceCount)) { 31291 return null; 31292 } 31293 31294 if (nIndex !== undefined && nIndex > +this.maxOccur && +this.maxOccur > -1) { 31295 return null; 31296 } 31297 31298 var addedBindNode = addedXfaInstance; 31299 if (addedXfaInstance && this.bindNode == null) { 31300 this.logger().error("AF", "Invalid argument addedXfaInstance."); 31301 } 31302 if (!addedXfaInstance && this.bindNode) { 31303 this.deafen = true; 31304 try { 31305 31306 addedBindNode = this.bindNode.insertInstance(nIndex); 31307 } 31308 finally { 31309 this.deafen = false;
31310 } 31311 } 31312 var template = this._instanceTemplate(); 31313 31314 31315 31316 var clonedJson = {}; 31317 var uniquePrefix = this.guideUtil.generateUID(), 31318 that = this; 31319 this.copyObject(template, clonedJson, 31320 { 31321 transformMaps : { 31322 "id" : function (srcValue, options, parentObj) { 31323 return uniquePrefix + "__" + parentObj.templateId; 31324 }, 31325 31326 31327 31328 "bindRef" : function (originalBindRef, options, src) { 31329 if (addedBindNode != null && that.bindNode != null) { 31330 if (template.bindRef === originalBindRef) { 31331 return addedBindNode.somExpression; 31332 } else if (originalBindRef.substring(0, template.bindRef.length) === template.bindRef) { 31333 return originalBindRef.replace(template.bindRef, addedBindNode.somExpression); 31334 } 31335 } 31336 31337 return originalBindRef; 31338 } 31339 } 31340 } 31341 ); 31342 31343 var options = ((addedBindNode && this.bindNode) ? {bindNode : addedBindNode} : null); 31344 if (this.options._guideContainer) { 31345 options = _.extend({}, options, {"_guideContainer" : this.options._guideContainer}); 31346 } 31347 var oChildAdded = guidelib.model.GuideModelRegistry.prototype.createModel(clonedJson, options); 31348 if (oChildAdded != null) { 31349 31350 31351 31352 this._manageChild(oChildAdded, nIndex); 31353 var oParentContainer = this.parent; 31354 if (oParentContainer != null) { 31355 if (this._instances.length > 0) { 31356 31357 31358 31359 31360 nIndex = nIndex !== undefined ? nIndex : this._instances.length - 1 ; 31361 if(nIndex === 0 ) { 31362 31363 31364 31365 oParentContainer._addChildAt(oChildAdded, oParentContainer._children.indexOf(this) + 1, muteEvent); 31366 } else { 31367 var lastInstanceIndex = oParentContainer._children.indexOf(this._instances[nIndex - 1]); 31368 oParentContainer._addChildAt(oChildAdded, lastInstanceIndex + 1, muteEvent); 31369 } 31370 } else { 31371 31372 31373 31374 31375 oParentContainer._addChildAt(oChildAdded, oParentContainer._children.indexOf(this) + 1, muteEvent); 31376 } 31377 var guideStateConstants = guidelib.model.GuideSchema.prototype.GuideStateConstants; 31378 var dataUtils = this._guide().internal.liveDataUtils; 31379 if (this._isDataNodeUpdateRequired(oChildAdded)) { 31380 var parentNode = dataUtils.getParentDataNode(this._getDataContext(oChildAdded), true, {}); 31381 var index = dataUtils._convertModelIndexToDataIndex(oChildAdded.instanceIndex); 31382 var node = dataUtils._getElement(parentNode, oChildAdded._getDataNodeName(), {index : index}); 31383 31384 31385 if (!node || (node && !(oChildAdded.instanceIndex == this._instances.length - 1))) { 31386 var dataNode = dataUtils.insertNode(parentNode, oChildAdded._getDataNodeName(), oChildAdded.instanceIndex); 31387 if (!dataNode) { 31388 this.logger().warn("AF", "Unable to store the data of the element"); 31389 } 31390 } 31391 } 31392 } 31393 this._execExpressions(nIndex); 31394 return oChildAdded; 31395 } else { 31396 this.logger().log("guide", "insertInstance could not create child" + this.jsonModel.instanceTemplateId); 31397 } 31398 return null; 31399 }, 31400 31401 31402 insertInstance : function (nIndex) { 31403 return this._insertInstance(nIndex); 31404 }, 31405 31406 31407 removeInstance : function (index) { 31408 this._removeInstance(index, true); 31409 }, 31410 31411 31412 _removeInstance : function (index, removeXfaInstance) { 31413 31414 if (this.instanceCount == 0 || this.minOccur >= this.instanceCount) { 31415 return; 31416 } 31417 31418 if (index >= +this.instanceCount) { 31419 return; 31420 } 31421 31422 if (removeXfaInstance && this.bindNode) { 31423 this.deafen = true; 31424 try { 31425 this.bindNode.removeInstance(index); 31426 } 31427 finally { 31428 this.deafen = false;
31429 } 31430 } 31431 31432 31433 31434 var oChild = this._instances[index]; 31435 var dataUtils = this._guide().internal.liveDataUtils; 31436 if (this._isDataNodeUpdateRequired(oChild)) { 31437 var parentNode = dataUtils.getParentDataNode(this._getDataContext(oChild)); 31438 dataUtils.removeChild(parentNode, oChild._getDataNodeName(), oChild.instanceIndex); 31439 } 31440 this._instances.splice(index, 1); 31441 var parent = oChild.parent; 31442 parent._removeChild(oChild); 31443 this._execExpressions(index); 31444 }, 31445 31446 _isDataNodeUpdateRequired : function (child) { 31447 var guideStateConstants = guidelib.model.GuideSchema.prototype.GuideStateConstants, 31448 guide = guideBridge._guide; 31449 return guide && guide.getGuideState() === guideStateConstants.GUIDE_STATE_MODEL_COMPLETE 31450 && child._hasLazyDescendant; 31451 }, 31452 31453 _getDataContext : function (model) { 31454 var dataUtils = this._guide().internal.liveDataUtils, 31455 elementContext = dataUtils._getXpathContext(model), 31456 xmlContext = dataUtils._getDataContext(model, elementContext.bound, 31457 elementContext.unBound), 31458 xpath = xmlContext.indexedXpath; 31459 xpath = dataUtils.addIndexToPath(xpath, model.instanceIndex); 31460 return { 31461 indexedXpath : xpath, 31462 xmlSec : xmlContext.xmlSec 31463 }; 31464 }, 31465 31466 _getInstanceName : function () { 31467 return this.jsonModel.instanceName; 31468 }, 31469 31470 _instanceIsTableRow : function () { 31471 31472 return this._instanceTemplate()["guideNodeClass"] === "guideTableRow"; 31473 }, 31474 31475 31476 _execExpressions : function (modifiedIndex) { 31477 try { 31478 31479 this._notifyDependants(); 31480 31481 31482 for (var i = modifiedIndex; i < this.instances.length; i++) { 31483 this.instances[i]._notifyDependants(); 31484 } 31485 31486 this._guide().runPendingExpressions(); 31487 } catch (ex) { 31488 this.logger().error("guide", ex.message); 31489 } 31490 } 31491 31492 }); 31493 GuideInstanceManager.defineProps({ 31494 31495 minOccur : { 31496 get : function () { 31497 var isTableRow = this._instanceIsTableRow(); 31498 31499 if (isTableRow) { 31500 return ((+this.jsonModel.minOccur) || 1); 31501 } else { 31502 return this.getOrElse(this.jsonModel.minOccur, 1); 31503 } 31504 } 31505 }, 31506 31507 31508 maxOccur : { 31509 get : function () { 31510 return this.getOrElse(this.jsonModel.maxOccur, 1); 31511 } 31512 }, 31513 31514 initialOccur : { 31515 get : function () { 31516 return this.getOrElse(this.jsonModel.initialOccur, 1); 31517 } 31518 }, 31519 31520 31521 instanceTemplateId : { 31522 get : function () { 31523 return this.jsonModel.instanceTemplateId; 31524 } 31525 }, 31526 31527 31528 instanceCount : { 31529 get : function () { 31530 var context = this._guide()._currentContext; 31531 if (context && context.managedExp) { 31532 31533 this._addDependant(context.contextNode, context.expression); 31534 } 31535 return this._instances.length ; 31536 } 31537 }, 31538 31539 31540 repeatable : { 31541 get : function () { 31542 return (this.minOccur != 1 || this.maxOccur != 1); 31543 } 31544 }, 31545 31546 instances : { 31547 31548 get : function () { 31549 var context = this._guide()._currentContext; 31550 if (context && context.managedExp) { 31551 31552 this._addDependant(context.contextNode, context.expression); 31553 } 31554 return (this._instances || []).slice(0); 31555 } 31556 } 31557 }); 31558 31559 GuideInstanceManager.addMixins([ 31560 guidelib.model.mixin.AddDependencyMgmt 31561 ]); 31562})(_, guidelib); 31563(function (_, guidelib) { 31564 31565 31566 var Field = guidelib.model.Field = guidelib.model.Scriptable.extend({ 31567 msClassName : "field", 31568 31569 _runValidation : true, 31570 initialize : function () { 31571 Field._super.initialize.call(this); 31572 this.jsonModel["{default}"] = this.getOrElse(this.jsonModel, "{default}", this.jsonModel._value); 31573 this.isValid = true; 31574 this.forceErrorShow = false;
31575 31576 this._bParentValidationsDisabled = false; 31577 31578 this._validationsDisabled = false; 31579 31580 this._failedTest = null; 31581 31582 31583 this._errorText = ""; 31584 31585 var effectiveBindRef = this._getEffectiveBindRef(); 31586 31587 if (this.isGlobal || (this._guide() && this._guide().internal.liveModel.isLive(effectiveBindRef))) { 31588 this._guide().internal.liveModel.add(effectiveBindRef, this); 31589 } 31590 }, 31591 _postInitialize: function() { 31592 Field._super._postInitialize.call(this); 31593 if (this.getAttribute("dorExclusion") !== null && this.jsonModel.visible === false) { 31594 if ((this._guide().getAttribute("excludeFromDoRIfHidden") === "true") 31595 || 31596 (this._guide().print && 31597 this._guide().print["excludeFromDoRIfHidden"] === "true")) { 31598 this.dorExclusion = true; 31599 } 31600 } 31601 }, 31602 _unloadModel : function () { 31603 var effectiveBindRef = this.bindRef || this.getAttribute("name"); 31604 if (this.isGlobal || this._guide().internal.liveModel.isLive(effectiveBindRef)) { 31605 this._guide().internal.liveModel.remove(effectiveBindRef, this); 31606 } 31607 Field._super._unloadModel.call(this); 31608 }, 31609 31610 _collectExpressions : function () { 31611 Field._super._collectExpressions.apply(this); 31612 if (this.calcExp) { 31613 this._compiledExpressions.calcExp = this._compileExpression(this.calcExp, "value"); 31614 } 31615 if (this.validateExp) { 31616 31617 this._compiledScripts.validateExp = this._compileExpression(this.validateExp, null); 31618 } 31619 if (this.valueCommitScript) { 31620 31621 31622 this._compiledScripts.valueCommitScript = this._compileExpression(this.valueCommitScript, null); 31623 } 31624 31625 this._compiledScripts.validateAllExp = this._compileExpression("this._runTests()", null); 31626 }, 31627 31628 _handleXfaModelChanged : function (event) { 31629 if (event._property === "rawValue") { 31630 this._triggerEvent(guidelib.event.GuideModelEvent.VALUE_CHANGED, "value", 31631 event.prevText, event.newText); 31632 } else if (event._property == "ClearError" || event._property == "ValidationState") { 31633 31634 this._guide().queueExpressions(this, ["validateAllExp"]); 31635 } else { 31636 Field._super._handleXfaModelChanged.call(this, event); 31637 } 31638 }, 31639 31640 31641 31642 validate : function (errorList) { 31643 31644 if (!this.visible) { 31645 return true; 31646 } 31647 if (_.isUndefined(errorList)) { 31648 errorList = []; 31649 } 31650 var status = true; 31651 this._runTests(true); 31652 if (this._errorText) { 31653 errorList.push({ 31654 som : this.somExpression, 31655 errorText : this._errorText 31656 }); 31657 status = false; 31658 } 31659 return status; 31660 }, 31661 31662 _getTypedValue : function (value) { 31663 if (this.checkIfNull(value)) { 31664 return null; 31665 } 31666 return value + ""; 31667 }, 31668 31669 _getFormattedValue : function (value) { 31670 if (_.isUndefined(value) || value === null || value === "") { 31671 return null; 31672 } 31673 31674 var picture = this.jsonModel.displayPictureClause; 31675 31676 if (picture) { 31677 try { 31678 31679 var formattedValue = xfalib.ut.PictureFmt.format(value + "", picture, null, true); 31680 31681 return formattedValue != null && formattedValue !== "" ? formattedValue : value; 31682 } catch (exception) { 31683 31684 } 31685 } 31686 return value; 31687 }, 31688 31689 _getValue : function () { 31690 if (this.bindNode) { 31691 return this.bindNode.rawValue; 31692 } 31693 return this._getTypedValue(this.jsonModel._value); 31694 }, 31695
31696 _triggerDisplayFormatChange : function () { 31697 var currValue = this._getValue(); 31698 this._triggerEvent(guidelib.event.GuideModelEvent.VALUE_CHANGED, "value", 31699 currValue, this._getFormattedValue(currValue)); 31700 }, 31701 31702 31703 checkIfNull : function (value) { 31704 return value == null || value === ""; 31705 }, 31706 31707 31708 isEmpty : function () { 31709 return this.checkIfNull(this.value); 31710 }, 31711 31712 _setXFAValue : function (value) { 31713 this.bindNode.rawValue = value; 31714 }, 31715 31716 31717 _setXFAMandatory : function (value) { 31718 31719 31720 var convertor = this._guide()._guideSchema.getConvertor("mandatory"); 31721 if (convertor) { 31722 31723 31724 this.bindNode.validate.nullTest = convertor.guideToXfa.apply(this, [!!value]); 31725 } 31726 }, 31727 31728 _setGuideValue : function (value) { 31729 this.jsonModel._value = (value === undefined || value === null) ? null : value; 31730 }, 31731 31732 _runMandatoryTest : function () { 31733 var currValue = this._getValue(), 31734 isNull = this.checkIfNull(currValue); 31735 return !isNull; 31736 }, 31737 31738 _runValidatePictureTest : function () { 31739 var value = this._getValue(), 31740 validateFlag = true, 31741 regex; 31742 if (!this.checkIfNull(value) && this.validatePictureClause) { 31743 31744 try { 31745 value = xfalib.ut.PictureFmt.format(value + "", this.validatePictureClause, null, false); 31746 } catch (exception) { 31747 31748 this.logger().log("AF", exception); 31749 31750 if (exception.indexOf("Invalid picture clause") !== -1) { 31751 value = undefined; 31752 } else { 31753 value = null; 31754 } 31755 } 31756 } 31757 if (_.isUndefined(value)) { 31758 try { 31759 31760 regex = new RegExp(this.validatePictureClause); 31761 if (regex) { 31762 validateFlag = regex.test(this._getValue()); 31763 } 31764 } catch (exception) { 31765 31766 this.logger().error("AF", "Invalid Regular Expression" + exception); 31767 validateFlag = false; 31768 } 31769 } else if (value === null) { 31770 validateFlag = false; 31771 } 31772 31773 return validateFlag; 31774 }, 31775 31776 31777 _runTests : function (forceRun) { 31778 31779 var validFlag = true, 31780 prevErrorText = this._errorText, 31781 prevValidationState = this.validationState, 31782 obj = { 31783 'validFlag' : validFlag, 31784 'forceRun' : forceRun 31785 }; 31786 31787 if (this.validationsDisabled === true) { 31788 31789 31790 return true; 31791 } 31792 31793 this._runValidations(obj); 31794 validFlag = obj.validFlag; 31795 31796 if (validFlag) { 31797 this._errorText = ""; 31798 this.validationState = true; 31799 31800 this._failedTest = null; 31801 } else { 31802 this.validationState = false; 31803 } 31804 31805 if ((prevErrorText !== this._errorText) || (prevValidationState !== this.validationState) || forceRun) { 31806 31807 if (forceRun) { 31808 this.forceErrorShow = true; 31809 } 31810 this._triggerEvent(guidelib.event.GuideModelEvent.ERROR_CHANGED, 31811 "validationStatus", this.validationState, this._errorText); 31812 } 31813 31814 return this.validationState; 31815 }, 31816 31817 playJson : function (pJsonModel) { 31818 var currValue = pJsonModel._value, 31819 _guide = this._guide(); 31820 31821 if (this.valueCommitScript && _guide.version.isOn(_guide.version.Flags.RUN_VALUE_COMMMIT_ON_PREFILL) && currValue) { 31822 31823 _guide.queueExpressions(this, ["valueCommitScript"]); 31824 } 31825 this._setGuideValue(pJsonModel._value); 31826 }, 31827 31828 31829 _runValidations : function (obj) { 31830 var isRegex = false, 31831 INVALID_PICTURE_CLAUSE_LIST = ["date.default{}", "date.short{}", "date.medium{}", 31832 "date.long{}", "date.full{}", "num.percent{}", "num.decimal{}", "num.currency{}"]; 31833 if (this.bindNode) { 31834 if (this.validatePictureClause && (this.value || this.value === 0)) { 31835 31836 31837 try { 31838 xfalib.ut.PictureFmt.format(this.value + "", this.validatePictureClause, null, false); 31839 } catch (exception) { 31840 if (INVALID_PICTURE_CLAUSE_LIST.indexOf(this.validatePictureClause) >= 0) { 31841 isRegex = false;
31842 } else if (exception.indexOf("Invalid picture clause") !== -1) { 31843 isRegex = true; 31844 } 31845 } 31846 } 31847 if (isRegex) { 31848 try { 31849 31850 var regex = new RegExp(this.validatePictureClause); 31851 if (regex) { 31852 obj.validFlag = regex.test(this._getValue()); 31853 } 31854 } catch (exception) { 31855 this.logger().error("AF", "Error in running regular expression" + exception); 31856 obj.validFlag = false; 31857 } 31858 if (!obj.validFlag) { 31859 this.bindNode._setErrorData("formatTest", this.getOrElse(this.bindNode.validate.formatTest, this.bindNode._defaults.validate.formatTest), this.bindNode.formatMessage); 31860 this._errorText = this.bindNode._errorText; 31861 xfalib.ut.XfaUtil.prototype._triggerOnBridge("elementValidationStatusChanged", this.bindNode, "validationStatus", false, true); 31862 this.bindNode.execEvent("validationState"); 31863 } 31864 } else { 31865 if (obj.forceRun) { 31866 this.bindNode.execValidate(); 31867 } 31868 this._errorText = this.bindNode._errorText; 31869 if (this._errorText) { 31870 obj.validFlag = false; 31871 } 31872 } 31873 31874 this._failedTest = this.bindNode._mFailedValTest; 31875 } else { 31876 31877 if (this.mandatory) { 31878 obj.validFlag = this._runMandatoryTest(); 31879 if (!obj.validFlag) { 31880 this._errorText = this.mandatoryMessage; 31881 this._failedTest = this.guideUtil.MANDATORY_TEST; 31882 } 31883 } 31884 if (obj.validFlag && this.validatePictureClause && !this.checkIfNull(this.value)) { 31885 obj.validFlag = this._runValidatePictureTest(); 31886 if (!obj.validFlag) { 31887 this._errorText = this.validatePictureClauseMessage; 31888 this._failedTest = this.guideUtil.FORMAT_TEST; 31889 } 31890 } 31891 } 31892 31893 if (obj.validFlag && this.validateExp) { 31894 obj.validFlag = this.executeExpression("validateExp"); 31895 if (!obj.validFlag) { 31896 this._errorText = this.validateExpMessage; 31897 this._failedTest = this.guideUtil.SCRIPT_TEST; 31898 } 31899 } 31900 }, 31901 31902 _collectValues : function (keyValue) { 31903 31904 keyValue[this.name] = this.value; 31905 }, 31906 31907 31908 resetData : function () { 31909 this._runValidation = false; 31910 this.value = this.jsonModel["{default}"]; 31911 this._runValidation = true; 31912 31913 this._errorText = ""; 31914 this.validationState = true; 31915 this._failedTest = null; 31916 this._triggerEvent(guidelib.event.GuideModelEvent.ERROR_RESET, 31917 "validationStatus", this.validationState, this._errorText); 31918 }, 31919 31920 _preserveLazyValue : function () { 31921 return !(_.contains(['guideButton', 'guideTextDraw', 'guideAdobeSignBlock'], this.className) || this._isXfaNode()); 31922 }, 31923 31924 31925 _updateLiveData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar) { 31926 if (this._preserveLazyValue()) { 31927 var dataUtils = this._guide().internal.liveDataUtils, 31928 dataContext = dataUtils._getDataContext(this, bound_indexedXpathSoFar, 31929 unBound_indexedXpathSoFar), 31930 isRichText = this instanceof guidelib.model.GuideTextBox && this.allowRichText, 31931 setValue = isRichText ? dataUtils.setRichTextValue : dataUtils.setDataValue; 31932 setValue.apply(dataUtils, [dataContext.indexedXpath, dataContext.xmlSec, 31933 !this.isEmpty(), this.isEmpty() ? "" : this.value]); 31934 } 31935 }, 31936 31937 31938 _playLiveData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar) { 31939 if (this._preserveLazyValue()) { 31940 var dataUtils = this._guide().internal.liveDataUtils, 31941 dataContext = dataUtils._getDataContext(this, bound_indexedXpathSoFar, 31942 unBound_indexedXpathSoFar), 31943 isRichText = this instanceof guidelib.model.GuideTextBox && this.allowRichText, 31944 getValue = isRichText ? dataUtils.getRichTextValue : dataUtils.getDataValue; 31945 var value = getValue.apply(dataUtils, [dataContext.indexedXpath, dataContext.xmlSec]); 31946 if (value != undefined) { 31947 this.value = value; 31948 } else if (this.jsonModel && this.jsonModel._value) { 31949 31950 var _guide = this._guide(); 31951 31952 if (this.valueCommitScript && _guide.version.isOn(_guide.version.Flags.RUN_VALUE_COMMMIT_ON_PREFILL)) { 31953 31954 _guide.queueExpressions(this, ["valueCommitScript"]); 31955 } 31956 } 31957 } 31958 }, 31959 31960 31961 _allowEmptyValueString : function () { 31962 return false;
31963 }, 31964 31965 markAsInvalid : function (errorText, shouldShowError) { 31966 shouldShowError = (typeof shouldShowError !== 'undefined') ? shouldShowError : false; 31967 this.validationState = false; 31968 if (!errorText) { 31969 errorText = this.validateExpMessage; 31970 } 31971 if(shouldShowError) { 31972 this._errorText = errorText; 31973 this.forceErrorShow = true; 31974 } 31975 this._triggerEvent(guidelib.event.GuideModelEvent.ERROR_CHANGED, 31976 "validationStatus", this.validationState, errorText); 31977 }, 31978 31979 31980 _isStateOverridden : function (property) { 31981 return this.getOrElse(this.jsonModel.stateOverrides, property, null) != null; 31982 } 31983 }); 31984 31985 Field.defineProps({ 31986 calcExp : { 31987 get : function () { 31988 return this.getAttribute("calcExp"); 31989 } 31990 }, 31991 31992 31993 isGlobal : { 31994 get : function () { 31995 return this.getAttribute('isGlobal') === "true"; 31996 } 31997 }, 31998 31999 32000 title : { 32001 get : function () { 32002 return this.getAttribute("jcr:title"); 32003 }, 32004 set : function (title) { 32005 this.setAttribute(title, "jcr:title"); 32006 } 32007 }, 32008 32009 valueCommitScript : { 32010 get : function () { 32011 return this.getAttribute("valueCommitScript"); 32012 } 32013 }, 32014 32015 validateExp : { 32016 get : function () { 32017 return this.getAttribute("validateExp"); 32018 } 32019 }, 32020 32021 32022 placeholderText : { 32023 get : function () { 32024 return this.getAttribute("placeholderText"); 32025 } 32026 }, 32027 32028 32029 value : { 32030 get : function () { 32031 var context = this.getOrElse(this._guide(), "_currentContext", null); 32032 if (context && context.managedExp 32033 32034 && !(context.contextNode === this 32035 && context.expression === "calcExp")) { 32036 32037 this._addDependant(context.contextNode, context.expression); 32038 } 32039 return this._getValue(); 32040 }, 32041 set : function (newValue) { 32042 var oldValue = this._getValue(), 32043 newTypedValue = this._getTypedValue(newValue), 32044 _guide = this._guide(); 32045 32046 if (this._allowEmptyValueString() && newValue === "") { 32047 newTypedValue = ""; 32048 } 32049 32050 32051 if (newTypedValue !== undefined && !(this.checkIfNull(newTypedValue) && this.checkIfNull(oldValue)) 32052 && (newTypedValue !== oldValue)) { 32053 if (this.bindNode) { 32054 this._setXFAValue(newTypedValue); 32055 } else if (this.jsonModel._value !== newValue) { 32056 this._setGuideValue(newTypedValue); 32057 } 32058 if (_guide && _guide.version.isOn(_guide.version.Flags.RUN_VALUE_COMMMIT_ON_SCRIPT_CHANGE)) { 32059 var context = _guide._currentContext, 32060 contextNode = this.getOrElse(context, "contextNode", null), 32061 contextExpression = this.getOrElse(context, "expression", null); 32062 if (!context || contextNode != this || contextExpression != "valueCommitScript") { 32063 32064 _guide.queueExpressions(this, ["valueCommitScript"]); 32065 } 32066 } 32067 32068 this._notifyDependants(); 32069 32070 if (this._runValidation && _guide) { 32071 _guide.queueExpressions(this, ["validateAllExp"]); 32072 } 32073 this._triggerOnBridge("elementValueChanged", this, "value", oldValue, newTypedValue); 32074 32075 32076 if (!this.bindNode || (this.bindNode && this.getAttribute("html5Type") !== undefined)) {
32077 this._triggerDisplayFormatChange(); 32078 } 32079 } 32080 } 32081 }, 32082 32083 32084 formattedValue : { 32085 get : function () { 32086 var value; 32087 if (this.bindNode) { 32088 value = this.bindNode.formattedValue; 32089 } else { 32090 value = this._getFormattedValue(this._getValue()); 32091 } 32092 return value; 32093 } 32094 }, 32095 32096 32097 displayPictureClause : { 32098 get : function () { 32099 return this.getAttribute("displayPictureClause"); 32100 } 32101 }, 32102 32103 32104 validatePictureClause : { 32105 get : function () { 32106 if (this.jsonModel.displayIsSameAsValidate) { 32107 return this.displayPictureClause; 32108 } 32109 return this.getAttribute("validatePictureClause"); 32110 } 32111 }, 32112 32113 32114 editPictureClause : { 32115 get : function () { 32116 if (this.jsonModel.isEditSameAsDisplayPattern) { 32117 return this.displayPictureClause; 32118 } 32119 return this.getAttribute("editPictureClause"); 32120 } 32121 }, 32122 32123 32124 isEditPictureClausePresent : { 32125 get : function () { 32126 return typeof this.editPictureClause !== 'undefined'; 32127 } 32128 }, 32129 32130 32131 mandatory : { 32132 get : function () { 32133 return this.getAttribute("mandatory"); 32134 }, 32135 32136 set : function (newValue) { 32137 var oldValue = this.getAttribute("mandatory"); 32138 if (newValue !== undefined && oldValue !== newValue) { 32139 if (this.bindNode) { 32140 this._setXFAMandatory(newValue); 32141 } else { 32142 32143 this.jsonModel.mandatory = !!newValue; 32144 } 32145 32146 this._triggerEvent(guidelib.event.GuideModelEvent.MODEL_CHANGED, "mandatory", oldValue, newValue); 32147 } 32148 } 32149 }, 32150 32151 32152 mandatoryMessage : { 32153 get : function () { 32154 return this.getAttribute("mandatoryMessage"); 32155 } 32156 }, 32157 32158 32159 validateExpMessage : { 32160 set : function (message) { 32161 32162 if (this.isValid) { 32163 this.jsonModel.validateExpMessage = message; 32164 } else { 32165 this.setAttribute(message, "validateExpMessage"); 32166 } 32167 }, 32168 get : function () { 32169 return this.getAttribute("validateExpMessage"); 32170 } 32171 }, 32172 32173 32174 validatePictureClauseMessage : { 32175 get : function () { 32176 return this.getAttribute("validatePictureClauseMessage"); 32177 } 32178 }, 32179 32180 32181 validationState : { 32182 get : function () { 32183 return this.isValid; 32184 }, 32185 set : function (newValue) { 32186 var oldVal = this.isValid; 32187 if (oldVal != newValue) { 32188 this.isValid = newValue; 32189 this._triggerOnBridge("elementValidationStatusChanged", this, 32190 "validationStatus", oldVal, newValue); 32191 } 32192 } 32193 }, 32194 32195 width : { 32196 get : function () { 32197 return this.getAttribute("width"); 32198 }, 32199 32200 set : function (newValue) { 32201 this.jsonModel.width = newValue; 32202 } 32203 }, 32204 32205 height : { 32206 get : function () { 32207 return this.getAttribute("height"); 32208 }, 32209 32210 set : function (newValue) { 32211 this.jsonModel.height = newValue; 32212 } 32213 } 32214 }); 32215 32216 Field.addMixins([ 32217 guidelib.model.mixin.AddDependencyMgmt, 32218 guidelib.model.mixin.ValidationsDisabled 32219 ]); 32220}(_, guidelib)); 32221 32222(function (_, guidelib) { 32223 32224 var GuideButton = guidelib.model.GuideButton = guidelib.model.Field.extend({ 32225 msClassName : "guideButton", 32226 defaultClickExpressions : { 32227 "moveNext" : "window.guideBridge.setFocus(this.panel.somExpression, 'nextItem', true)", 32228 "movePrev" : "window.guideBridge.setFocus(this.panel.somExpression, 'prevItem', true)" 32229 }, 32230 defaultNavigationExpressions : { 32231 "moveNext" : "this.visible=this.panel.navigationContext.hasNextItem", 32232 "movePrev" : "this.visible=this.panel.navigationContext.hasPrevItem" 32233 }, 32234 32235 _collectExpressions : function () { 32236 GuideButton._super._collectExpressions.apply(this); 32237 if (this.clickExp) { 32238 this._compiledScripts["clickExp"] = this._compileExpression(this.clickExp, null); 32239 } else if (this.targetVersion >= 1.1 && this.defaultClickExpressions[this.type]) { 32240 this.jsonModel.clickExp = this.defaultClickExpressions[this.type]; 32241 this._compiledScripts["clickExp"] = this._compileExpression(this.clickExp, null); 32242 } 32243 if (this.navigationChangeExp) { 32244 this._compiledScripts["navigationChangeExp"] = this._compileExpression(this.navigationChangeExp, null); 32245 } else if (this.targetVersion >= 1.1 && this.defaultNavigationExpressions[this.type]) { 32246 this.jsonModel.navigationChangeExp = this.defaultNavigationExpressions[this.type]; 32247 this._compiledScripts["navigationChangeExp"] = this._compileExpression(this.navigationChangeExp, null); 32248 } 32249 }, 32250 32251 }); 32252 32253 GuideButton.defineProps({ 32254 clickExp : { 32255 get : function () { 32256 return this.jsonModel.clickExp; 32257 } 32258 }, 32259 navigationChangeExp : { 32260 get : function () { 32261 return this.jsonModel.navigationChangeExp; 32262 } 32263 }, 32264 32265 type : { 32266 get : function () { 32267 return this.getAttribute("type"); 32268 } 32269 } 32270 }); 32271})(_, guidelib); 32272 32273(function (_, guidelib) { 32274 var GuideListFileAttachmentButton = guidelib.model.GuideListFileAttachmentButton = guidelib.model.GuideButton.extend({ 32275 msClassName : "guideListFileAttachmentButton", 32276 initialize : function () { 32277 32278 if (_.isUndefined(this.jsonModel.clickExp)) { 32279 this.jsonModel.clickExp = "guideBridge._updateFileListing.call(this,this)"; 32280 32281 } 32282 GuideListFileAttachmentButton._super.initialize.apply(this, arguments); 32283 } 32284 }); 32285 32286})(_, guidelib); 32287(function (_, guidelib) { 32288 var GuideCompositeFieldItem = guidelib.model.GuideCompositeFieldItem = guidelib.model.Field.extend({ 32289 msClassName : "GuideCompositeFieldItem" 32290 }); 32291 32292 GuideCompositeFieldItem.defineProps({ 32293 32294 bindRef : { 32295 get : function () { 32296 if (this.parent && !this.parent._isXfaNode() && !_.isEmpty(this.parent.bindRef)) { 32297 return this.parent.bindRef + '/' + this.getAttribute("name").replace(/\s+/g, ''); 32298 } else { 32299 return (this.getAttribute("bindRef") || "").replace(/\s+/g, ''); 32300 } 32301 } 32302 } 32303 }); 32304 32305})(_, guidelib); 32306(function (_, guidelib) { 32307 var GuideTextDraw = guidelib.model.GuideTextDraw = guidelib.model.Field.extend({ 32308 msClassName : "guideTextDraw", 32309 32310 _valueEscapeRegex : new RegExp('\\$', 'g'), 32311 32312 32313 _getValue : function () { 32314 if (this.bindNode) { 32315 return this.bindNode._getValue(null, true); 32316 } 32317 return this._getTypedValue(this.jsonModel._value); 32318 }, 32319 32320 32321 playJson : function (pJsonModel) { 32322 32323 this._setGuideValue(this._floatingFieldResolutionFunction(pJsonModel)); 32324 }, 32325 32326 _allowEmptyValueString : function () { 32327 return true; 32328 }, 32329 32330 _isFloatingField : function () { 32331 return this.documentFragmentVariables && this.documentFragmentVariables.length > 0; 32332 }, 32333 32334 _floatingFieldResolutionFunction : function (jsonModel) { 32335 var resolvedValue = this.value, 32336 variableRegexMap = this._variableRegexMap, 32337 valueEscapeRegex = this._valueEscapeRegex, 32338 somExpression = this.somExpression, 32339 self = this, 32340 32341 32342 variablesDefaultValue = [], 32343 documentFragmentVariables = this.documentFragmentVariables; 32344 if (jsonModel.documentFragmentVariables) { 32345 for (var index = 0 ; index < jsonModel.documentFragmentVariables.length ; index++) { 32346 variablesDefaultValue[index] = jsonModel.documentFragmentVariables[index]._value; 32347 } 32348 } 32349 this.jsonModel.defaultValue = variablesDefaultValue; 32350 _.each(variableRegexMap, function (regexPattern, variableId) { 32351 var textVariable, 32352 bindRef, 32353 floatingFieldValue; 32354 textVariable = documentFragmentVariables.filter(function (variable) { 32355 return variable.variableId === variableId; 32356 })[0]; 32357 bindRef = textVariable.bindRef; 32358 if (!bindRef) { 32359 bindRef = textVariable.name; 32360 } 32361 32362 if (jsonModel && jsonModel.documentFragmentVariables && jsonModel.documentFragmentVariables.length > 0) { 32363 var variableFromPlayJson = jsonModel.documentFragmentVariables.filter(function (variable) { 32364 return variable.variableId === variableId; 32365 })[0]; 32366 floatingFieldValue = variableFromPlayJson._value; 32367 } else { 32368 floatingFieldValue = guidelib.util.GuideUtil.getValueForBindRefField(bindRef, somExpression, this._guide()); 32369 } 32370 if (!floatingFieldValue) { 32371 32372 floatingFieldValue = ""; 32373 } else { 32374 32375 32376 floatingFieldValue = floatingFieldValue.replace(valueEscapeRegex, '$$$$'); 32377 } 32378 if (floatingFieldValue) { 32379 var dataType = textVariable.dataType, 32380 displayPattern = textVariable.displayPictureClause; 32381 if (dataType === 'number' || dataType === 'integer') { 32382 displayPattern = displayPattern ? displayPattern : 'num{zzz,zzz,zzz,zzz,zzz,zzz,zzz.zzzzzzzzzzzzzzz}'; 32383 } else if (dataType === 'date-time' || dataType === 'date') { 32384 displayPattern = displayPattern ? displayPattern : 'date{' + guidelib.i18n.datePatterns.med + '}'; 32385 } 32386 32387 if (displayPattern) { 32388 if (floatingFieldValue.indexOf(',') !== -1) { 32389 32390 var valArray = floatingFieldValue.split(','), 32391 tmpValue = ""; 32392 valArray.forEach(function (val) { 32393 tmpValue = tmpValue + guidelib.util.GuideUtil.formatValue(val, displayPattern, dataType) + ", " ; 32394 }); 32395 floatingFieldValue = tmpValue.substr(0, tmpValue.length - 2); 32396 } else { 32397 floatingFieldValue = guidelib.util.GuideUtil.formatValue(floatingFieldValue, displayPattern, dataType); 32398 } 32399 } 32400 } 32401 resolvedValue = resolvedValue.replace(regexPattern, floatingFieldValue); 32402 }); 32403 return resolvedValue; 32404 }, 32405 32406 initialize : function () { 32407 if (this._isFloatingField()) { 32408 var variableRegexMap = this._variableRegexMap = {}; 32409 _.each(this.documentFragmentVariables, function (documentFragmentVariable) { 32410 var variableId = documentFragmentVariable.variableId, 32411 regexPattern; 32412 if (!variableRegexMap[variableId]) { 32413 32414 regexPattern = '(?:<df-variable[^>]*variableid="' + variableId + '"[^>]*>)[^<]*(?:<\/df-variable>)'; 32415 variableRegexMap[variableId] = new RegExp(regexPattern, 'ig'); 32416 } 32417 }); 32418 } 32419 GuideTextDraw._super.initialize.apply(this, [arguments]); 32420 } 32421 }); 32422 32423 GuideTextDraw.defineProps({ 32424 calcExp : { 32425 get : function () { 32426 return this._calcExp; 32427 } 32428 }, 32429 32430 documentFragmentVariables : { 32431 get : function () { 32432 return this.jsonModel.documentFragmentVariables; 32433 } 32434 } 32435 }); 32436}(_, guidelib)); 32437 32438(function (_, guidelib) { 32439 var GuideAdobeSignBlock = guidelib.model.GuideAdobeSignBlock = guidelib.model.GuideTextDraw.extend({ 32440 msClassName : "guideAdobeSignBlock" 32441 }); 32442}(_, guidelib)); 32443 (function (_, guidelib) { 32444 var GuideFootnotePlaceHolder = guidelib.model.GuideFootnotePlaceHolder = guidelib.model.GuideTextDraw.extend({ 32445 msClassName : "guideFootnotePlaceHolder", 32446 32447 initialize : function () { 32448 GuideFootnotePlaceHolder._super.initialize.apply(this); 32449 } 32450 }); 32451 GuideFootnotePlaceHolder.defineProps({ 32452 footnoteMap : { 32453 get : function () { 32454 if (this.options._guideContainer.jsonModel.textReplacementMap) { 32455 var footnoteMap = {}; 32456 var footnoteArray = Object.entries(this.options._guideContainer.jsonModel.textReplacementMap) 32457 var parentDiv = document.createElement("p"); 32458 parentDiv.setAttribute("class", "footnoteClass"); 32459 for (var i = 0; i < footnoteArray.length; i++) { 32460 var pTag = $("p[id=\"" + footnoteArray[i][0] + "\"]")[0]; 32461 if (pTag != null && pTag.tagName == 'P') { 32462 var childTag = document.createElement("p"); 32463 32464 childTag.setAttribute("role", "footnote"); 32465 childTag.setAttribute("aria-live", "polite"); 32466 childTag.setAttribute("aria-atomic", "true"); 32467 var supTag = document.createElement('sup'); 32468 var anchorTag = document.createElement('a'); 32469 var parentTag = pTag.cloneNode(true); 32470 parentTag.removeAttribute("id"); 32471 anchorTag.setAttribute('id', footnoteArray[i][0]+ "_ftn"); 32472 anchorTag.innerHTML = footnoteArray[i][1]; 32473 supTag.appendChild(anchorTag); 32474 parentTag.insertBefore(supTag, parentTag.children[0]); 32475 parentTag.style.display = "block"; 32476 childTag.appendChild(parentTag); 32477 footnoteMap[footnoteArray[i][0]] = childTag.outerHTML; 32478 } 32479 } 32480 return footnoteMap; 32481 } 32482 return null; 32483 } 32484 } 32485 }); 32486 32487}(_, guidelib)); 32488 32489 32490(function (_, guidelib) { 32491 32492 var GuideTextBox = guidelib.model.GuideTextBox = guidelib.model.Field.extend({ 32493 msClassName : "guideTextBox", 32494 32495 32496 _runMinimumLengthTest : function () { 32497 return this.value && this.value.length >= this.minLength; 32498 }, 32499 32500 32501 _runTotalLengthTest : function () { 32502 return this.value && this.value.length === this.length; 32503 }, 32504 32505 32506 _runValidations : function (obj) { 32507 GuideTextBox._super._runValidations.call(this, obj); 32508 if (obj.validFlag) { 32509 32510 if (this.length != null) {
32511 obj.validFlag = this._runTotalLengthTest(); 32512 if (!obj.validFlag) { 32513 this._errorText = this.guideUtil.getLocalizedMessage("", guidelib.i18n.strings.totalLengthMessage, [this.length]); 32514 this._failedTest = this.guideUtil.LENGTH_TEST; 32515 } 32516 } else if (this.minLength != null) { 32517 obj.validFlag = this._runMinimumLengthTest(); 32518 if (!obj.validFlag) { 32519 this._errorText = this.guideUtil.getLocalizedMessage("", guidelib.i18n.strings.minimumLengthMessage, [this.minLength]); 32520 this._failedTest = this.guideUtil.MINIMUM_LENGTH_TEST; 32521 } 32522 } 32523 32524 } 32525 }, 32526 32527 32528 _runMandatoryTest : function () { 32529 if (this.allowRichText) { 32530 32531 32532 var getTextContent = function (htmlString) { 32533 var result = htmlString, 32534 regex = null; 32535 if (htmlString != null) { 32536 32537 32538 regex = /(<([^>]+)>)/ig; 32539 result = htmlString.replace(regex, ""); 32540 } 32541 return result; 32542 }, 32543 currValue = getTextContent(this._getValue()), 32544 isNull = this.checkIfNull(currValue); 32545 return !isNull; 32546 } else { 32547 return GuideTextBox._super._runMandatoryTest.apply(this, arguments); 32548 } 32549 }, 32550 32551 _allowEmptyValueString : function () { 32552 return true; 32553 } 32554 32555 }); 32556 32557 GuideTextBox.defineProps({ 32558 32559 "multiLine" : { 32560 get : function () { 32561 return this.getAttribute("multiLine"); 32562 } 32563 }, 32564 32565 32566 "maxChars" : { 32567 get : function () { 32568 return this.getAttribute("maxChars"); 32569 } 32570 }, 32571 32572 32573 "minLength" : { 32574 get : function () { 32575 return this.getAttribute("minLength"); 32576 } 32577 }, 32578 32579 32580 "length" : { 32581 get : function () { 32582 return this.getAttribute("length"); 32583 } 32584 }, 32585 32586 "allowRichText" : { 32587 get : function () { 32588 return this.getAttribute("allowRichText"); 32589 } 32590 } 32591 }); 32592 32593}(_, guidelib)); 32594 32595(function (_, guidelib) { 32596 32597 var countriesDialingCodesMap = { 32598 '441481' : 'Guernsey', 32599 '441624' : 'Isle of Man', 32600 '441534' : 'Jersey', 32601 '1868' : 'Trinidad and Tobago', 32602 '1473' : 'Grenada', 32603 '1670' : 'Northern Mariana Islands', 32604 '1869' : 'Saint Kitts and Nevis', 32605 '1758' : 'Saint Lucia', 32606 '1671' : 'Guam', 32607 "1684" : "American Samoa", 32608 "1268" : "Antigua and Barbuda", 32609 "1264" : "Anguilla", 32610 "1242" : "Bahamas", 32611 "1246" : "Barbados", 32612 '1441' : 'Bermuda', 32613 '1284' : 'British Virgin Islands', 32614 '1345' : 'Cayman Islands', 32615 '1787' : 'Puerto Rico', 32616 '1876' : 'Jamaica', 32617 '1939' : 'Puerto Rico', 32618 '1767' : 'Dominica', 32619 '1809' : 'Dominican Republic', 32620 '1829' : 'Dominican Republic', 32621 '1664' : 'Montserrat', 32622 '1849' : 'Dominican Republic', 32623 '1340' : 'U.S. Virgin Islands', 32624 '1784' : 'Saint Vincent and the Grenadines', 32625 '1649' : 'Turks and Caicos Islands', 32626 '1721' : 'Sint Maarten', 32627 "355" : "Albania", 32628 "213" : "Algeria", 32629 "376" : "Andorra", 32630 "244" : "Angola", 32631 "672" : "Antarctica", 32632 "374" : "Armenia", 32633 "297" : "Aruba", 32634 "994" : "Azerbaijan", 32635 "973" : "Bahrain", 32636 "880" : "Bangladesh", 32637 "375" : "Belarus", 32638 "501" : "Belize", 32639 "229" : "Benin", 32640 '975' : 'Bhutan', 32641 '591' : 'Bolivia', 32642 '387' : 'Bosnia and Herzegovina', 32643 '267' : 'Botswana', 32644 '246' : 'British Indian Ocean Territory', 32645 '673' : 'Brunei', 32646 '359' : 'Bulgaria', 32647 '226' : 'Burkina Faso', 32648 '257' : 'Burundi', 32649 '855' : 'Cambodia', 32650 '237' : 'Cameroon', 32651 '238' : 'Cape Verde', 32652 '236' : 'Central African Republic', 32653 '235' : 'Chad', 32654 '269' : 'Comoros', 32655 '682' : 'Cook Islands', 32656 '506' : 'Costa Rica', 32657 '385' : 'Croatia', 32658 32659 '357' : 'Cyprus', 32660 '420' : 'Czech Republic', 32661 '243' : 'Democratic Republic of the Congo', 32662 '253' : 'Djibouti', 32663 '670' : 'East Timor', 32664 '593' : 'Ecuador', 32665 '503' : 'El Salvador', 32666 '240' : 'Equatorial Guinea', 32667 '291' : 'Eritrea', 32668 '372' : 'Estonia', 32669 '251' : 'Ethiopia', 32670 '500' : 'Falkland Islands', 32671 '298' : 'Faroe Islands', 32672 '679' : 'Fiji', 32673 '358' : 'Finland', 32674 '689' : 'French Polynesia', 32675 '241' : 'Gabon', 32676 '220' : 'Gambia', 32677 '995' : 'Georgia', 32678 '233' : 'Ghana', 32679 '350' : 'Gibraltar', 32680 '299' : 'Greenland', 32681 '502' : 'Guatemala', 32682 '224' : 'Guinea', 32683 '245' : 'Guinea-Bissau', 32684 '592' : 'Guyana', 32685 '509' : 'Haiti', 32686 '504' : 'Honduras', 32687 '852' : 'Hong Kong', 32688 '354' : 'Iceland', 32689 '964' : 'Iraq', 32690 '353' : 'Ireland', 32691 '972' : 'Israel', 32692 '225' : 'Ivory Coast', 32693 '962' : 'Jordan', 32694 '254' : 'Kenya', 32695 '686' : 'Kiribati', 32696 '383' : 'Kosovo', 32697 '965' : 'Kuwait', 32698 '996' : 'Kyrgyzstan', 32699 '856' : 'Laos', 32700 '371' : 'Latvia', 32701 '961' : 'Lebanon', 32702 '266' : 'Lesotho', 32703 '231' : 'Liberia', 32704 '218' : 'Libya', 32705 '423' : 'Liechtenstein', 32706 '370' : 'Lithuania', 32707 '352' : 'Luxembourg', 32708 '853' : 'Macau', 32709 '389' : 'Macedonia', 32710 '261' : 'Madagascar', 32711 '265' : 'Malawi', 32712 '960' : 'Maldives', 32713 '223' : 'Mali', 32714 '356' : 'Malta', 32715 '692' : 'Marshall Islands', 32716 '222' : 'Mauritania', 32717 '230' : 'Mauritius', 32718 32719 '691' : 'Micronesia', 32720 '373' : 'Moldova', 32721 '377' : 'Monaco', 32722 '976' : 'Mongolia', 32723 '382' : 'Montenegro', 32724 32725 '258' : 'Mozambique', 32726 '264' : 'Namibia', 32727 '674' : 'Nauru', 32728 '977' : 'Nepal', 32729 '599' : 'Netherlands Antilles', 32730 '687' : 'New Caledonia', 32731 '505' : 'Nicaragua', 32732 '227' : 'Niger', 32733 '234' : 'Nigeria', 32734 '683' : 'Niue', 32735 '850' : 'North Korea', 32736 '968' : 'Oman', 32737 '680' : 'Palau', 32738 '970' : 'Palestine', 32739 '507' : 'Panama', 32740 '675' : 'Papua New Guinea', 32741 '595' : 'Paraguay', 32742 '351' : 'Portugal', 32743 '974' : 'Qatar', 32744 '242' : 'Republic of the Congo', 32745 '262' : 'Reunion', 32746 '250' : 'Rwanda', 32747 32748 '290' : 'Saint Helena', 32749 '590' : 'Saint Martin', 32750 '508' : 'Saint Pierre and Miquelon', 32751 '685' : 'Samoa', 32752 '378' : 'San Marino', 32753 '239' : 'Sao Tome and Principe', 32754 '966' : 'Saudi Arabia', 32755 '221' : 'Senegal', 32756 '381' : 'Serbia', 32757 '248' : 'Seychelles', 32758 '232' : 'Sierra Leone', 32759 '421' : 'Slovakia', 32760 '386' : 'Slovenia', 32761 '677' : 'Solomon Islands', 32762 '252' : 'Somalia', 32763 '211' : 'South Sudan', 32764 '249' : 'Sudan', 32765 '597' : 'Suriname', 32766 '268' : 'Swaziland', 32767 '963' : 'Syria', 32768 '886' : 'Taiwan', 32769 '992' : 'Tajikistan', 32770 '255' : 'Tanzania', 32771 '228' : 'Togo', 32772 '690' : 'Tokelau', 32773 '676' : 'Tonga', 32774 '216' : 'Tunisia', 32775 '993' : 'Turkmenistan', 32776 '688' : 'Tuvalu', 32777 '256' : 'Uganda', 32778 '380' : 'Ukraine', 32779 '971' : 'United Arab Emirates', 32780 '598' : 'Uruguay', 32781 '998' : 'Uzbekistan', 32782 '678' : 'Vanuatu', 32783 '379' : 'Vatican', 32784 '681' : 'Wallis and Futuna', 32785 '212' : 'Western Sahara', 32786 '967' : 'Yemen', 32787 '260' : 'Zambia', 32788 '263' : 'Zimbabwe', 32789 '60' : 'Malaysia', 32790 '58' : 'Venezuela', 32791 '30' : 'Greece', 32792 '84' : 'Vietnam', 32793 '44' : 'United Kingdom', 32794 '45' : 'Denmark', 32795 '53' : 'Cuba', 32796 '46' : 'Sweden', 32797 '52' : 'Mexico', 32798 '41' : 'Switzerland', 32799 '40' : 'Romania', 32800 32801 '36' : 'Hungary', 32802
32803 "43" : "Austria", 32804 '34' : 'Spain', 32805 '91' : 'India', 32806 '62' : 'Indonesia', 32807 '98' : 'Iran', 32808 '94' : 'Sri Lanka', 32809 '27' : 'South Africa', 32810 '95' : 'Myanmar', 32811 '65' : 'Singapore', 32812 '39' : 'Italy', 32813 '82' : 'South Korea', 32814 "32" : "Belgium", 32815 '81' : 'Japan', 32816 '31' : 'Netherlands', 32817 '20' : 'Egypt', 32818 "54" : "Argentina", 32819 "93" : "Afghanistan", 32820 32821 '56' : 'Chile', 32822 '86' : 'China', 32823 '51' : 'Peru', 32824 '63' : 'Philippines', 32825 '64' : 'Pitcairn', 32826 '48' : 'Poland', 32827 '47' : 'Norway', 32828 '33' : 'France', 32829 32830 '61' : 'Cocos Islands', 32831 '55' : 'Brazil', 32832 '92' : 'Pakistan', 32833 '49' : 'Germany', 32834 '57' : 'Colombia', 32835 '66' : 'Thailand', 32836 '90' : 'Turkey', 32837 32838 '1' : 'Canada', 32839 32840 '7' : 'Russia' 32841 }; 32842 32843 var GuideTelephone = guidelib.model.GuideTelephone = guidelib.model.GuideTextBox.extend({ 32844 msClassName : "guideTelephone", 32845 32846 _extractNumericDigits : function (telephoneNumber) { 32847 var digitArray, 32848 number = ""; 32849 if (telephoneNumber) { 32850 digitArray = telephoneNumber.match(/\d+/g); 32851 if (digitArray) { 32852 number = digitArray.join(""); 32853 } 32854 } 32855 return number; 32856 }, 32857 32858 _extractCountryCode : function (telephoneNumber) { 32859 var number = this._extractNumericDigits(telephoneNumber); 32860 if (!number || (telephoneNumber && number && telephoneNumber.lastIndexOf("+", 0) !== 0)) { 32861 return ""; 32862 } 32863 for (var countryCode in countriesDialingCodesMap) { 32864 if (number && number.lastIndexOf(countryCode, 0) === 0) { 32865 return countryCode; 32866 } 32867 } 32868 return ""; 32869 }, 32870 32871 _extractPhoneNumber : function (telephoneNumber) { 32872 var countryCode = this._extractCountryCode(telephoneNumber), 32873 number = this._extractNumericDigits(telephoneNumber), 32874 phoneNumber = ""; 32875 if (number) { 32876 phoneNumber = number.substr(countryCode.length); 32877 } 32878 return phoneNumber; 32879 } 32880 }); 32881 32882 GuideTelephone.defineProps({ 32883 32884 countryCode : { 32885 get : function () { 32886 var value = this._getValue(); 32887 return this._extractCountryCode(value); 32888 } 32889 }, 32890 32891 32892 phoneNumber : { 32893 get : function () { 32894 var value = this._getValue(); 32895 return this._extractPhoneNumber(value); 32896 } 32897 } 32898 }); 32899 32900}(_, guidelib)); 32901 32902(function (_, guidelib) { 32903 32904 var GuideCaptcha = guidelib.model.GuideCaptcha = guidelib.model.Field.extend({ 32905 msClassName : "guideCaptcha", 32906 32907 initialize : function () { 32908 GuideCaptcha._super.initialize.call(this); 32909 var invisibleMandatoryRecaptchaInitialization = "af.invisibleMandatoryRecaptchaInitialization"; 32910 32911 var isHcaptchaOrTurnstileInvisible = (this.isWidgetHcaptcha || this.isWidgetTurnstile) && this.captchaInvisible; 32912 var isRecaptchaInvisible = (this.isWidgetRecaptcha && ((this.captchaEnterprise && !this.checkBoxkey) || (this.captchaInvisible && this.mandatory))); 32913 32914 if (isHcaptchaOrTurnstileInvisible || isRecaptchaInvisible) { 32915 32916 this.captchaValidate = false; 32917 this._triggerOnBridge(invisibleMandatoryRecaptchaInitialization, this, null, null, null); 32918 } 32919 }, 32920 32921 showCaptchaError : function (serverErrorMessage) { 32922 if (this.captchaEnterprise) { 32923 if (this.checkBoxkey) { 32924 serverErrorMessage = this.errorMessage; 32925 } else { 32926 window.alert(this.errorMessage); 32927 return; 32928 } 32929 } 32930 if (this.captchaInvisible) { 32931 window.alert(this.errorMessage); 32932 return; 32933 } 32934 if (this.isWidgetHcaptcha || this.isWidgetTurnstile) { 32935 serverErrorMessage = this.errorMessage; 32936 } else { 32937 if (_.isEmpty(serverErrorMessage)) { 32938 serverErrorMessage = guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.LogMessages["AEM-AF-901-006"]); 32939 } 32940 } 32941 32942 this._triggerEvent(guidelib.event.GuideModelEvent.ERROR_CHANGED, 32943 "validationStatus", false, serverErrorMessage); 32944 }, 32945 32946 validate : function (errorList) { 32947 if (_.isUndefined(errorList)) { 32948 errorList = []; 32949 } 32950 32951 if(!this.captchaValidate) { 32952 return; 32953 } 32954 if (window.guideBridge.hostName !== "server") { 32955 if ((this.visible && !this.value) || (this.mandatory && !this.visible)) { 32956 errorList.push({ 32957 som : this.somExpression, 32958 errorText : this.mandatoryMessage 32959 }); 32960 this._triggerEvent(guidelib.event.GuideModelEvent.ERROR_CHANGED, 32961 "validationStatus", false, this.mandatoryMessage); 32962 return false;
32963 } else { 32964 this._triggerEvent(guidelib.event.GuideModelEvent.ERROR_CHANGED, 32965 "validationStatus", true, null); 32966 } 32967 } 32968 }, 32969 32970 _updateLiveData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar) { 32971 32972 }, 32973 32974 _playLiveData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar) { 32975 32976 } 32977 }); 32978 32979 GuideCaptcha.defineProps({ 32980 value : { 32981 get : function () { 32982 return this.jsonModel._value; 32983 }, 32984 set : function (value) { 32985 var oldValue = this.jsonModel._value, 32986 newTypedValue; 32987 32988 this.jsonModel._value = (value === undefined) ? oldValue : value; 32989 newTypedValue = this.jsonModel._value; 32990 this.validate(); 32991 this._triggerOnBridge("elementValueChanged", this, "value", oldValue, newTypedValue); 32992 } 32993 }, 32994 captchaWidget : { 32995 get : function () { 32996 return this.getAttribute("captchaService"); 32997 } 32998 }, 32999 captchaValidate : { 33000 get : function () { 33001 return this._captchaValidate == undefined ? true : this._captchaValidate; 33002 }, 33003 set : function (value) { 33004 this._captchaValidate = value; 33005 } 33006 }, 33007 captchaInvisible : { 33008 get : function () { 33009 if (this.captchaWidget === "turnstile") { 33010 return this.getAttribute("widgetType") == "invisible" ? true : false; 33011 } else if (this.captchaWidget === "hcaptcha") { 33012 return this.getAttribute("size") == "invisible" ? true : false; 33013 } else if (this.captchaWidget === "recaptcha" && this.captchaEnterprise) { 33014 return this.getAttribute("rcKeyType") === "score" ? true : false; 33015 } else { 33016 return this.getAttribute("rcSize") == "invisible" ? true : false; 33017 } 33018 } 33019 }, 33020 captchaEnterprise : { 33021 get : function () { 33022 return (this.getAttribute("rcVersion") === "enterprise") ? true : false; 33023 } 33024 }, 33025 checkBoxkey : { 33026 get : function () { 33027 return this.getAttribute("rcKeyType") === "checkbox" ? true : false; 33028 } 33029 }, 33030 errorMessage : { 33031 get: function () { 33032 return this.getAttribute("errorMessage"); 33033 } 33034 }, 33035 isWidgetRecaptcha : { 33036 get: function () { 33037 return (this.captchaWidget === "recaptcha"); 33038 } 33039 }, 33040 isWidgetHcaptcha : { 33041 get: function () { 33042 return (this.captchaWidget === "hcaptcha"); 33043 } 33044 }, 33045 isWidgetTurnstile : { 33046 get: function () { 33047 return (this.captchaWidget === "turnstile"); 33048 } 33049 } 33050 33051 33052 }); 33053 33054}(_, guidelib)); 33055 33056(function (_, guidelib) { 33057 var GuidePasswordBox = guidelib.model.GuidePasswordBox = guidelib.model.Field.extend({ 33058 msClassName : "guidePasswordBox", 33059 33060 _getReducedJSON : function () { 33061 33062 33063 if (this.submitPassword) { 33064 return GuidePasswordBox._super._getReducedJSON.call(this); 33065 } 33066 33067 var whitelistedProperties = ["name", "templateId", "guideNodeClass"], 33068 reducedJsonObject = {}; 33069 guidelib.model.util.CommonUtils.returnMinimalJSON(whitelistedProperties, reducedJsonObject, this); 33070 return reducedJsonObject; 33071 }, 33072 33073 _preserveLazyValue : function () { 33074 return !!this.submitPassword && GuidePasswordBox._super._preserveLazyValue.call(this); 33075 }, 33076 33077 _allowEmptyValueString : function () { 33078 return true; 33079 } 33080 }); 33081 GuidePasswordBox.defineProps({ 33082 submitPassword : { 33083 get : function () { 33084 return this.getAttribute("submitPassword"); 33085 } 33086 } 33087 }); 33088 33089})(_, guidelib); 33090 33091(function (_, guidelib) { 33092 var GuideScribble = guidelib.model.GuideScribble = guidelib.model.Field.extend({ 33093 msClassName : "guideScribble" 33094 }); 33095})(_, guidelib); 33096 33097 33098(function (_, guidelib) { 33099 var AbstractField = guidelib.model.AbstractField = guidelib.model.GuideNode.extend({ 33100 msClassName : "abstractField", 33101 33102 initialize : function () { 33103 this._name = this.options.name || ""; 33104 this._className = this.options.className || ""; 33105 this._bindRef = this.options.bindRef || ""; 33106 this._afDataSom = this.options.afDataSom || ""; 33107 this._dataSom = this._isXfaNode() ? this.options.dataSom : ""; 33108 this.dependants = []; 33109 33110 this._depdendantIds = []; 33111 }, 33112 33113 _getValue : function () { 33114 return this.jsonModel._value; 33115 }, 33116 33117 _setValue : function (value) { 33118 this.jsonModel._value = value; 33119 }, 33120 33121 resetData : function () { 33122 return guidelib.model.Field.prototype.resetData.call(this); 33123 }, 33124 33125 _isXfaNode : function () { 33126 return this.bindRef.indexOf("xfa[0].form[0].") === 0; 33127 }, 33128 33129 getAttribute : function (attrName) { 33130 var attrValue; 33131 switch (attrName) { 33132 case "name": 33133 attrValue = this.name; 33134 break; 33135 case "bindRef": 33136 attrValue = this.bindRef; 33137 break; 33138 default: 33139 attrValue = null; 33140 break; 33141 } 33142 return attrValue; 33143 } 33144 }); 33145 33146 AbstractField.defineProps({ 33147 somExpression : { 33148 get : function () { 33149 return ""; 33150 } 33151 }, 33152 name : { 33153 get : function () { 33154 return (this._name || "").replace(/\s+/g, ''); 33155 } 33156 }, 33157 className : { 33158 get : function () { 33159 return (this._className || ""); 33160 } 33161 }, 33162 bindRef : { 33163 get : function () { 33164 return (this._bindRef || "").replace(/\s+/g, ''); 33165 } 33166 }, 33167 dataSom : { 33168 get : function () { 33169 return this._dataSom; 33170 } 33171 }, 33172 afDataSom : { 33173 get : function () { 33174 return this._afDataSom.replace(/\s+/g, ''); 33175 } 33176 }, 33177 33178 value : { 33179 get : function () { 33180 var context = this._guide()._currentContext; 33181 if (context && context.managedExp && context.contextNode && context.expression) { 33182 this._addDependant(context.contextNode, context.expression); 33183 33184 this._depdendantIds.push(context.contextNode.id); 33185 } 33186 return this.jsonModel._value; 33187 }, 33188 set : function (newValue) { 33189 if (this.jsonModel._value !== newValue) { 33190 this.jsonModel._value = newValue; 33191 33192 var guideDirtyMarkerAndVisitor = this._guide().internal.GuideDirtyMarkerAndVisitor, 33193 visitMap = guideDirtyMarkerAndVisitor.visitMap, 33194 listOfDependents = this._depdendantIds; 33195 guideDirtyMarkerAndVisitor._findAndMarkDirty(visitMap, listOfDependents); 33196 this._notifyDependants(); 33197 } 33198 } 33199 } 33200 }); 33201 33202 AbstractField.addMixins([ 33203 guidelib.model.mixin.AddDependencyMgmt 33204 ]); 33205}(_, guidelib)); 33206 33207(function ($, guidelib, _) { 33208 var ModelTemplateCacheStore = guidelib.model.util.ModelTemplateCacheStore = xfalib.ut.Class.extend({ 33209 initialize : function () { 33210 ModelTemplateCacheStore._super.initialize.apply(this); 33211 this._modelIdCache = {}; 33212 this._templateIdCache = {}; 33213 33214 33215 33216 33217 this._lazyTemplateIdCache = {}; 33218 var guideJson = JSON.parse(JSON.stringify(this.options.modelTemplateJson)); 33219 this._putTemplate(guideJson); 33220 }, 33221 33222 33223 putModel : function (model) { 33224 if (model.id) { 33225 var modelId = model.id; 33226 this._modelIdCache[modelId] = model; 33227 if (model.children) { 33228 _.each(model.children, function (child) { 33229 this.putModel(child); 33230 }, this); 33231 } 33232 } else { 33233 this.logger().log("no Id found for model" + model.getAttribute("name")); 33234 } 33235 }, 33236 33237 33238 removeModel : function (id) { 33239 if (this._modelIdCache.hasOwnProperty(id)) { 33240 delete this._modelIdCache[id]; 33241 } 33242 }, 33243 33244 getModel : function (id) { 33245 if (this._modelIdCache.hasOwnProperty(id)) { 33246 return this._modelIdCache[id]; 33247 } 33248 }, 33249 33250 33251 _putTemplate : function (jsonTemplate) { 33252 if (jsonTemplate.templateId && jsonTemplate.guideNodeClass) { 33253 this._templateIdCache[jsonTemplate.templateId] = jsonTemplate; 33254 } 33255 _.each(jsonTemplate, function (childTemplate, key) { 33256 if (_.isObject(childTemplate)) { 33257 this._putTemplate(childTemplate); 33258 } 33259 }, this); 33260 }, 33261 33262 33263 _putLazyTemplate : function (lazyTemplateJson) { 33264 if (lazyTemplateJson.templateId && lazyTemplateJson.guideNodeClass) { 33265 this._lazyTemplateIdCache[lazyTemplateJson.templateId] = lazyTemplateJson; 33266 } 33267 }, 33268 33269 cloneJsonTemplate : function (templateId) { 33270 if (this._templateIdCache[templateId]) { 33271 var template = this._templateIdCache[templateId]; 33272 return JSON.parse(JSON.stringify(template)); 33273 } 33274 }, 33275 33276 _getTemplate : function (templateId, lookupLazyStore) { 33277 var template = this._templateIdCache[templateId]; 33278 33279 33280 33281 if (lookupLazyStore && guidelib.util.GuideUtil.isLazyJson(template)) { 33282 template = this._lazyTemplateIdCache[templateId]; 33283 } 33284 33285 if (!_.isUndefined(template)) { 33286 return JSON.parse(JSON.stringify(template)); 33287 33288 } 33289 } 33290 }); 33291 33292 ModelTemplateCacheStore.defineProps({ 33293 }); 33294}($, guidelib, window._)); 33295(function ($, guidelib) { 33296 var DomTemplateCacheStore = guidelib.view.util.DomTemplateCacheStore = xfalib.ut.Class.extend({ 33297 cloneDomElement : function (htmlId) { 33298 return this.$htmlTemplateDom.find(htmlId).clone(); 33299 }, 33300 33301 putDomElement : function (parentIdSelector, $child) { 33302 33303 this.$htmlTemplateDom.find(parentIdSelector).eq(0).append($child); 33304 }, 33305 33306 removeDomElement : function (parentIdSelector) { 33307 33308 this.$htmlTemplateDom.find(parentIdSelector).children().remove(); 33309 } 33310 }); 33311 33312 DomTemplateCacheStore.defineProps({ 33313 $htmlTemplateDom : { 33314 get : function () { 33315 return this.options.$htmlTemplateDom;
33316 } 33317 } 33318 }); 33319}($, guidelib)); 33320(function (_, guidelib) { 33321 33322 var AddMinMaxValidation = guidelib.model.mixin.AddMinMaxValidation = { 33323 normalProperties : { 33324 33325 _runMaximumValueTest : function () { 33326 if (this.exclusiveMaximum) { 33327 return this.value < this.maximum; 33328 } else { 33329 return this.value <= this.maximum; 33330 } 33331 }, 33332 33333 _runMinimumValueTest : function () { 33334 if (this.exclusiveMinimum) { 33335 return this.value > this.minimum; 33336 } else { 33337 return this.value >= this.minimum; 33338 } 33339 }, 33340 33341 33342 _minMaxValidation : function (value, obj) { 33343 if (value != null && obj.validFlag) { 33344 33345 if (this.maximum) { 33346 obj.validFlag = this._runMaximumValueTest(); 33347 if (!obj.validFlag) { 33348 var maxFormattedValue = this._getFormattedValue(this.maximum); 33349 this._errorText = this.exclusiveMaximum ? this.guideUtil.getLocalizedMessage("", guidelib.i18n.strings.exclusiveMaxValErrorMessage, [maxFormattedValue]) : 33350 this.guideUtil.getLocalizedMessage("", guidelib.i18n.strings.maxValErrorMessage, [maxFormattedValue]); 33351 this._failedTest = this.guideUtil.MAXIMUM_VALUE_TEST; 33352 } 33353 } 33354 33355 if (obj.validFlag && this.minimum !== null) { 33356 obj.validFlag = this._runMinimumValueTest(); 33357 if (!obj.validFlag) { 33358 var minFormattedValue = this._getFormattedValue(this.minimum); 33359 this._errorText = this.exclusiveMinimum ? this.guideUtil.getLocalizedMessage("", guidelib.i18n.strings.exclusiveMinValErrorMessage, [minFormattedValue]) : 33360 this.guideUtil.getLocalizedMessage("", guidelib.i18n.strings.minValErrorMessage, [minFormattedValue]); 33361 this._failedTest = this.guideUtil.MINIMUM_VALUE_TEST; 33362 } 33363 } 33364 } 33365 } 33366 33367 }, 33368 propertyDescriptors : { 33369 33370 maximum : { 33371 get : function () { 33372 return this.getAttribute("maximum"); 33373 } 33374 }, 33375 33376 33377 minimum : { 33378 get : function () { 33379 return this.getAttribute("minimum"); 33380 } 33381 }, 33382 33383 33384 exclusiveMaximum : { 33385 get : function () { 33386 return this.getAttribute("exclusiveMaximum"); 33387 } 33388 }, 33389 33390 33391 exclusiveMinimum : { 33392 get : function () { 33393 return this.getAttribute("exclusiveMinimum"); 33394 } 33395 } 33396 33397 } 33398 }; 33399 33400}(_, guidelib)); 33401(function (_, guidelib) { 33402 33403 33404 var GuideNumericBox = guidelib.model.GuideNumericBox = guidelib.model.Field.extend({ 33405 msClassName : "guideNumericBox", 33406 33407 _getTypedValue : function (value) { 33408 var dataType = this.dataType, 33409 tmpValue, str, leadD, fracD; 33410 33411 if (this.checkIfNull(value)) { 33412 return null; 33413 } 33414 switch (dataType) { 33415 case "integer": 33416 tmpValue = parseInt(value); 33417 break; 33418 case "float": 33419 tmpValue = parseFloat(value); 33420 break; 33421 case "decimal": 33422 tmpValue = parseFloat(value); 33423 if (!isNaN(tmpValue)) { 33424 str = tmpValue.toString(); 33425 leadD = str.indexOf("."); 33426 leadD = leadD === -1 ? str.length : leadD; 33427 leadD = str.indexOf("-") === 0 ? leadD - 1 : leadD; 33428 fracD = str.length - leadD - 1; 33429 if (fracD > this.fracDigits && this.fracDigits !== -1) { 33430 tmpValue = parseFloat(tmpValue.toFixed(this.fracDigits)); 33431 } 33432 if (leadD > this.leadDigits && this.leadDigits !== -1) { 33433 return undefined; 33434 } 33435 } 33436 break; 33437 } 33438 if (isNaN(tmpValue)) { 33439 return undefined; 33440 } 33441 return tmpValue; 33442 }, 33443 _getFormattedValue : function (value) { 33444 if (_.isUndefined(value) || value === null || value === "") { 33445 return null; 33446 } 33447 33448 var picture = this.jsonModel.displayPictureClause, 33449 defaultPattern = "zzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzz"; 33450 33451 33452 try { 33453 if (picture && this.jsonModel.html5Type !== "number") { 33454 return xfalib.ut.PictureFmt.format(value + "", picture, guideBridge._readRuntimeLocale(), true); 33455 } else { 33456 var pattern = (this.jsonModel.html5Type === "number") ? defaultPattern : guidelib.i18n.numberPatterns.numeric; 33457 return xfalib.ut.PictureFmt.format(value + "", "num{" + pattern + "}", 33458 guideBridge._readRuntimeLocale(), true, true); 33459 } 33460 } catch (exception) { 33461 this.logger().error("Cannot format value " + value + " " + exception); 33462 33463 return value; 33464 } 33465 }, 33466 33467 33468 _totalDigitValidation : function (value, obj) {
33469 if (value && obj.validFlag && this.leadDigits > -1) { 33470 obj.validFlag = true; 33471 if (this.dataType === "integer") { 33472 obj.validFlag = this.value.toString().length <= this.leadDigits; 33473 } 33474 if (!obj.validFlag) { 33475 this._errorText = guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.totalDigitMessage, [this.leadDigits]); 33476 this._failedTest = this.guideUtil.TOTAL_DIGITS_TEST; 33477 } 33478 } 33479 }, 33480 33481 33482 _datatypeValidation : function (obj) { 33483 if (obj.validFlag) { 33484 var value = this.getAttribute("_value"); 33485 obj.validFlag = !isNaN(value); 33486 if (!obj.validFlag) { 33487 this._errorText = guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.datatypeMessage, ["numeric"]); 33488 this._failedTest = this.guideUtil.FORMAT_TEST; 33489 } 33490 } 33491 }, 33492 33493 33494 _runValidations : function (obj) { 33495 var value = this.value; 33496 GuideNumericBox._super._runValidations.call(this, obj); 33497 this._datatypeValidation(obj); 33498 this._minMaxValidation(value, obj); 33499 this._totalDigitValidation(value, obj); 33500 } 33501 }); 33502 GuideNumericBox.defineProps({ 33503 33504 dataType : { 33505 get : function () { 33506 return this.getAttribute("dataType"); 33507 } 33508 }, 33509 33510 33511 leadDigits : { 33512 get : function () { 33513 return this.getAttribute("leadDigits"); 33514 } 33515 }, 33516 33517 33518 fracDigits : { 33519 get : function () { 33520 return this.getAttribute("fracDigits"); 33521 } 33522 } 33523 }); 33524 33525 GuideNumericBox.addMixins([ 33526 guidelib.model.mixin.AddMinMaxValidation 33527 ]); 33528 33529})(_, guidelib); 33530 33531(function (_, guidelib) { 33532 33533 var GuideDatePicker = guidelib.model.GuideDatePicker = guidelib.model.Field.extend({ 33534 msClassName : "guideDatePicker", 33535 errorList : [], 33536 that : this, 33537 33538 initialize : function () { 33539 GuideDatePicker._super.initialize.call(this); 33540 if (_.isEmpty(this.jsonModel._value) && this.jsonModel.defaultToCurrentDate === "true") { 33541 this._setGuideValue(new Date().toISOString().slice(0, 10)); 33542 } 33543 }, 33544 33545 _setGuideValue : function (value) { 33546 var retVal = guidelib.util.GuideUtil._reformatDate(value, this.isEditPictureClausePresent); 33547 GuideDatePicker._super._setGuideValue.call(this, retVal); 33548 }, 33549 33550 _getTypedValue : function (value) { 33551 if (value) { 33552 return value; 33553 } 33554 return null; 33555 }, 33556 33557 33558 _datatypeValidation : function (obj) { 33559 if (obj.validFlag) { 33560 var value = this.getAttribute("_value"); 33561 obj.validFlag = true; 33562 if (value != null && xfalib.ut.DateInfo.Parse(value, undefined, this.isEditPictureClausePresent) == null) { 33563 obj.validFlag = false; 33564 } 33565 if (!obj.validFlag) { 33566 this._errorText = guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.datatypeMessage, ["date"]); 33567 this._failedTest = this.guideUtil.FORMAT_TEST; 33568 } 33569 } 33570 }, 33571 33572 _validateDatePart : function (field, datePart, errorList) { 33573 if (field === "D") { 33574 if (datePart > 31) { 33575 errorList.push(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.genericInvalidDatePart, [guidelib.i18n.calendarSymbols.month, guidelib.i18n.calendarSymbols.more, 31, guidelib.i18n.calendarSymbols.days])); 33576 } 33577 if (datePart < 1) { 33578 errorList.push(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.genericInvalidDatePart, [guidelib.i18n.calendarSymbols.month, guidelib.i18n.calendarSymbols.less, 1, guidelib.i18n.calendarSymbols.days])); 33579 } 33580 } 33581 if (field === "M") { 33582 if (datePart > 12) { 33583 errorList.push(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.genericInvalidDatePart, [guidelib.i18n.calendarSymbols.year, guidelib.i18n.calendarSymbols.more, 12, guidelib.i18n.calendarSymbols.months])); 33584 } 33585 if (datePart < 1) { 33586 errorList.push(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.genericInvalidDatePart, [guidelib.i18n.calendarSymbols.year, guidelib.i18n.calendarSymbols.less, 1, guidelib.i18n.calendarSymbols.months])); 33587 } 33588 } 33589 if (field === "Y") { 33590 if (datePart.length < 4) { 33591 errorList.push(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.genericInvalidYearPart)); 33592 } 33593 33594 } 33595 }, 33596 _getOrderedDateParts : function (value) { 33597 var dateFormat = this.jsonModel.dateDisplayFormat || "date{M/D/YYYY}"; 33598 var separator = dateFormat.match(/^date\{.*([^mdy]).*\}$/i)[1]; 33599 var fieldOrder = ['M', 'D', 'Y'] 33600 .map(function (val) { 33601 return { 33602 value : val, 33603 index : dateFormat.indexOf(val) 33604 }; 33605 }) 33606 .sort(function (a, b) { 33607 return a.index - b.index; 33608 }) 33609 .map(function (obj) { 33610 return obj.value; 33611 }); 33612 var dateParts = value.split(separator); 33613 return [dateParts, fieldOrder]; 33614 }, 33615 _checkIsolatedDateValidity : function (obj, value, errorList) { 33616 var orderedParts = this._getOrderedDateParts(value); 33617 var dateParts = orderedParts[0], fieldOrder = orderedParts[1]; 33618 for (var i = 0; i < fieldOrder.length; i++) { 33619 var field = fieldOrder[i]; 33620 var datePart = dateParts[i]; 33621 if (!_.isEmpty(datePart)) {
33622 this._validateDatePart(field, datePart, errorList); 33623 } 33624 } 33625 }, 33626 _validateDaysOfMonth : function (obj, value, errorList) { 33627 var orderedParts = this._getOrderedDateParts(value); 33628 var dateParts = orderedParts[0], fieldOrder = orderedParts[1]; 33629 month = dateParts[fieldOrder.indexOf('M')], 33630 day = dateParts[fieldOrder.indexOf('D')], 33631 year = dateParts[fieldOrder.indexOf('Y')]; 33632 if (month !== "" && day !== "") { 33633 month = Number(month) || 0; 33634 day = Number(day) || 0; 33635 var currentMonthName = guidelib.i18n.calendarSymbols.monthNames[month - 1]; 33636 if (31 === day && [4,6,9,11].includes(month)) { 33637 errorList.push(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.nonFebruaryMessage, [currentMonthName, day - 1])); 33638 } 33639 } 33640 }, 33641 _validateFieldCompleteness : function (obj, value, errorList) { 33642 var orderedParts = this._getOrderedDateParts(value); 33643 var dateParts = orderedParts[0], fieldOrder = orderedParts[1]; 33644 var localizedFieldMapping = { 33645 M : guidelib.i18n.calendarSymbols.month, 33646 D : guidelib.i18n.calendarSymbols.day, 33647 Y : guidelib.i18n.calendarSymbols.year 33648 }; 33649 var emptyFields = fieldOrder 33650 .map(function (fieldName) { 33651 return localizedFieldMapping[fieldName]; 33652 }) 33653 .filter(function (_, index) { 33654 return dateParts[index] === ""; 33655 }); 33656 if (emptyFields.length !== 3 && emptyFields.length > 0) { 33657 errorList.push(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.fieldCompletenessMessage, [emptyFields.join(", ")])); 33658 } 33659 }, 33660 _validateFullDate : function (obj, value, errorList) { 33661 var orderedParts = this._getOrderedDateParts(value); 33662 var dateParts = orderedParts[0], fieldOrder = orderedParts[1]; 33663 month = dateParts[fieldOrder.indexOf('M')], 33664 day = dateParts[fieldOrder.indexOf('D')], 33665 year = dateParts[fieldOrder.indexOf('Y')]; 33666 if (month !== "" && day !== "" && year !== "") { 33667 month = Number(month) || 0; 33668 day = Number(day) || 0; 33669 year = Number(year) || 0; 33670 var isLeapYear = (year % 400 === 0 || (year % 4 === 0 && year % 100 !== 0)); 33671 if (month === 2) { 33672 var maxFebruary = isLeapYear ? 29 : 28; 33673 if (day === 29 && !isLeapYear) { 33674 errorList.push(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.februaryMessage, [maxFebruary, year])); 33675 } 33676 if (day >= 30) { 33677 errorList.push(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.februaryMessage, [maxFebruary, year])); 33678 } 33679 } 33680 } 33681 }, 33682 _computeErrors : function (obj, errorList) { 33683 var that = this; 33684 obj.validFlag = errorList.length === 0; 33685 if (!obj.validFlag) { 33686 that._errorText = errorList.join(" "); 33687 that._failedTest = that.guideUtil.FORMAT_TEST; 33688 } 33689 }, 33690 33691 33692 _runValidations : function (obj) { 33693 var value = this.value; 33694 if (this.jsonModel.titleDay || this.jsonModel.titleMonth || this.jsonModel.titleYear) { 33695 if (null === value) { 33696 value = "//"; 33697 } 33698 var errorList = []; 33699 33700 this._checkIsolatedDateValidity(obj, value, errorList); 33701 33702 if (errorList.length === 0) { 33703 this._validateDaysOfMonth(obj, value, errorList); 33704 } 33705 33706 if (errorList && errorList.length === 0) { 33707
33708 this._validateFieldCompleteness(obj, value, errorList); 33709 } 33710 33711 if (errorList.length === 0) { 33712 this._validateFullDate(obj, value, errorList); 33713 } 33714 this._computeErrors(obj, errorList); 33715 33716 33717 if (errorList.length === 0) { 33718 this.value = value = this.value === "//" ? "" : this.value; 33719 GuideDatePicker._super._runValidations.call(this, obj); 33720 try { 33721 this.value = value = this.value !== null && this.value !== "" ? xfalib.ut.PictureFmt.parseDate(this.value, (this.jsonModel.dateDisplayFormat || "date{M/D/YYYY}")) : this.value; 33722 } catch (error) {} 33723 this._minMaxValidation(value, obj); 33724 } 33725 } else { 33726 GuideDatePicker._super._runValidations.call(this, obj); 33727 this._datatypeValidation(obj); 33728 this._minMaxValidation(value, obj); 33729 } 33730 } 33731 }); 33732 33733 GuideDatePicker.addMixins([ 33734 guidelib.model.mixin.AddMinMaxValidation 33735 ]); 33736 33737})(_, guidelib); 33738 33739(function (guidelib, $, _) { 33740 var ErrorConstants = guidelib.util.ErrorConstants = { 33741 DATA_ATTRIBUTE_ERROR_ITEM : "data-af-global-error-item", 33742 DATA_ATTRIBUTE_DISPLAY_ON : "data-af-global-errors-display-on", 33743 DATA_ATTRIBUTE_ERROR_TEXT_CONTAINER : "data-af-global-error-text", 33744 DATA_ATTRIBUTE_ERROR_CONTAINER : "data-af-global-errors", 33745 DATA_ATTRIBUTE_SOM : "data-af-som", 33746 CONTEXT_SUBMISSION : "form", 33747 CONTEXT_NAVIGATION : "panel", 33748 CONTEXT_FIELD : "field" 33749 33750 }; 33751 ErrorConstants[ErrorConstants.CONTEXT_SUBMISSION] = 4; 33752 ErrorConstants[ErrorConstants.CONTEXT_NAVIGATION] = 2; 33753 ErrorConstants[ErrorConstants.CONTEXT_FIELD] = 1; 33754 33755 var GlobalErrorContainer = function ($el, options) { 33756 this.$container = $el; 33757 var $items = $el.find("[" + ErrorConstants.DATA_ATTRIBUTE_ERROR_ITEM + "]").first(), 33758 displayOnAttribute = $el.attr(ErrorConstants.DATA_ATTRIBUTE_DISPLAY_ON) || ""; 33759 this.displayOn = 0; 33760 this.errorCount = 0; 33761 this.$container.addClass("no-validation-errors"); 33762 _.each(displayOnAttribute.split(","), function (displayOn) { 33763 var val = ErrorConstants[displayOn] || 0; 33764 this.displayOn += val; 33765 }, this); 33766 this.$item = $items.eq(0).clone(); 33767 $items.remove(); 33768 }; 33769 _.extend(GlobalErrorContainer.prototype, { 33770 33771 showError : function (msg, context, fieldSom) { 33772 var nContext, 33773 $el = this.$container.find('[' + ErrorConstants.DATA_ATTRIBUTE_SOM + '="' + fieldSom + '"]');; 33774 if ($el.length > 0) { 33775 $el.find("[" + ErrorConstants.DATA_ATTRIBUTE_ERROR_TEXT_CONTAINER + "]") 33776 .addBack("[" + ErrorConstants.DATA_ATTRIBUTE_ERROR_TEXT_CONTAINER + "]") 33777 .text(msg); 33778 } else { 33779 if (typeof ErrorConstants[context] !== "number") { 33780 return; 33781 } 33782 nContext = ErrorConstants[context]; 33783 if ((nContext & this.displayOn) === nContext) { 33784 if (this.errorCount === 0) { 33785 this.$container.removeClass("no-validation-errors"); 33786 } 33787 this.errorCount++; 33788 this.$item.clone() 33789 .find("[" + ErrorConstants.DATA_ATTRIBUTE_ERROR_TEXT_CONTAINER + "]") 33790 .addBack("[" + ErrorConstants.DATA_ATTRIBUTE_ERROR_TEXT_CONTAINER + "]") 33791 .text(msg) 33792 .click(function (evnt) { 33793 guideBridge.setFocus(fieldSom); 33794 }) 33795 .end() 33796 .end() 33797 .attr(ErrorConstants.DATA_ATTRIBUTE_SOM, fieldSom) 33798 .appendTo(this.$container); 33799 } 33800 } 33801 }, 33802 hideError : function (fieldSom) { 33803 var $err = this.$container.find('[' + ErrorConstants.DATA_ATTRIBUTE_SOM + '="' + fieldSom + '"]'); 33804 if ($err.length > 0) { 33805 $err.remove(); 33806 this.errorCount--; 33807 } 33808 if (this.errorCount === 0) { 33809 this.$container.addClass("no-validation-errors"); 33810 } 33811 } 33812 }); 33813 33814 $.fn.globalErrorContainer = function (options) { 33815 var args = arguments; 33816 return this.each(function () { 33817 var $this = $(this), 33818 obj = $this.data("global-error-container"); 33819 if (obj === undefined) { 33820 obj = new GlobalErrorContainer($this, $.extend({}, typeof options === "object" && options)); 33821 $this.data("global-error-container", obj); 33822 } 33823 if (typeof options === "string" && typeof obj[options] === "function") { 33824 obj[options].apply(obj, [].splice.apply(args, [1])); 33825 } 33826 }); 33827 }; 33828}(guidelib, $, _)); 33829 33830(function (guidelib, $, _) { 33831 33832 var ErrorConstants = guidelib.util.ErrorConstants, 33833 $GlobalErrorContainer; 33834 var GuideErrorManager = guidelib.util.GuideErrorManager = xfalib.ut.Class.extend({ 33835 33836 _defaultErrorMessage : "There is an error in this field !", 33837 33838 initialize : function () { 33839 GuideErrorManager._super.initialize.apply(arguments); 33840 $GlobalErrorContainer = $("[" + ErrorConstants.DATA_ATTRIBUTE_ERROR_CONTAINER + "]").globalErrorContainer(); 33841 }, 33842 33843 33844 33845 markError : function (msg, wrapper, fieldSom, context, type) { 33846 var errorDiv; 33847 33848 if (_.isUndefined(msg)) { 33849 msg = this._defaultErrorMessage; 33850 } 33851 33852 msg = msg.trim(); 33853 33854 $GlobalErrorContainer.globalErrorContainer("showError", msg, context, fieldSom); 33855 33856 33857 if (wrapper) { 33858 if (wrapper.length >= 1) { 33859 errorDiv = wrapper.find(".guideFieldError"); 33860 if (errorDiv.length < 1) { 33861 $("<div class='guideFieldError'></div>").appendTo(wrapper).text(msg); 33862 } else { 33863 errorDiv.text(msg); 33864 var roleAttr = errorDiv.attr('role'); 33865 if (roleAttr != undefined || roleAttr !== false) { 33866 errorDiv.attr('role', 'alert'); 33867 } 33868 errorDiv.show(); 33869 } 33870 33871 } 33872 } 33873 }, 33874 33875 unMarkError : function (wrapper, fieldSom) { 33876 33877 33878 wrapper.find(".guideFieldError").text(""); 33879 $GlobalErrorContainer.globalErrorContainer("hideError", fieldSom); 33880 } 33881 }); 33882})(guidelib, $, _); 33883(function (_, guidelib) { 33884 guidelib.model.mixin.ChoiceGroupOptionHandler = { 33885 normalProperties : { 33886 33887 _getOptionsArray : function (saveValueKey, displayValueKey) { 33888 var items = [], items1 = this.items; 33889 saveValueKey = saveValueKey || "saveValue"; 33890 displayValueKey = displayValueKey || "displayValue"; 33891 if (_.isArray(items1)) { 33892 _.each(items1, function (val) { 33893 33894 33895 var temp = val.split('='), 33896 obj = {}; 33897 obj[saveValueKey] = temp[0]; 33898 obj[displayValueKey] = temp[1] || temp[0]; 33899 items.push(obj); 33900 }); 33901 } 33902 return items; 33903 }, 33904 33905 33906 _getPossibleValueArray : function () { 33907 var values = [], items1 = this.items; 33908 if (_.isArray(items1)) { 33909 _.each(items1, function (val) { 33910 33911 var temp = val.split('='); 33912 values.push(temp[0]); 33913 }); 33914 } 33915 return values; 33916 }, 33917 33918 33919 _triggerItemsChange : function (oldValue, newValue) { 33920 this.trigger(guidelib.event.GuideModelEvent.ITEMS_CHANGED, 33921 guidelib.event.GuideModelEvent.createEvent( 33922 guidelib.event.GuideModelEvent.ITEMS_CHANGED, 33923 this, 33924 "items", 33925 oldValue, 33926 newValue 33927 ) 33928 ); 33929 }, 33930 33931 _resetModelValueForOptionChange : function () { 33932 if (!_.isUndefined(this.jsonModel._value) && this.jsonModel._value != null) { 33933 var valueArr = this.jsonModel._value.split(","); 33934 var possibleValues = this._getPossibleValueArray(); 33935 var modelValue = ""; 33936 _.each(valueArr, function (val) { 33937 if ($.inArray(val, possibleValues, 0) !== -1) { 33938 modelValue += val + ","; 33939 } 33940 }, this); 33941 if (modelValue.length > 0) { 33942 modelValue = modelValue.substring(0, modelValue.length - 1); 33943 } 33944 this.jsonModel._value = modelValue; 33945 } 33946 } 33947 } 33948 }; 33949 33950}(_, guidelib)); 33951(function (_, guidelib) { 33952 var GuideCheckBox = guidelib.model.GuideCheckBox = guidelib.model.Field.extend({ 33953 msClassName : "guideCheckBox", 33954 33955 _collectExpressions : function () { 33956 GuideCheckBox._super._collectExpressions.apply(this); 33957 if (this.optionsExp) { 33958 this._compiledExpressions.optionsExp = this._compileExpression(this.optionsExp, "items"); 33959 } 33960 }, 33961 33962 getOnOffValues : function (index) { 33963 var temp = this.jsonModel.options || [], items = [], on, off; 33964 if (this.bindNode) { 33965 on = this.bindNode.getSaveItem(0); 33966 off = this.bindNode.getSaveItem(1); 33967 } else { 33968 33969 if (temp.length == 0) { 33970 on = "0"; 33971 } else { 33972 on = temp[index].split('=')[0].trim(); 33973 } 33974 off = "-100"; 33975 } 33976 33977 items = [on, off]; 33978 return items; 33979 }, 33980 33981 _setXFAValue : function (value) { 33982 33983 if (value === "" || value === null) { 33984 this.bindNode.rawValue = this.bindNode.getSaveItem(1) || null; 33985 } else { 33986 this.bindNode.rawValue = value; 33987 } 33988 }, 33989 33990 _getCustomAssist : function (index) { 33991 var customAssist, item; 33992 33993 if (index == null) { 33994 33995 if (this.bindNode && this.bindNode.assist && this.bindNode.assist.speak && this.bindNode.assist.speak.value) { 33996 return this.bindNode.assist.speak.value; 33997 } 33998 return null; 33999 } 34000 34001 if (this.bindNode && this.bindNode.members && this.bindNode.members.item) { 34002 item = this.bindNode.members.item(index); 34003 if (item && item.assist && item.assist.speak && item.assist.speak.value) { 34004 customAssist = item.assist.speak.value; 34005 } 34006 } else if (this.jsonModel.custom) { 34007 34008 var custom; 34009 custom = this.jsonModel.custom || []; 34010 if (_.isString(custom) && index <= 0) { 34011 customAssist = custom; 34012 } else if (!custom.length === 0) { 34013 customAssist = custom[index]; 34014 } 34015 } 34016 return customAssist; 34017 }, 34018 _getToolTip : function (index) { 34019 var toolTip, item; 34020 if (this.bindNode && this.bindNode.members && this.bindNode.members.item) { 34021 item = this.bindNode.members.item(index); 34022 34023 if (item && item.assist && item.assist.speak && item.assist.speak.value) { 34024 toolTip = item.assist.toolTip.value; 34025 } 34026 34027 }
34027 else if (this.jsonModel.shortDescription) { 34028 toolTip = this.jsonModel.shortDescription; 34029 } 34030 return toolTip; 34031 }, 34032 _getCaption : function (index) { 34033 var item, caption, option; 34034 if (index == null) { 34035 34036 if (this.bindNode && this.bindNode.caption && this.bindNode.caption.value && this.bindNode.caption.value.oneOfChild && this.bindNode.caption.value.oneOfChild.value) { 34037 return this.bindNode.caption.value.oneOfChild.value; 34038 } 34039 return null; 34040 } 34041 if (this.bindNode && this.bindNode.members && this.bindNode.members.item) { 34042 item = this.bindNode.members.item(index); 34043 if (item.caption && item.caption.value && item.caption.value.oneOfChild && item.caption.value.oneOfChild.value) { 34044 caption = item.caption.value.oneOfChild.value; 34045 } 34046 34047 } else if (this.jsonModel.options) { 34048 var options; 34049 options = this.jsonModel.options || []; 34050 if (index < 0) { 34051 index = 0; 34052 } 34053 if (!options.length == 0) { 34054 option = options[index]; 34055 caption = guidelib.util.GuideUtil.getOptionsKeyValue(option).pop(); 34056 } 34057 34058 } 34059 return caption; 34060 }, 34061 _getName : function (index) { 34062 if (this.bindNode && this.bindNode.members && this.bindNode.members.item && this.bindNode.members.item(index)) { 34063 34064 return this.bindNode.members.item(index).name; 34065 } 34066 return null; 34067 }, 34068 34069 _getScreenReaderText : function (index) { 34070 var screenReaderText, assistPriority = this._getAssistPriority() || "caption"; 34071 34072 if (this.bindNode) { 34073 screenReaderText = GuideCheckBox._super._getScreenReaderText.apply(this, [index]); 34074 } else { 34075 if (assistPriority == "custom") { 34076 screenReaderText = this._getCustomAssist(index) || this._getCaption(index); 34077 } else if (assistPriority == "caption") { 34078 screenReaderText = this._getCaption(index); 34079 } 34080 } 34081 return screenReaderText; 34082 } 34083 }); 34084 34085 GuideCheckBox.defineProps({ 34086 34087 optionsExp : { 34088 get : function () { 34089 return this.getAttribute("optionsExp"); 34090 } 34091 }, 34092 34093 34094 items : { 34095 get : function () { 34096 var items = this.jsonModel.options; 34097 if (items && !_.isArray(items)) { 34098 items = items.split(","); 34099 } else if (items) { 34100 items = items.slice(0); 34101 } 34102 return items; 34103 }, 34104 set : function (newValue) { 34105 if (!this.bindNode) { 34106 var oldValue = this.jsonModel.options; 34107 if (JSON.stringify(newValue) !== JSON.stringify(oldValue)) { 34108 34109 this.jsonModel.options = newValue; 34110 this._resetModelValueForOptionChange(); 34111 this._addStateOverride("options", {"option" : this._getOptionsArray()}); 34112 this._triggerItemsChange(oldValue, newValue); 34113 } 34114 } 34115 } 34116 } 34117 }); 34118 34119 GuideCheckBox.addMixins([ 34120 guidelib.model.mixin.ChoiceGroupOptionHandler 34121 ]); 34122})(_, guidelib); 34123(function (_, guidelib) { 34124 var GuideSwitch = guidelib.model.GuideSwitch = guidelib.model.GuideCheckBox.extend({ 34125 msClassName : "guideSwitch", 34126 34127 initialize : function () { 34128 34129 var uncheckedValue = this.getOnOffValues()[1]; 34130 this.jsonModel["_value"] = this.getOrElse(this.jsonModel, "_value", uncheckedValue); 34131 GuideSwitch._super.initialize.call(this); 34132 }, 34133 34134 getOnOffValues : function (index) { 34135 var options, checkedLabel, uncheckedLabel, items; 34136 if (this.bindNode) { 34137 checkedLabel = this.bindNode.getSaveItem(0); 34138 uncheckedLabel = this.bindNode.getSaveItem(1); 34139 } else { 34140 items = this.jsonModel.options; 34141 34142 if (Array.isArray(items) && items.length > 0) { 34143 checkedLabel = items[0].split('=')[0].trim(); 34144 } else if (!_.isUndefined(items) && items.length > 0) { 34145 checkedLabel = items.split('=')[0].trim(); 34146 } else { 34147 checkedLabel = "1"; 34148 } 34149 if (Array.isArray(items) && items.length > 1) { 34150 uncheckedLabel = items[1].split('=')[0].trim(); 34151 } else { 34152 uncheckedLabel = "0"; 34153 } 34154 } 34155 options = [checkedLabel, uncheckedLabel]; 34156 return options; 34157 }, 34158 34159 resetData : function () { 34160 this.value = this.jsonModel["{default}"]; 34161 } 34162 }); 34163})(_, guidelib); 34164(function (_, guidelib) { 34165 var GuideRadioButton = guidelib.model.GuideRadioButton = guidelib.model.Field.extend({ 34166 msClassName : "guideRadioButton", 34167 prevOnItem : null, 34168 initialize : function () { 34169 34170 GuideRadioButton._super.initialize.call(this); 34171 }, 34172 34173 _postInitialize : function () { 34174 GuideRadioButton._super._postInitialize.call(this);
34175 this.prevOnItem = this.getSelectedIndex(this.value); 34176 if (this.bindNode && this.bindNode.members) { 34177 for (var i = 0; i < this.bindNode.members.length; i++) { 34178 var field = this.bindNode.members.item(i); 34179 field.on(xfalib.script.XfaModelEvent.FORM_MODEL_CHANGED, this); 34180 } 34181 } 34182 }, 34183 34184 _unloadModel : function () { 34185 if (this.bindNode && this.bindNode.members) { 34186 for (var i = 0; i < this.bindNode.members.length; i++) { 34187 var field = this.bindNode.members.item(i); 34188 field.off(xfalib.script.XfaModelEvent.FORM_MODEL_CHANGED, this); 34189 } 34190 } 34191 34192 GuideRadioButton._super._unloadModel.call(this); 34193 }, 34194 34195 34196 _collectExpressions : function () { 34197 GuideRadioButton._super._collectExpressions.apply(this); 34198 if (this.optionsExp) { 34199 this._compiledExpressions.optionsExp = this._compileExpression(this.optionsExp, "items"); 34200 } 34201 }, 34202 34203 34204 getItemIdentifier : function (index) { 34205 if (this.bindNode) { 34206 return this.bindNode.members.item(index).somExpression; 34207 } else { 34208 return index; 34209 } 34210 34211 }, 34212 34213 playJson : function (pJsonModel) { 34214 GuideRadioButton._super.playJson.call(this, pJsonModel); 34215 this.prevOnItem = this.getSelectedIndex(this.jsonModel._value); 34216 }, 34217 34218 getOnOffValues : function (index) { 34219 var temp = this.jsonModel.options || [], 34220 items = [], 34221 on, 34222 off; 34223 if (this.bindNode) { 34224 var item = this.bindNode.members.item(index); 34225 on = item.getSaveItem(0); 34226 off = item.getSaveItem(1) ? item.getSaveItem(1) : null; 34227 } else { 34228 34229 if (temp.length == 0) { 34230 on = "0"; 34231 } else { 34232 on = temp[index].split('=')[0].trim(); 34233 } 34234 off = null; 34235 } 34236 34237 items = [on, off]; 34238 return items; 34239 }, 34240 34241 _handleXfaModelChanged : function (event) { 34242 if (event._property == "rawValue") { 34243 this.trigger(guidelib.event.GuideModelEvent.VALUE_CHANGED, 34244 guidelib.event.GuideModelEvent.createEvent( 34245 guidelib.event.GuideModelEvent.VALUE_CHANGED, 34246 this, 34247 "value", 34248 event.target.somExpression, 34249 event.newText 34250 ) 34251 ); 34252 } else { 34253 GuideRadioButton._super._handleXfaModelChanged.call(this, event); 34254 } 34255 }, 34256 34257 getSelectedIndex : function (value) { 34258 var index = null; 34259 if (!_.isEmpty(this.jsonModel.options) && !_.isArray(this.jsonModel.options)) { 34260 this.jsonModel.options = [this.jsonModel.options]; 34261 } 34262 var currOption = _.find(this.jsonModel.options, function (opt, i) { 34263 var items = this.getOnOffValues(i); 34264 index = i; 34265 return (items[0] == value); 34266 }, this); 34267 34268 if (currOption) { 34269 return index; 34270 } else { 34271 return null; 34272 } 34273 34274 }, 34275 34276 34277 34278 _triggerDisplayFormatChange : function () { 34279 if (!this.bindNode) { 34280 var currValue = this._getValue(); 34281 var currSelected = this.getSelectedIndex(currValue); 34282 34283 if (this.prevOnItem !== null) { 34284 this._triggerEvent(guidelib.event.GuideModelEvent.VALUE_CHANGED, "value", this.prevOnItem, null); 34285 } 34286 if (currSelected !== null) { 34287 this._triggerEvent(guidelib.event.GuideModelEvent.VALUE_CHANGED, "value", currSelected, this._getFormattedValue(currValue)); 34288 } 34289 this.prevOnItem = currSelected; 34290 } 34291 }, 34292 _getCustomAssist : function (index) { 34293 var customAssist, item; 34294 34295 if (index == null) { 34296 34297 if (this.bindNode && this.bindNode.assist && this.bindNode.assist.speak && this.bindNode.assist.speak.value) { 34298 return this.bindNode.assist.speak.value; 34299 } 34300 return null; 34301 } 34302 34303 if (this.bindNode && this.bindNode.members && this.bindNode.members.item) { 34304 item = this.bindNode.members.item(index); 34305 if (item && item.assist && item.assist.speak && item.assist.speak.value) { 34306 customAssist = item.assist.speak.value; 34307 } 34308 } else if (this.jsonModel.custom) { 34309 34310 var custom; 34311 custom = this.jsonModel.custom || []; 34312 if (_.isString(custom) && index <= 0) { 34313 34314 customAssist = custom; 34315 } else { 34316 if (!custom.length == 0) { 34317 customAssist = custom[index]; 34318 } 34319 } 34320 } 34321 return customAssist; 34322 }, 34323 _getToolTip : function (index) { 34324 var toolTip, item; 34325 if (this.bindNode && this.bindNode.members && this.bindNode.members.item) { 34326 item = this.bindNode.members.item(index); 34327 34328 if (item && item.assist && item.assist.speak && item.assist.speak.value) { 34329 toolTip = item.assist.toolTip.value; 34330 } 34331 34332 }
34332 else if (this.jsonModel.shortDescription) { 34333 toolTip = this.jsonModel.shortDescription; 34334 } 34335 return toolTip; 34336 }, 34337 _getCaption : function (index) { 34338 var item, caption, option; 34339 if (index == null) { 34340 34341 if (this.bindNode && this.bindNode.caption && this.bindNode.caption.value && this.bindNode.caption.value.oneOfChild && this.bindNode.caption.value.oneOfChild.value) { 34342 return this.bindNode.caption.value.oneOfChild.value; 34343 } 34344 return null; 34345 } 34346 if (this.bindNode && this.bindNode.members && this.bindNode.members.item) { 34347 item = this.bindNode.members.item(index); 34348 if (item.caption && item.caption.value && item.caption.value.oneOfChild && item.caption.value.oneOfChild.value) { 34349 caption = item.caption.value.oneOfChild.value; 34350 } 34351 34352 } else if (this.jsonModel.options) { 34353 var options; 34354 options = this.jsonModel.options || []; 34355 if (index < 0) { 34356 index = 0; 34357 } 34358 if (!options.length == 0) { 34359 option = options[index]; 34360 caption = guidelib.util.GuideUtil.getOptionsKeyValue(option).pop(); 34361 } 34362 34363 } 34364 return caption; 34365 }, 34366 _getName : function (index) { 34367 if (this.bindNode && this.bindNode.members && this.bindNode.members.item && this.bindNode.members.item(index)) { 34368 34369 return this.bindNode.members.item(index).name; 34370 } 34371 return null; 34372 }, 34373 34374 _getScreenReaderText : function (index) { 34375 var screenReaderText, assistPriority = this._getAssistPriority() || "caption"; 34376 34377 if (this.bindNode) { 34378 screenReaderText = GuideRadioButton._super._getScreenReaderText.apply(this, [index]); 34379 } else { 34380 if (assistPriority == "custom") { 34381 screenReaderText = this._getCustomAssist(index) || this._getCaption(index); 34382 } else if (assistPriority == "caption") { 34383 screenReaderText = this._getCaption(index); 34384 } 34385 } 34386 return screenReaderText; 34387 } 34388 }); 34389 34390 GuideRadioButton.defineProps({ 34391 34392 optionsExp : { 34393 get : function () { 34394 return this.getAttribute("optionsExp"); 34395 } 34396 }, 34397 34398 34399 items : { 34400 get : function () { 34401 var items = this.jsonModel.options; 34402 if (items && !_.isArray(items)) { 34403 items = items.split(","); 34404 } else if (items) { 34405 items = items.slice(0); 34406 } 34407 return items; 34408 }, 34409 set : function (newValue) { 34410 if (!this.bindNode && newValue && newValue.length > 1) { 34411 var oldValue = this.jsonModel.options; 34412 if (JSON.stringify(newValue) !== JSON.stringify(oldValue)) { 34413 34414 this.jsonModel.options = newValue; 34415 this._resetModelValueForOptionChange(); 34416 this._addStateOverride("options", {"option" : this._getOptionsArray()}); 34417 this._triggerItemsChange(oldValue, newValue); 34418 } 34419 } 34420 } 34421 } 34422 }); 34423 34424 GuideRadioButton.addMixins([ 34425 guidelib.model.mixin.ChoiceGroupOptionHandler 34426 ]); 34427})(_, guidelib); 34428 34429(function (_, guidelib) { 34430 34431 34432 var GuideDropDownList = guidelib.model.GuideDropDownList = guidelib.model.Field.extend({ 34433 msClassName : "guideDropDownList" , 34434 34435 _collectExpressions : function () { 34436 GuideDropDownList._super._collectExpressions.apply(this); 34437 if (this.optionsExp) { 34438 this._compiledExpressions["optionsExp"] = this._compileExpression(this.optionsExp, "items"); 34439 } 34440 }, 34441 34442 _handleXfaModelChanged : function (event) { 34443 if (event._property === "addItem" || event._property === "clearItems" || event._property === "deleteItem") { 34444 this._triggerEvent(guidelib.event.GuideModelEvent.MODEL_CHANGED, event._property, event.prevText, event.newText); 34445 } else { 34446 GuideDropDownList._super._handleXfaModelChanged.call(this, event); 34447 } 34448 }, 34449 34450 _getDisplayValue : function (saveValue) { 34451 var items = this._getOptionsArray(), 34452 displayValue = null; 34453 _.each(items, function (val) { 34454 if (saveValue === val.saveValue) { 34455 displayValue = val.displayValue; 34456 } 34457 }, this);
34458 return displayValue; 34459 }, 34460 34461 _getItems : function () { 34462 return this.jsonModel.options; 34463 }, 34464 34465 _setXFAItems : function (options) { 34466 var optionsStr = this._getXFAOptionStringFromGuideItems(options); 34467 var SET_ITEMS_INSERT_MODE_PAIR = 2; 34468 if (optionsStr) { 34469 this.bindNode.setItems(optionsStr, SET_ITEMS_INSERT_MODE_PAIR); 34470 } else { 34471 this.bindNode.clearItems(); 34472 } 34473 }, 34474 34475 34476 _allowEmptyValueString : function () { 34477 return true; 34478 } 34479 34480 }); 34481 34482 GuideDropDownList.defineProps({ 34483 34484 34485 34486 multiSelect : { 34487 get : function () { 34488 return this.getAttribute("multiSelect"); 34489 }, 34490 set : function () { 34491 this.setAttribute("multiSelect"); 34492 } 34493 }, 34494 34495 optionsExp : { 34496 get : function () { 34497 return this.getAttribute("optionsExp"); 34498 } 34499 }, 34500 34501 34502 displayValue : { 34503 get : function () { 34504 return this._getDisplayValue(this.value); 34505 } 34506 }, 34507 34508 34509 34510 items : { 34511 get : function () { 34512 var items = []; 34513 if (this.bindNode) { 34514 var that = this.bindNode; 34515 for (var index = 0; index < that.length; index++) { 34516 var item = that.getSaveItem(index) + "=" + that.getDisplayItem(index); 34517 items.push(item); 34518 } 34519 return items; 34520 } else { 34521 items = this._getItems(); 34522 if (items && !_.isArray(items)) { 34523 items = items.split(","); 34524 } else if (items) { 34525 items = items.slice(0); 34526 } 34527 return items; 34528 } 34529 }, 34530 set : function (newValue) { 34531 var oldValue = this._getItems(); 34532 if (JSON.stringify(newValue) !== JSON.stringify(oldValue)) { 34533 if (this.bindNode) { 34534 this._setXFAItems(newValue); 34535 } else { 34536 this.jsonModel.options = newValue; 34537 } 34538 if (this.multiSelect) { 34539 this._resetModelValueForOptionChange(); 34540 } 34541 this._addStateOverride("options", {"option" : this._getOptionsArray()}); 34542 this._triggerItemsChange(oldValue, this.items); 34543 } 34544 } 34545 } 34546 }); 34547 GuideDropDownList.addMixins([ 34548 guidelib.model.mixin.ChoiceGroupOptionHandler 34549 ]); 34550})(_, guidelib); 34551 34552 34553(function (guidelib, $, _) { 34554 34555 var GuideLazyUtil = guidelib.util.GuideLazyUtil = xfalib.ut.Class.extend({ 34556 34557 34558 putDirtyToTemplateCacheIfMissing : function (guide) { 34559 var guideDirtyMarker = guide.internal.GuideDirtyMarkerAndVisitor || this._guide().internal.GuideDirtyMarkerAndVisitor, 34560 listOfDirtyChildren = guideDirtyMarker._flattenDirtyPanelToList(); 34561 this._getAllDirtyJsonTemplateInCache(listOfDirtyChildren); 34562 }, 34563 34564 34565 _getAllDirtyJsonTemplateInCache : function (listOfTemplateIds) { 34566 var modelTemplateCache = window.guideBridge._guide._modelTemplateCacheStore, 34567 toGetFromServer = this._generateListOfCacheMissFromTemplateJson(listOfTemplateIds); 34568 if (toGetFromServer.length > 0 && window.guideBridge.panelProvider) { 34569 var options = { 34570 path : window.guideBridge._getGuidePathUrl(".jsonhtmlemitter"), 34571 listOfTemplateIds : toGetFromServer, 34572 success : addToTemplateCache 34573 }; 34574 window.guideBridge.panelProvider.getMultipleTemplateJson(options); 34575 } 34576 34577 function addToTemplateCache(toInsertToTemplateCache) { 34578 _.each(toInsertToTemplateCache, function (jsonModelString) { 34579 var template = JSON.parse(jsonModelString); 34580 modelTemplateCache._putLazyTemplate(template); 34581 }); 34582 } 34583 }, 34584 34585 34586 _generateListOfCacheMissFromTemplateJson : function (listOfTemplateIds) { 34587 var templateCache = window.guideBridge._guide._modelTemplateCacheStore, 34588 cacheMiss = []; 34589 _.each(listOfTemplateIds, function (templateID) { 34590 var templateJson = templateCache._getTemplate(templateID, true); 34591 if (guidelib.util.GuideUtil.isLazyJson(templateJson)) { 34592 cacheMiss.push(templateID); 34593 } 34594 }); 34595 return cacheMiss; 34596 }, 34597 34598 _guide : function () { 34599 return this.options._guideContainer; 34600 } 34601 34602 }); 34603})(guidelib, $, _); 34604(function (_, guidelib) { 34605 var guideSchema = {}, 34606 convertor = { 34607 "visible" : { 34608 "xfaToGuide" : function (xfaValue) { 34609 return xfaValue === "visible"; 34610 }, 34611 "guideToXfa" : function (guideValue) { 34612 return guideValue === true ? "visible" : "hidden"; 34613 } 34614 }, 34615 "enabled" : { 34616 "xfaToGuide" : function (xfaValue) { 34617 return xfaValue === "open"; 34618 }, 34619 "guideToXfa" : function (guideValue) { 34620 return guideValue === true ? "open" : "readOnly"; 34621 } 34622 }, 34623 "assistPriority" : { 34624 "xfaToGuide" : function (xfaValue) { 34625 return { 34626 "custom" : "custom",
34627 "toolTip" : "shortDescription", 34628 "caption" : "label", 34629 "name" : "name" 34630 }[xfaValue]; 34631 }, 34632 "guideToXfa" : function (guideValue) { 34633 return { 34634 "custom" : "custom", 34635 "shortDescription" : "toolTip", 34636 "title" : "caption", 34637 "name" : "name" 34638 }[guideValue]; 34639 } 34640 }, 34641 "mandatory" : { 34642 "xfaToGuide" : function (xfaValue) { 34643 return xfaValue === "error"; 34644 }, 34645 "guideToXfa" : function (guideValue) { 34646 return guideValue === true ? "error" : "disabled"; 34647 } 34648 }, 34649 "multiLine" : { 34650 "xfaToGuide" : function (xfaValue) { 34651 return xfaValue == 1; 34652 }, 34653 "guideToXfa" : function (guideValue) { 34654 return guideValue === true ? 1 : 0; 34655 } 34656 }, 34657 34658 34659 "options" : { 34660 "xfaToGuide" : function (xfaValue) { 34661 var items = []; 34662 if (xfaValue) { 34663 var bndNode = this.bindNode; 34664 _.each(xfaValue, function (item, index, list) { 34665 items.push(bndNode.getSaveItem(index) + "=" + bndNode.getDisplayItem(index)); 34666 }); 34667 } 34668 return items; 34669 }, 34670 "guideToXfa" : function (guideValue) { 34671 return guideValue; 34672 } 34673 }, 34674 "multiSelect" : { 34675 "xfaToGuide" : function (xfaValue) { 34676 return xfaValue === "multiSelect"; 34677 }, 34678 "guideToXfa" : function (guideValue) { 34679 return guideValue === true ? "multiSelect" : "userControl"; 34680 } 34681 }, 34682 "calcExp" : { 34683 "xfaToGuide" : function (xfaValue) { 34684 return xfaValue !== null && xfaValue !== "" ? null : undefined; 34685 }, 34686 "guideToXfa" : function (guideValue) { 34687 return guideValue !== null && guideValue !== "" ? null : undefined; 34688 } 34689 }, 34690 "dataType" : { 34691 "xfaToGuide" : function (xfaValue) { 34692 return xfaValue; 34693 }, 34694 "guideToXfa" : function (guideValue) { 34695 return undefined; 34696 } 34697 } 34698 }; 34699 convertor.validateExp = convertor.visibleExp = 34700 convertor.enabledExp = 34701 convertor.clickExp = 34702 convertor.calcExp; 34703 34704 guidelib.model.GuideSchema = xfalib.ut.Class.extend({ 34705 34706 GuideStateConstants : { 34707 34708 GUIDE_STATE_MODEL_CREATION : 0, 34709 34710 GUIDE_STATE_MODEL_CREATED : 1, 34711 34712 GUIDE_STATE_MERGE_PROGRESS : 2, 34713 34714 GUIDE_STATE_MERGE_COMPLETE : 3, 34715 34716 GUIDE_STATE_MODEL_COMPLETE : 4 34717 }, 34718 34719 initialize : function () { 34720 34721 this.addSchema('guideNode', 34722 [ 34723 ["name", "string", null], 34724 ["id", "string", null], 34725 ["jcr:title", "string", null], 34726 ["jcr:description", "string", null], 34727 ["css", "string", ""], 34728 ["fd:targetVersion", "float", 1.0] 34729 ]); 34730 34731 this.addSchema("scriptable", 34732 [ 34733 ["visibleExp", "string", null], 34734 ["enabledExp", "string", null], 34735 ["visible", "boolean", true, "presence"], 34736 ["enabled", "boolean", true, "access"], 34737 ["assistPriority", "string", null, "assist.speak.priority"], 34738 ["custom", "string", null, "assist.speak.value"],
34739 ["shortDescription", "string", null, "assist.toolTip.value"], 34740 ["longDescription", "string", null] 34741 ], 34742 'guideNode'); 34743 34744 this.addSchema("guideInstanceManager", [], "guideNode"); 34745 34746 this.addSchema("esign", [], "guideNode"); 34747 34748 this.addSchema("verify", [], "guideNode"); 34749 34750 this.addSchema("guideItemsContainer", [], "scriptable"); 34751 34752 this.addSchema("guideImage", [], "scriptable"); 34753 34754 this.addSchema("guideContainerNode", 34755 [ 34756 ["disableSwipeGesture", "boolean", false] 34757 ], 34758 "guideItemsContainer"); 34759 34760 this.addSchema("guidePanel", 34761 [ 34762 ["validateOnStepCompletion","boolean",false] 34763 ], 34764 "guideItemsContainer"); 34765 34766 this.addSchema("rootPanelNode", [], "guidePanel"); 34767 34768 this.addSchema("guideTable", [], "guidePanel"); 34769 34770 this.addSchema("guideTableRow", [], "guidePanel"); 34771 34772 this.addSchema("guideToolbar", [], "guideItemsContainer"); 34773 34774 this.addSchema("guideCompositeField", [], "guideItemsContainer"); 34775 34776 this.addSchema("guideFileUpload", 34777 [ 34778 ["multiSelection", "boolean", false], 34779 ["buttonText", "string", null], 34780 ["fileSizeLimit", "integer", 2], 34781 ["showComment", "boolean", false] 34782 ], 34783 "guideCompositeField"); 34784 34785 34786 34787 this.addSchema("guideField", 34788 [ 34789 ["jcr:title", "string", null, "caption.value.oneOfChild.value","Guide"], 34790 ["calcExp", "string", null, "calculate.script.value", "Guide"], 34791 ["validateExp", "string", null, "validate.script.value", "Guide"], 34792 ["_value", "string", null, "rawValue"], 34793 ["displayPictureClause", "string", null, "format.picture.value"], 34794 ["validatePictureClause", "string", null, "validate.picture.value"], 34795 ["mandatory", "boolean", false, "validate.nullTest"], 34796 ["mandatoryMessage", "string", guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.LogMessages["AEM-AF-901-005"]), 34797 "mandatoryMessage"], 34798 ["validateExpMessage", "string", guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.LogMessages["AEM-AF-901-006"]), 34799 "validationMessage","Guide"], 34800 ["validatePictureClauseMessage", "string", guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.LogMessages["AEM-AF-901-007"]), 34801 "formatMessage"], 34802 ["validationState", "boolean", false], 34803 ["width", "string", null], 34804 ["height", "string", null] 34805 ], 34806 "scriptable"); 34807 34808 this.addSchema("guideTextBox", 34809 [ 34810 ["multiLine", "boolean", false, "ui.textEdit.multiLine"], 34811 ["maxChars", "integer", 0, "value.text.maxChars"], 34812 ["minLength", "integer", null], 34813 ["length", "integer", null] 34814 ], 34815 "guideField"); 34816 34817 this.addSchema("guideCaptcha", [], "guideField"); 34818 34819 this.addSchema("guideTelephone", [], "guideField"); 34820 34821 this.addSchema("guideNumericBox", 34822 [ 34823 ["dataType", "string", "decimal", "value.oneOfChild.className"], 34824 ["leadDigits", "integer", -1, "value.decimal.leadDigits"], 34825 ["fracDigits", "integer", 2, "value.decimal.fracDigits"], 34826 ["maximum", "integer", null], 34827 ["minimum", "integer", null], 34828 ["exclusiveMaximum", "boolean", null], 34829 ["exclusiveMinimum", "boolean", null] 34830 ], 34831 "guideField"); 34832 34833 this.addSchema("guidePasswordBox", [], "guideField"); 34834 34835 this.addSchema("guideRadioButton", [ 34836 ["optionsExp", "string", null], 34837 ["options", "object", null, "items"] 34838 ], "guideField"); 34839 34840 this.addSchema("guideCheckBox", [ 34841 ["optionsExp", "string", null], 34842 ["options", "object", null, "items"] 34843 ], "guideField"); 34844 34845 this.addSchema("guideSwitch", [], "guideCheckBox"); 34846 34847 this.addSchema("guideScribble", [], "guideField"); 34848 34849 this.addSchema("guideDatePicker", 34850 [ 34851 ["maximum", "string", null], 34852 ["minimum", "string", null], 34853 ["exclusiveMaximum", "boolean", null], 34854 ["exclusiveMinimum", "boolean", null] 34855 ], "guideField"); 34856 34857 this.addSchema("guideButton", [], "guideField"); 34858 34859 this.addSchema("guideListFileAttachmentButton", [], "guideButton"); 34860 34861 this.addSchema("guideTextDraw", 34862 [ 34863 ["documentFragmentVariables", "string", null] 34864 ], 34865 "guideField"); 34866 34867 this.addSchema("guideFootnotePlaceHolder",[], "guideTextDraw"); 34868 34869 this.addSchema("guideAdobeSignBlock", 34870 [ 34871 ["documentFragmentVariables", "string", null] 34872 ], 34873 "guideField"); 34874 34875 this.addSchema("guideCompositeFieldItem", [], "guideField"); 34876 34877 this.addSchema("guideDropDownList", 34878 [ 34879 ["title", "string", "DropDown"], 34880 ["multiSelect", "boolean", false, "ui.oneOfChild.open"], 34881 ["optionsExp", "string", null], 34882 ["options", "object", null, "items"] 34883 ], 34884 "guideField"); 34885 34886 this.addSchema("guideTermsAndConditions", 34887 [ 34888 ["showLink", "boolean", false], 34889 ["showAsPopUp", "boolean", false], 34890 ["clickStatus", "string", null] 34891 ], 34892 "guideCompositeField"); 34893 34894 this.addSchema("guideChart", [ 34895 ["height", "integer", 300], 34896 ["width", "integer", 100], 34897 ["data", "object", null], 34898 ["xAxisTitle", "string", null], 34899 ["yAxisTitle", "string", null], 34900 ["chartType", "string", "linepoint"], 34901 ["repeatableItem", "string", null], 34902 ["xExp", "string", null], 34903 ["reducerXFunction", "string", "none"], 34904 ["yExp", "string", null], 34905 ["reducerYFunction", "string", "none"], 34906 ["innerRadius", "integer", 0], 34907 ["lineColor", "string", "#000000"], 34908 ["pointColor", "string", "#000000"], 34909 ["areaColor", "string", "#000000"], 34910 ["tooltipHtml", "string", "<p>${x}(${y})</p>"], 34911 ["showLegends", "boolean", false], 34912 ["legendPosition", "string", "right"] 34913 ], "scriptable"); 34914 34915 this.addSchema("guideAdModule", [["_value", "string", null]], "scriptable"); 34916 this.addSchema("guideAdModuleGroup", [["_value", "string", null]], "scriptable"); 34917 }, 34918 34919 addSchema : function (elementName, attrArray, superElement) { 34920 var el = {}; 34921 if (typeof superElement === "object") { 34922 _.extend(el, superElement); 34923 } else if (typeof superElement === "string" && guideSchema[superElement]) { 34924 _.extend(el, guideSchema[superElement]); 34925 } 34926 this.addAttributes(el, attrArray); 34927 guideSchema[elementName] = el; 34928 }, 34929 34930 addAttributes : function (element, attrArray) { 34931 _.each(attrArray, function (elem) { 34932 element[elem[0]] = { 34933 "type" : elem[1], 34934 "default" : elem[2], 34935 "xfaProp" : elem[3], 34936 "priority" : elem[4] 34937 }; 34938 }); 34939 }, 34940 34941 getAttributeProps : function (element, attribute) { 34942 try { 34943 return guideSchema[element][attribute] || {}; 34944 } catch (e) { 34945 this.logger().error("AF", "schema has no element " + element); 34946 } 34947 }, 34948 getAttributes : function (element) { 34949 return guideSchema[element]; 34950 }, 34951 34952 getTypedValue : function (type, value) { 34953 if (value === null || value === undefined) { 34954 return value; 34955 } 34956 if (type instanceof Array) { 34957 return value; 34958 } 34959 switch (type) { 34960 case "string": 34961 return value + ""; 34962 case "integer": 34963 return parseInt(value); 34964 case "boolean": 34965 return value === true || value === "true" ? true : false;
34966 case "float": 34967 return parseFloat(value); 34968 default : 34969 return value; 34970 } 34971 }, 34972 34973 getConvertor : function (attr) { 34974 return convertor[attr]; 34975 } 34976 }); 34977 34978}(_, guidelib)); 34979 34980(function (_, guidelib) { 34981 34982 34983 34984 var GuideContainerNode = guidelib.model.GuideContainerNode = guidelib.model.GuideItemsContainer.extend({ 34985 msClassName : "guideContainerNode", 34986 34987 setGuideState : function (guideState) { 34988 var isStateValid = _.some(guidelib.model.GuideSchema.prototype.GuideStateConstants, function (val) { 34989 return val === guideState; 34990 }); 34991 if (isStateValid === true) { 34992 this._guideState = guideState; 34993 } 34994 }, 34995 34996 getGuideState : function () { 34997 return this._guideState; 34998 }, 34999 35000 initialize : function () { 35001 var configString = ""; 35002 35003 guidelib.__runtime__.guide = this; 35004 35005 35006 35007 this._guideState = guidelib.model.GuideSchema.prototype.GuideStateConstants.GUIDE_STATE_MODEL_CREATION; 35008 35009 35010 this.internal = this.internal || {}; 35011 35012 35013 this.internal.liveDataUtils = this.options.liveDataUtils || new guidelib.model.LiveXmlUtils(); 35014 this.internal.liveModel = this.options.liveModel || new guidelib.model.LiveModel(); 35015 this.internal.GuideDirtyMarkerAndVisitor = new guidelib.model.GuideDirtyMarkerAndVisitor(); 35016 35017 35018 this.runtime = { 35019 guideContext : {}, 35020 _private : {}, 35021 errorManager : {} 35022 }; 35023 35024 35025 this.runtime.errorManager = new guidelib.util.GuideErrorManager(); 35026 35027 this._modelTemplateCacheStore = 35028 new guidelib.model.util.ModelTemplateCacheStore({modelTemplateJson : this.jsonModel}); 35029 this._guideSchema = new guidelib.model.GuideSchema(); 35030 this.guideLazyUtil = new guidelib.util.GuideLazyUtil({"_guideContainer" : this}); 35031 this._pendingQueues = { 35032 calcExp : [], 35033 valueCommitScript : [], 35034 enabledExp : [], 35035 visibleExp : [], 35036 validateAllExp : [], 35037 optionsExp : [], 35038 navigationChangeExp : [], 35039 summaryExp : [], 35040 autoSaveStartExp : [], 35041 aggregateExp : [], 35042 submitSuccess : [], 35043 submitError : [], 35044 saveSuccess : [], 35045 saveError : [] 35046 }; 35047 this._resetExpressionCounters(); 35048 this._currentContext = null; 35049 GuideContainerNode._super.initialize.call(this); 35050 this.autoSaveStart = false;
35051 35052 35053 this._modelTemplateCacheStore.putModel(this); 35054 this._postInitialize(); 35055 var xfaHost = this.getOrElse(xfalib, "runtime.xfa.host", null); 35056 if (xfaHost !== null) { 35057 xfaHost.on(xfalib.script.XfaModelEvent.FORM_MODEL_REFRESH, 35058 function (evnt) { 35059 switch (evnt.name) { 35060 case xfalib.script.XfaModelEvent.FORM_MODEL_REFRESH: 35061 this._triggerEvent(guidelib.event.GuideModelEvent.MODEL_REFRESH, "jsonModel", null, null); 35062 break; 35063 default: 35064 35065 } 35066 }, 35067 this); 35068 } 35069 }, 35070 35071 _resetExpressionCounters : function () { 35072 this._runningExpressionCount = { 35073 calcExp : {}, 35074 valueCommitScript : {}, 35075 enabledExp : {}, 35076 visibleExp : {}, 35077 validateAllExp : {}, 35078 optionsExp : {}, 35079 navigationChangeExp : {}, 35080 summaryExp : {}, 35081 autoSaveStartExp : {}, 35082 aggregateExp : {}, 35083 submitSuccess : {}, 35084 submitError : {}, 35085 saveSuccess : {}, 35086 saveError : {} 35087 }; 35088 }, 35089 35090 _getReducedJSON : function () { 35091 35092 35093 var reducedJSONChildren = guidelib.model.GuideNode.prototype._getReducedJSON.call(this), 35094 addtionalWhitelistedProperties = ["xdpRef", "xsdRef", "id", "dorTemplateRef", "dorType", "excludeFromDoRIfHidden", "schemaRef", "schemaType"]; 35095 guidelib.model.util.CommonUtils.returnMinimalJSON(addtionalWhitelistedProperties, reducedJSONChildren, this); 35096 reducedJSONChildren["rootPanel"] = this["rootPanel"]._getReducedJSON(); 35097 if (this.jsonModel.toolbar) { 35098 reducedJSONChildren["toolbar"] = this["toolbar"]._getReducedJSON(); 35099 } 35100 return reducedJSONChildren; 35101 }, 35102 35103 _initChildren : function () { 35104 35105 var options = {"_guideContainer" : this}; 35106 this.rootPanel = guidelib.model.GuideModelRegistry.prototype.createModel(this.jsonModel.rootPanel, options); 35107 this._initializeChild(this.rootPanel); 35108 this._children.push(this.rootPanel); 35109 35110 var instanceManager = guidelib.model.GuideModelRegistry.prototype.createInstanceManager(this.rootPanel); 35111 this._initializeChild(instanceManager); 35112 this._children.splice(this._children.indexOf(this.rootPanel), 0, instanceManager); 35113 instanceManager._manageChild(this.rootPanel); 35114 35115 if (this.jsonModel.toolbar) { 35116 var options = {}; 35117 if (this._guide()) { 35118 options = _.extend({}, options, {"_guideContainer" : this._guide()}); 35119 } 35120 this.toolbar = guidelib.model.GuideModelRegistry.prototype.createModel(this.jsonModel.toolbar, options); 35121 this._initializeChild(this.toolbar); 35122 this._children.push(this.toolbar); 35123 } 35124 }, 35125 35126 35127 _addToExcludeFromDorMap : function (fieldTemplateId, bExcludeFromDor) { 35128 this._excludeFromDorMap = this._excludeFromDorMap || {}; 35129 this._excludeFromDorMap[fieldTemplateId] = bExcludeFromDor; 35130 }, 35131 35132 35133 _getExcludeFromDorMap : function () { 35134 var that = this; 35135 if (!_.isUndefined(that._excludeFromDorMap)) { 35136 return _.keys(that._excludeFromDorMap).map(function (key) { 35137 35138 return key + "=" + that._excludeFromDorMap[key]; 35139 }); 35140 } 35141 }, 35142 35143 35144 _addToStateOverrideMap : function (fieldName, fieldsOverrid
35144denMap) { 35145 this._stateOverrideMap = this._stateOverrideMap || {}; 35146 this._stateOverrideMap[fieldName] = fieldsOverriddenMap; 35147 }, 35148 35149 35150 _getStateOverrideMap : function () { 35151 var that = this; 35152 var retval = {}; 35153 if (!_.isUndefined(that._stateOverrideMap)) { 35154 var elementsArray = _.keys(that._stateOverrideMap).map(function (key) { 35155 return that._stateOverrideMap[key]; 35156 }); 35157 retval = {"element" : elementsArray}; 35158 } 35159 return retval; 35160 35161 }, 35162 35163 35164 _resolveAfDataSom : function (afDataSom) { 35165 var resolvedField = null; 35166 35167 35168 _.each(this.internal.liveModel.getCrossFragmentFields(), function (fields) { 35169 35170 var globalFieldModels = this.internal.liveModel.getAllAbstractFieldModels(_.keys(fields)); 35171 _.each(globalFieldModels, function (globalField) { 35172 if (globalField.afDataSom === afDataSom) { 35173 resolvedField = globalField; 35174 return false; 35175 } 35176 }); 35177 if (resolvedField) { 35178 return false; 35179 } 35180 }); 35181 return resolvedField; 35182 }, 35183 35184 35185 _getSigners : function () { 35186 var signers = {}; 35187 35188 if (this.enableAdobeSign && (_.isString(this.xdpRef) || _.isString(this.xsdRef) || (!_.isString(this.jsonModel.schemaRef)))) { 35189 var signer, 35190 that = this, 35191 email, 35192 number, 35193 countryCode, 35194 evalExp = function (fldSom, fldAfDataSom, type) { 35195 var val = null, 35196 resolvedField; 35197 try { 35198 resolvedField = guideBridge._guide.resolveNode(fldSom); 35199 if (!resolvedField) { 35200 resolvedField = guideBridge._guide._resolveAfDataSom(fldAfDataSom); 35201 } 35202 val = resolvedField.value; 35203 if (resolvedField.className === 'guideTelephone') { 35204 if (type === 'countryCode') { 35205 val = guidelib.model.GuideTelephone.prototype._extractCountryCode(val); 35206 } else if (type === 'phone') { 35207 val = guidelib.model.GuideTelephone.prototype._extractPhoneNumber(val); 35208 } 35209 } 35210 } catch (e) { 35211 35212 } 35213 35214 35215 return val ? val.toString() : val; 35216 }; 35217 if (this.signerInfo) { 35218 _.each(_.keys(this.signerInfo), function (name) { 35219 signer = that.signerInfo[name]; 35220 if (signer && typeof signer === "object") { 35221 email = null; 35222 number = null; 35223 countryCode = null; 35224 if (signer.emailSource === 'form' && signer.email) { 35225 email = evalExp(signer.email, signer.emailAfDataSom, 'email'); 35226 } 35227 signers[name] = {}; 35228 signers[name].email = email ? email : ""; 35229 if (signer.securityOption === 'PHONE') { 35230 if (signer.phoneSource === 'form' && signer.phone) { 35231 number = evalExp(signer.phone, signer.phoneAfDataSom, 'phone'); 35232 } 35233 if (signer.countryCodeSource === 'form' && signer.countryCode) { 35234 countryCode = evalExp(signer.countryCode, signer.countryCodeAfDataSom, 'countryCode'); 35235 } 35236 signers[name].phone = {}; 35237 signers[name].phone.countryCode = countryCode ? countryCode : ""; 35238 signers[name].phone.number = number ? number : ""; 35239 } 35240 } 35241 }); 35242 } 35243 } 35244 35245 return signers; 35246 }, 35247 35248 35249 defaultSubmitSuccess : "window.guideBridge._defaultSubmitSuccessHandler($event.data)", 35250 35251 35252 defaultSubmitError : "window.guideBridge._handleServerValidationError($event.data)", 35253 35254 35255 defaultSaveSuccess : "window.guideBridge._defaultSaveSuccessHandler($event.data)", 35256 defaultSaveError : "window.guideBridge._defaultSaveErrorHandler($event.data)", 35257 35258 35259 _collectExpressions : function () { 35260 if (this.autoSaveStartExpression) { 35261 this._compiledExpressions["autoSaveStartExp"] = this._compileExpression(this.autoSaveStartExpression, "autoSaveStart"); 35262 } 35263 35264 35265 if (!this.submitSuccess) { 35266 this.jsonModel.submitSuccess = this.defaultSubmitSuccess; 35267 } 35268 this._compiledScripts.submitSuccess = this._compileExpression(this.submitSuccess, null); 35269 35270 if (!this.submitError) { 35271 this.jsonModel.submitError = this.defaultSubmitError; 35272 } 35273 this._compiledScripts.submitError = this._compileExpression(this.submitError, null); 35274 35275 if (!this.saveSuccess) { 35276 this.jsonModel.saveSuccess = this.defaultSaveSuccess; 35277 } 35278 this._compiledScripts.saveSuccess = this._compileExpression(this.saveSuccess, null); 35279 35280 if (!this.saveError) { 35281 this.jsonModel.saveError = this.defaultSaveError; 35282 } 35283 this._compiledScripts.saveError = this._compileExpression(this.saveError, null); 35284 }, 35285 35286 prepare : function () { 35287 35288 35289 if ((this.getGuideState() !== guidelib.model.GuideSchema.prototype.GuideStateConstants.GUIDE_STATE_MERGE_PROGRESS) && (this.getGuideState() !== guidelib.model.GuideSchema.prototype.GuideStateConstants.GUIDE_STATE_MODEL_CREATION)) { 35290 _.each(this._children, function (childNode) { 35291 childNode.prepare(); 35292 }, this); 35293 this.queueExpressions(this, ["autoSaveStartExp"]); 35294 this.runPendingExpressions(); 35295 } 35296 }, 35297 35298 runPendingExpressions : function () { 35299 35300 this._runExpressionQueue("calcExp"); 35301 this._runExpressionQueue("enabledExp"); 35302 this._runExpressionQueue("visibleExp"); 35303 this._runExpressionQueue("valueCommitScript"); 35304 this._runExpressionQueue("validateAllExp"); 35305 this._runExpressionQueue("optionsExp"); 35306 this._runExpressionQueue("navigationChangeExp"); 35307 this._runExpressionQueue("summaryExp"); 35308 this._runExpressionQueue("aggregateExp"); 35309 this._runExpressionQueue("submitSuccess"); 35310 this._runExpressionQueue("submitError"); 35311 this._runExpressionQueue("saveSuccess"); 35312 this._runExpressionQueue("saveError"); 35313 35314 if (window.guideBridge.hostName !== "server") { 35315 this._runExpressionQueue("autoSaveStartExp"); 35316 } 35317 this._resetExpressionCounters(); 35318 }, 35319 35320 _runExpressionQueue : function (expName) { 35321 var expQueue = this._pendingQueues[expName], node; 35322 if (expQueue) { 35323 while (expQueue.length > 0) { 35324 node = this._pendingQueues[expName].shift(); 35325 if (node) { 35326 node.executeExpression(expName); 35327 } 35328 } 35329 } 35330 }, 35331 35332 queueExpressions : function (node, expressionArray) { 35333 if (!node || !expressionArray) { 35334 return; 35335 } 35336 if (_.isString(expressionArray)) { 35337 expressionArray = [expressionArray]; 35338 } 35339 _.each(expressionArray, function (expression) { 35340 var expQueue = this._pendingQueues[expression], 35341 som = node.somExpression, 35342 counters = this._runningExpressionCount[expression]; 35343 counters[som] = counters[som] || 0; 35344 if (expQueue && expQueue.indexOf(node) < 0 && counters[som] < 10) { 35345 expQueue.push(node); 35346 counters[som] += 1; 35347 } 35348 }, this); 35349 }, 35350 35351 playJson : function (pJsonModel, attachments) { 35352 this.rootPanel.playJson(pJsonModel.rootPanel, attachments); 35353 if (this.toolbar) { 35354 this.toolbar.playJson(pJsonModel.toolbar, attachments); 35355 } 35356 }, 35357 35358 _guide : function () { 35359 return this; 35360 }, 35361 35362 _collectValues : function (keyValue) { 35363 _.each(this._children, function (childNode) { 35364 childNode._collectValues(keyValue); 35365 }, this); 35366 }, 35367 35368 35369 _isFirstSignerFormFiller : function () { 35370 return this.signerInfo.firstSignerFormFiller === "true"; 35371 }, 35372 35373 35374 resolveNode : function (somExpression) { 35375 if (!somExpression || somExpression === "") { 35376 return; 35377 } 35378 var hierarchy = somExpression.split("."), 35379 componentInModel = null; 35380 if (hierarchy[0] === "guide[0]") { 35381 hierarchy.shift(); 35382 componentInModel = this; 35383 } 35384 if (hierarchy[0] === this._escapeQualifiedName()) { 35385 componentInModel = this; 35386 hierarchy.shift(); 35387 } else if (this.hasOwnProperty(hierarchy[0])) { 35388 componentInModel = this[hierarchy[0]]; 35389 hierarchy.shift(); 35390 } else if (!componentInModel) { 35391 componentInModel = this.rootPanel; 35392 } 35393 _.each(hierarchy, function (element) { 35394 if (componentInModel && componentInModel._findChildren) { 35395 componentInModel = componentInModel._findChildren(element, false)[0]; 35396 } else { 35397 componentInModel = null; 35398 } 35399 }, this); 35400 if (componentInModel == null) { 35401 35402 var relativeName = somExpression; 35403 componentInModel = this.getOrElse(this._guide().runtime, relativeName, null); 35404 } 35405 return componentInModel; 35406 } 35407 }); 35408 35409 GuideContainerNode.defineProps({ 35410 35411 submitSuccess : { 35412 get : function () { 35413 return this.jsonModel.submitSuccess; 35414 } 35415 }, 35416 35417 submitError : { 35418 get : function () { 35419 return this.jsonModel.submitError; 35420 } 35421 }, 35422 35423 saveSuccess : { 35424 get : function () { 35425 return this.jsonModel.saveSuccess; 35426 } 35427 }, 35428 35429 saveError : { 35430 get : function () { 35431 return this.jsonModel.saveError; 35432 } 35433 }, 35434 35435 35436 "autoSaveStart" : { 35437 get : function () { 35438 return this.jsonModel.autoSaveStart; 35439 }, 35440 35441 set : function (newValue) { 35442 this.jsonModel.autoSaveStart = newValue; 35443 if (newValue === true) { 35444 delete this._compiledExpressions.autoSaveStartExp; 35445 this._triggerOnBridge(window.guideBridge.GUIDE_AUTO_SAVE_START, this); 35446 } 35447 } 35448 }, 35449 35450 35451 "enableAutoSave" : { 35452 set : function (newValue) { 35453 this.jsonModel.enableAutoSave = newValue; 35454 }, 35455 35456 get : function () { 35457 return this.jsonModel.enableAutoSave || false; 35458 } 35459 }, 35460 35461 35462 "autoSaveStartExpression" : { 35463 get : function () { 35464 return this.jsonModel.autoSaveStartExpression; 35465 } 35466 }, 35467 35468 35469 "autoSaveInfo" : { 35470 get : function () { 35471 return this.jsonModel.autoSaveInfo; 35472 } 35473 }, 35474 35475 35476 "globalMetaInfo" : { 35477 get : function () { 35478 return this.jsonModel.globalMetaInfo; 35479 } 35480 }, 35481 35482 35483 "submissionMetaInfo" : { 35484 get : function () { 35485 return this.jsonModel.submissionMetaInfo; 35486 } 35487 }, 35488 35489 35490 "signerInfo" : { 35491 get : function () { 35492 return this.jsonModel.signerInfo; 35493 } 35494 }, 35495 35496 "xdpRef" : { 35497 get : function () { 35498 return this.jsonModel.xdpRef; 35499 } 35500 }, 35501 35502 "dorTemplateRef" : { 35503 get : function () { 35504 return this.jsonModel.dorTemplateRef; 35505 } 35506 }, 35507 35508 "dorType" : { 35509 get : function () { 35510 return this.jsonModel.dorType; 35511 } 35512 }, 35513 35514 "actionType" : { 35515 get : function () { 35516 return this.jsonModel.actionType; 35517 } 35518 }, 35519 35520 "xsdRef" : { 35521 get : function () { 35522 return this.jsonModel.xsdRef; 35523 } 35524 }, 35525 35526 35527 panel : { 35528 get : function () { 35529 return this.rootPanel; 35530 } 35531 }, 35532 35533 35534 print : { 35535 get : function () { 35536 if (this.dorType === "generate" && this.jsonModel.view) { 35537 return this.jsonModel.view.print; 35538 } 35539 35540 return null; 35541 } 35542 }, 35543 35544 35545 "allLazyChildren" : { 35546 get : function () { 35547 return this.jsonModel.allLazyChildren; 35548 } 35549 }, 35550 35551 35552 "enableAsyncSubmission" : { 35553 set : function (newValue) { 35554 this.jsonModel.enableAsyncSubmission = newValue; 35555 }, 35556 35557 get : function () { 35558 if (this.jsonModel.enableAsyncSubmission && (this.jsonModel.enableAsyncSubmission === "true" || this.jsonModel.enableAsyncSubmission === true)) { 35559 return true; 35560 } else { 35561 return false;
35562 } 35563 } 35564 }, 35565 35566 35567 "enableAdobeSign" : { 35568 get : function () { 35569 return this.jsonModel._useSignedPdf; 35570 } 35571 }, 35572 35573 35574 "enableFocusOnFirstField" : { 35575 set : function (newValue) { 35576 this.jsonModel.enableFocusOnFirstField = newValue; 35577 }, 35578 35579 get : function () { 35580 if (this.jsonModel.enableFocusOnFirstField === undefined) { 35581 return true; 35582 } 35583 return this.jsonModel.enableFocusOnFirstField; 35584 } 35585 } 35586 }); 35587}(_, guidelib)); 35588(function (_, guidelib) { 35589 guidelib.model.mixin.AddNavigationContext = { 35590 propertyDescriptors : { 35591 "navigationContext" : { 35592 get : function () { 35593 if (!this._navigationContext) { 35594 this._navigationContext = new guidelib.model.util.GuideNavigationContext({ 35595 currentItem : null, 35596 parentPanel : this.panel 35597 }); 35598 } 35599 return this._navigationContext; 35600 } 35601 } 35602 } 35603 }; 35604})(_, guidelib); 35605 35606(function (_, guidelib) { 35607 35608 35609 var GuidePanel = guidelib.model.GuidePanel = guidelib.model.GuideItemsContainer.extend({ 35610 msClassName : "guidePanel", 35611 defaultExpressions : { 35612 "summary" : "this.title + (this.instanceIndex > 0 ? ' ' + this.instanceIndex : '')" 35613 }, 35614 35615 initialize : function () { 35616 GuidePanel._super.initialize.call(this); 35617 this._currentItem = null; 35618 35619 this._navigationContext = null; 35620 }, 35621 35622 _collectExpressions : function () { 35623 GuidePanel._super._collectExpressions.call(this); 35624 if (this.completionExp) { 35625 this._compiledScripts.completionExp = this._compileExpression(this.completionExp, null); 35626 } 35627 if (this.jsonModel.summaryExp) { 35628 this._compiledExpressions.summaryExp = this._compileExpression(this.jsonModel.summaryExp, "summary"); 35629 } else { 35630 this._compiledExpressions.summaryExp = this._compileExpression(this.defaultExpressions["summary"], "summary"); 35631 } 35632 }, 35633 35634 _initializeInstanceManager : function (child, index, insertOffset) { 35635 var instanceManager = guidelib.model.GuideModelRegistry.prototype.createInstanceManager(child); 35636 this._initializeChild(instanceManager); 35637 35638 this._children.splice(index + insertOffset++, 0, instanceManager); 35639 instanceManager._manageChild(child); 35640 35641 var bindNode = child._getBindNode(), 35642 bindNodeInstCount = this.getOrElse(bindNode, "instanceManager.count", 0), 35643 35644 panelInstancesToAdd = Math.max(child.minOccur, bindNodeInstCount) - 1, 35645 bindNodeOffset = 1, 35646 addedXfaInstance; 35647 while (panelInstancesToAdd > 0) { 35648 35649 addedXfaInstance = null; 35650 if (bindNodeInstCount > 1) { 35651 35652 addedXfaInstance = bindNode.instanceManager.instances[bindNodeOffset++]; 35653 } 35654 instanceManager.addInstance(addedXfaInstance); 35655 panelInstancesToAdd -= 1; 35656 insertOffset += 1; 35657 } 35658 return insertOffset; 35659 }, 35660 35661 35662 _initChildren : function (bLazyInitialization) { 35663 GuidePanel._super._initChildren.call(this); 35664 if (!bLazyInitialization) { 35665 this._instanceManager = null; 35666 } 35667 this._childInitializeGoingOn = true; 35668 var currentChildren = this.children, 35669 insertOffset = 0; 35670 _.each(currentChildren, function (child, index) { 35671 if (child instanceof guidelib.model.GuidePanel) { 35672 insertOffset = this._initializeInstanceManager(child, index, insertOffset); 35673 } 35674 }, this); 35675 if (this.jsonModel.toolbar) { 35676 var options = {}; 35677 if (this.options._guideContainer) { 35678 options = _.extend({}, options, {"_guideContainer" : this.options._guideContainer}); 35679 } 35680 var toolbar = guidelib.model.GuideModelRegistry.prototype.createModel(this.jsonModel.toolbar, options); 35681 this._initializeChild(toolbar); 35682 this._children.push(toolbar); 35683 } 35684 this._summary = null; 35685 this._childInitializeGoingOn = false;
35686 }, 35687 35688 _postInitialize : function () { 35689 GuidePanel._super._postInitialize.call(this); 35690 35691 this.instanceManager._postInitializeBinding(); 35692 }, 35693 35694 _addChildAt : function (child, childIndex, muteEvent) { 35695 if (child) { 35696 this._initializeChild(child); 35697 this._guide()._modelTemplateCacheStore.putModel(child); 35698 var newItemIndex = this._getItemsInsertIndex(childIndex - 1); 35699 var newItems = {}; 35700 var newItemKey = child.id; 35701 var lastItemIndex = -1; 35702 _.each(this.jsonModel.items, function (value, key) { 35703 if (lastItemIndex == newItemIndex - 1) { 35704 newItems[newItemKey] = child.jsonModel; 35705 } 35706 newItems[key] = value; 35707 lastItemIndex++; 35708 }, this); 35709 if (lastItemIndex == newItemIndex - 1) { 35710 newItems[newItemKey] = child.jsonModel; 35711 } 35712 this.jsonModel.items = newItems; 35713 child._isItem = true; 35714 this._children.splice(childIndex, 0, child); 35715 this._normalizeChildren(); 35716 child._postInitialize(); 35717 if (this._guide().getGuideState() >= guidelib.model.GuideSchema.prototype.GuideStateConstants.GUIDE_STATE_MERGE_COMPLETE) { 35718 child.prepare(); 35719 } 35720 35721 35722 35723 if (!(this._lazyReference && this._childInitializeGoingOn)) { 35724 if (!muteEvent) { 35725 this._triggerEvent(guidelib.event.GuideModelEvent.CHILD_CHANGED, "childAdded", null, child); 35726 } 35727 } 35728 } 35729 }, 35730 35731 35732 validate : function (errorList) { 35733 var markInvalid = false; 35734 35735 35736 if (!this.visible) { 35737 return true; 35738 } 35739 var lazyModelUnloadPending = false; 35740 35741 if (this._lazyReference && this.guideUtil.isLazyJson(this.jsonModel)) { 35742 var guideDirtyMarker = this._guide().internal.GuideDirtyMarkerAndVisitor, 35743 visitMap = guideDirtyMarker.visitMap, 35744 modelTemplateCacheStore = this._guide()._modelTemplateCacheStore, 35745 guideUtil = guidelib.util.GuideUtil, 35746 templateJson, 35747 templateId = this.templateId, 35748 uniquePrefix; 35749 35750 if (visitMap[templateId] === 0) { 35751 if (this._ancestorRepeatable) { 35752 uniquePrefix = guideUtil.generateUID(); 35753 } 35754 35755 templateJson = modelTemplateCacheStore._getTemplate(templateId, true); 35756 35757 35758 if (!_.isEmpty(templateJson)) { 35759 this._embedJson(templateJson.items, uniquePrefix); 35760 this._guide().internal.liveDataUtils.playLiveData(this); 35761 35762 this.prepare(); 35763 this._guide().runPendingExpressions(); 35764 this._guide().internal.liveDataUtils.updateLiveData(); 35765 lazyModelUnloadPending = true; 35766 } else { 35767 35768 markInvalid = true; 35769 } 35770 35771 } 35772 35773 } 35774 var validationResult = GuidePanel._super.validate.call(this, errorList); 35775 if (lazyModelUnloadPending) { 35776 35777 35778 this._unloadLazyReferenceModel(true); 35779 } 35780 if (markInvalid === true) { 35781 validationResult = false;
35782 } 35783 return validationResult; 35784 }, 35785 35786 _loadLazyFragment : function (options) { 35787 options = options || {}; 35788 35789 35790 if (_.isUndefined(this._itemsLoaded)) { 35791 35792 var modelAlreadyLoaded = this._children && this._children.length > 0; 35793 35794 35795 var externalizedPath; 35796 35797 externalizedPath = guideBridge._getGuidePathUrl(".jsonhtmlemitter"); 35798 35799 35800 this._fetchFromAjaxCall(externalizedPath, options, modelAlreadyLoaded); 35801 } else { 35802 if (_.isFunction(options.success)) { 35803 options.success.call(this); 35804 } 35805 } 35806 35807 35808 }, 35809 35810 _fetchFromAjaxCall : function (externalizedPath, options, skipJsonEmbedding) { 35811 if (options && _.isFunction(options.preFetch)) { 35812 options.preFetch.call(this); 35813 } 35814 var that = this, 35815 urlSuffix = "", 35816 lazyOptions, 35817 commonCallbacks = { 35818 success: fetchCallback, 35819 error: (options && _.isFunction(options.error)) ? options.error : errorCallback, 35820 complete: completeCallback, 35821 async: options.async 35822 }; 35823 35824 35825 35826 urlSuffix = [ 35827 "/templateId-" + that.templateId, 35828 "/fetchJSON-" + (skipJsonEmbedding ? "false" : "true"), 35829 "/fetchHTML-true", 35830 ".json" 35831 ].join(""); 35832 35833 lazyOptions = _.extend({ 35834 path: externalizedPath + urlSuffix 35835 }, commonCallbacks); 35836 35837 window.guideBridge.panelProvider.getHtmlJson(lazyOptions); 35838 35839 function fetchCallback(jsonHtml) { 35840 var uniquePrefix; 35841 35842 35843 35844 if (that.repeatable || that._ancestorRepeatable) { 35845 uniquePrefix = that.guideUtil.generateUID(); 35846 } 35847 if (guidelib.util.GuideUtil._embedHtml(that, jsonHtml["html"], uniquePrefix)) { 35848 that._ajaxCallDone = true; 35849 35850 35851 if (!skipJsonEmbedding) { 35852 35853 35854 var referredJson = JSON.parse(jsonHtml["json"])["items"]; 35855 that._embedJson(referredJson, uniquePrefix); 35856 35857 var guideDirtyMarkerAndVisitor = that._guide().internal.GuideDirtyMarkerAndVisitor; 35858 35859 if (!that.repeatable) { 35860 guideDirtyMarkerAndVisitor._updateCountOrInsert(guideDirtyMarkerAndVisitor.visitMap, that.templateId); 35861 } 35862 35863 that._guide().internal.liveDataUtils.playLiveData(that); 35864 35865 that.prepare(); 35866 } 35867 35868 35869 that._postProcessLazyLoad(options); 35870 } 35871 } 35872 35873 function errorCallback() { 35874 var errorMessage = skipJsonEmbedding ? "Failed to fetch HTML for :" : "Failed to fetch HTML and JSON for :"; 35875 that.logger().error("AF", errorMessage + externalizedPath); 35876 } 35877 35878 function completeCallback() { 35879 if (options && _.isFunction(options.postFetch)) { 35880 options.postFetch.call(this); 35881 } 35882 } 35883 35884 }, 35885 35886 35887 _postProcessLazyLoad : function (options) { 35888 35889 this._itemsLoaded = true; 35890 this._guide().trigger(guidelib.event.GuideModelEvent.LAZY_LOADED); 35891 35892 this._triggerOnBridge("elementLazyLoaded", this); 35893 35894 35895 if (options && _.isFunction(options.success)) { 35896 options.success.call(this); 35897 } 35898 35899 35900 35901 }, 35902 35903 35904 _unloadLazyReferenceModel : function (muteValidation) { 35905 try { 35906 if (this._lazyReference) { 35907 window.guideBridge._populateBindRefToSomMap(this); 35908 if (!muteValidation) {
35909 var validationStatus = this.validate(), 35910 visitMap = this._guide().internal.GuideDirtyMarkerAndVisitor.visitMap; 35911 if (validationStatus === false && visitMap[this.id] > 0) { 35912 visitMap[this.id] = 0; 35913 } 35914 } 35915 35916 35917 _.each(this.children, function (child) { 35918 child._unloadModel(muteValidation); 35919 var nIndex = this._children.indexOf(child); 35920 35921 this._children.splice(nIndex, 1); 35922 var childKey = null; 35923 35924 _.each(this.jsonModel.items, function (value, key) { 35925 if (value === child.jsonModel) { 35926 childKey = key; 35927 } 35928 }, this); 35929 if (childKey) { 35930 delete this.jsonModel.items[childKey]; 35931 } 35932 35933 this._normalizeChildren(); 35934 }, this); 35935 35936 this._navigationContext = null; 35937 this._currentItem = null; 35938 } 35939 } catch (exception) { 35940 this.logger().error(exception); 35941 } 35942 35943 }, 35944 35945 _unloadModel : function (muteValidation) { 35946 var visitMap = this._guide().internal.GuideDirtyMarkerAndVisitor.visitMap; 35947 _.each(this.children, function (child) { 35948 if (this._lazyReference && !muteValidation) { 35949 var validationStatus = child.validate(); 35950 if (validationStatus === false) { 35951 if (!_.isUndefined(visitMap[this.templateId])) { 35952 visitMap[this.templateId] = 0; 35953 } 35954 } 35955 } 35956 child._unloadModel(muteValidation); 35957 }, this); 35958 guidelib.model.Scriptable.prototype._unloadModel.call(this); 35959 }, 35960 35961 _removeChild : function (oChild) { 35962 oChild._unloadModel(); 35963 var nIndex = this._children.indexOf(oChild); 35964 this._children.splice(nIndex, 1); 35965 var childKey = null; 35966 _.each(this.jsonModel.items, function (value, key) { 35967 if (value === oChild.jsonModel) { 35968 childKey = key; 35969 } 35970 }, this); 35971 if (childKey) { 35972 delete this.jsonModel.items[childKey]; 35973 } 35974 this._normalizeChildren(); 35975 this._triggerEvent(guidelib.event.GuideModelEvent.CHILD_CHANGED, "childRemoved", oChild, null); 35976 }, 35977 35978 35979 _embedJson : function (referredJson, uniquePrefix) { 35980 35981 var bIsSuccess = false; 35982 var clonedJson = JSON.parse(JSON.stringify(referredJson)), 35983 currentPanelId = this.id, 35984 referredPanelRoot = null, 35985 referredPanelRootName = null, 35986 bindRefPrefix = this.jsonModel.bindRef; 35987 35988 currentPanelId = currentPanelId.slice(0, -2); 35989 if (referredJson) { 35990 35991 if (this.repeatable || this._ancestorRepeatable) { 35992 this.copyObject(referredJson, clonedJson, 35993 { 35994 transformMaps : { 35995 "id" : function (srcValue, options, parentObj) { 35996 return uniquePrefix + "__" + parentObj.templateId; 35997 } 35998 } 35999 } 36000 ); 36001 } 36002 36003 36004 _.each(clonedJson, function (panelJson, panelName) { 36005 if (_.isObject(panelJson)) { 36006 bIsSuccess = true; 36007 36008 this.jsonModel.items = this.jsonModel.items || {}; 36009 this.jsonModel.items[panelName] = panelJson; 36010 36011 this._guide()._modelTemplateCacheStore._putTemplate(JSON.parse(JSON.stringify(panelJson))); 36012 } 36013 }, this); 36014 36015 this._embedModel(); 36016 36017 } 36018 if (bIsSuccess === true) { 36019 36020 } 36021 return bIsSuccess; 36022 }, 36023 36024 36025 _embedModel : function () { 36026 36027 this._initChildren(true); 36028 36029 36030 this._guide()._modelTemplateCacheStore.putModel(this); 36031 36032 this._postInitialize(); 36033 36034 this._normalizeChildren(); 36035 }, 36036 36037 _getItemsInsertIndex : function (childIndex) { 36038 var itemIndex = 0; 36039 _.find(this._children, function (child, index) { 36040 if (child._isItem) { 36041 itemIndex++; 36042 } 36043 if (index >= childIndex) { 36044 return true; 36045 } 36046 }, this); 36047 return itemIndex; 36048 }, 36049 36050 playJson : function (pJsonModel, attachments) { 36051 var playNonPanelItems = {}; 36052 var playPanelItems = {}; 36053 _.each(pJsonModel.items, function (item) { 36054 if (_.isObject(item)) { 36055 36056 if (item.guideNodeClass === "guidePanel" || item.guideNodeClass === "guideTable" || item.guideNodeClass === "guideTableRow") { 36057 if (playPanelItems[item.name]) { 36058 playPanelItems[item.name].push(item); 36059 } else { 36060 playPanelItems[item.name] = [item]; 36061 } 36062 } else { 36063 if (playNonPanelItems[item.name]) { 36064 playNonPanelItems[item.name].push(item); 36065 } else { 36066 playNonPanelItems[item.name] = [item]; 36067 } 36068 } 36069 } 36070 }, this); 36071 36072 36073 var panelIMs = _.filter(this._children, function (child) { 36074 return child instanceof guidelib.model.GuideInstanceManager; 36075 }, this); 36076 36077 _.each(panelIMs, function (instanceManager) { 36078 var panelName = instanceManager._getInstanceName(); 36079 var newPanelItems = playPanelItems[panelName] || []; 36080 var panelInstances = instanceManager._instances.slice(0); 36081 _.each(panelInstances, function (panelInstance, index) { 36082 if (newPanelItems.length > 0) { 36083 var panelJson = newPanelItems.shift(); 36084 panelInstance.playJson(panelJson, attachments); 36085 } else { 36086 instanceManager.removeInstance(index); 36087 } 36088 }, this); 36089 if (newPanelItems.length > 0) { 36090 _.each(newPanelItems, function (paneljson) { 36091 var addedInstance = instanceManager.addInstance(); 36092 if (addedInstance) { 36093 addedInstance.playJson(paneljson, attachments); 36094 } 36095 }, this); 36096 } 36097 }, this); 36098 36099 36100 _.each(this.items, function (child) { 36101 if (!(child instanceof guidelib.model.GuidePanel)) { 36102 var nonPanelItemName = child.name; 36103 var nonPanelItem = playNonPanelItems[nonPanelItemName]; 36104 if (nonPanelItem && nonPanelItem.length > 0) { 36105 child.playJson(nonPanelItem.shift(), attachments); 36106 } 36107 } 36108 }, this); 36109 36110 36111 if (this.toolbar) { 36112 this.toolbar.playJson(pJsonModel.toolbar, attachments); 36113 } 36114 }, 36115 36116 _getReducedJSON : function (isParentRepeatable) { 36117 var reducedJSONChildren, 36118 isRepeatable; 36119 isRepeatable = isParentRepeatable || this.canBeRepeatable; 36120 reducedJSONChildren = GuidePanel._super._getReducedJSON.call(this, isRepeatable); 36121 36122 36123 if (this.jsonModel.toolbar) { 36124 reducedJSONChildren["toolbar"] = this.toolbar._getReducedJSON(); 36125 } 36126 return reducedJSONChildren; 36127 }, 36128 36129 _getRole : function () { 36130 var guideRole, xfaRole, roleMap; 36131 36132 roleMap = { 36133 "Table" : "grid", 36134 "Header Row" : "rowHeader", 36135 "Body Row" : "rowGroup", 36136 "Footer Row" : "rowGroup", 36137 "List" : "list" 36138 }; 36139 if (this.bindNode) { 36140 xfaRole = this.getOrElse(this.bindNode.assist && this.bindNode.assist.role, null); 36141 if (xfaRole) { 36142 guideRole = roleMap[xfaRole]; 36143 } 36144 } 36145 return guideRole; 36146 }, 36147 _getAssistPriority : function () { 36148 return (this.getAttribute("assistPriority") || "description"); 36149 }, 36150 36151 _getScreenReaderText : function () { 36152 var screenReaderText, assistPriority = this._getAssistPriority(); 36153 if (assistPriority !== "description") { 36154 screenReaderText = GuidePanel._super._getScreenReaderText.apply(this); 36155 } 36156 return screenReaderText; 36157 }, 36158 36159 execCompletion : function () { 36160 var complete = true; 36161 _.find(this.children, function (childModel) { 36162 36163 if (childModel instanceof guidelib.model.GuidePanel && !childModel.execCompletion()) { 36164 complete = false;
36165 return true; 36166 } 36167 }, this); 36168 if (complete && this.completionExp) { 36169 complete = this.executeExpression("completionExp"); 36170 } 36171 return complete; 36172 }, 36173 36174 _preserveLazyValue : function () { 36175 return !this._isXfaNode() && !(this instanceof guidelib.model.RootPanelNode) 36176 && (this.canBeRepeatable || this._guide().internal.liveDataUtils.isIndexedPath(this.bindRef)); 36177 }, 36178 36179 36180 _syncModelAndData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar, updateInstances, recurse) { 36181 var dataUtils = this._guide().internal.liveDataUtils; 36182 if (this._preserveLazyValue()) { 36183 36184 var dataContext = dataUtils._getDataContext(this, bound_indexedXpathSoFar, unBound_indexedXpathSoFar), 36185 indexedXpath = dataContext.indexedXpath; 36186 36187 if (this.canBeRepeatable) { 36188 36189 if (_.isFunction(updateInstances) && this.instanceIndex === 0) { 36190 updateInstances(dataUtils.getDataInstances(dataContext, this._getDataNodeName()), 36191 dataUtils.getParentDataNode(dataContext)); 36192 } 36193 indexedXpath = dataUtils.addIndexToPath(indexedXpath, this.instanceIndex); 36194 } 36195 36196 36197 if (dataContext.xmlSec === dataUtils.constants.UNBOUND_TAG) { 36198 unBound_indexedXpathSoFar = indexedXpath; 36199 } else if (dataContext.xmlSec === dataUtils.constants.BOUND_TAG) { 36200 bound_indexedXpathSoFar = indexedXpath; 36201 } 36202 } 36203 36204 if (_.isString(recurse)) { 36205 36206 _.each(this.items, function (item) { 36207 if (_.isFunction(item[recurse])) { 36208 item[recurse](bound_indexedXpathSoFar, unBound_indexedXpathSoFar); 36209 } 36210 }); 36211 } 36212 36213 return { 36214 'bound' : bound_indexedXpathSoFar, 36215 'unBound' : unBound_indexedXpathSoFar 36216 }; 36217 }, 36218 36219 _getDataNodeName : function () { 36220 var bindRef = this.bindRef, 36221 dataNodeName; 36222 if (bindRef) { 36223 dataNodeName = bindRef.substring(bindRef.lastIndexOf("/") + 1); 36224 } else { 36225 36226 dataNodeName = this.getAttribute("name"); 36227 } 36228 return dataNodeName; 36229 }, 36230 36231 _updateLiveData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar) { 36232 var dataUtils = this._guide().internal.liveDataUtils, 36233 that = this; 36234 36235 function updateDataInstances(dataNodes, parentNode) { 36236 var count = that.instanceManager.instanceCount; 36237 if (dataNodes && (dataNodes.length > count)) { 36238 36239 36240 for (var i = dataNodes.length -1; i >= count; --i) { 36241 dataUtils.removeChild(parentNode, that._getDataNodeName(), i); 36242 } 36243 } 36244 } 36245 36246 var contextSoFar = this._syncModelAndData(bound_indexedXpathSoFar, unBound_indexedXpathSoFar, updateDataInstances, '_updateLiveData'); 36247 }, 36248 36249 _playLiveData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar) { 36250 var parentArgs = arguments, 36251 that = this; 36252 36253 function updateModelInstances(dataNodes, parentNode) { 36254 var _dataNodes = dataNodes; 36255 if (_dataNodes == null) { 36256 _dataNodes = []; 36257 } 36258 36259 var i; 36260 if (_dataNodes && (_dataNodes.length < that.instanceManager.instanceCount)) { 36261 36262 for (i = Math.max(_dataNodes.length, Math.abs(that.minOccur)); i < that.instanceManager.instanceCount; ++i) { 36263 that.instanceManager.removeInstance(i); 36264 } 36265 } else if (_dataNodes && (_dataNodes.length > that.instanceManager.instanceCount)) { 36266 36267 var totalInstances = that.maxOccur < 0 ? _dataNodes.length : Math.min(_dataNodes.length, that.maxOccur); 36268 for (i = that.instanceManager.instanceCount; i < totalInstances; ++i) { 36269 var addedInstance = that.instanceManager.addInstance(); 36270 if (addedInstance) { 36271 that._playLiveData.apply(addedInstance, parentArgs); 36272 } 36273 } 36274 } 36275 } 36276 36277 this._syncModelAndData(bound_indexedXpathSoFar, unBound_indexedXpathSoFar, updateModelInstances, '_playLiveData'); 36278 } 36279 }); 36280 36281 GuidePanel.defineProps({ 36282 36283 completionExp : { 36284 get : function () { 36285 return this.getAttribute("completionExp"); 36286 } 36287 }, 36288 36289 completionExpReq : { 36290 get : function () { 36291 return this.getAttribute("completionExpReq"); 36292 } 36293 }, 36294 36295 36296 minOccur : { 36297 get : function () { 36298 return this.getOrElse(this.jsonModel.minOccur, 1); 36299 } 36300 }, 36301 36302 36303 maxOccur : { 36304 get : function () { 36305 return this.getOrElse(this.jsonModel.maxOccur, 1); 36306 } 36307 }, 36308 initialOccur : { 36309 get : function () { 36310 return this.getOrElse(this.jsonModel.initialOccur, 1); 36311 } 36312 }, 36313 36314 repeatable : { 36315 get : function () { 36316 return (this.minOccur != 1 || this.maxOccur != 1); 36317 } 36318 }, 36319 36320 36321 canBeRepeatable : { 36322 get : function () { 36323 return (this.maxOccur < 0 || this.maxOccur > 1); 36324 } 36325 }, 36326 36327 panel : { 36328 get : function () { 36329 return this; 36330 } 36331 }, 36332 toolbar : { 36333 get : function () { 36334 this.getElement("guideToolbar"); 36335 } 36336 }, 36337 36338 instanceManager : { 36339 get : function () { 36340 return this._instanceManager; 36341 } 36342 }, 36343 36344 36345 instanceIndex : { 36346 get : function () { 36347 var context = this._guide()._currentContext; 36348 if (context && context.managedExp) { 36349 this._addDependant(context.contextNode, context.expression); 36350 } 36351 return this.instanceManager._instances.indexOf(this); 36352 } 36353 }, 36354 36355 title : { 36356 get : function () { 36357 return this.jsonModel["jcr:title"]; 36358 }, 36359 set : function (value) { 36360 var oldTitle = this.title; 36361 if (oldTitle !== value) { 36362 this.jsonModel["jcr:title"] = value; 36363 this.trigger(guidelib.event.GuideModelEvent.MODEL_CHANGED, 36364 guidelib.event.GuideModelEvent.createEvent( 36365 guidelib.event.GuideModelEvent.MODEL_CHANGED, 36366 this, 36367 "title", 36368 oldTitle, 36369 value 36370 ) 36371 ); 36372 } 36373 } 36374 }, 36375 36376 summary : { 36377 get : function () { 36378 return this._summary; 36379 }, 36380 set : function (value) { 36381 var oldSummary = this._summary; 36382 if (oldSummary !== value) { 36383 this._summary = value; 36384 this.trigger(guidelib.event.GuideModelEvent.MODEL_CHANGED, 36385 guidelib.event.GuideModelEvent.createEvent( 36386 guidelib.event.GuideModelEvent.MODEL_CHANGED, 36387 this, 36388 "summary", 36389 oldSummary, 36390 this._summary 36391 ) 36392 ); 36393 } 36394 } 36395 }, 36396 enableLayoutOptimization : { 36397 get : function () { 36398 return this.getOrElse(this.jsonModel, "layout.enableLayoutOptimization", false); 36399 } 36400 }, 36401 36402 36403 isNavigable : { 36404 get : function () { 36405 var isNonNavigable = this.getOrElse(this.jsonModel, "layout.nonNavigable", false); 36406 36407 36408 if (typeof isNonNavigable === 'string') { 36409 return !(isNonNavigable === "true"); 36410 } else { 36411 return !isNonNavigable; 36412 } 36413 } 36414 }, 36415 36416 _hopsToRootPanel : { 36417 get : function () { 36418 return guidelib.util.GuideUtil._countHopsToRootPanel(this); 36419 } 36420 36421 }, 36422 36423 _ancestorRepeatable : { 36424 get : function () { 36425 var parentOrAncestor = this.parent; 36426 while (parentOrAncestor) { 36427 if (parentOrAncestor && parentOrAncestor.repeatable) { 36428 return true; 36429 } 36430 parentOrAncestor = parentOrAncestor.parent; 36431 } 36432 36433 return false;
36434 } 36435 }, 36436 36437 36438 enabled : { 36439 get : function () { 36440 return guidelib.model.Scriptable.prototype._getEnabled.call(this); 36441 }, 36442 36443 set : function (value) { 36444 var oldValue = this.enabled; 36445 guidelib.model.Scriptable.prototype._setEnabled.call(this, value); 36446 if (this._parentAccess && value != oldValue) { 36447 this._changeContainerAccess(value); 36448 } 36449 } 36450 }, 36451 36452 36453 _hasLazyDescendant : { 36454 get : function () { 36455 if (!_.isEmpty(guideBridge._guide.allLazyChildren)) { 36456 return true; 36457 } 36458 return false; 36459 } 36460 } 36461 }); 36462 36463 36464 GuidePanel.addMixins([ 36465 guidelib.model.mixin.AddNavigationContext, 36466 guidelib.model.mixin.AddDependencyMgmt 36467 ]); 36468 36469})(_, guidelib); 36470 36471(function (_, guidelib) { 36472 var GuideTableRow = guidelib.model.GuideTableRow = guidelib.model.GuidePanel.extend({ 36473 msClassName : "guideTableRow" 36474 }); 36475}(_, guidelib)); 36476(function (_, guidelib) { 36477 36478 36479 var GuideTable = guidelib.model.GuideTable = guidelib.model.GuidePanel.extend({ 36480 msClassName : "guideTable" 36481 }); 36482 36483 GuideTable.defineProps({ 36484 36485 mobileLayout : { 36486 get : function () { 36487 return this.jsonModel.layout.mobileLayout; 36488 } 36489 }, 36490 36491 columnWidth : { 36492 get : function () { 36493 return this.jsonModel.columnWidth; 36494 } 36495 } 36496 }); 36497})(_, guidelib); 36498 36499(function (_, guidelib) { 36500 var RootPanelNode = guidelib.model.RootPanelNode = guidelib.model.GuidePanel.extend({ 36501 msClassName : "rootPanelNode", 36502 36503 _clearInactiveLazyViews : function (panelView) { 36504 _.each(this.childViews, function (item) { 36505 item._clearInactiveLazyViews(panelView); 36506 }); 36507 } 36508 36509 }); 36510 RootPanelNode.defineProps({ 36511 toolbar : { 36512 get : function () { 36513 36514 return this.getElement("guideToolbar") || this.parent.toolbar; 36515 } 36516 } 36517 }); 36518})(_, guidelib); 36519(function ($, guidelib, _) { 36520 function negate(predicateFunc) { 36521 return function () { 36522 return !predicateFunc.apply(this, arguments); 36523 }; 36524 } 36525 36526 function getPredicate(condition) { 36527 return condition instanceof Array 36528 ? Array.prototype.includes.bind(condition) 36529 : condition; 36530 } 36531 36532 var CommonUtils = { 36533 36534 36535 returnMinimalJSON : function (whitelistedProperties, reducedJsonObject, that) { 36536 if (!_.isObject(reducedJsonObject)) { 36537 reducedJsonObject = {}; 36538 } 36539 _.each(whitelistedProperties, function (whitelistedProperty) { 36540 if (!_.isUndefined(that.jsonModel[whitelistedProperty])) { 36541 reducedJsonObject[whitelistedProperty] = that.jsonModel[whitelistedProperty] ; 36542 36543 } else if (!_.isUndefined(that[whitelistedProperty])) { 36544 reducedJsonObject[whitelistedProperty] = that[whitelistedProperty]; 36545 } 36546 }); 36547 }, 36548 36549 createMap : function (list, value) { 36550 return _.mapObject(_.object(list, []), function () { 36551 return value; 36552 }); 36553 }, 36554 36555 updatedMapIfNot : function (map, condition, value) { 36556 return this._updateMap(map, negate(getPredicate(condition)), value); 36557 }, 36558 36559 updateMap : function (map, condition, value) { 36560 return this._updateMap(map, getPredicate(condition), value); 36561 }, 36562 36563 _updateMap : function (map, condition, value) { 36564 var newMap = {}, 36565 prop; 36566 for (prop in map) { 36567 if (map.hasOwnProperty(prop)) { 36568 newMap[prop] = condition(prop) ? value : map[prop]; 36569 } 36570 } 36571 return newMap; 36572 }, 36573 36574 _getScope : function (context) { 36575 var mergedScope = Object.assign(guidelib.runtime, context._guide().runtime); 36576 return mergedScope; 36577 } 36578 }; 36579 36580 guidelib.model.util.CommonUtils = CommonUtils; 36581}($, guidelib, _)); 36582(function (_, $, guidelib) { 36583 var getOrElse = xfalib.ut.XfaUtil.prototype.getOrElse, 36584 commonUtils = guidelib.model.util.CommonUtils, 36585 logger, 36586 constants = guidelib.model.GuideSchema.prototype.GuideStateConstants; 36587 36588 var initializeLogger = function (isXfaForm) {
36589 var configString = window.AF_log_config === undefined ? "0-a9" 36590 : "1-" + window.AF_log_config; 36591 36592 xfalib.ut.XfaUtil.prototype.registerLocaleProperties(guidelib.i18n); 36593 if (isXfaForm && window.formBridge) { 36594 window.formBridge.registerConfig("contextPath", window.guideBridge.userConfig["contextPath"]); 36595 window.formBridge.registerConfig("LoggerConfig", { 36596 "logConfigString" : configString, 36597 "categoryAcronyms" : {"d" : "AF"} 36598 }); 36599 } else { 36600 xfalib.ut.XfaUtil.prototype.logger = new xfalib.ut.Logger({ 36601 "jsonModel" : { 36602 "logConfigString" : configString, 36603 "categoryAcronyms" : {"d" : "AF"} 36604 } 36605 }); 36606 logger = xfalib.ut.XfaUtil.prototype.logger; 36607 } 36608 }; 36609 36610 var utils = { 36611 triggerEventOnWindow : function (eventPayload) { 36612 $(window).trigger(eventPayload); 36613 }, 36614 36615 postExternalMessage : function (name) { 36616 window.guideBridge._postExternalMessage({name : name}); 36617 } 36618 }; 36619 36620 var viewOnlyUtils = { 36621 createView : function (guide, $element) { 36622 utils.postExternalMessage("_layoutstart"); 36623 36624 var guideContainerView = new guidelib.view.GuideContainerView({ 36625 element : $element, 36626 model : guide 36627 }); 36628 36629 36630 window.guideBridge._setGuideView(guideContainerView); 36631 guidelib.util.GuideUtil.initializeHelp(); 36632 36633 36634 guidelib.util.AdUtil.applyDescriptionPlugin(); 36635 36636 utils.postExternalMessage("_layoutend"); 36637 36638 $(window).on("mousedown.guidebridge", function () { 36639 window.guideBridge.clickedOnWindow = true; 36640 }); 36641 }, 36642 36643 getLastFocusItem : function (guide) { 36644 var lastFocusItem; 36645 if (guide.runtime.guideContext) { 36646 lastFocusItem = guidelib.util.GuideUtil.fetchXMLNodeValue(guide.runtime.guideContext.guidePrefillXml, "lastFocusItem"); 36647 } 36648 36649 if (_.isUndefined(lastFocusItem)) { 36650 lastFocusItem = guidelib.util.GuideUtil._fetchJSONNodeValue(guide.runtime.guideContext.guidePrefillJson, "afSubmissionInfo.lastFocusItem"); 36651 } 36652 36653 if (_.isUndefined(lastFocusItem)) { 36654 lastFocusItem = window.guideBridge.customContextProperty("lastFocusItem"); 36655 } 36656 return lastFocusItem; 36657 }, 36658 36659 setFocus : function (item) { 36660 if (item) { 36661 window.guideBridge.setFocus(item); 36662 } else { 36663 window.guideBridge.setFocus(); 36664 } 36665 }, 36666 36667 preventCheckBoxMovementOnClick : function () { 36668 36669 36670 36671 36672 if (xfalib.ut.XfaUtil.prototype.isSafari() && !xfalib.ut.TouchUtil.TOUCH_ENABLED) { 36673 $('#guideContainerForm').addClass('macSafariForm'); 36674 } 36675 }, 36676 36677 disableDefaultSubmit : function () { 36678 36679 36680 $("#guideContainerForm").submit(function (evnt) { 36681 evnt.preventDefault(); 36682 }); 36683 }, 36684 36685 preventFormSubmitOnEnter : function () { 36686 36687 36688 $("#guideContainerForm input").keypress(function (evnt) { 36689 if (evnt.keyCode == 13 || evnt.charCode == 13 || evnt.which == 13) { 36690 evnt.preventDefault(); 36691 } 36692 }); 36693 }, 36694 36695 renderView : function (guide, $guideElement) { 36696 viewOnlyUtils.createView(guide, $guideElement); 36697 36698 var lastFocusItem = viewOnlyUtils.getLastFocusItem(guide); 36699 viewOnlyUtils.setFocus(lastFocusItem); 36700 utils.triggerEventOnWindow({type : "guideInitialized", guide : guide}); 36701 36702 viewOnlyUtils.preventCheckBoxMovementOnClick(); 36703 viewOnlyUtils.disableDefaultSubmit(); 36704 viewOnlyUtils.preventFormSubmitOnEnter(); 36705 } 36706 36707 }; 36708 36709 36710 guidelib.model._createXfaAndGuideModel = function (guideJson, xfaJson, options) { 36711 if (xfaJson) { 36712 xfalib.script.XfaModelRegistry.prototype.createModel(xfaJson); 36713 36714 new xfalib.acrobat.Acrobat(); 36715 } 36716 var guide = {}; 36717 guide = guidelib.model.GuideModelRegistry.prototype.createModel(guideJson, options); 36718 36719 guide._bindRefMap = {}; 36720 return guide; 36721 36722 }; 36723 36724 36725 guidelib.model._getGuideJsonWithSyncXfaProps = function (guideJson, xfaJson) { 36726 36727 var guide = guidelib.model._createXfaAndGuideModel(guideJson, xfaJson); 36728 36729 guide.syncXFAProps(); 36730 36731 36732 return { 36733 "guidejson" : JSON.stringify(guideJson), 36734 "xfajson" : JSON.stringify(xfaJson) 36735 }; 36736 }; 36737 36738 guidelib.model._prepareGuide = function (prefillData, guide) { 36739 var liveDataUtils = guide.internal.liveDataUtils, 36740 liveModel = guide.internal.liveModel, 36741 _getFileAttachmentWrappers = function(prefillDataAttachments) { 36742 var fileAttachmentWrappers = []; 36743 try { 36744 var atts = JSON.parse(prefillDataAttachments); 36745 fileAttachmentWrappers = atts.map(function (x) { 36746 return new guidelib.model.FileAttachmentWrapper(JSON.parse(x)) 36747 }); 36748 } catch (e) { 36749 if (e.stack) { 36750 guide.logger().error(e.stack); 36751 } 36752 } 36753 return fileAttachmentWrappers; 36754 }; 36755 36756 if (prefillData.isMergedJson && prefillData.data) { 36757 36758 if (prefillData.data.guideState && prefillData.data.guideState.attachments) { 36759 prefillData.data["attachments"] = _getFileAttachmentWrappers(prefillData.data.guideState.attachments); 36760 } 36761 window.guideBridge.restoreGuideState(prefillData.data); 36762 } else if (prefillData.data) { 36763 guide.setGuideState(constants.GUIDE_STATE_MERGE_PROGRESS); 36764 liveDataUtils.initLiveData(prefillData.data, 36765 null, 36766 _.isString(guide.xdpRef), 36767 _.isString(guide.xsdRef), 36768 guide.getAttribute("xsdRootElement"), 36769 _getFileAttachmentWrappers(prefillData.attachments)); 36770 liveDataUtils.playLiveData(guide.rootPanel); 36771 liveModel.prefillCrossFragFields(guide); 36772 guide.setGuideState(constants.GUIDE_STATE_MERGE_COMPLETE); 36773 guide.prepare(); 36774 } else { 36775 guide.prepare(); 36776 liveDataUtils.initLiveData(null, null, 36777 _.isString(guide.xdpRef), _.isString(guide.xsdRef), 36778 guide.getAttribute("xsdRootElement")); 36779 } 36780 36781 var fileAttachmentMap, 36782 obj = guideBridge.customContextProperty("fileAttachmentMap"); 36783 if (!_.isUndefined(obj) && typeof(obj) === "string") { 36784 try { 36785 obj = JSON.parse(obj); 36786 } catch (e) { 36787 if (e.stack) { 36788 guide.logger().error(e.stack); 36789 } 36790 obj = undefined; 36791 } 36792 } 36793 fileAttachmentMap = obj; 36794 36795 var i, node, fieldValue, 36796 fileAttachmentsList = window.guideBridge._getFileAttachmentsList(); 36797 36798 36799 if (!_.isUndefined(fileAttachmentMap)) { 36800 for (i = 0; i < fileAttachmentsList.length; i++) { 36801 node = fileAttachmentsList[i]; 36802 fieldValue = fileAttachmentMap[node.somExpression]; 36803 node.fileAttachment.value = fieldValue; 36804 if (!_.isEmpty(fieldValue)) { 36805 node._fileList = fieldValue.split("\n"); 36806 } 36807 } 36808 } 36809 guide.setGuideState(constants.GUIDE_STATE_MODEL_COMPLETE); 36810 }; 36811 36812 guidelib.model.markDirtyPanels = function (lazyChildren, dataString, dirtyPanels, guide) {
36813 var lazyChildrenMap = commonUtils.createMap(lazyChildren, 0); 36814 36815 if (!_.isEmpty(dataString)) { 36816 if (dirtyPanels === null || dirtyPanels.length === 0) { 36817 dirtyPanels = guide.internal.liveDataUtils.getListOfDirtyPanels(dataString); 36818 } 36819 if (dirtyPanels && dirtyPanels.length > 0) { 36820 lazyChildrenMap = commonUtils.updatedMapIfNot(lazyChildrenMap, dirtyPanels, 1); 36821 guide.internal.GuideDirtyMarkerAndVisitor.visitMap = lazyChildrenMap; 36822 } 36823 } else { 36824 guide.internal.GuideDirtyMarkerAndVisitor.visitMap = lazyChildrenMap; 36825 } 36826 }; 36827 36828 guidelib.model.initializeLiveDataUtils = function (schemaType) { 36829 var liveDataUtils = null; 36830 if (schemaType === "formdatamodel" || schemaType === "jsonschema") { 36831 liveDataUtils = new guidelib.model.LiveJsonUtils(); 36832 } else { 36833 liveDataUtils = new guidelib.model.LiveXmlUtils(); 36834 } 36835 return liveDataUtils; 36836 }; 36837 36838 guidelib.model.prepareInput = function (guideJsonData) { 36839 return { 36840 guideJson : JSON.parse(guideJsonData.guidejson || "null"), 36841 guideContext : JSON.parse(guideJsonData.guidecontext || "null"), 36842 guidemergedjson : JSON.parse(guideJsonData.guidemergedjson || "null"), 36843 xfaJson : JSON.parse(guideJsonData.xfajson || "null"), 36844 xfaRenderContext : JSON.parse(guideJsonData.xfarendercontext || "null") 36845 }; 36846 }; 36847 36848 guidelib.model.mergeData = function (prefillData, guide, guideContext) { 36849 var rawData = prefillData.data, 36850 liveDataUtils = guide.internal.liveDataUtils, 36851 dirtyPanels = [], 36852 customPropertyMap = {}, 36853 mergedXfaRenderContext = null; 36854 36855 guide.runtime.guideContext = guide.runtime.guideContext || {}; 36856 36857 if (prefillData.isMergedJson) { 36858 if (typeof prefillData.data === "string") { 36859 try { 36860 prefillData.data = JSON.parse(prefillData.data); 36861 } catch (e) { 36862 prefillData.data = ""; 36863 } 36864 } 36865 rawData = getOrElse(prefillData.data, 36866 "guideState.guideLiveData", 36867 getOrElse(rawData, 36868 "guideState.guidePrefillXml", 36869 getOrElse(prefillData.data, 36870 "guideState.guidePrefillJson", undefined))); 36871 36872 var dirtyPanelsStr = getOrElse(prefillData.data, 36873 "guideState.guideContext.afSubmissionInfo.afDraft", "") 36874 .replace(/\"/g, ""); 36875 36876 if (dirtyPanelsStr) { 36877 dirtyPanels = dirtyPanelsStr.split(","); 36878 } 36879 customPropertyMap = getOrElse(prefillData.data, 36880 "guideState.guideContext.customPropertyMap", 36881 {}); 36882 36883 var ccpMapViaNewPrefillService = getOrElse(prefillData.data, "guideState.customContext", null); 36884 var ccpMapViaOldImplementation = getOrElse(guidelib, "__runtime__.guideContext.customPropertyMap", {}); 36885 var ccpMapViaOldAndNewImplementation = _.extend({}, ccpMapViaOldImplementation, getOrElse(guide, "runtime.guideContext.customPropertyMap", {})); 36886 if (!_.isEmpty(ccpMapViaNewPrefillService) && _.isEmpty(ccpMapViaOldAndNewImplementation)) { 36887 guideBridge.customContextProperty(ccpMapViaNewPrefillService); 36888 } 36889 36890 var fileMapViaNewPrefillService = getOrElse(prefillData.data, "guideState.fileAttachmentMap", null); 36891 var fileMapViaOldImplementation = guideBridge.customContextProperty("fileAttachmentMap"); 36892 if (!_.isEmpty(fileMapViaNewPrefillService) && _.isEmpty(fileMapViaOldImplementation)) { 36893 guideBridge.customContextProperty("fileAttachmentMap", fileMapViaNewPrefillService); 36894 } 36895 } else { 36896 customPropertyMap = prefillData.customContext || {}; 36897 guideBridge.customContextProperty("fileAttachmentMap", prefillData.fileAttachmentMap); 36898 guideBridge.customContextProperty("fileAttachmentWrappers", prefillData.fileAttachmentWrappers); 36899 } 36900 36901 if (guide.xdpRef) { 36902 mergedXfaRenderContext = getOrElse(prefillData.data, "guideState.xfaState.xfaRenderContext", null); 36903 36904 if (mergedXfaRenderContext != null) { 36905 36906 xfalib.runtime.renderContext = JSON.parse(mergedXfaRenderContext); 36907 } 36908 36909 xfalib.runtime.xfa.form._initialize(true);
36910 $(window).trigger("XfaInitialized"); 36911 } 36912 36913 if (rawData !== "") { 36914 if (guideContext.schemaType === "formdatamodel" || guideContext.schemaType === "jsonschema") { 36915 guideContext.guidePrefillJson = rawData; 36916 } else { 36917 guideContext.guidePrefillXml = rawData; 36918 } 36919 } 36920 36921 guideContext.customPropertyMap = $.extend({}, guideContext.customPropertyMap, customPropertyMap); 36922 36923 36924 $.extend(true, guide.runtime.guideContext, guideContext); 36925 36926 guidelib.model.markDirtyPanels(guide.allLazyChildren, rawData, dirtyPanels, guide); 36927 36928 guidelib.model._prepareGuide(prefillData, guide); 36929 36930 36931 36932 if (guide.allLazyChildren.length > 0 && guideBridge.customContextProperty("fileAttachmentMap")) { 36933 var fileAttachmentMap = guideBridge.customContextProperty("fileAttachmentMap"); 36934 if (typeof fileAttachmentMap === "string") { 36935 fileAttachmentMap = JSON.parse(fileAttachmentMap); 36936 } 36937 guide.internal.liveDataUtils._updateLazyAttachmentMap(fileAttachmentMap); 36938 } 36939 }; 36940 36941 guidelib.model.fireOnContainerDomElementReady = function (guideJsonData, fetchData, $htmlElement, localContextCustomPropertyMap) { 36942 36943 var inputData = this.prepareInput(guideJsonData), 36944 guideJson = inputData.guideJson, 36945 guideContext = inputData.guideContext, 36946 guidemergedjson = inputData.guidemergedjson, 36947 xfaJson = inputData.xfaJson, 36948 xfaRenderContext = inputData.xfaRenderContext, 36949 localStorage, 36950 guide, 36951 dataPromise; 36952 initializeLogger(xfaJson != null); 36953 if (guideJson === null || guideContext == null) { 36954 console.error("Unable to load Form. Adaptive Form Json is invalid."); 36955 return; 36956 } 36957 36958 if (window.guideBridge !== undefined) { 36959 localStorage = window.guideBridge._getStorage(); 36960 } 36961 try { 36962 36963 localContextCustomPropertyMap = _.isObject(localContextCustomPropertyMap) ? 36964 JSON.stringify(localContextCustomPropertyMap) : localContextCustomPropertyMap; 36965 localContextCustomPropertyMap = JSON.parse(localContextCustomPropertyMap); 36966 } catch(e) { 36967 localContextCustomPropertyMap = {}; 36968 } 36969 36970 if (fetchData && (guidemergedjson === null || guidemergedjson === "" || getOrElse(localStorage, "guideState", null) !== null)) { 36971 if (fetchData instanceof Function) { 36972 var result = fetchData(); 36973 if (result.then instanceof Function) { 36974 dataPromise = result; 36975 } else { 36976 dataPromise = _.extend({}, {isMergedJson : false}, fetchData()); 36977 } 36978 } else { 36979 36980 36981
36982 var originalRequestParams = getOrElse(window.guideBridge, "userConfig.requestParams", {}); 36983 if ((guideJson.prefillService !== undefined && guideJson.prefillService !== "none") || 36984 (new URLSearchParams(window.location.search)).get("dataRef") !== null || 36985 !!originalRequestParams.dataRef) { 36986 var formContainerPath = getOrElse(window.guideBridge, "userConfig.submitConfig.aemFormComponentPath", guideContext.guidePath); 36987 var guideUrl = window.guideBridge._getGuidePathUrl(".af.prefilldata.json", formContainerPath); 36988 dataPromise = this.fetchData(guideUrl + window.location.search, originalRequestParams); 36989 } else { 36990 dataPromise = {data: "", isMergedJson: false}; 36991 } 36992 } 36993 } else { 36994 var _mergeData = guidemergedjson; 36995 if (getOrElse(localStorage, "guideState", null) !== null) { 36996 _mergeData = localStorage; 36997 } 36998 36999 37000 dataPromise = { 37001 data : _mergeData, 37002 isMergedJson : true 37003 }; 37004 } 37005 37006 37007 var liveDataUtils = this.initializeLiveDataUtils(guideContext.schemaType), 37008 liveModel = new guidelib.model.LiveModel(); 37009 37010 if (window.guideBridge.hostName == "server") { 37011 37012 if (!FD.isToggleEnabled(guidelib.util.FeatureToggleConstants.FT_BROWSERLESS_SUBMISSION)) { 37013 liveModel._disableFunctions(); 37014 liveDataUtils._disableFunctions(); 37015 } 37016 37017 _.each(_.functions(viewOnlyUtils), function (funcName) { 37018 viewOnlyUtils[funcName] = function () {}; 37019 }); 37020 37021 if (window.formBridge) { 37022 37023 37024 37025 window.formBridge.ajaxCallMode = "server"; 37026 } 37027 } 37028 37029 liveModel.createDataNodes(guideJson.repeatBindRef); 37030 var allLazyChildren = getOrElse(guideJson, "allLazyChildren", []); 37031 37032 var options = {}; 37033 options = _.extend({}, options, {"liveModel" : liveModel, "liveDataUtils" : liveDataUtils}); 37034 37035 utils.postExternalMessage("_formdomstart"); 37036 try { 37037 guide = guidelib.model._createXfaAndGuideModel(guideJson, xfaJson, options); 37038 37039 guide.runtime.guideContext.customPropertyMap = _.extend({}, guide.runtime.guideContext.customPropertyMap, localContextCustomPropertyMap); 37040 37041 guide.runtime.guideContext.guidePath = guide.jcrPath; 37042 if (allLazyChildren.length > 0) { 37043 liveModel.createCrossFragFields(guideJson.guideGlobalLazyField, guide); 37044 } 37045 guide.version = new guidelib.util.Version({ 37046 scriptingBehaviourVersion: guideContext.scriptingBehaviourVersion 37047 }); 37048 guide.setGuideState(constants.GUIDE_STATE_MODEL_CREATED); 37049 if (xfaJson && xfaRenderContext) { 37050 xfalib.runtime.renderContext = xfaRenderContext; 37051 } 37052 utils.triggerEventOnWindow({type: "guideModelInitialized", guide: guide}); 37053 } catch (e) { 37054 37055 if (e.stack) { 37056 console.error(e.stack); 37057 } 37058 } 37059 37060 var $guideElement = $htmlElement || $("div.guideContainerWrapperNode"); 37061 37062 if (dataPromise.then instanceof Function) { 37063 return dataPromise.then(function (result) { 37064 guidelib.model.mergeData(result, guide, guideContext); 37065 viewOnlyUtils.renderView(guide, $guideElement); 37066 }); 37067 } else { 37068 37069 guidelib.model.mergeData(dataPromise, guide, guideContext); 37070 viewOnlyUtils.renderView(guide, $guideElement); 37071 return guide; 37072 } 37073 }; 37074 37075 37076 guidelib.model.fetchData = function (path, requestParams) { 37077 var deferred = $.Deferred(); 37078 if (window.guideBridge.hostName === "server") { 37079 deferred.resolve({ 37080 data : "", 37081 isMergedJson : false 37082 }); 37083 } else { 37084 var url = path;
37085 if (requestParams && !$.isEmptyObject(requestParams)) { 37086 var queryStart = url.indexOf('?'); 37087 var existingParams = new URLSearchParams(queryStart !== -1 ? url.slice(queryStart + 1) : ''); 37088 var extra = {}; 37089 $.each(requestParams, function (key, value) { 37090 if (!existingParams.has(key)) { 37091 extra[key] = value; 37092 } 37093 }); 37094 if (!$.isEmptyObject(extra)) { 37095 url += (queryStart !== -1 ? '&' : '?') + $.param(extra); 37096 } 37097 } 37098 $.ajax({ 37099 url : url, 37100 type : 'POST', 37101 dataType : 'json' 37102 }).done(function (data) { 37103 var obj = _.extend({}, data, {isMergedJson : false}); 37104 deferred.resolve(obj); 37105 }).fail(function (obj, textStatus, errorThrown) { 37106 console.error(textStatus + " " + errorThrown); 37107 deferred.resolve({ 37108 data : "", 37109 isMergedJson : false 37110 }); 37111 }); 37112 } 37113 return deferred.promise(); 37114 }; 37115})(_, $, window.guidelib); 37116 37117(function ($) { 37118 var xfaUtil = xfalib.ut.XfaUtil.prototype; 37119 $.widget("xfaWidget.imageCheckButtonWidget", $.xfaWidget.XfaCheckBox, { 37120 37121 _widgetName : "imageCheckButtonWidget", 37122 37123 getOptionsMap : function () { 37124 var parentOptionsMap = $.xfaWidget.XfaCheckBox.prototype.getOptionsMap.apply(this, arguments); 37125 return $.extend({}, parentOptionsMap, { 37126 "displayValue" : function (val) { 37127 parentOptionsMap.displayValue.apply(this, arguments); 37128 var rbParent = this.$userControl.parents('.guideRadioButtonItem, .guideCheckBoxItem'); 37129 if (rbParent) { 37130 rbParent.toggleClass('imageCheckButtonChecked', this.checkedState); 37131 } 37132 if (this.$userControl.attr('disabled') === 'disabled') { 37133 rbParent.addClass('imageCheckButtonDisabled'); 37134 } 37135 } 37136 }); 37137 } 37138 }); 37139})($); 37140(function (_, guidelib) { 37141 var GuideModelRegistry = guidelib.model.GuideModelRegistry = xfalib.ut.Class.extend({ 37142 37143 _nodeClassToFactoryMap : { 37144 37145 }, 37146 37147 createModel : function (jsonModel, options) { 37148 var model = null; 37149 var guideNodeClassTag = "GuideNode"; 37150 if (jsonModel.guideNodeClass && jsonModel.guideNodeClass.length > 0) { 37151 guideNodeClassTag = jsonModel.guideNodeClass.charAt(0).toUpperCase() + jsonModel.guideNodeClass.substr(1); 37152 } 37153 var factoryFnName = "create" + guideNodeClassTag ; 37154 if (jsonModel.guideNodeClass && this._nodeClassToFactoryMap[jsonModel.guideNodeClass]) { 37155 factoryFnName = this._nodeClassToFactoryMap[jsonModel.guideNodeClass]; 37156 } 37157 if (this[factoryFnName]) { 37158 model = this[factoryFnName].call(this, jsonModel, options); 37159 } 37160 37161 if (!model && guidelib.model[guideNodeClassTag]) { 37162 model = new guidelib.model[guideNodeClassTag](this._getOptions(jsonModel, options)); 37163 } 37164 37165 if (!model) { 37166 if (jsonModel.items) { 37167 model = new guidelib.model.GuideItemsContainer(this._getOptions(jsonModel, options)); 37168 } else { 37169 model = new guidelib.model.GuideNode(this._getOptions(jsonModel, options)); 37170 } 37171 } 37172 return model; 37173 }, 37174 37175 _getOptions : function (jsonModel, options) { 37176 return _.extend({}, options, {"jsonModel" : jsonModel}); 37177 }, 37178 37179 createInstanceManager : function (guidePanelModel) { 37180 var name = guidePanelModel.getAttribute("name"), 37181 imJson = { 37182 guideNodeClass : "guideInstanceManager", 37183 minOccur : guidePanelModel.minOccur, 37184 maxOccur : guidePanelModel.maxOccur, 37185 initialOccur : guidePanelModel.initialOccur, 37186 instanceTemplateId : guidePanelModel.templateId, 37187 name : "_" + name, 37188 instanceName : name, 37189 templateId : "im_" + guidePanelModel.templateId, 37190 id : "im_" + guidePanelModel.id 37191 }; 37192 var options = {}; 37193 if (guidePanelModel.options._guideContainer) { 37194 options = _.extend({}, options, {"_guideContainer" : guidePanelModel.options._guideContainer}); 37195 } 37196 return guidelib.model.GuideModelRegistry.prototype.createModel(imJson, options); 37197 } 37198 }); 37199})(_, guidelib); 37200 37201/************************************************************************* 37202 * 37203 * ADOBE CONFIDENTIAL 37204 * __________________ 37205 * 37206 * Copyright 2014 Adobe Systems Incorporated 37207 * All Rights Reserved. 37208 *
37209 * NOTICE: All information contained herein is, and remains 37210 * the property of Adobe Systems Incorporated and its suppliers, 37211 * if any. The intellectual and technical concepts contained 37212 * herein are proprietary to Adobe Systems Incorporated and its 37213 * suppliers and may be covered by U.S. and Foreign Patents, 37214 * patents in process, and are protected by trade secret or copyright law. 37215 * Dissemination of this information or reproduction of this material 37216 * is strictly forbidden unless prior written permission is obtained 37217 * from Adobe Systems Incorporated. 37218 **************************************************************************/ 37219 37220/** 37221 * Created with IntelliJ IDEA. 37222 * User: rismehta 37223 * Date: 1/15/14 37224 * Time: 5:49 PM 37225 * To change this template use File | Settings | File Templates. 37226 */ 37227 37228/*anonymous function to handle show of file list view */ 37229(function ($, guidelib) { 37230 37231 // Was causing problem in IE9 37232 // hence have added timeout to ensure that once button is rendered, event handler is registered 37233 // todo: may have to think of better namespace ? 37234 guidelib.intervals = guidelib.intervals || {}; 37235 guidelib.intervals.intId = setInterval(function () { 37236 var fileAttachmentListingBtn = $("div.fileattachmentlisting button[data-guide-fileListing]"); 37237 if (fileAttachmentListingBtn.length > 0) { 37238 clearInterval(guidelib.intervals.intId); 37239 var self; 37240 fileAttachmentListingBtn.click(function () { 37241 self = $(this); 37242 // added because in mobile devices it was causing problem of backdrop 37243 $("#fileAttachment").addClass("fileAttachmentDialog") 37244 $("#fileAttachment").appendTo('body'); 37245 $("#fileAttachment").modal("show"); 37246 }); 37247 // bring focus back to file attachment listing button on dialog hide 37248 $(".fileAttachmentDialog").on('hidden.bs.modal', function (e) { 37249 $(this).removeClass("fileAttachmentDialog"); 37250 self.focus(); 37251 }); 37252 } 37253 }, 1000); 37254}($, guidelib)); 37255 37256/************************************************************************* 37257 * 37258 * ADOBE CONFIDENTIAL 37259 * __________________ 37260 * 37261 * Copyright 2014 Adobe Systems Incorporated 37262 * All Rights Reserved. 37263 *
37264 * NOTICE: All information contained herein is, and remains 37265 * the property of Adobe Systems Incorporated and its suppliers, 37266 * if any. The intellectual and technical concepts contained 37267 * herein are proprietary to Adobe Systems Incorporated and its 37268 * suppliers and may be covered by U.S. and Foreign Patents, 37269 * patents in process, and are protected by trade secret or copyright law. 37270 * Dissemination of this information or reproduction of this material 37271 * is strictly forbidden unless prior written permission is obtained 37272 * from Adobe Systems Incorporated. 37273 **************************************************************************/ 37274 37275(function ($) { 37276 37277 // GUIDE ADD REMOVE CLASS DEFINITION 37278 // ==================== 37279 37280 var GuideAddRemove = function (element) { 37281 this.element = $(element); 37282 }; 37283 37284 GuideAddRemove.prototype.add = function () { 37285 $this = this.element; 37286 var id = $this.attr("data-guide-id"), 37287 nextPanel; 37288 37289 if (id) { 37290 if (window.guideBridge) { 37291 var guidePanel = window.guideBridge._resolveId(id); 37292 if (guidePanel) { 37293 nextPanel = guidePanel.instanceManager.insertInstance(guidePanel.instanceIndex + 1); 37294 if (nextPanel) { 37295 window.guideBridge.setFocus(nextPanel.somExpression, "firstItem"); 37296 } 37297 } 37298 } else { 37299 console.log("could not add new instance" + id); 37300 } 37301 } 37302 }; 37303 37304 GuideAddRemove.prototype.remove = function () { 37305 $this = this.element; 37306 var id = $this.attr("data-guide-id"); 37307 37308 if (id) { 37309 if (window.guideBridge) { 37310 var guidePanel = window.guideBridge._resolveId(id); 37311 if (guidePanel) { 37312 guidePanel.instanceManager.removeInstance(guidePanel.instanceIndex); 37313 } 37314 } else { 37315 console.log("could not remove instance"); 37316 } 37317 } 37318 }; 37319 37320 // GUIDE ADD REMOVE PLUGIN DEFINITION 37321 // ===================== 37322 37323 var old = $.fn.guideAddRemove; 37324 37325 $.fn.guideAddRemove = function (option) { 37326 return this.each(function () { 37327 var $this = $(this); 37328 var data = $this.data('guideAddRemove'); 37329 37330 if (!data) { 37331 $this.data('guideAddRemove', (data = new GuideAddRemove(this))); 37332 } 37333 if (typeof option == 'string') { 37334 data[option](); 37335 } 37336 }); 37337 }; 37338 37339 $.fn.guideAddRemove.Constructor = GuideAddRemove(); 37340 37341 // ADD REMOVE NO CONFLICT 37342 // =============== 37343 37344 $.fn.guideAddRemove.noConflict = function () { 37345 $.fn.guideAddRemove = old; 37346 return this; 37347 }; 37348 37349 // ADD REMOVE DATA-API 37350 // ============ 37351 37352 $(document).on('click.guideAddRemove.data-api keypress.guideAddRemove.data-api', '[data-guide-addremove="add"]', function (e) { 37353 if (e.type == "keypress" && !guidelib.util.GuideUtil.isEnterKeyPressed(e)) { 37354 return; 37355 } 37356 e.preventDefault(); 37357 //This is required for setting the focus on the new panel. Otherwise the focus remains on the previous panel. 37358 e.stopImmediatePropagation(); 37359 $(this).guideAddRemove('add'); 37360 }).on('click.guideAddRemove.data-api keypress.guideAddRemove.data-api', '[data-guide-addremove="remove"]', function (e) { 37361 if (e.type == "keypress" && !guidelib.util.GuideUtil.isEnterKeyPressed(e)) { 37362 return; 37363 } 37364 e.preventDefault(); 37365 $(this).guideAddRemove('remove'); 37366 }); 37367 37368}($)); 37369 37370/************************************************************************* 37371 * 37372 * ADOBE CONFIDENTIAL 37373 * __________________ 37374 * 37375 * Copyright <year> Adobe Systems Incorporated 37376 * All Rights Reserved. 37377 *
37378 * NOTICE: All information contained herein is, and remains 37379 * the property of Adobe Systems Incorporated and its suppliers, 37380 * if any. The intellectual and technical concepts contained 37381 * herein are proprietary to Adobe Systems Incorporated and its 37382 * suppliers and may be covered by U.S. and Foreign Patents, 37383 * patents in process, and are protected by trade secret or copyright law. 37384 * Dissemination of this information or reproduction of this material 37385 * is strictly forbidden unless prior written permission is obtained 37386 * from Adobe Systems Incorporated. 37387 **************************************************************************/ 37388 37389(function ($) { 37390 37391 // TABLE LAYOUT PLUGIN 37392 // ============ 37393 37394 $(document).on('panelRemoved.af', '.guideTableNode', function (e, $childRemoved, index) { 37395 // this plugin is specific to a layout 37396 // one can also check the layout based on CSS class set and perform things accordingly 37397 // prevent the bubbling up of the event 37398 e.stopPropagation(); 37399 // this would work only in runtime 37400 var $bodyRows = $(e.target).find("tr.guideTableRowNode:not(.guideTableHeader)"); 37401 // Set focus to first child 37402 if (index > 1) { 37403 // set focus on prev row since index is greater than 1 37404 var $prevRow = $bodyRows.eq(index - 1); 37405 guidelib.util.GuideUtil.setFocusOnFirstItemOfTableRow($prevRow); 37406 } else if (index == 1) { 37407 var $nextRow = $bodyRows.eq(1); 37408 // may there is only one row which has got deleted, hence check if next row actually exists 37409 if ($nextRow.length > 0) { 37410 guidelib.util.GuideUtil.setFocusOnFirstItemOfTableRow($nextRow); 37411 } 37412 } 37413 }); 37414 37415}($)); 37416 37417/************************************************************************* 37418 * 37419 * ADOBE CONFIDENTIAL 37420 * __________________ 37421 * 37422 * Copyright 2014 Adobe Systems Incorporated 37423 * All Rights Reserved. 37424 *
37425 * NOTICE: All information contained herein is, and remains 37426 * the property of Adobe Systems Incorporated and its suppliers, 37427 * if any. The intellectual and technical concepts contained 37428 * herein are proprietary to Adobe Systems Incorporated and its 37429 * suppliers and may be covered by U.S. and Foreign Patents, 37430 * patents in process, and are protected by trade secret or copyright law. 37431 * Dissemination of this information or reproduction of this material 37432 * is strictly forbidden unless prior written permission is obtained 37433 * from Adobe Systems Incorporated. 37434 **************************************************************************/ 37435 37436/*handle click of default next and previous navigator*/ 37437$(function ($) { 37438 var getPanelSom = function (panelId) { 37439 var panel = window.guideBridge._resolveId(panelId); 37440 if (panel === undefined || panel === null) { 37441 return ""; 37442 } 37443 return panel.somExpression; 37444 }, 37445 pointerup_evnt = xfalib.ut.TouchUtil.POINTER_UP; 37446 37447 if (pointerup_evnt === "touchend") { 37448 // touchend happens before blur, hence the value of the current 37449 // focused field is not committed and setFocus API receives the old 37450 // value. So as a hack we are using mouseup instead of touchend to 37451 // make sure that the value gets committed 37452 pointerup_evnt = "mouseup"; 37453 } 37454 $('body').on(pointerup_evnt + " keydown", '[data-guide-wizard-nav]', function (e) { 37455 var triggerKeyEvent = false; 37456 // check for event type and key press space/enter 37457 if (e.type === "keydown" && (e.keyCode === 32 || e.keyCode === 13)) { 37458 e.preventDefault(); 37459 triggerKeyEvent = true; // set to trigger key event 37460 } 37461 37462 // when event is pointerup(click) or space/enter key is pressed, trigger navigation 37463 if (e.type === "pointerup" || triggerKeyEvent) { 37464 var $this = $(this), 37465 options = $this.data("guide-wizard-nav"); 37466 if (_.isObject(options)) { //case of all the options, get som expression out of id 37467 options.somExpression = getPanelSom(options.panelId); 37468 } else { //case where its value of somId 37469 var somExpr = getPanelSom(options), 37470 navType = $(this).data("guide-wizard-nav-type"); 37471 options = { 37472 somExpression: somExpr, 37473 focusOption: navType, 37474 runCompletionScript: true 37475 }; 37476 } 37477 window.guideBridge.setFocus(options); 37478 } 37479 }); 37480 37481 window.guideBridge.on("elementNavigationChanged", 37482 function (evntName, evnt) { 37483 var activePanelSom = evnt.newText, 37484 activePanel = window.guideBridge._guideView.getView(activePanelSom), 37485 scrollDirection, 37486 scrollStep, 37487 scrollPos, 37488 list, 37489 $listElements; 37490 if (activePanel instanceof guidelib.view.GuidePanelView) { 37491 $listElements = activePanel.parentView.$element.find('[id*="' + guidelib.util.GuideUtil.GUIDE_ITEM_NAV_CONTAINER_SUFFIX + '"]'); 37492 if (!_.isUndefined($listElements) && !_.isNull($listElements) && $listElements.length > 0) { 37493 list = $listElements.eq(0); 37494 if (_.isUndefined(list.attr("data-guide-nav-scroll-pos"))) { 37495 list.attr("data-guide-nav-scroll-pos", 0); 37496 } 37497 scrollPos = parseInt(list.attr("data-guide-nav-scroll-pos"), 10); 37498 //Find index among the visible panels 37499 var parentChildViews = activePanel.parentView.childViews, 37500 iterator, 37501 navPos = 0; 37502 for (iterator = 0; iterator < parentChildViews.length; iterator++) { 37503 if (activePanel === parentChildViews[iterator]) { 37504 break; 37505 } 37506 if (parentChildViews[iterator]._model.visible) { 37507 navPos = navPos + 1; 37508 } 37509 } 37510 if (navPos > scrollPos) { 37511 scrollDirection = "right"; 37512 } else { 37513 scrollDirection = "left"; 37514 } 37515 scrollStep = Math.abs(navPos - scrollPos); 37516 guidelib.util.GuideUtil.navScroll(list, scrollDirection, scrollStep, '[id*="' + guidelib.util.GuideUtil.GUIDE_ITEM_
37516NAV_SUFFIX + '"]:not(.hidden)'); 37517 } 37518 } 37519 }); 37520}); 37521 37522/************************************************************************* 37523 * 37524 * ADOBE CONFIDENTIAL 37525 * __________________ 37526 * 37527 * Copyright 2014 Adobe Systems Incorporated 37528 * All Rights Reserved. 37529 * 37530 * NOTICE: All information contained herein is, and remains 37531 * the property of Adobe Systems Incorporated and its suppliers, 37532 * if any. The intellectual and technical concepts contained 37533 * herein are proprietary to Adobe Systems Incorporated and its 37534 * suppliers and may be covered by U.S. and Foreign Patents, 37535 * patents in process, and are protected by trade secret or copyright law. 37536 * Dissemination of this information or reproduction of this material 37537 * is strictly forbidden unless prior written permission is obtained 37538 * from Adobe Systems Incorporated. 37539 **************************************************************************/ 37540 37541$(function ($) { 37542 37543 /* handle swipe*/ 37544 var setSwipeGestureState = function () { 37545 var swipeEnabled = !window.guideBridge._guide.getAttribute("disableSwipeGesture"); 37546 window.guideBridge.enableSwipeGesture(swipeEnabled, swipeEnabled); 37547 }; 37548 window.guideBridge.connect(setSwipeGestureState, this); 37549 37550 /*show scroll indication on mobile devices*/ 37551 var scrollIndicator = function () { 37552 if ($(window).scrollTop() == $(document).height() - $(window).height()) { 37553 $('[data-guide-scroll-indicator]').removeClass('mobileScrollIndicator'); 37554 } else if ($(window).scrollTop() < $(document).height() - $(window).height()) { 37555 $('[data-guide-scroll-indicator]').addClass('mobileScrollIndicator'); 37556 } 37557 }; 37558 37559 //this should be changed back to $(document).ready(scrollIndicator) instead of windows onload, 37560 //once jquery version is bumped 37561 $(window).on('load scroll resize', scrollIndicator); 37562 window.guideBridge.on('elementNavigationChanged', scrollIndicator); 37563}); 37564 37565/************************************************************************* 37566 * 37567 * ADOBE CONFIDENTIAL 37568 * __________________ 37569 * 37570 * Copyright 2014 Adobe Systems Incorporated 37571 * All Rights Reserved. 37572 *
37573 * NOTICE: All information contained herein is, and remains 37574 * the property of Adobe Systems Incorporated and its suppliers, 37575 * if any. The intellectual and technical concepts contained 37576 * herein are proprietary to Adobe Systems Incorporated and its 37577 * suppliers and may be covered by U.S. and Foreign Patents, 37578 * patents in process, and are protected by trade secret or copyright law. 37579 * Dissemination of this information or reproduction of this material 37580 * is strictly forbidden unless prior written permission is obtained 37581 * from Adobe Systems Incorporated. 37582 **************************************************************************/ 37583/*anonymous function to handle click of default next and previous navigator*/ 37584(function ($) { 37585 window.guideBridge.on("elementNavigationChanged", 37586 function (evntName, evnt) { 37587 var activePanelSom = evnt.newText, 37588 activePanel = window.guideBridge.resolveNode(activePanelSom); 37589 if (activePanel) { 37590 var dynamicContentSelector = "[data-target-guide-content]", 37591 text = $(dynamicContentSelector).text(); 37592 // if there is an active panel already set and active panel is not an instance of root panel node 37593 // only then set the active panel title to the content 37594 if (text != null && text.length > 0 37595 && (!(activePanel instanceof guidelib.model.RootPanelNode) 37596 && !(activePanel instanceof guidelib.model.GuideToolbar))) { 37597 $(dynamicContentSelector).text(activePanel.title ? activePanel.title : ""); 37598 } 37599 } 37600 }); 37601}($)); 37602 37603// jscs:disable requireDotNotation 37604/* 37605 * *********************************************************************** 37606 * ADOBE CONFIDENTIAL 37607 * __________________ 37608 * 37609 * Copyright 2015 Adobe Systems Incorporated 37610 * All Rights Reserved. 37611 *
37612 * NOTICE: All information contained herein is, and remains 37613 * the property of Adobe Systems Incorporated and its suppliers, 37614 * if any. The intellectual and technical concepts contained 37615 * herein are proprietary to Adobe Systems Incorporated and its 37616 * suppliers and may be covered by U.S. and Foreign Patents, 37617 * patents in process, and are protected by trade secret or copyright law. 37618 * Dissemination of this information or reproduction of this material 37619 * is strictly forbidden unless prior written permission is obtained 37620 * from Adobe Systems Incorporated. 37621 * *********************************************************************** 37622 */ 37623 37624(function ($, guidelib, _) { 37625 var GuideUtil = guidelib.util.GuideUtil, 37626 CHART_TYPE = GuideUtil.chartType, 37627 37628 ChartUtils = guidelib.chartUtils = { 37629 37630 reducerOptions : window.chartReducer.reducerOptions, 37631 37632 /** 37633 * Returns the display format of axis data 37634 * @param dataType {string} representing data type of axis 37635 * @returns {string} 37636 */ 37637 getDisplayFormat : function (dataType) { 37638 var displayFormat = ""; 37639 if (dataType === 'date' || dataType === 'date-time') { 37640 displayFormat = 'date{' + guidelib.i18n.datePatterns.med + '}'; 37641 } 37642 return displayFormat; 37643 }, 37644 37645 /** 37646 * Reads chart model for chart configuration and computes the data for chart 37647 * @param chartModel 37648 * @returns {{}} 37649 */ 37650 gatherAxisData : function (chartModel) { 37651 var categoryExp, 37652 valueExp, 37653 reducerFunction, 37654 repeatableInstances, 37655 repeatableItem, 37656 seriesRepeatableItem, 37657 series, 37658 relativeSeriesNameExp, 37659 currentSeries, 37660 repeatablePath, 37661 seriesLength = 0, 37662 seriesRepeatableInstances, 37663 relativeSeriesRefExp, 37664 data = new Map(), 37665 chartBuildOptions = {}, 37666 isWebChannelChart = chartModel.jsonModel["sling:resourceType"] === 'fd/ccm/web-channel/components/chart/v1/chart', 37667 dataToFill = {}; 37668 chartBuildOptions.isFDMDataSource = chartModel.dataSourceType === "fdm" ? true : false; 37669 chartBuildOptions.chartModel = chartModel; 37670 dataToFill.valueDisplayFormat = ""; 37671 dataToFill.labelDisplayFormat = ""; 37672 dataToFill.categoryDataType = ""; 37673 dataToFill.valueDataType = ""; 37674 37675 repeatableItem = chartModel.getOrElse(chartModel._guide().runtime, chartModel.repeatableItem, undefined); 37676 37677 //Do not support reducer functions on x-axis for Web channel charts 37678 if (chartModel.reducerXFunction && chartModel.reducerXFunction !== 'none' && !isWebChannelChart) { 37679 chartBuildOptions.categoryExp = chartModel.yExp; 37680 chartBuildOptions.valueExp = chartModel.xExp; 37681 chartBuildOptions.reducerFunction = chartModel.reducerXFunction; 37682 dataToFill = ChartUtils._setProp(dataToFill, "categoryDataType", chartModel.jsonModel.yDataType); 37683 dataToFill = ChartUtils._setProp(dataToFill, "valueDataType", chartModel.jsonModel.xDataType); 37684 } else { 37685 chartBuildOptions.categoryExp = chartModel.xExp; 37686 chartBuildOptions.valueExp = chartModel.yExp; 37687 dataToFill = ChartUtils._setProp(dataToFill, "categoryDataType", chartModel.jsonModel.yDataType); 37688 dataToFill = ChartUtils._setProp(dataToFill, "valueDataType", chartModel.jsonModel.xDataType); 37689 if (chartModel.reducerYFunction && chartModel.reducerYFunction !== 'none') { 37690 chartBuildOptions.reducerFunction = chartModel.reducerYFunction; 37691 } 37692 } 37693 37694 if (chartBuildOptions.isFDMDataSource) { 37695 dataToFill.valueDisplayFormat = ChartUtils.getDisplayFormat(dataToFill.valueDataType); 37696 dataToFill.labelDisplayFormat = ChartUtils.getDisplayFormat(dataToFill.categoryDataType); 37697 repeatableItem = chartModel.repeatableItem; 37698 chartBuildOptions.categoryExp = chartBuildOptions.categoryExp.substring(repeatableItem.length + 1, chartBuildOptions.categoryExp.length).split("/"); 37699 chartBuildOptions.valueExp = chartBuildOptions.valueExp.substring(repeatableItem.length + 1, chartBuildOptions.valueExp.length).split("/"); 37700 if (isWebChannelChart) { 37701 dataToFill.series = series = []; 37702 if (chartModel.jsonModel.chartType === 'quadrant') { 37703 chartBuildOptions.isXYReferencePointSet = false;
37704 if (chartModel.jsonModel.referencePointType === 'staticReferencePoint') { 37705 if (chartModel.jsonModel.xDataType === 'date' || chartModel.jsonModel.xDataType === 'date-time') { 37706 //Whenx-axis is of Date type we need to compute reference value in milliseconds. 37707 chartModel.jsonModel.xAxisReferencePoint = new Date(chartModel.jsonModel.xAxisReferencePoint).getTime(); 37708 } 37709 chartBuildOptions.isXYReferencePointSet = true; 37710 } 37711 } 37712 } 37713 if ("true" == chartModel.jsonModel.multiSeries) { 37714 seriesRepeatableItem = chartModel.jsonModel.seriesRepeatableItem; 37715 relativeSeriesNameExp = chartModel.jsonModel.seriesName.substring(seriesRepeatableItem.length + 1, chartModel.jsonModel.seriesName.length); 37716 seriesRepeatableInstances = this._getRepeatableInstances(seriesRepeatableItem, null, chartModel); 37717 seriesLength = seriesRepeatableInstances ? seriesRepeatableInstances.length : seriesLength; 37718 repeatablePath = repeatableItem.substring(seriesRepeatableItem.length, repeatableItem.length); 37719 if (chartModel.jsonModel.chartType === 'quadrant' && chartModel.jsonModel.referencePointType === 'fdmReferencePoint') { 37720 relativeSeriesRefExp = chartModel.jsonModel.seriesReferenceExp.substring(seriesRepeatableItem.length + 1, chartModel.jsonModel.seriesReferenceExp.length); 37721 } 37722 for (var i = 0; i < seriesLength; i++) { 37723 chartBuildOptions.repeatableInstances = this._getRepeatableInstances(repeatablePath, seriesRepeatableInstances[i], chartModel); 37724 chartBuildOptions.repeatableItemForReferencePoint; 37725 if (relativeSeriesRefExp && !chartBuildOptions.isXYReferencePointSet) { 37726 chartBuildOptions.repeatableItemForReferencePoint = undefined; 37727 if (this.matchUserInputWithFDM(chartModel.jsonModel.seriesReferenceDataType, seriesRepeatableInstances[i][relativeSeriesRefExp], chartModel.jsonModel.seriesReferenceValue)) { 37728 chartBuildOptions.repeatableItemForReferencePoint = repeatableItem; 37729 } 37730 } 37731 currentSeries = this.buildChartData(chartBuildOptions); 37732 currentSeries.name = seriesRepeatableInstances[i][relativeSeriesNameExp]; 37733 series.push(currentSeries); 37734 } 37735 } else { 37736 chartBuildOptions.repeatableInstances = this._getRepeatableInstances(repeatableItem, null, chartModel); 37737 chartBuildOptions.repeatableItemForReferencePoint = repeatableItem; 37738 currentSeries = this.buildChartData(chartBuildOptions); 37739 series.push(currentSeries); 37740 } 37741 if (isWebChannelChart && chartModel.jsonModel.chartType === 'quadrant' && chartModel.jsonModel.referencePointType === 'fdmReferencePoint' && !chartBuildOptions.isXYReferencePointSet) { 37742 chartModel.jsonModel.xAxisReferencePoint = undefined; 37743 chartModel.jsonModel.yAxisReferencePoint = undefined; 37744 } 37745 chartBuildOptions.repeatableInstances = null; 37746 } else if (repeatableItem) { 37747 chartBuildOptions.repeatableInstances = repeatableItem.instanceManager.instances; 37748 } 37749 if (chartBuildOptions.repeatableInstances) { 37750 var chartData = this.buildChartData(chartBuildOptions); 37751 dataToFill.label = chartData.label; 37752 dataToFill.value = chartData.value; 37753 } 37754 return dataToFill; 37755 }, 37756 37757 buildChartData : function (chartBuildOptions) { 37758 var dataToFill = {}, 37759 data = new Map(), 37760 referencePointExp, 37761 isFDMReferencePointSet = false;
37762 dataToFill.value = []; 37763 dataToFill.label = []; 37764 37765 if (chartBuildOptions.chartModel.jsonModel.chartType === 'quadrant' && chartBuildOptions.chartModel.jsonModel.referencePointType === 'fdmReferencePoint' && chartBuildOptions.repeatableItemForReferencePoint) { 37766 referencePointExp = chartBuildOptions.chartModel.jsonModel.xyReferencePointExp.substring(chartBuildOptions.repeatableItemForReferencePoint.length + 1, chartBuildOptions.chartModel.jsonModel.xyReferencePointExp.length).split("/"); 37767 } 37768 var that = this; 37769 _.each(chartBuildOptions.repeatableInstances, function (repeatableInstance, index) { 37770 var categoryPropVal, 37771 valuePropVal, 37772 xyReferenceVal; 37773 if (chartBuildOptions.isFDMDataSource) { 37774 if (_.isArray(chartBuildOptions.categoryExp) && _.isArray(chartBuildOptions.valueExp)) { 37775 //Handling composite key case. 37776 var temp = repeatableInstance; 37777 _.each(chartBuildOptions.categoryExp, function (obj) { 37778 temp = temp[obj]; 37779 }); 37780 categoryPropVal = temp; 37781 37782 temp = repeatableInstance; 37783 _.each(chartBuildOptions.valueExp, function (obj) { 37784 temp = temp[obj]; 37785 }); 37786 valuePropVal = temp; 37787 37788 if (chartBuildOptions.chartModel.jsonModel.chartType === 'quadrant' && !chartBuildOptions.isXYReferencePointSet) { 37789 if (chartBuildOptions.repeatableItemForReferencePoint && chartBuildOptions.chartModel.jsonModel.referencePointType === 'fdmReferencePoint') { 37790 temp = repeatableInstance; 37791 _.each(referencePointExp, function (obj) { 37792 temp = temp[obj]; 37793 }); 37794 xyReferenceVal = temp; 37795 if (that.matchUserInputWithFDM(chartBuildOptions.chartModel.jsonModel.xyReferencePointDataType, xyReferenceVal, chartBuildOptions.chartModel.jsonModel.xyReferencePointValue)) { 37796 //For date type x-axis FDM value we need to get time in milliseconds to send to Highcharts 37797 chartBuildOptions.chartModel.jsonModel.xAxisReferencePoint = (chartBuildOptions.chartModel.jsonModel.xDataType === 'date' || chartBuildOptions.chartModel.jsonModel.xDataType === 'date-time') ? new Date(categoryPropVal).getTime() : categoryPropVal; 37798 chartBuildOptions.chartModel.jsonModel.yAxisReferencePoint = valuePropVal; 37799 chartBuildOptions.isXYReferencePointSet = true; 37800 } 37801 } 37802 } 37803 } 37804 } else { 37805 categoryPropVal = repeatableInstance[chartBuildOptions.categoryExp].value; 37806 valuePropVal = repeatableInstance[chartBuildOptions.valueExp].value; 37807 } 37808 37809 categoryPropVal = _.isUndefined(categoryPropVal) ? '' : categoryPropVal; 37810 valuePropVal = _.isUndefined(valuePropVal) ? '' : valuePropVal; 37811 if (chartBuildOptions.reducerFunction) { 37812 if (!data.has(categoryPropVal)) { 37813 data.set(categoryPropVal, []); 37814 } 37815 data.get(categoryPropVal).push(valuePropVal); 37816 } else { 37817 dataToFill.label.push(categoryPropVal); 37818 dataToFill.value.push(valuePropVal); 37819 } 37820 }); 37821 37822 if (chartBuildOptions.reducerFunction) { 37823 var reducer = ChartUtils.reducerOptions[chartBuildOptions.reducerFunction] || window[chartBuildOptions.reducerFunction]; 37824 data.forEach(function (value, key) { 37825 dataToFill.label.push(key); 37826 dataToFill.value.push(reducer(data.get(key))); 37827 }); 37828 } 37829 return dataToFill; 37830 }, 37831 37832 matchUserInputWithFDM : function (fdmObjectDataType, fdmObjectValue, userInputValue) { 37833 return (((fdmObjectDataType == 'date-time' || fdmObjectDataType == 'date') && new Date(userInputValue).getTime() == new Date(fdmObjectValue).getTime()) 37834 || (fdmObjectDataType == 'boolean' && JSON.parse(userInputValue) == fdmObjectValue) 37835 || (userInputValue == fdmObjectValue)); 37836 }, 37837 37838 /** 37839 * Returns dv.chart object created from chart model. 37840 * @param chartModel 37841 * @param $chartElement 37842 * @returns {dv.chart} 37843 */ 37844 constructChart : function (chartModel, $chartElement) { 37845 var chartType = chartModel.chartType, 37846 showLegends = chartModel.showLegends, 37847 legendPosition = chartModel.legendPosition, 37848 tooltipHtml = chartModel.tooltipHtml, 37849 innerRadius = chartModel.innerRadius, 37850 lineColor = chartModel.lineColor, 37851 pointColor = chartModel.pointColor, 37852 areaColor = chartModel.areaColor, 37853 dataToFill = chartModel.data, 37854 chartBehavior = [], 37855 axisMap = {}, 37856 axisScale = {}, 37857 chartLayers, 37858 chart, 37859 categoryAxis, 37860 valueAxis; 37861 if (chartModel.reducerXFunction && chartModel.reducerXFunction !== 'none') { 37862 categoryAxis = 'y'; 37863 valueAxis = 'x'; 37864 } else { 37865 categoryAxis = 'x'; 37866 valueAxis = 'y'; 37867 } 37868 37869 if (dataToFill.labelDisplayFormat) { 37870 dataToFill.label = dataToFill.label.map(function (value) { 37871 return guidelib.util.GuideUtil.formatValue(value, 37872 dataToFill.labelDisplayFormat, 37873 dataToFill.categoryDataType); 37874 }); 37875 } 37876 37877 if (dataToFill.valueDisplayFormat) { 37878 dataToFill.value = dataToFill.value.map(function (value) { 37879 return guidelib.util.GuideUtil.formatValue(value, 37880 dataToFill.valueDisplayFormat, 37881 dataToFill.valueDataType); 37882 }); 37883 } 37884 37885 axisMap[categoryAxis] = 'label'; 37886 axisMap[valueAxis] = 'value'; 37887 axisScale[valueAxis] = dv.scale.linear().lowerLimit(0); 37888 37889 try { 37890 if (GuideUtil.isChartTooltipApplicable(chartType)) { 37891 if (tooltipHtml && tooltipHtml !== '') { 37892 var xValMap = axisMap['x'], 37893 yValMap = axisMap['y']; 37894 chartBehavior = [dv.behavior.rollover().content(function (d) { 37895 var tooltip = tooltipHtml.replace(/\${x}/g, d.data[xValMap]); 37896 tooltip = tooltip.replace(/\${y}/g, d.data[yValMap]); 37897 return tooltip; 37898 })]; 37899 } 37900 } 37901 axisScale[categoryAxis] = dv.scale.ordinal(); 37902 chart = dv.chart(); 37903 chart.map('fill', 'label') 37904 .map('x', axisMap['x'], axisScale['x']) 37905 .map('y', axisMap['y'], axisScale['y']); 37906 37907 var chartPoint = dv.geom.point().set('fill', pointColor).behaviors(chartBehavior), 37908 chartLine = dv.geom.line().set('fill', lineColor), 37909 chartArea = dv.geom.area().set('alpha', 0.1).set('fill', areaColor), 37910 flippedCaretesianCoord = dv.coord.cartesian().flip(true),
37911 lineCommon = function () { 37912 chart.set('stroke', lineColor); 37913 chartLayers = [dv.geom.line()]; 37914 }, 37915 barTypeCommon = function () { 37916 chartLayers = [dv.geom.bar().behaviors(chartBehavior)]; 37917 chart.map('x', 'label', axisScale[categoryAxis]) 37918 .map('y', 'value'); 37919 }, 37920 barCommon = function () { 37921 barTypeCommon(); 37922 if (categoryAxis === 'x') { 37923 chart.coord(flippedCaretesianCoord); 37924 } 37925 }, 37926 columnCommon = function () { 37927 barTypeCommon(); 37928 if (categoryAxis === 'y') { 37929 chart.coord(flippedCaretesianCoord); 37930 } 37931 }, 37932 pieCommon = function (radius) { 37933 columnCommon(); 37934 dataToFill[categoryAxis] = Array.apply(null, Array(dataToFill["label"].length)).map(function () { 37935 return 1; 37936 }); 37937 axisMap[categoryAxis] = categoryAxis; 37938 if (radius > 0) { 37939 axisScale[categoryAxis] = axisScale[categoryAxis].padding(.3); 37940 } 37941 37942 chart.map('x', axisMap[categoryAxis], axisScale[categoryAxis]); 37943 37944 chart.coord(dv.coord.polar().flip(true).innerRadius(radius)) 37945 .guide(['x', 'y'], 'none') 37946 .position('fill'); 37947 }; 37948 37949 switch (chartType) { 37950 case CHART_TYPE.LINE: 37951 lineCommon(); 37952 chartLayers.push(chartLine); 37953 break; 37954 case CHART_TYPE.POINT: 37955 lineCommon(); 37956 chartLayers.push(chartPoint); 37957 break; 37958 case CHART_TYPE.AREA: 37959 lineCommon(); 37960 chartLayers.push(chartLine); 37961 chartLayers.push(chartArea); 37962 break; 37963 case CHART_TYPE.LINE_POINT: 37964 lineCommon(); 37965 chartLayers.push(chartPoint); 37966 chartLayers.push(chartLine); 37967 break; 37968 case CHART_TYPE.BAR: 37969 barCommon(); 37970 break; 37971 case CHART_TYPE.COLUMN: 37972 columnCommon(); 37973 break; 37974 case CHART_TYPE.PIE: 37975 pieCommon(0); 37976 break; 37977 case CHART_TYPE.DONUT: 37978 pieCommon(innerRadius); 37979 break; 37980 } 37981 37982 chart.layers(chartLayers); 37983 chart.data(dataToFill) 37984 .width(chartModel.width + '%') 37985 .height(chartModel.height) 37986 .parent("#" + $chartElement.attr('id')) 37987 .padding({"left" : 10, "top" : 10, "right" : 10, "bottom" : 10}); 37988 37989 if (GuideUtil.isChartAxisTitleApplicable(chartType)) { 37990 chart.guide('x', dv.guide.axis().title(chartModel.xAxisTitle)) 37991 .guide('y', dv.guide.axis().title(chartModel.yAxisTitle)); 37992 } 37993 37994 if (GuideUtil.isChartLegendApplicable(chartType) && showLegends) { 37995 chart.guide('fill', dv.guide.legend().orientation(legendPosition)); 37996 } 37997 } catch (exception) { 37998 window.guideBridge._guide.logger().log("Error while constructing chart " + exception); 37999 } 38000 return chart; 38001 }, 38002 38003 _setProp : function (object, prop, value) { 38004 if (object.constructor == {}.constructor && !_.isEmpty(value)) { 38005 object[prop] = value; 38006 } 38007 return object; 38008 }, 38009 38010 /** 38011 * Retrieves Repeatable Instances using liveDataUtils API for the given 38012 * repeatablePath. This API internally handles naked/non-naked case. 38013 * 38014 * @param repeatablePath 38015 * @param data 38016 * @return Repeatable Instances for the given repeatablePath using liveDataUtils. 38017 * 38018 * TODO Move this API to data utils. 38019 */ 38020 _getRepeatableInstances : function (repeatablePath, data, chartModel) { 38021 var liveDataUtils = chartModel._guide().internal.liveDataUtils, 38022 liveData = data ? data : liveDataUtils._liveDataDoc, 38023 xpath = ""; 38024 38025 if (_.isEmpty(liveData) || _.isEmpty(repeatablePath)) { 38026 return; 38027 } 38028 38029 if (!_.isEmpty(liveData.afData)) {//Non-Naked data case 38030 liveData = liveData.afData; 38031 xpath = liveDataUtils.constants.BOUND_DATA_XPATH; 38032 } else {//Naked data case or multiple series case 38033 repeatablePath = repeatablePath.substring(1, repeatablePath.length); 38034 } 38035 38036 //Find the repeatable instances. 38037 repeatableInstances = liveDataUtils._getElement(liveData, xpath + repeatablePath); 38038 38039 return repeatableInstances; 38040 } 38041 }; 38042}($, guidelib, _)); 38043 38044//Poly-filling request animation frame function for IE 9 38045(function () { 38046 var lastFramePaintTime = 0; 38047 if (!window.requestAnimationFrame) { 38048 window.requestAnimationFrame = function (callback, element) { 38049 var currTime = new Date().getTime(), 38050 timeToCall = Math.max(0, 16 - (currTime - lastFramePaintTime)), //16-16 frames per second 38051 id = window.setTimeout(function () { 38052 callback(currTime + timeToCall); 38053 }, timeToCall); 38054 lastFramePaintTime = currTime + timeToCall; 38055 return id; 38056 }; 38057 } 38058 38059 if (!window.cancelAnimationFrame) { 38060 window.cancelAnimationFrame = function (id) { 38061 clearTimeout(id); 38062 }; 38063 } 38064}()); 38065 38066/* 38067 * *********************************************************************** 38068 * ADOBE CONFIDENTIAL 38069 * __________________ 38070 * 38071 * Copyright 2015 Adobe Systems Incorporated 38072 * All Rights Reserved. 38073 *
38074 * NOTICE: All information contained herein is, and remains 38075 * the property of Adobe Systems Incorporated and its suppliers, 38076 * if any. The intellectual and technical concepts contained 38077 * herein are proprietary to Adobe Systems Incorporated and its 38078 * suppliers and may be covered by U.S. and Foreign Patents, 38079 * patents in process, and are protected by trade secret or copyright law. 38080 * Dissemination of this information or reproduction of this material 38081 * is strictly forbidden unless prior written permission is obtained 38082 * from Adobe Systems Incorporated. 38083 * *********************************************************************** 38084 */ 38085 38086(function ($, guidelib, xfalib, _) { 38087 var errorHandler = function (jqXHR) { 38088 var errorPayload; 38089 38090 // Actually we need clean-up old data but its not even happening in case of success with empty data 38091 // Running output mapping with empty result set to ensure old data is cleared 38092 38093 if (jqXHR.responseText) { 38094 var inputMapping = this.inputMapping; 38095 try { 38096 errorPayload = JSON.parse(jqXHR.responseText); 38097 } catch (error) { 38098 // result should be json if its not wel formed json or empty then ignoring it 38099 } 38100 if(errorPayload && errorPayload.errors) { 38101 38102 // Iterating over violations received and set it at field level using input mapping provided. 38103 var violations = errorPayload.errors; 38104 $.each(violations, function (i, violation) { 38105 if(violation && violation.bindRef && violation.errorMessages) { 38106 var key = violation.bindRef.slice(1).split("/").join("."); 38107 var field = inputMapping[key]; 38108 if (field) { 38109 field.markAsInvalid(violation.errorMessages.join("\n")); 38110 } 38111 } 38112 }); 38113 } 38114 } 38115 // Invoke author register error handler (if any) 38116 if(this.customErrorHandler) { 38117 this.customErrorHandler.call(this, jqXHR, errorPayload); 38118 } 38119 }; 38120 38121 var defaultErrorHandler = function (responseJson, headerMap) { 38122 if (responseJson) { 38123 if (responseJson && responseJson.validationErrors) { 38124 var violations = responseJson.validationErrors; 38125 $.each(violations, function (key, violation) { 38126 if (violation && violation.details && (violation.fieldName || violation.dataRef)) { 38127 if (!window.guideBridge._guide._bindRefMap || Object.keys(window.guideBridge._guide._bindRefMap).length === 0) { 38128 window.guideBridge._populateBindRefToSomMap(); 38129 } 38130 var som = (violation.fieldName) ? violation.fieldName : window.guideBridge._guide._bindRefMap[violation.dataRef]; 38131 var field = window.guideBridge.resolveNode(som); 38132 if (field) { 38133 field.markAsInvalid(violation.details.join("\n")); 38134 } 38135 } 38136 }); 38137 } 38138 } 38139 }; 38140 38141 var defaultErrorHandlerWrapper = function(jqXHR) { 38142 if (jqXHR.responseText) { 38143 try { 38144 responseJson = JSON.parse(jqXHR.responseText); 38145 } catch (error) { 38146 // result should be json if its not well formed json or empty then ignoring it 38147 } 38148 } 38149 38150 var headers = jqXHR.getAllResponseHeaders(); 38151 38152 // Convert the header string into an array 38153 // of individual headers 38154 var arr = headers.trim().split(/[\r\n]+/); 38155 38156 // Create a map of header names to values 38157 var headerMap = {}; 38158 arr.forEach(function (line) { 38159 var parts = line.split(': '); 38160 var header = parts.shift(); 38161 var value = parts.join(': '); 38162 headerMap[header] = value; 38163 }); 38164 38165 if (this.customErrorHandler === "guidelib.dataIntegrationUtils.defaultErrorHandler") { 38166 defaultErrorHandler(responseJson, headerMap); 38167 } else { 38168 if(this.customErrorHandler) { 38169 this.customErrorHandler.call(this, responseJson, headerMap); 38170 } 38171 } 38172 } 38173 38174 // Counts the number of Array(repeatable) in the output JSON of the WSDL. 38175 var outputJsonRepeatCount = function (wsdlOutputId, outputJSONObj) { 38176 var count = 0, 38177 wsdlOutputHierarchy = wsdlOutputId.split("."); 38178 if (Array.isArray(outputJSONObj)) { 38179 count++; 38180 outputJSONObj = outputJSONObj[0]; 38181 } 38182 $.each(wsdlOutputHierarchy, function (depth) { 38183 if (outputJSONObj) { 38184 outputJSONObj = outputJSONObj[wsdlOutputHierarchy[depth]]; 38185 if (Array.isArray(outputJSONObj)) { 38186 count++; 38187 outputJSONObj = outputJSONObj[0]; 38188 } 38189 } 38190 }); 38191 return count; 38192 }; 38193 38194 //Traversing to the highest repeatable field in hierarchy as a starting point. 38195 var outputRepeatAncestor = function (targetNode, repeatCount, targetNameHierarchy) { 38196 while (repeatCount > 0) { 38197 if (_.isNull(targetNode.parent)) { 38198 return targetNode;
38199 } 38200 targetNameHierarchy.push(targetNode.name); 38201 targetNode = targetNode.parent; 38202 if (targetNode.repeatable) { 38203 repeatCount--; 38204 } 38205 } 38206 return targetNode; 38207 }; 38208 38209 /** 38210 * Extract value of a hierarchy of properties 38211 * from a nested javascript object. 38212 * @param {Object} obj Nested javascript object 38213 * @param {Array|String} props list of properties 38214 * or dot separated string from root to leaf object 38215 * @return {Array} return list of values found 38216 */ 38217 function extractValues(obj, props) { 38218 // handle easy cases 38219 if (obj === null || typeof(obj) === "undefined") { 38220 return []; 38221 } 38222 if (typeof(props) == "string") { 38223 props = props.split("."); 38224 } 38225 if (props.length == 0) { 38226 return [obj]; 38227 } 38228 var ret = []; 38229 if (obj instanceof Array) { 38230 for (var i = 0; i < obj.length; i++) { 38231 ret = ret.concat(extractValues(obj[i], props)); 38232 } 38233 return ret; 38234 } 38235 if (!obj.hasOwnProperty(props[0])) { 38236 return []; 38237 } 38238 // handle actual case now 38239 38240 var key = props[0]; 38241 var remainingKeys = props.slice(1); 38242 var values = obj[key]; 38243 if (!(values instanceof Array)) { 38244 values = [values]; 38245 } 38246 for (var x = 0; x < values.length; x++) { 38247 ret = ret.concat(extractValues(values[x], remainingKeys)); 38248 } 38249 return ret; 38250 } 38251 //Maps the output JSON(outputJSONObj) to the Model(targetNode) 38252 var outputJsonMapping = function (wsdlOutputId, targetNode, targetNameHierarchy, outputJSONObj) { 38253 if (targetNameHierarchy.length === 0) { 38254 targetNode.value = xfalib.ut.XfaUtil.prototype.getOrElse(outputJSONObj, wsdlOutputId, ""); 38255 return; 38256 } 38257 var targetName = targetNameHierarchy.pop(); 38258 if (targetNode.repeatable) { 38259 //Gets respective array for this repeatable field. 38260 while (typeof outputJSONObj === "object" && !Array.isArray(outputJSONObj)) { 38261 var argsIndex = wsdlOutputId.indexOf('.'); 38262 outputJSONObj = outputJSONObj[wsdlOutputId.substring(0, argsIndex)] || ""; 38263 wsdlOutputId = wsdlOutputId.substring(argsIndex + 1); 38264 } 38265 //Adjust the number of instances to the number of array elements. 38266 var jsonLength = outputJSONObj.length, 38267 instanceCount = targetNode.instanceManager.instanceCount; 38268 if (instanceCount < jsonLength) { 38269 targetNode.instanceManager.addInstances({ 38270 instanceCount : jsonLength 38271 }); 38272 } 38273 //Check as "" might occur too for incorrect mappings. 38274 if (Array.isArray(outputJSONObj)) { 38275 //Recursive call for every instance with corresponding value. 38276 $.each(outputJSONObj, function (index) { 38277 // if the output from external API call contains more records, than the number 38278 // of instances present, return 38279 if (index >= targetNode.instanceManager.instanceCount) { 38280 return false; 38281 } 38282 targetNode = targetNode.instanceManager.instances[index]; 38283 outputJsonMapping(wsdlOutputId, targetNode[targetName], targetNameHierarchy, outputJSONObj[index]); 38284 }); 38285 } 38286 } else { 38287 //Recursive call down the hierarchy. 38288 outputJsonMapping(wsdlOutputId, targetNode[targetName], targetNameHierarchy, outputJSONObj); 38289 } 38290 //Pushing back the hierarchy for next instance if any. 38291 targetNameHierarchy.push(targetName); 38292 }; 38293 38294 var populateWsdlOutput = function (wsdlOutput, textStatus, jqXHR) { 38295 if (wsdlOutput == null || wsdlOutput.length == 0) { 38296 return; 38297 } 38298 38299 var origOutputJSONObj, 38300 outputMappingObj = this.callbackData; 38301 try { 38302 origOutputJSONObj = JSON.parse(wsdlOutput); 38303 } catch (e) { 38304 //Handling primitive output 38305 origOutputJSONObj = {"response" : wsdlOutput}; 38306 } 38307 38308 /* For each entry in outputMappingObj, we need to find the corresponding value in responseObj. 38309 * wsdlOutputId - wsdlOutput hierarchy, targetNode - field in the form whose value is to be set. 38310 * e.g. {ipinfo.ip, txtfield} */ 38311 $.each(outputMappingObj, function (wsdlOutputId, targetNode) { 38312 /* Gets value in outputJSONObj corresponding to targetNode. 38313 * First, It counts the number of Array in hierarchy as repeatCount. 38314 * Next, targetNode is taken to the starting point for traversal. 38315 * It's the topmost repeatable node in hierarchy. 38316 * Lastly, The outputJson is mapped to the TargetNode.*/ 38317 var repeatCount = outputJsonRepeatCount(wsdlOutputId, origOutputJSONObj), 38318 targetNameHierarchy = [], 38319 targetNode = outputRepeatAncestor(targetNode, repeatCount, targetNameHierarchy); 38320 outputJsonMapping(wsdlOutputId, targetNode, targetNameHierarchy, origOutputJSONObj); 38321 }); 38322 window.guideBridge._guide.runPendingExpressions(); 38323 }; 38324 38325 /** 38326 * Create and set items to dropdown field from wsdl response. 38327 * @this {Object} is of form {callbackData:data} 38328 */ 38329 function setOptionsCallback(wsdlOutput) { 38330 var cbData = this.callbackData; 38331 var options = []; 38332 if (!_.isEmpty(wsdlOutput)) { 38333 var wsdlOutputObj = JSON.parse(wsdlOutput); 38334 var savedValues = extractValues(wsdlOutputObj, cbData.savedValue); 38335 var displayedValues = extractValues(wsdlOutputObj, cbData.displayedValue); 38336 for (var i = 0; i < savedValues.length; i++) {
38337 options.push(savedValues[i] + "=" + displayedValues[i]); 38338 } 38339 } 38340 cbData.field.items = options; 38341 } 38342 38343 function setValueCallback(wsdlOutput) { 38344 var cbData = this.callbackData; 38345 var wsdlOutputObj = JSON.parse(wsdlOutput); 38346 cbData.field.value = extractValues(wsdlOutputObj, cbData.value); 38347 } 38348 38349 function appendLoadingIcon() { 38350 $("#loadingPage").addClass("guideServiceLoading"); 38351 } 38352 38353 function removeLoadingIcon() { 38354 $("#loadingPage").removeClass("guideServiceLoading"); 38355 } 38356 38357 function executeOperationInternal (wsdlInfoObj, jsonInputMappingObj, jsonOutputMappingObj, processOutputCallback, customErrorHandler, model, defaultErrorHandler, apiVersion) { 38358 // populate operationDetails object 38359 var successHandler = processOutputCallback || populateWsdlOutput; 38360 var wsdlInputObj = {}; 38361 38362 /* Iterate through the jsonInputMapping and create the input object. 38363 * wsdlInputId - wsdlInput hierarchy, targetNode - field in the form whose value is to be retrieved.*/ 38364 $.each(jsonInputMappingObj, function (wsdlInputId, targetNode) { 38365 var argsHierarchy = wsdlInputId.split("."), 38366 wsdlArgObj = wsdlInputObj, 38367 argDepth, 38368 valueToBeAssigned; 38369 38370 for (argDepth = 0; argDepth < argsHierarchy.length - 1; argDepth++) { 38371 wsdlArgObj[argsHierarchy[argDepth]] = wsdlArgObj[argsHierarchy[argDepth]] || {}; 38372 wsdlArgObj = wsdlArgObj[argsHierarchy[argDepth]]; 38373 } 38374 // assign the value of targetNode 38375 if (typeof targetNode === "object") { 38376 valueToBeAssigned = targetNode.value; 38377 } else { 38378 valueToBeAssigned = targetNode; 38379 } 38380 wsdlArgObj[argsHierarchy[argDepth]] = valueToBeAssigned; 38381 }); 38382 38383 var wsdlEndPoint = wsdlInfoObj.wsdlEndPoint, 38384 operationDetails = {}; 38385 operationDetails.operationName = wsdlInfoObj.operationName; 38386 operationDetails.input = JSON.stringify(wsdlInputObj); 38387 operationDetails.port = wsdlInfoObj.port; 38388 operationDetails.soapActionURI = wsdlInfoObj.soapActionURI; 38389 operationDetails.namespace = wsdlInfoObj.namespace; 38390 operationDetails.inputRoot = wsdlInfoObj.inputRoot; 38391 operationDetails.inputAttr = JSON.stringify(wsdlInfoObj.inputAttr); 38392 operationDetails.serviceEndPoint = wsdlInfoObj.serviceEndPoint; 38393 if (!model) { 38394 console.log("No model parameter passed to this API, this may fail during server side re-validation. Please correct your scripts."); 38395 } 38396 // TODO: this needs to be fixed, this API does not have access to guideContext but would execute in context of AF always 38397 var guide = model && model._guide && model._guide(); 38398 var wsdlServletURL = ((guide ? guide.jcrPath : guidelib.__runtime__.guide.jcrPath) + ".af.dermis"); 38399 var externalizedWSDLServletURL; 38400 if (guideBridge != null) { 38401 externalizedWSDLServletURL = guideBridge._getUrl(wsdlServletURL); 38402 } else { 38403 externalizedWSDLServletURL = Granite.HTTP.externalize(wsdlServletURL); 38404 } 38405 38406 var invokeData = {}; 38407 if (wsdlInfoObj.wsdlEndPoint) { 38408 invokeData.functionToExecute = 'invokeWsdlOperation'; 38409 invokeData.wsdlEndPoint = wsdlEndPoint; 38410 invokeData.operationName = operationDetails.operationName; 38411 invokeData.input = operationDetails.input; 38412 38413 if (operationDetails.port) { 38414 invokeData.port = operationDetails.port; 38415 } 38416 if (operationDetails.soapActionURI) { 38417 invokeData.soapActionURI = operationDetails.soapActionURI; 38418 } 38419 if (operationDetails.namespace) { 38420 invokeData.namespace = operationDetails.namespace; 38421 } 38422 if (operationDetails.inputRoot) { 38423 invokeData.inputRoot = operationDetails.inputRoot; 38424 } 38425 if (operationDetails.inputAttr) {
38426 invokeData.inputAttr = operationDetails.inputAttr; 38427 } 38428 if (operationDetails.serviceEndPoint) { 38429 invokeData.serviceEndPoint = operationDetails.serviceEndPoint; 38430 } 38431 } else if (wsdlInfoObj.formDataModelId) { 38432 invokeData.functionToExecute = 'invokeFDMOperation'; 38433 invokeData.formDataModelId = wsdlInfoObj.formDataModelId; 38434 invokeData.input = JSON.stringify(wsdlInputObj); 38435 invokeData.operationName = wsdlInfoObj.operationName; 38436 invokeData.runValidation = wsdlInfoObj.runValidation; 38437 invokeData.apiVersion = apiVersion; 38438 if (wsdlInfoObj.schemaRef) { 38439 invokeData.schemaRef = wsdlInfoObj.schemaRef; 38440 } 38441 if (wsdlInfoObj.schemaType) { 38442 invokeData.schemaType = wsdlInfoObj.schemaType; 38443 } 38444 } 38445 invokeData.guideNodePath = guide ? guide._currentContext.contextNode.jcrPath : guidelib.__runtime__.guide._currentContext.contextNode.jcrPath; 38446 38447 $.ajax({ 38448 type : 'POST', 38449 url : externalizedWSDLServletURL, 38450 data : invokeData, 38451 beforeSend : appendLoadingIcon, 38452 complete : removeLoadingIcon, 38453 dataType : 'text', 38454 success : successHandler, 38455 error : defaultErrorHandler, 38456 context : {callbackData : jsonOutputMappingObj, inputMapping: jsonInputMappingObj, customErrorHandler: customErrorHandler} 38457 }); 38458 } 38459 38460 var DataIntegrationUtils = guidelib.dataIntegrationUtils = { 38461 38462 setOptionsFromService : function (wsdlInfoObj, jsonInputMapping, jsonOutputMapping) { 38463 this.executeOperation(wsdlInfoObj, jsonInputMapping, jsonOutputMapping, setOptionsCallback); 38464 return jsonOutputMapping.field.items; 38465 }, 38466 38467 setValueFromService : function (wsdlInfoObj, jsonInputMapping, jsonOutputMapping) { 38468 this.executeOperation(wsdlInfoObj, jsonInputMapping, jsonOutputMapping, setValueCallback); 38469 return jsonOutputMapping.field.items; 38470 }, 38471 38472 /** 38473 * @deprecated 38474 */ 38475 executeOperation : function (wsdlInfoObj, jsonInputMappingObj, jsonOutputMappingObj, processOutputCallback, customErrorHandler, model) { 38476 var defaultErrorHandler = errorHandler; 38477 executeOperationInternal(wsdlInfoObj, jsonInputMappingObj, jsonOutputMappingObj, processOutputCallback, customErrorHandler, model, defaultErrorHandler); 38478 }, 38479 38480 executeOperationV2 : function (wsdlInfoObj, jsonInputMappingObj, jsonOutputMappingObj, processOutputCallback, customErrorHandler, model) { 38481 var defaultErrorHandler = defaultErrorHandlerWrapper; 38482 var apiVersion = "2"; 38483 executeOperationInternal(wsdlInfoObj, jsonInputMappingObj, jsonOutputMappingObj, processOutputCallback, customErrorHandler, model, defaultErrorHandler, apiVersion); 38484 }, 38485 38486 defaultErrorHandler : defaultErrorHandler 38487 }; 38488 38489 var WsdlUtils = guidelib.wsdlUtils = { 38490 /** 38491 * Internal API, called for invoking webservice and setting items in a drop down 38492 */ 38493 setOptionsFromWSDL : function (wsdlInfoObj, jsonInputMapping, jsonOutputMapping) { 38494 DataIntegrationUtils.executeOperation(wsdlInfoObj, jsonInputMapping, jsonOutputMapping, setOptionsCallback); 38495 return jsonOutputMapping.field.items; 38496 }, 38497 38498 setValueFromWSDL : function (wsdlInfoObj, jsonInputMapping, jsonOutputMapping) { 38499 DataIntegrationUtils.executeOperation(wsdlInfoObj, jsonInputMapping, jsonOutputMapping, setValueCallback); 38500 return jsonOutputMapping.field.items; 38501 }, 38502 38503 executeWSDLFunction : function (wsdlInfoObj, jsonInputMappingObj, jsonOutputMappingObj) { 38504 // populate operationDetails object 38505 DataIntegrationUtils.executeOperation(wsdlInfoObj, jsonInputMappingObj, jsonOutputMappingObj); 38506 } 38507 }; 38508}($, guidelib, xfalib, _)); 38509 38510/* 38511 * *********************************************************************** 38512 * ADOBE CONFIDENTIAL 38513 * __________________ 38514 * 38515 * Copyright 2015 Adobe Systems Incorporated 38516 * All Rights Reserved. 38517 *
38518 * NOTICE: All information contained herein is, and remains 38519 * the property of Adobe Systems Incorporated and its suppliers, 38520 * if any. The intellectual and technical concepts contained 38521 * herein are proprietary to Adobe Systems Incorporated and its 38522 * suppliers and may be covered by U.S. and Foreign Patents, 38523 * patents in process, and are protected by trade secret or copyright law. 38524 * Dissemination of this information or reproduction of this material 38525 * is strictly forbidden unless prior written permission is obtained 38526 * from Adobe Systems Incorporated. 38527 * *********************************************************************** 38528 */ 38529 38530/** 38531 * @package guidelib.model.GuideDirtyMarkerAndVisitor 38532 * @version 0.0.1 38533 */ 38534 38535(function ($, _, guidelib) { 38536 var GuideDirtyMarkerAndVisitor = guidelib.model.GuideDirtyMarkerAndVisitor = xfalib.ut.EventClass.extend({ 38537 38538 initialize : function() { 38539 // need to save the map while save and restore - will do it in getGuideState 38540 this.visitMap = {}; 38541 }, 38542 /** 38543 * Return a list of dirty children 38544 * @returns {Array} 38545 * @private 38546 */ 38547 _flattenDirtyPanelToList : function () { 38548 var csv = this.flattenDirtyPanelMapToCSV(); 38549 if (csv.length > 0) { 38550 return csv.split(","); 38551 } 38552 }, 38553 /** 38554 * If any dirty element then save it to CSV 38555 */ 38556 flattenDirtyPanelMapToCSV : function () { 38557 var listOfDirtyPanels = ""; 38558 _.each(_.keys(this.visitMap), function (key, index) { 38559 if (this.visitMap[key] === 0) { 38560 listOfDirtyPanels += key + ","; 38561 } 38562 }, this); 38563 if (listOfDirtyPanels.length > 0) { 38564 // strip last , 38565 listOfDirtyPanels = listOfDirtyPanels.substring(0, listOfDirtyPanels.length - 1); 38566 } 38567 return listOfDirtyPanels; 38568 }, 38569 /** 38570 * This method finds and marks dirty all the lazy children that were dependant of global field's value 38571 * @param mapOfLazyChildren 38572 * @param listOfIdsOfDependents 38573 * @private 38574 */ 38575 _findAndMarkDirty : function (mapOfLazyChildren, listOfIdsOfDependents) { 38576 var listOfLazyChildren = _.keys(mapOfLazyChildren); 38577 38578 _.each(listOfIdsOfDependents, function (depenId, index) { 38579 var longestPrefixLenSoFar = 0, 38580 currentPrefixLen = 0, 38581 nearestLazyId = null, 38582 i; 38583 // find hierarchically closest field by matching longest som prefix 38584 for (i = 0; i < listOfLazyChildren.length; ++i) { 38585 currentPrefixLen = guidelib.util.GuideUtil.commonPrefixLen(depenId, listOfLazyChildren[i]); 38586 if (longestPrefixLenSoFar < currentPrefixLen) { 38587 longestPrefixLenSoFar = currentPrefixLen; 38588 nearestLazyId = listOfLazyChildren[i]; 38589 } 38590 } 38591 // Mark dirty 38592 if (longestPrefixLenSoFar > 0) { 38593 mapOfLazyChildren[nearestLazyId] = 0; 38594 } 38595 }); 38596 }, 38597 /** 38598 * Iterates a map and finds the first occurrence of value found in any key 38599 * @param map 38600 * @param value 38601 */ 38602 _iterateMapAndReturnKeyOnValueFound : function (map, value) { 38603 var keyToReturn; 38604 _.each(_.keys(map), function (key, index) { 38605 if (map[key] === value) { 38606 keyToReturn = key; 38607 } 38608 }); 38609 return keyToReturn; 38610 }, 38611 /** 38612 * Updates the value of the key in map by one if present otherwise puts the key with value zero 38613 * @param map 38614 * @param key 38615 * @returns {*} 38616 */ 38617 _updateCountOrInsert : function (map, key) { 38618 if (_.isUndefined(map[key])) { 38619 map[key] = 0; 38620 } else { 38621 map[key]++; 38622 } 38623 38624 return map; 38625 } 38626 }); 38627 38628}($, _, window.guidelib)); 38629 38630/* 38631 * *********************************************************************** 38632 * ADOBE CONFIDENTIAL 38633 * __________________ 38634 * 38635 * Copyright 2016 Adobe Systems Incorporated 38636 * All Rights Reserved. 38637 *
38638 * NOTICE: All information contained herein is, and remains 38639 * the property of Adobe Systems Incorporated and its suppliers, 38640 * if any. The intellectual and technical concepts contained 38641 * herein are proprietary to Adobe Systems Incorporated and its 38642 * suppliers and may be covered by U.S. and Foreign Patents, 38643 * patents in process, and are protected by trade secret or copyright law. 38644 * Dissemination of this information or reproduction of this material 38645 * is strictly forbidden unless prior written permission is obtained 38646 * from Adobe Systems Incorporated. 38647 * *********************************************************************** 38648 */ 38649 38650(function ($) { 38651 //Firing resize as, CSS is loaded after table mobile layout, cell width is adjusted for repeatable row, to accommodate +, - controls 38652 $(function () { 38653 $(window).trigger('resize'); 38654 }); 38655}($));
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.