vendor: 2,088 bytes, lines 1-58
1/* 2 * *********************************************************************** 3 * ADOBE CONFIDENTIAL 4 * __________________ 5 * 6 * Copyright 2015 Adobe Systems Incorporated 7 * All Rights Reserved. 8 * 9 * NOTICE: All information contained herein is, and remains 10 * the property of Adobe Systems Incorporated and its suppliers, 11 * if any. The intellectual and technical concepts contained 12 * herein are proprietary to Adobe Systems Incorporated and its 13 * suppliers and may be covered by U.S. and Foreign Patents, 14 * patents in process, and are protected by trade secret or copyright law. 15 * Dissemination of this information or reproduction of this material 16 * is strictly forbidden unless prior written permission is obtained 17 * from Adobe Systems Incorporated. 18 * *********************************************************************** 19 */ 20 21(function ($) { 22 $.uaMatch = function( ua ) { 23 ua = ua.toLowerCase(); 24 var match = /(chrome)[ \/]([\w.]+)/.exec( ua ) || 25 /(webkit)[ \/]([\w.]+)/.exec( ua ) || 26 /(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) || 27 /(msie) ([\w.]+)/.exec( ua ) || 28 ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) || []; 29 return { 30 browser: match[ 1 ] || "", 31 version: match[ 2 ] || "0" 32 }; 33 }; 34 // Not clobbering any existing $.browser 35 if ( !$.browser ) { 36 var 37 matched = $.uaMatch( navigator.userAgent ), 38 browser = {}; 39 if ( matched.browser ) { 40 browser[ matched.browser ] = true; 41 browser.version = matched.version; 42 } 43 // Chrome is Webkit, but Webkit is also Safari. 44 if ( browser.chrome ) { 45 browser.webkit = true; 46 } else if ( browser.webkit ) { 47 browser.safari = true; 48 } 49 $.browser = browser; 50 } 51})($); 52/************************************************************************* 53 * ADOBE CONFIDENTIAL 54 * ___________________ 55 * 56 * Copyright 2013 Adobe Systems Incorporated 57 * All Rights Reserved. 58 *
59 * NOTICE: All information contained herein is, and remains 60 * the property of Adobe Systems Incorporated and its suppliers, 61 * if any. The intellectual and technical concepts contained 62 * herein are proprietary to Adobe Systems Incorporated and its 63 * suppliers and are protected by all applicable intellectual property 64 * laws, including trade secret and copyright laws. 65 * Dissemination of this information or reproduction of this material 66 * is strictly forbidden unless prior written permission is obtained 67 * from Adobe Systems Incorporated. 68 **************************************************************************/ 69 70 71/** 72 * @package xfalib.ut.Class 73 */ 74(function(_, xfalib){ 75 76 xfalib.ns = xfalib.ns || function (namespaceString) { 77 var parts = namespaceString.split('.'), 78 parent = window, 79 currentPart = ''; 80 81 for(var i = 0, length = parts.length; i < length; i++) { 82 currentPart = parts[i]; 83 parent[currentPart] = parent[currentPart] || {}; 84 parent = parent[currentPart]; 85 } 86 87 return parent; 88 }; 89 90 var Class = xfalib.ut.Class = function(options) { 91 this.options = _.extend({}, this.options, options); 92 if(!this.options.jsonModel) 93 this.options.jsonModel = {}; 94 //For perf reason, we are setting jsonModel as direct property instead of using property descriptor 95 this.jsonModel = this.options.jsonModel; 96 this.initialize.apply(this, arguments); 97 }; 98 99 _.extend(Class.prototype, { 100 initialize : function(){ 101 }, 102 103 xfaUtil :function(){ 104 return xfalib.ut.XfaUtil.prototype; 105 }, 106 107 copyArray : function(src,dst,options) { 108 var keepReference = this.getOrElse(options, "keepReference", true); 109 if(src instanceof Array) 110 { 111 for (var i = 0;i<src.length;i++) 112 { 113 var obj; 114 if(src[i] instanceof Array) 115 { 116 obj = this._createDestination(dst, i, keepReference, []); 117 this.copyArray(src[i],obj,options); 118 } 119 else if(typeof src[i] == "object") 120 { 121 obj = this._createDestination(dst, i, keepReference, {}); 122 this.copyObject(src[i],obj,options); 123 } else { 124 obj = src[i]; 125 } 126 dst[i] = obj; 127 } 128 if(dst.length > src.length){ 129 dst.splice(src.length, (dst.length - src.length)); //Remove ths rest of the extra destination items 130 } 131 } 132 }, 133 134 /** 135 * 136 * @param src 137 * @param dst 138 * @param options e.g. {keepReference: true, exceptions:["htmlId"], transformMaps: {"dataId", function(src, options){ return src "33"+src; }}} 139 */ 140 copyObject : function(src,dst,options) { 141 var keepReference = this.getOrElse(options, "keepReference", true); 142 var exceptions = this.getOrElse(options, "exceptions", []); 143 var transformMaps = this.getOrElse(options, "transformMaps", {}); 144 if(typeof src == "object") { 145 for (var child in src) { 146 if(exceptions.indexOf(child) == -1) { 147 if(src[child] instanceof Array) { 148 dst[child] = this._createDestination(dst, child, keepReference, []); 149 this.copyArray(src[child],dst[child],options); 150 } 151 else if(typeof src[child] == "object" && src[child] != null) { 152 dst[child] = this._createDestination(dst, child, keepReference, {}); 153 this.copyObject(src[child],dst[child],options); 154 } 155 else{ 156 if(!_.isUndefined(transformMaps[child])){ 157 dst[child] = transformMaps[child](src[child], options, src); 158 } 159 else 160 dst[child] = src[child]; 161 } 162 } 163 } 164 } 165 }, 166 167 _createDestination : function(obj, property, keepReference, defaultValue) { 168 if(!keepReference) 169 return defaultValue; 170 else if(_.isObject(obj) && !obj.hasOwnProperty(property)) 171 return defaultValue; 172 else 173 return obj[property] || defaultValue ; //Would handle both, Array and objects 174 }, 175 176 /** 177 * will replace functions in the object with noop function based on a predicate function's result. 178 * If no predicate is passed all functions will be disabled. 179 * Warning once disabled object cant be re-enabled. 180 * 181 * sample predicate to disable all 'public' functions : function (funcName) { return funcName[0] != '_'} 182 * 183 * @param predicate 184 * @private 185 */ 186 _disableFunctions: function (predicate) { 187 var noop = function () {}, 188 disableAll = !_.isFunction(predicate); 189 190 _.each(_.functions(this), function (funcName) { 191 if (disableAll || predicate(funcName)) { 192 this[funcName] = noop; 193 } 194 }, this); 195 }, 196 197 /** 198 * getOrElse can take multiple arguments. 199 * arg1(obj): base Object 200 * arg2: string representing property chain where properties are concatenated via dot 201 * arg3: default value 202 **/ 203 204 getOrElse : function(obj){ 205 var currObject = obj; 206 if(arguments.length < 2) 207 return currObject; 208 else if(arguments.length == 2) { 209 if(!_.isUndefined(currObject)){ 210 return currObject; 211 } else { 212 return _.clone(arguments[1]); 213 } 214 } 215 else { 216 var propChain = (arguments[1] || "").split("."); 217 var defaultValue = arguments[2]; 218 _.each(propChain, function(prop){ 219 if(_.isObject(currObject)) 220 currObject = currObject[prop]; 221 else 222 currObject = undefined; 223 }, this); 224 225 if(!_.isUndefined(currObject)) 226 return currObject; 227 else { 228 return _.clone(defaultValue) ; //May have to do deep clone in future. TODO: support for conditional clone 229 } 230 } 231 }, 232 233 jqId: function (id) { 234 return xfalib.ut.XfaUtil.prototype.jqId(id); 235 }, 236 237 logger : function(){ 238 return this.xfaUtil().getLogger(); 239 }, 240 241 validateInput : function(param, dataType,fallback){ 242 if(typeof param !== "undefined" && param !== null) { 243 switch(dataType) { 244 case "string": 245 param = param+""; 246 break; 247 case "object": 248 if(typeof param !== "object") 249 param = fallback; 250 break; 251 case "integer": 252 param = parseInt(param); 253 if(isNaN(param)) 254 param = fallback; 255 break; 256 case "measurement": 257 break; 258 default: 259 if(dataType instanceof Array) { 260 if(!~dataType.indexOf(param)) 261 param = fallback 262 } 263 } 264 } 265 return param; 266 } 267 268 }); 269 270 _.extend(Class, { 271 defineProps : function(propsMap){ 272 _.each(propsMap, function(propDesc, propName){ 273 //Check property can be resolved using resolveNode 274 if(propDesc.resolve) { 275 //Check whether prototype owns the object resolveProperties 276 if(!this.prototype.hasOwnProperty("resolveProperties")) { 277 //check whether prototype inherits the object resolveProperties 278 if(this.prototype.resolveProperties) { 279 //clone the object since we do not want to modify parent's prototype 280 this.prototype.resolveProperties = _.clone(this.prototype.resolveProperties); 281 } 282 else 283 this.prototype.resolveProperties = []; 284 } 285 this.prototype.resolveProperties.push(propName) 286 } 287 Object.defineProperty(this.prototype, propName, propDesc); 288 289 }, this); 290 }, 291 extend : function(props){ 292 var child = inherits(this, props); 293 child.extend = this.extend; 294 return child; 295 }, 296 addMixins : function(mixinBakers){ 297 if(!_.isArray(mixinBakers)){ 298 mixinBakers = [mixinBakers]; 299 } 300 _.each(mixinBakers, function(mixinBaker){ 301 if(mixinBaker.normalProperties){ 302 _.extend(this.prototype, mixinBaker.normalProperties); 303 } 304 if(mixinBaker.propertyDescriptors){ 305 this.defineProps(mixinBaker.propertyDescriptors); 306 } 307 }, this); 308 } 309 }); 310 311 // Shared empty constructor function to aid in prototype-chain creation. 312 var ctor = function(){}; 313 314 // Helper function to correctly set up the prototype chain, for subclasses. 315 // Similar to `goog.inherits`, but uses a hash of prototype properties and 316 // class properties to be extended. 317 function inherits(parent, protoProps, staticProps) { 318 var child; 319 var _super = parent.prototype; 320 // The constructor function for the new subclass is either defined by you 321 // (the "constructor" property in your `extend` definition), or defaulted 322 // by us to simply call the parent's constructor. 323 if (protoProps && protoProps.hasOwnProperty('constructor')) { 324 child = protoProps.constructor; 325 } else { 326 child = function(){ parent.apply(this, arguments); }; 327 } 328 329 // Inherit class (static) properties from parent. 330 _.extend(child, parent); 331 332 // Set the prototype chain to inherit from `parent`, without calling 333 // `parent`'s constructor function. 334 ctor.prototype = parent.prototype; 335 child.prototype = new ctor(); 336 child._super = parent.prototype; 337 child._superClass = parent; 338 339 // Add prototype properties (instance properties) to the subclass, 340 // if supplied.
341 if (protoProps) { //_.extend(child.prototype, protoProps); 342 // Copy the properties over onto the new prototype 343 for (var name in protoProps) { 344 if(name == "_defaults"){ 345 protoProps[name] = _.extend({}, _super[name], protoProps[name]); 346 } 347 child.prototype[name] = protoProps[name]; 348 } 349 } 350 351 352 // Add static properties to the constructor function, if supplied. 353 if (staticProps) _.extend(child, staticProps); 354 355 // Correctly set child's `prototype.constructor`. 356 child.prototype.constructor = child; 357 358 // Set a convenience property in case the parent's prototype is needed later. 359 child.__super__ = parent.prototype; 360 361 return child; 362 }; 363})(_, window.xfalib); 364/** 365 * Created by vdua on 2/18/2015. 366 */ 367(function (_, xfalib) { 368 var XMLUtils = { 369 dataSom2xpath: function (dataSom) { 370 var xpath = ""; 371 372 if (!_.isEmpty(dataSom)) { 373 // any dot preceded by ], takes care of dot-s in name, 374 // and remove constant prefix "xfa[0].datasets[0].data[0]" and form root name, then join using '/' 375 _.each(dataSom.split(/\]\./).slice(4), 376 function (part) { 377 var openBracketPos = part.lastIndexOf('['); 378 xpath += part.substring(0, openBracketPos + 1) + 379 (parseInt(part.substring(openBracketPos + 1)) + 1) + // increment index by 1 for xpath query 380 "]/"; 381 }); 382 383 if (_.isEmpty(xpath)) { 384 xpath = dataSom; 385 } else if (xpath[xpath.length - 1] === '/') { 386 xpath = xpath.slice(0, -1); 387 } 388 } 389 390 return xpath; 391 }, 392 393 /** 394 * Converts an xPathResult of type iterator to an array 395 * @param xPathResult 396 * @returns {Array} 397 */ 398 iteratorToArray: function (xPathResult) { 399 var result = []; 400 // in some browsers, if xpath is invalid xPath result is null whereas some browsers return XpathResult with empty iterator 401 var node = xPathResult ? xPathResult.iterateNext() : null; 402 while (node != null) { 403 result.push(node); 404 node = xPathResult.iterateNext(); 405 } 406 return result; 407 }, 408 /** 409 * Wrapper API for document.evaluate to provide cross-browser support. 410 * @param xpath 411 * @param node 412 * @param nsResolver 413 * @param resultType 414 * @param result 415 * @returns {Object|*} 416 */ 417 evaluateXPath: function (xpath, node, nsResolver, resultType, result) { 418 try { 419 if(_.isEmpty(xpath) || !_.isString(xpath) || !(node instanceof Node)) { 420 return null; 421 } 422 423 // Determine the appropriate document context for searching. 424 var searchContext = node instanceof Document ? node : node.ownerDocument; 425 // Check if the document.evaluate function is undefined or if we're in a server-side context. 426 var isEvaluateUndefined = typeof searchContext.evaluate === 'undefined'; 427 var isServerSide = window.guideBridge && window.guideBridge.hostName === "server"; 428 var needsXPathPolyfill = isEvaluateUndefined || isServerSide; 429 if (needsXPathPolyfill) { 430 // Install the wgxpath polyfill to provide evaluate functionality. 431 wgxpath.install(window, true); 432 // Assign the newly installed evaluate function to the search context. 433 searchContext.evaluate = window.document.evaluate; 434 } 435 436 var documentToEval = searchContext.evaluate ? searchContext : document; 437 xpath = this.sanitizeXPath(xpath); 438 439 return documentToEval.evaluate(xpath, node, nsResolver, resultType, result); 440 441 } catch (exception) { 442 xfalib.ut.XfaUtil.prototype.getLogger().error("Could not evaluate xpath: " + xpath + exception); 443 444 } 445 446 }, 447 /** 448 *Removes all [*] other than ['numeric'] from xpath 449 *@param xpath
450 *@returns xpath after removing "[*]" 451 */ 452 sanitizeXPath: function(xpath) { 453 var xpathArray=xpath.split("/"), 454 resultXpath = _.map(xpathArray, function (path) { 455 return path.replace(/\[(.*\D+.*)\]|\[\]/g,""); 456 }).join("/"); 457 return resultXpath; 458 }, 459 460 /** 461 * Creates all the Elements (if they don't exist) in the xpath leading to the node being searched for in the 462 * xpath relative to the element. Optionally creates the node as well if bParentsOnly is false 463 * @param xpath 464 * @param element 465 * @param bParentsOnly whether to create only the parents or the node as well 466 * @returns node that is being represented by the xpath relative to the element. 467 */ 468 createElementsFromXPath: function (xpath, element, bParentsOnly) { 469 if (xpath != null || element != null) { 470 var parts = xpath.split("/"), 471 actualParts = bParentsOnly ? _.initial(parts) : parts, 472 el = element; 473 _.each(actualParts, function (part, index) { 474 var som = part.match(/^([^[]+)(\[(\d+)\])?/), 475 childEl; 476 if (som == null) { 477 xfalib.ut.XfaUtil.prototype.getLogger().error("Unsupported expression in Bindref " + part); 478 return null; 479 } 480 //only the last element can be attribute 481 childEl = this.findOrCreateElement(part, el, index === actualParts.length - 1); 482 el = childEl; 483 }, this); 484 return el; 485 } 486 return null; 487 }, 488 489 /** 490 * Form an xpath part returns the index as well as the tagName. Index can be * as well 491 * @param xpathName 492 * @returns {*} 493 * @private 494 */ 495 _getElementNameAndIndexFromXPathPart: function (xpathName) { 496 var som = xpathName.match(/^([^[]+)(?:\[(\d+|\*)\])?/); 497 if (som !== null) { 498 return { 499 name: som[1], 500 index: som[2] || 0 501 }; 502 } 503 return null; 504 }, 505 506 /** 507 * create an element with the tagName elementName for the ownerDocument of element. 508 * @param elementName 509 * @param element 510 * @returns {HTMLElement} 511 */ 512 createElement: function (elementName, element) { 513 var el = element.ownerDocument.createElement(elementName); 514 return el; 515 }, 516 517 /** 518 * Searches for the nodeXpath relative to element. If it doesn't exists creates it and returns the node 519 * @param element 520 * @param nodeXpath 521 * @param bAttribute if true then check for attribute otherwise not. 522 * @returns {Node|*} 523 */ 524 findOrCreateElement: function (nodeXpath, element, bAttribute) { 525 try { 526 if (element == null) { 527 return null; 528 } 529 var result = this.evaluateXPath(nodeXpath, element, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null), 530 el = result.iterateNext(), 531 res; 532 if (el == null) { 533 res = this._getElementNameAndIndexFromXPathPart(nodeXpath); 534 if (res != null) { 535 if (bAttribute && res.name.match(/^@/)) { 536 var attrName = res.name.replace(/^@/, ""); 537 el = element.ownerDocument.createAttribute(attrName); 538 element.setAttributeNode(el); 539 } else { 540 el = element.ownerDocument.createElement(res.name); 541 element.appendChild(el); 542 } 543 } 544 } 545 return el; 546 547 } catch (exception) { 548 xfalib.ut.XfaUtil.prototype.getLogger().error("Following exception " 549 + "occurred while executing findOrCreateElement " + exception); 550 } 551 552 }, 553 554 /** 555 * Returns the Root Form Elment from the xmlDocumentElement 556 * @param xmlDocumentElement It can be a document or Element. If the root element is xdp element, it returns 557 * the grand grand child of that element. otherwise the root element is returned. The root 558 * Element can be either the element itself or documentElement of the element. 559 */ 560 getXFARootFormElementFromXML: function (xmlDocumentElement) { 561 if(_.isUndefined(document.evaluate)) { 562 wgxpath.install(); 563 } 564 var isElement = xmlDocumentElement instanceof Element, 565 docElemName = isElement ? xmlDocumentElement.nodeName : xmlDocumentElement.documentElement.nodeName, 566 rootElement = isElement ? xmlDocumentElement : xmlDocumentElement.documentElement, 567 nodeList; 568 569 if ("xdp:xdp" === docElemName || "xdp" === docElemName) { 570 if (xfalib.ut.XfaUtil.prototype.isIE()) { 571 //IE doesn't support evaluating namespace elements 572 var datasets = rootElement.firstElementChild, 573 data = datasets.firstElementChild; 574 rootElement = data.firstElementChild; 575 } else { 576 // assumption is that the xml will be of format <xdp><datasets><data><form1> 577 // TODO: change first * to xfa:datasets 578 nodeList = this.evaluateXPath("*/xfa:data/*", rootElement, formBridge.nsResolver, 579 XPathResult.ORDERED_NODE_ITERATOR_TYPE, null); 580 rootElement = nodeList.iterateNext(); 581 } 582 } 583 return rootElement; 584 }, 585 586 /**
587 * Returns an object containing the prefix and namespaces present in the rootElement. For default namespace the 588 * prefix is "_default" 589 * @param rootElement {Element} xml element which has to be looked for namespaces 590 * @returns {object} object whose keys are the prefix and values are the namespace 591 */ 592 getNamespaces: function (rootElement) { 593 var namespaces = { 594 "_default" : null 595 }; 596 _.each(rootElement.attributes, function (attr) { 597 var name = attr.name, 598 parsedAttrName = name.match(/^xmlns(?:\:(.*))?/), 599 isNamespace = parsedAttrName != null, 600 namespaceName = isNamespace ? parsedAttrName[1] || "_default" : null; 601 if (namespaceName) { 602 namespaces[namespaceName] = attr.value; 603 } 604 }); 605 return namespaces; 606 }, 607 608 /** 609 * Returns a namespace resolver given a element. The nsResolver returns the namespace given a prefix by 610 * using the namespaces mentioned in the element. 611 * @param rootElement element from which to create the nsResolver 612 * @returns {function} the function returns the namespace given a prefix. 613 */ 614 getNsResolver: function (rootElement) { 615 var namespaces = this.getNamespaces(rootElement), 616 nsResolver = (function (namespaces) { 617 return function (nsPrefix) { 618 var namespace = formBridge.nsResolver(nsPrefix) || namespaces[nsPrefix]; 619 return namespace; 620 }; 621 }(namespaces)); 622 return nsResolver; 623 }, 624 625 /** 626 * Removes default namespaces from xml, basically the namespace defined as xmlns="some namespace". The 627 * side-effect of the API is it removes the string "xmlns='some namespace'" from any attribute value as well. 628 * @param xml {string} 629 * @returns {string} 630 */ 631 removeDefaultNamespace: function (xml) { 632 var stringRegex = "(\\s+)" + // any number of spaces 633 "(xmlns=" + // then xmlns= 634 "('[^']*'|\"[^\"]*\"))" + // then value in single quotes ('[^']') or 635 // double quotes ("[^"]") 636 "(?=[^<>]*>)", // followed by closing tag (implies attribute) and before another 637 // opening tag(implies text) 638 regex = new RegExp(stringRegex, "g"); 639 return xml.replace(regex, "$1"); 640 } 641 }; 642 xfalib.ut.XMLUtils = XMLUtils; 643}(_, xfalib)); 644/** 645 * @package xfalib.ut.Logger 646 * @import xfalib.ut.Class 647 */ 648 649(function(_, xfalib, $){ 650 var categoryAcronyms = { 651 "a": "xfa", 652 "b": "xfaView", 653 "c": "xfaPerf" 654 }, 655 loggerTypes = ["off", "console", "server", "consoleServer"]; 656 var Logger = xfalib.ut.Logger = xfalib.ut.Class.extend({ 657 658// Count of log messages so far. 659 LOG_COUNT : { 660 level : { 661 "FATAL" : 0, 662 "ERROR" : 0, 663 "WARN" : 0, 664 "INFO" : 0, 665 "DEBUG" : 0, 666 "TRACE" : 0, 667 "ALL" : 0 668 }, 669 category : { 670 "xfa" : 0, 671 "xfaView" : 0, 672 "xfaPerf" : 0, 673 "Unknown" : 0 674 } 675 }, 676 677 /** 678 * Log level to turn logging off (default). 679 * @static 680 * @final 681 * @type Number 682 */ 683 OFF : 0, 684 685 /** 686 * Log level for fatal error messages. 687 * @static 688 * @final 689 * @type Number 690 */ 691 FATAL : 1, 692 693 /** 694 * Log level for error messages. 695 * @static 696 * @type Number 697 * @final 698 */ 699 ERROR : 2, 700 701 /** 702 * Log level for warning messages. 703 * @static 704 * @type Number 705 * @final 706 */ 707 WARN : 3, 708 709 /** 710 * Log level for info messages. 711 * @static 712 * @type Number 713 * @final 714 */ 715 INFO : 4, 716 717 /** 718 * Log level for debug messages. 719 * @static 720 * @type Number 721 * @final 722 */ 723 DEBUG : 5, 724 725 /** 726 * Log level for trace messages. 727 * @static 728 * @type Number 729 * @final 730 */ 731 TRACE : 6, 732 733 /** 734 * Log level for all messages. 735 * @static 736 * @type Number 737 * @final 738 */ 739 ALL : 7, 740 741 742 logLevelNames : ["OFF", "FATAL", "ERROR", "WARN", "INFO", "DEBUG", "TRACE", "ALL"], 743 744 initialize : function(){ 745 var str = "", 746 that =this; 747 Logger._super.initialize.call(this); 748 this.logs = {}; 749 this.logMessages = ""; 750 this.logServiceProxy = this.options.logServiceProxy; 751 this.contextPath = this.options.contextPath; 752 this.renderContext = this.options.renderContext;
753 if(this.jsonModel.logConfigString) { 754 _.extend(this.jsonModel, this.parse(this.jsonModel.logConfigString)); 755 } 756 _.each(this.jsonModel.category, function(category) { 757 that.LOG_COUNT.category[category] = 0; 758 }) 759 }, 760 761 /** 762 * parses a log config string of the form <0,1,2,3>-<category string><level integer>-<category string><level integer>.. 763 * and returns an a config object that logger uses. The function is a private and not to be called outside 764 * this function 765 * 766 * category can not contain numbers and only valid characters are a-zA-Z 767 * level can be any integer. 768 * 769 * category string is converted into actual category for the logger by using default categoryAcronyms 770 * [a : xfa, b: xfaView, c: xfaPerf} and the categoryAcronyms passed to the options while instantiating the 771 * object. If not found in both the acronyms then the value category string is used as actual category 772 * 773 * For example for the input string 1-a9-b9-c9 return object is 774 * {on: true, category: [xfa,xfaView, xfaPerf], level: [9, 9, 9], type: console} 775 * 776 * For the input string 1-a9-b9-c9-d9-e11 with options.categoryAcronyms {a:a, d:AF} return object is 777 * {on: true, category: [xfa,xfaView, xfaPerf, AF, e], level: [9, 9, 9, 9, 11], type: console} 778 */ 779 parse : function(configString) { 780 var arr = configString.split("-"), 781 logType = _.first(arr), 782 logConfig = _.rest(arr), 783 res = { 784 on: logType === "0" ? "false": "true", 785 category: [], 786 level:[], 787 type:loggerTypes[parseInt(logType)] 788 }; 789 _.each(logConfig, function(item, index) { 790 var config = item.match(/^([A-Za-z]+)(\d+)$/), 791 category; 792 if (config && config.length === 3) { 793 category = this.getOrElse(categoryAcronyms, config[1], 794 this.getOrElse(this.jsonModel, "categoryAcronyms." + config[1], config[1])); 795 res.category.push(category); 796 res.level.push(parseInt(config[2])); 797 } else { 798 //calling this because logger is not initialized as of now 799 this.consoleHandler(this.resolveMessage(xfalib.locale.LogMessages["ALC-FRM-901-020"], 800 [item, configString])) 801 } 802 }, this); 803 return res; 804 }, 805 806 /* 807 * 808 */ 809 resolveMessage : function(message, snippets) { 810 snippets = snippets || []; 811 return message.replace(/{(\d+)}/g, function(match, number) { 812 return typeof snippets[number] != 'undefined' 813 ? snippets[number] 814 : match 815 ; 816 }); 817 }, 818 819 /** 820 * Writes a message to the console. 821 * @private 822 * @param {Number} level The log level 823 * @param {String} message The log message 824 * @param {String/String[]} snippets (optional) The texts replacing 825 * <code>{n}</code> 826 * @return The log message
827 * @type String 828 */ 829 log : function(category, level, message, snippets) { 830 var d= new Date(); 831 var day = d.getDate(); 832 var month = d.getMonth() + 1; 833 var year = d.getFullYear(); 834 var mili = d.getMilliseconds(); 835 var sec = d.getSeconds(); 836 var min = d.getMinutes(); 837 var hour = d.getHours(); 838 var date = day + "." + month + "." + year +" " + hour + ":" + min + ":" + sec + ":" + mili; 839 if(this.jsonModel && this.jsonModel.category) { 840 for(var i = 0; i<this.jsonModel.category.length; i++) { 841 if (level != 0 && this.jsonModel.level[i] >= level && this.jsonModel.category[i] == category && this.jsonModel.on == "true") { 842 843 var resolvedMessage = message; 844 if(snippets){ 845 //resolve message with snippet 846 resolvedMessage = this.resolveMessage(message, snippets); 847 } 848 849 var text = ""; 850 text += date ; 851 text += " *" + this.logLevelNames[level] + "*"; 852 text += " [" + category + "]" ; 853 text += " " + resolvedMessage + "\r\n" ; 854 this.logMessages += text ; 855 if(this.jsonModel.type == "console" || this.jsonModel.type == "consoleServer" ) { 856 ++this.LOG_COUNT.category[category || 'Unknown']; 857 ++this.LOG_COUNT.level[this.logLevelNames[parseInt(level) < 8? level:7]]; 858 this.consoleHandler(text, level); 859 } 860 } 861 } 862 } 863 }, 864 865 consoleHandler : function(text, level){ 866 if(typeof console != "undefined") { 867 var levelName = typeof this.logLevelNames[level] === "string" 868 ? this.logLevelNames[level].toLowerCase() 869 : "log", 870 logFunction = console.log; 871 if (typeof console[levelName] === "function") { 872 logFunction = console[levelName] 873 } 874 logFunction.call(console, "\n\n\n" + text); 875 //Error log already shows the call stack for debugging. 876 if(levelName !== "error") { 877 try { 878 n.test 879 } catch (exception) { 880 if (exception.stack) { 881 logFunction.call(console, exception.stack.replace("ReferenceError: n is not defined", "")); 882 } 883 } 884 } 885 } 886 887 }, 888 889 /* 890 * Helper function to ger submit service proxy url 891 */ 892 _getLogServiceProxyUrl: function() { 893 var logServiceProxyUrl = ""; 894 if(this.logServiceProxy) 895 logServiceProxyUrl += this.logServiceProxy; 896 else //finally hard code it 897 logServiceProxyUrl += ((this.contextPath && this.contextPath != "/") ? this.contextPath : "") + "/content/xfaforms/profiles/default.log.html"; 898 return logServiceProxyUrl; 899 }, 900 901 _invokeAtServer: function(options) { 902 var localSubmitUrl = this._getLogServiceProxyUrl(); 903 var params = { 904 async: true, 905 url: localSubmitUrl, 906 type: 'POST', 907 contentType: 'application/x-www-form-urlencoded; charset=UTF-8', 908 data: options 909 }; 910 $.ajax(params); 911 }, 912 913 isServerLoggingEnabled : function(){ 914 if((this.jsonModel.on == "true") && (this.jsonModel.type == "server" || this.jsonModel.type == "consoleServer")) 915 return true; 916 else 917 return false; 918 }, 919 920 serverHandler :function() { 921 var options = {'logMessages' : this.logMessages, 'renderContext' : this.renderContext}; 922 this._invokeAtServer(options); 923 this.logMessages = "" ; 924 }, 925 926 /** 927 * Writes a message to the console if log level is set to 928 * {@link #FATAL} or higher. 929 * @static 930 * @param {String} message The log message 931 * @param {String/String[]} snippets (optional) The texts replacing 932 * <code>{n}</code> 933 */ 934 fatal : function(category, message, snippets) { 935 this.log(category, this.FATAL, message, snippets); 936 }, 937 938 /** 939 * Writes a message to the console if log level is set to 940 * {@link #ERROR} or higher. 941 * @static 942 * @param {String} message The log message 943 * @param {String/String[]} snippets (optional) The texts replacing 944 * <code>{n}</code> 945 */ 946 error : function(category, message, snippets) { 947 this.log(category, this.ERROR, message, snippets); 948 }, 949 950 /** 951 * Writes a message to the console if log level is set to 952 * {@link #WARN} or higher. 953 * @static 954 * @param {String} message The log message 955 * @param {String/String[]} snippets (optional) The texts replacing 956 * <code>{n}</code> 957 */ 958 warn : function(category, message, snippets) { 959 this.log(category, this.WARN, message, snippets); 960 }, 961 962 /** 963 * Writes a message to the console if log level is set to 964 * {@link #INFO} or higher. 965 * @static 966 * @param {String} message The log message 967 * @param {String/String[]} snippets (optional) The texts replacing 968 * <code>{n}</code> 969 */ 970 info : function(category, message, snippets) { 971 this.log(category, this.INFO, message, snippets); 972 }, 973 974 /** 975 * Writes a message to the console if log level is set to 976 * {@link #DEBUG} or higher. 977 * @static 978 * @param {String} message The log message 979 * @param {String/String[]} snippets (optional) The texts replacing 980 * <code>{n}</code> 981 */ 982 debug : function(category, message, snippets) { 983 this.log(category, this.DEBUG, message, snippets); 984 }, 985 986 /** 987 * Writes a message to the console if log level is set to 988 * {@link #TRACE} or higher. 989 * @static 990 * @param {String} message The log message 991 * @param {String/String[]} snippets (optional) The texts replacing 992 * <code>{n}</code> 993 */ 994 trace : function(category, message, snippets) { 995 this.log(category, this.TRACE, message, snippets); 996 }, 997 998 isLogEnabled : function(category, level) { 999 if(this.jsonModel.on == "true") { 1000 var pos = this.jsonModel.category.indexOf(category) ; 1001 if(this.jsonModel.level[pos] >= level) 1002 return true; 1003 } 1004 return false;
1005 } 1006 1007 }); 1008})(_, xfalib, $); 1009/** 1010 * @package xfalib.ut.EventClass 1011 * @import xfalib.ut.Class 1012 */ 1013(function(_, xfalib){ 1014 // Regular expression used to split event strings 1015 // Regular expression used to split event strings 1016 var eventSplitter = /\s+/; 1017 1018 // A module that can be mixed in to *any object* in order to provide it with 1019 // custom events. You may bind with `on` or remove with `off` callback functions 1020 // to an event; trigger`-ing an event fires all callbacks in succession. 1021 // 1022 var EventClass = xfalib.ut.EventClass = xfalib.ut.Class.extend({ 1023 1024 // Bind one or more space separated events, `events`, to a `listener` 1025 // object. The object should implement `handleEvent` function which will be 1026 // called on event dispatch 1027 on: function(event, listener, context) { 1028 1029 var calls, list,retVal = true; 1030 var fnCallback = _.isFunction(listener) ? listener : null; 1031 if (!listener || (!listener["handleEvent"] && !fnCallback)) return false; 1032 1033 calls = this._callbacks || (this._callbacks = {}); 1034 1035 list = calls[event] || (calls[event] = []); 1036 if(fnCallback){ 1037 context = context || this; 1038 var found = _.find(list, function(callback){ 1039 return (callback.fn == fnCallback && callback.context == context); 1040 }, this); 1041 if(found) 1042 return false; 1043 else { 1044 list.push({"fn" : fnCallback, "context": context}); 1045 } 1046 } 1047 else{ 1048 if(~list.indexOf(listener)) 1049 return false; 1050 else 1051 list.push(listener); 1052 } 1053 1054 return true; 1055 }, 1056 1057 // Remove one or many callbacks. If `listener` is null, removes all listener for the 1058 // event. If `events` is null, removes all bound callbacks for all events. 1059 off: function(events, listener, context) { 1060 var event, calls, node; 1061 1062 // No events, or removing *all* events. 1063 if (!(calls = this._callbacks)) return; 1064 if (!(events || listener)) { 1065 delete this._callbacks; 1066 return this; 1067 } 1068 1069 var fnCallback = _.isFunction(listener) ? listener : null; 1070 // Loop through the listed events and contexts and remove the required ones. 1071 events = events ? events.split(eventSplitter) : _.keys(calls); 1072 while (event = events.shift()) { 1073 node = calls[event]; 1074 calls[event] = _.filter(calls[event],function(elem) { 1075 if(typeof(listener) !== "undefined"){ 1076 if(fnCallback && elem.fn == fnCallback && elem.context == context) 1077 return false; 1078 else if(!fnCallback && listener === elem) 1079 return false; 1080 } 1081 else{ 1082 return false; 1083 } 1084 return true; 1085 }); 1086 if(!calls[event].length) 1087 delete calls[event]; 1088 } 1089 1090 return this; 1091 }, 1092 1093 // Trigger one or many events, firing all bound callbacks. Callbacks are 1094 // passed the same arguments as `trigger` except the first 1095 trigger: function(events) { 1096 var event, calls, rest; 1097 if (!(calls = this._callbacks)) return this; 1098 events = events.split(eventSplitter); 1099 var payLoad = _.rest(arguments); 1100 while (event = events.shift()) { 1101 _.each(calls[event],function(callback) { 1102 if(callback.fn && callback.context){ 1103 callback.fn.apply(callback.context, payLoad); 1104 } 1105 else if (_.isFunction(callback.handleEvent)){ 1106 callback.handleEvent.apply(callback, payLoad); 1107 } 1108 }); 1109 } 1110 1111 return this; 1112 } 1113 1114 }); 1115 1116 1117})(_, xfalib); 1118 1119 1120(function (_, $, xfalib) { 1121 var XfaUtil = xfalib.ut.XfaUtil = function () { 1122 }, 1123 registeredLocaleProperties = null, 1124 timeoutListenerAttached = false, 1125 timeouts = [], 1126 attachClearTimeoutListener = function (timeout) { 1127 timeouts.push(timeout); 1128 if (timeoutListenerAttached === false) { 1129 $(window).one("destroy.xfa", function () { 1130 _.each(timeouts, function (_timeout) { 1131 clearTimeout(_timeout); 1132 }); 1133 timeouts = []; 1134 timeoutListenerAttached = false;
1135 }); 1136 timeoutListenerAttached = true; 1137 } 1138 }; 1139 _.extend(XfaUtil.prototype, { 1140 _globalUniqueId: (new Date()).getTime(), 1141 logger: null, 1142 1143 formScaleFactor: 1, // used to appropriately scale the form when contained inside an iframe 1144 1145 getOrElse: xfalib.ut.Class.prototype.getOrElse, 1146 //map of event names between XTG and Mobile Form 1147 //Mobile Form uses different names for some the event and let's fix those names before sending them to XTG. 1148 _xtgEventName: { 1149 "$formready": "ready", 1150 "$layoutready": "ready" 1151 }, 1152 1153 generateUID: function () { 1154 return "UID" + (++XfaUtil.prototype._globalUniqueId); 1155 }, 1156 1157 matchJsonType: function (jsonModel, _class) { //TODO: handle getOrElse 1158 return (jsonModel && _class && XfaUtil.prototype.getOrElse(jsonModel._class, "").toLowerCase() == ("" + _class).toLowerCase()); 1159 }, 1160 1161 $data: function (elem, name, data) { 1162 if (!$.data(elem, "_xfaInitialized")) { 1163 //Initialized data- attributes parse for once using this call. 1164 // Next onward don't use this. Instead use $.data which is cheap/ 1165 $(elem).data(); 1166 $.data(elem, "_xfaInitialized", true); //Mark the element to say that data has been initialized. 1167 } 1168 return $.data(elem, name, data); 1169 }, 1170 1171 /* 1172 * alternative to jQuery.css which sets style properties directly through element.style. This is much faster then 1173 * corresponding jQuery.css alternative. 1174 * 1175 * Warning: this only supports standard css property names and does not do any pre-processing of name and value. 1176 * So calling this, make sure the style names are compatible. 1177 */ 1178 $css: function (elem, stylesObj) { 1179 // Exclude the following css properties to add px. copied from jquery.cssNumber to add hyphenated style names 1180 var cssNumber = { 1181 "fillOpacity": true, 1182 "fill-opacity": true, 1183 "fontWeight": true, 1184 "font-weight": true, 1185 "lineHeight": true, 1186 "line-height": true, 1187 "zIndex": true, 1188 "z-index": true, 1189 "opacity": true, 1190 "orphans": true, 1191 "widows": true, 1192 "zoom": true 1193 }; 1194 1195 for (var prop in stylesObj) { 1196 var value = stylesObj[prop]; 1197 // If a number was passed in, add 'px' to the (except for certain CSS properties) 1198 if (_.isNumber(value) && !cssNumber[ prop ]) { 1199 value += "px"; 1200 } 1201 elem.style[prop] = value; 1202 } 1203 }, 1204 1205 isTableHF: function (iChildNode) { 1206 //model can be a Node object or simply a json 1207 var assistJson = _.find(iChildNode.children, function (jChild) { 1208 return jChild._class == "assist"; 1209 }, this); 1210 var childRole = (assistJson || {}).role; 1211 if (childRole == "TH" || childRole == "TF") 1212 return true; 1213 else 1214 return false; 1215 }, 1216 1217 getUiOneOfChildTag: function (uiParent) { 1218 var uiEl = _.find(uiParent.children, function (child) { 1219 return child._class == "ui"; 1220 }); 1221 if (!uiEl) 1222 return undefined; 1223 var uiOneOfChildMap = xfalib.runtime.xfa._templateSchema._getOneOfChild("ui"); 1224 var uiOneOfChild = _.find(uiEl.children, function (child) { 1225 return uiOneOfChildMap[child._class] == true; 1226 }); 1227 if (!uiOneOfChild) 1228 return undefined; 1229 return uiOneOfChild._class; 1230 }, 1231 1232 //TODO: this should be removed. One of the worst function. 1233 dIndexOf: function (searchArray, item2Find) { 1234 var ind = -1; 1235 _.find(searchArray, function (item, index) { 1236 return item == item2Find && (ind = index) 1237 }); 1238 return ind; 1239 }, 1240 1241 splitStringByWidth: function (value, width, refEl) { 1242 var i = value.length , expectedWidth; 1243 do { 1244 expectedWidth = xfalib.view.util.TextMetrics.measureExtent(value.slice(0, i), {"refEl": refEl, maxWidth: -1}).width; 1245 i--; 1246 } while (expectedWidth > width) 1247 if (i != value.length - 1) 1248 return value.slice(0, i + 1); 1249 return value; 1250 }, 1251 1252 isRepeatabeEl: function (elTag) { 1253 if (elTag == "subform" || elTag == "subformSet") 1254 return true; 1255 else 1256 return false;
1257 }, 1258 1259 /** 1260 * @function 1261 * stripOrCall(toStrip, diffFunc, fArgs) 1262 * @description 1263 * common utility function to handle final submission payload stripping 1264 * @param {bool} toStrip : flag to signify whether to optimize jsonModelDiff size, by stripping off unnecessary properties 1265 * @param {function} diffFunc : callback func. call in case submit is not on 1266 * @param {Array} fArgs : arguments to be passed to the diff func. 1267 * @returns {object} object containing the jsonDiff 1268 */ 1269 // should ALWAYS be called with a flag signifying if a submission is in progress, 1270 // and a callback function to compute the json to be sent back during submission, usually an apt '_computeJsonDiff' 1271 stripOrCall: function (toStrip, diffFunc, fArgs) { 1272 if (toStrip) { 1273 return { 1274 "changed": false, 1275 "jsonDifference": {} 1276 }; 1277 } 1278 else if (_.isFunction(diffFunc)) { 1279 return diffFunc.apply(this, fArgs); 1280 } 1281 }, 1282 1283 /** 1284 * @function 1285 * partialStripOrCall(stripLvl, diffFunc, fArgs) 1286 * @description 1287 * common utility function to handle final submission payload stripping or for output of getFormState. 1288 * @param {int} diff_level : flag to signify whether to optimize jsonModelDiff size, by stripping off unnecessary properties 1289 * must be 0,1, or 2, as with "diff_level" param of _computeJsonDiff. 1290 * @param {function} diffFunc : callback func. call in case submit is not on 1291 * @returns {object}
1291 object containing the jsonDiff 1292 */ 1293 partialStripOrCall: function (diff_level, diffFunc) { 1294 var diffObj = diffFunc.call(this, diff_level); 1295 1296 if (!diffObj.changed) { 1297 if(diff_level === 1) { 1298 diffObj = { 1299 "changed": true, 1300 "jsonDifference": { 1301 "_class": this.jsonModel._class, 1302 "name": this.jsonModel.name 1303 } 1304 }; 1305 } else { 1306 diffObj.jsonDifference = {}; // don't need stuff for other cases 1307 } 1308 } 1309 1310 return diffObj; 1311 }, 1312 1313 /** 1314 * @function 1315 * stripObject(obj, exceptionNames) 1316 * @description 1317 * Utility function to strip unnecessary properties from an object 1318 * @param {object} obj : the object to strip 1319 * @param {Array} exceptionNames : array holding names of important properties to preserve 1320 * @returns {boolean} : true if this obj, or any of it's descendant is returned un-stripped 1321 */ 1322 stripObject: function (obj, exceptionNames) { 1323 if (_.isEmpty(obj) || !_.isObject(obj)) { 1324 return true; 1325 } else { 1326 var dontStrip = false; 1327 _.each(_.keys(obj), function (propName) { 1328 var keepProp = false; 1329 if (!_.contains(exceptionNames, propName)) { 1330 if (_.isArray(obj[propName])) { 1331 _.each(obj[propName], function (arrElem) { 1332 var isUnStripped = XfaUtil.prototype.stripObject(arrElem, exceptionNames); 1333 keepProp = keepProp || isUnStripped; 1334 }); 1335 } else if (_.isObject(obj[propName])) { 1336 keepProp = XfaUtil.prototype.stripObject(obj[propName], exceptionNames); 1337 } 1338 1339 if (!keepProp) { 1340 delete obj[propName]; 1341 } else { 1342 dontStrip = true; 1343 } 1344 } else { 1345 dontStrip = true; 1346 } 1347 }); 1348 return dontStrip; 1349 } 1350 }, 1351 1352 computeDomJsonDiff: function (domNode, diff_level) { 1353 var changed = true; 1354 if (domNode.hasOwnProperty("_modelChanged")) { 1355 changed = domNode._modelChanged; 1356 } 1357 var jsonDiff = {}; 1358 if (changed) { 1359 this.copyObject(domNode.jsonModel, jsonDiff, {"exceptions": ["children", "{default}", "extras"]}); 1360 } else { 1361 jsonDiff = {_class: domNode.className}; 1362 } 1363 if (!changed && domNode.jsonModel.hasOwnProperty("name")) { 1364 jsonDiff.name = domNode.jsonModel.name; 1365 } 1366 if (domNode.name === "FS_EXTRAS" && diff_level === 3) { 1367 domNode._childModified = true; 1368 } 1369 return { 1370 "changed": changed, 1371 jsonDifference: jsonDiff 1372 }; 1373 }, 1374 1375 getLogger: function () { 1376 return XfaUtil.prototype.logger || XfaUtil.prototype.getOrElse(xfalib, "runtime.xfa.Logger", null); 1377 }, 1378 1379 getErrorManager: function () { 1380 return XfaUtil.prototype.getOrElse(xfalib, "runtime.xfa.ErrorManager", null); 1381 }, 1382 1383 XFA_CLICK_EVENT: "xfaclick", 1384 XFA_EXIT_EVENT: "xfaexit", 1385 XFA_ENTER_EVENT: "xfaenter", 1386 XFA_CHANGE_EVENT: "xfachange", 1387 XFA_PREOPEN_EVENT: "xfapreopen", 1388 1389 btwn: function (val, a, b) { 1390 return val > a && val < b; 1391 }, 1392 1393 // function to detect if Browser is chrome / safari (webkit) 1394 isWebkit: function () { 1395 return !!$.browser.webkit || /webkit/.test(navigator.userAgent.toLowerCase()) || !!window.chrome || !!$.browser.chrome || /chrom(e|ium)/.test(navigator.userAgent.toLowerCase()) || !!$.browser.safari || !!window.webkitURL || 1396 ( /safari/.test(navigator.userAgent.toLowerCase()) && 1397 /apple computer/.test(navigator.vendor.toLowerCase()) ); 1398 1399 // TODO : find a better way to do this as $.browser is deprecated and 1400 // userAgent may be spoofed 1401 }, 1402 1403 clearTimeoutOnDestroy: function (timeout) { 1404 attachClearTimeoutListener(timeout); 1405 }, 1406 1407 // function to detect if Browser is safari 1408 isSafari: function () { 1409 return ( /safari/.test(navigator.userAgent.toLowerCase()) && 1410 /apple computer/.test(navigator.vendor.toLowerCase()) ); 1411 }, 1412
1413 getLocaleStrings: function () { 1414 return xfalib.locale.Strings; 1415 }, 1416 1417 getLogMessages: function () { 1418 return xfalib.locale.LogMessages; 1419 }, 1420 1421 /* 1422 * This function should not be added in the prototype of any Object 1423 * as in the case of other functions 1424 */ 1425 registerLocaleProperties: function (props) { 1426 registeredLocaleProperties = props; 1427 }, 1428 1429 /* 1430 * This function should not be added in the prototype of any Object 1431 * as in the case of other functions 1432 */ 1433 getDefaultLocaleProperty: function (property) { 1434 var localeProps = registeredLocaleProperties || this.getOrElse(xfalib, "script.Xfa._defaultLocale", null); 1435 return this.getOrElse(localeProps, property, null); 1436 }, 1437 1438 /** 1439 * Encodes <script> and </script> with <script> and </script> 1440 * Does same with img, video and audio tags also. 1441 * These tags are being removed since scripts can be run through 1442 * <img onerror="script" /> (same for audio and video). 1443 */ 1444 encodeScriptableTags: function (str) { 1445 var index; 1446 if (_.isString(str)) { 1447 return str.replace(/<(\/?)(script[^<>]*)>/gi, '<$1$2>') 1448 .replace(/<(\/?)(img[^<>]*)>/gi, '<$1$2>') 1449 .replace(/<(\/?)(video[^<>]*)>/gi, '<$1$2>') 1450 .replace(/<(\/?)(audio[^<>]*)>/gi, '<$1$2>') 1451 } 1452 }, 1453 1454 /** 1455 * 1456 * @param id : a string representing an HTML element id. 1457 * 1458 * return after applying an escaping '\' before each # . : [ ] 1459 */ 1460 jqId: function(id) { 1461 return "#" + id.replace(/(#|:|\.|\[|\])/g, "\\$1"); 1462 }, 1463 1464 _triggerOnBridge: function (eventName, target, property, oldVal, newVal) { 1465 var evnt = xfalib.script.XfaModelEvent.createEvent(eventName, target, 1466 property, oldVal, newVal); 1467 if(formBridge){ 1468 window.formBridge.trigger(eventName, evnt); 1469 } 1470 }, 1471 1472 /* 1473 * pads the passed in String str by pre-pending padChars to convert it to a string of given width. 1474 * If string length is already greater that equal to given width, original string is returned. 1475 */ 1476 padString : function (str, width, padChar) { 1477 padChar = padChar || '0'; 1478 str = str + ''; 1479 return str.length >= width ? str : new Array(width - str.length + 1).join(padChar) + str; 1480 }, 1481 1482 /** 1483 * returns true if the browser is IE otherwise false 1484 * @returns {boolean} 1485 */ 1486 isIE: function () { 1487 return $.browser.msie || (navigator.appName === "Netscape" && navigator.userAgent.match(/Trident\//)) 1488 }, 1489 1490 /** 1491 * returns false if other browser 1492 * if ie tries to return browser version (non falsy) 1493 * @returns {*} 1494 */ 1495 1496 detectIE: function () { 1497 // 1st try jq 1498 if($.browser.msie) { 1499 if($.browser.version && parseInt($.browser.version, 10)) { 1500 return parseInt($.browser.version, 10); 1501 } 1502 } 1503 1504 var ua = window.navigator.userAgent; 1505 1506 // IE 10 1507 // ua = 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)'; 1508 1509 // IE 11 1510 // ua = 'Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko'; 1511 1512 // IE 12 / Spartan 1513 // 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'; 1514 1515 // Edge (IE 12+) 1516 // 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'; 1517 1518 var msie = ua.indexOf('MSIE '); 1519 if (msie > 0) { 1520 // IE 10 or older => return version number 1521 return parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10); 1522 } 1523 1524 var trident = ua.indexOf('Trident/'); 1525 if (trident > 0) { 1526 // IE 11 => return version number 1527 var rv = ua.indexOf('rv:'); 1528 return parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10); 1529 } 1530 1531 var edge = ua.indexOf('Edge/'); 1532 if (edge > 0) { 1533 // Edge (IE 12+) => return version number
1534 return parseInt(ua.substring(edge + 5, ua.indexOf('.', edge)), 10); 1535 } 1536 1537 // other browser 1538 return false; 1539 }, 1540 /** 1541 * returns true if the browser is chrome otherwise false 1542 * @returns {boolean} 1543 */ 1544 detectChrome : function () { 1545 return (!!window.chrome || !!$.browser.chrome || /chrom(e|ium)/.test(navigator.userAgent.toLowerCase())); 1546 }, 1547 1548 /** 1549 * @param {String} val: value to be verified 1550 * @returns {boolean} 1551 * returns true if the provided string contains DOM element 1552 */ 1553 isHTML: function(val) { 1554 //check whether string contains tags, so that $val does not contain result of the val used as selector 1555 // eg: val = "a" will return result for $(val) which is not required 1556 if(val && /<[a-z][\s\S]*>/.test(val)) { 1557 try { 1558 var $val = $(val); 1559 return $val.length > 0; 1560 } catch (exception) { 1561 // if jquery throws exception that means string is not a proper HTML 1562 return false; 1563 } 1564 } else { 1565 return false; 1566 } 1567 }, 1568 1569 /** 1570 * returns true if passed key is non printable, false otherwise. 1571 * @param {String} key event.key property of a Keyboard event 1572 */ 1573 isNonPrintableKey : function (key) { 1574 return (key // In IE, event.key returns words instead of actual characters for some keys. 1575 && !_.contains(['MozPrintableKey','Divide','Multiply','Subtract','Add','Enter','Decimal','Spacebar','Del'],key) 1576 && key.length != 1 ) 1577 }, 1578 1579 /** 1580 * returns true for ipad 1581 * @returns {boolean} 1582 */ 1583 _isIpad : function () { 1584 return navigator.userAgent.match(/iPad/i) != null; 1585 }, 1586 1587 /** 1588 * returns true if the subform is table or having role table else false 1589 * @param {Object} view 1590 */ 1591 _tableCheckForAccessibility : function (view) { 1592 var assist = view.model.getElement("assist", 0, true); 1593 return this.getOrElse(view, "layoutModel.layout", null) == xfalib.view.LayoutConst.LAYOUT_TABLE 1594 || this.getOrElse(assist, "role", null) == "Table"; 1595 }, 1596 1597 /** 1598 * returns value of tooltip to be assigned as title based on values provided in accessibility 1599 * @param {Object} model 1600 * @returns toolTipText 1601 */ 1602 _getToolTipText : function (model) { 1603 var assist = model.getElement("assist", 0, true), 1604 toolTipText = ""; 1605 // going against xfa spec, on hover show tooltip or speak text or element name, don't show caption as it's already visible 1606 // assist priority doesn't matter, but selecting none will disable tooltip on hover 1607 if (this.getOrElse(assist, "speak.disable", 0) != 1) { // loose compare str
1607ing value 1608 toolTipText = this.getOrElse(assist, "toolTip.value", "") || 1609 this.getOrElse(assist, "speak.value", "") || 1610 this.getOrElse(model, "jsonModel.name", ""); 1611 } 1612 return toolTipText; 1613 }, 1614 1615 /** 1616 * returns value of mandatory message 1617 * @param {Object} model 1618 * @returns mandatoryMessage 1619 */ 1620 _getMandatoryMessage : function (model) { 1621 var defaultMessage = model._defaults.validate.message.defaultMessage, 1622 msg = this.getOrElse(model, "validate.message.nullTest", defaultMessage); 1623 return (msg && msg.value) ? msg.value : defaultMessage.value; 1624 }, 1625 /** 1626 * returns boolean based on val1, val2, checkEqual 1627 * For comparing date, use date object 1628 */ 1629 _compareVal : function (val1, val2, checkEqual) { 1630 if(!val1 || !val2) { 1631 return false; 1632 } 1633 1634 if(checkEqual) { 1635 return val1 >= val2; 1636 } else { 1637 return val1 > val2; 1638 } 1639 } 1640 }); 1641 1642 //Special handling for IE. 1643 if ($.browser.msie || $.browser.mozilla) { 1644 XfaUtil.prototype.$css = function (elem, stylesObj) { 1645 $(elem).css(stylesObj); 1646 } 1647 } 1648})(_, $, xfalib); 1649/************************************************************************* 1650 * 1651 * ADOBE CONFIDENTIAL 1652 * ___________________ 1653 * 1654 * Copyright 2013 Adobe Systems Incorporated 1655 * All Rights Reserved. 1656 *
1657 * NOTICE: All information contained herein is, and remains 1658 * the property of Adobe Systems Incorporated and its suppliers, 1659 * if any. The intellectual and technical concepts contained 1660 * herein are proprietary to Adobe Systems Incorporated and its 1661 * suppliers and are protected by trade secret or copyright law. 1662 * Dissemination of this information or reproduction of this material 1663 * is strictly forbidden unless prior written permission is obtained 1664 * from Adobe Systems Incorporated. 1665 **************************************************************************/ 1666 1667 1668 1669(function (_, $, xfalib) { 1670 xfalib.ut.Utilities = { 1671 1672 isIE11: function () { 1673 return !!navigator.userAgent.match(/Trident.*rv\:11\./); 1674 }, 1675 1676 checkMinMozillaVersion: function (version) { 1677 return (!this.isIE11() && $.browser.mozilla && parseInt($.browser.version) >= version); 1678 }, 1679 1680 getObjectFromKeyValueStringList: function (list) { 1681 var key, value, object = {}, tempArray; 1682 _.each(list, function (keyValuePair, index) { 1683 tempArray = keyValuePair.split("="); 1684 if (tempArray && tempArray.length > 1) { 1685 object[tempArray[0]] = tempArray[1]; 1686 } 1687 }); 1688 return object; 1689 }, 1690 1691 _getNameWithoutMarker: function (fileName) { 1692 var markerIndex = fileName.indexOf("__afAttachment__"); 1693 if (markerIndex !== -1) { 1694 fileName = fileName.substring(markerIndex + "__afAttachment__".length, fileName.length); 1695 } 1696 return fileName; 1697 }, 1698 1699 /* 1700 * This is to check support of multiple files selection in one add new dialog 1701 */ 1702 _isDataContainerSupported : function () { 1703 try { 1704 var dataContainer = new DataTransfer() || (new ClipboardEvent("")).clipboardData; 1705 if (dataContainer && dataContainer.items) { 1706 return true; 1707 } 1708 } catch(err) { 1709 // if err comes then dataContainer is not supported 1710 } 1711 return false; 1712 } 1713 }; 1714})(_, $, xfalib); 1715/** 1716 * @package xfalib.ut.Scanner 1717 * @fileOverview helper class to scan over a string. 1718 * @version 0.0.1 1719 */ 1720 1721/** 1722 * @constructor 1723 * @param Object {jsonModel:{_str: String}} 1724 */ 1725 1726(function(_,xfalib){ 1727 var Scanner = xfalib.ut.Scanner = xfalib.ut.Class.extend({ 1728 1729 initialize: function() { 1730 this._pos = 0; 1731 }, 1732 1733 isEOF : function(){ 1734 return (this.jsonModel._str.length <= this._pos); 1735 }, 1736 1737 peek : function(){ 1738 return (this.isEOF()) ? null : this.jsonModel._str.charAt(this._pos); 1739 }, 1740 1741 optionalConsumeChar : function(aChar){ 1742 if(this.jsonModel._str.charAt(this._pos) == aChar){ 1743 this._pos++; 1744 return aChar; 1745 }else{ 1746 return null; 1747 } 1748 }, 1749 1750 /** 1751 * Gets next char ignore quoted string. 1752 * | 1753 * abc returns c. 1754 * | 1755 * abc'de'f returns f. 1756 * @param aChar 1757 */ 1758 getNCharIQS : function(){ 1759 this._pos++; 1760 if(this.jsonModel._str.length <= this._pos){ 1761 var current = this.jsonModel._str.charAt(this._pos); 1762 if(current != '\''){ 1763 return current; 1764 }else{ 1765 if(moveNextExpectedChar('\'')){ 1766 return this.jsonModel._str.charAt(this._pos); 1767 } 1768 } 1769 } 1770 return null; 1771 }, 1772 1773 moveNextExpectedChar : function(aChar){ 1774 this._pos++;// currently point to ' 1775 while(this._pos< this.jsonModel._str.length && this.jsonModel._str.charAt(this._pos) != aChar){ 1776 this._pos++; 1777 } 1778 return this._pos < this.jsonModel._str.length; 1779 }, 1780 1781 readInteger : function(len){ 1782 if(this.pos+len >this.jsonModel._str.length){ 1783 return null; 1784 } 1785 var integer = xfalib.ut.PictureUtils.parseIntExact(this.jsonModel._str,this._pos,len); 1786 this._pos+=len; 1787 return integer; 1788 } 1789 }); 1790 1791 Scanner.lookupNext = function(pat, patPos, filter){ 1792 var patLen = pat.length; 1793 if(patPos >= patLen){ 1794 return null; 1795 } 1796 1797 var token = {}; 1798 token.startPos = patPos; 1799 1800 var firstChar = pat.charAt(patPos); 1801 var patValid = false;
1802 // 1803 if (firstChar == '\''){ 1804 for (var i = patPos+1; i < patLen;i++ ){ 1805 var chr = pat.charAt(i); 1806 if(chr =='\''){ 1807 token.type=1; 1808 token.len = i - patPos + 1; 1809 patValid = true; 1810 break; 1811 } 1812 } 1813 1814 }else if( ('a' <= firstChar && firstChar <= 'z' || 'A' <= firstChar && firstChar <= 'Z') || filter.call(null, firstChar)){ 1815 var endPos = patLen;//end is exclusive 1816 for (var i = 1; patPos+i < patLen;i++ ){ 1817 if(pat.charAt(patPos+i)!=firstChar){ 1818 endPos = patPos+i; 1819 break; 1820 } 1821 } 1822 token.type=2; 1823 token.len = endPos - patPos; 1824 token.patChar = firstChar; 1825 token.patPos = patPos; 1826 patValid = true; 1827 }else{ 1828 if (firstChar == '?' || firstChar == '+' || firstChar == '*') { 1829 token.type=3; 1830 token.len = 1; 1831 }else{ 1832 token.type=4; 1833 token.len = 1; 1834 } 1835 patValid = true; 1836 } 1837 if(patValid){ 1838 return token; 1839 }else{ 1840 throw "Picture is invalid."; 1841 } 1842 } 1843})(_,xfalib); 1844 1845 1846/** 1847 * @package xfalib.ut.PictureFmt 1848 * @fileOverview The file defines methods to parse and format data 1849 * according to XFA picture patterns. 1850 * @version 0.0.1 1851 */ 1852(function(_,xfalib) { 1853 1854 var PictureFmt = xfalib.ut.PictureFmt = function() {}; 1855 PictureFmt.DatePicturePattern = /^date(?:\([a-zA-Z]*_[a-zA-Z]*\))?\{([\w\W]*?)\}$/; 1856 PictureFmt.TimePicturePattern = /^time(?:\([a-zA-Z]*_[a-zA-Z]*\))?\{([\w\W]*?)\}$/; 1857 PictureFmt.TextPicturePattern = /^text\{([\w\W]*?)\}$/; 1858 PictureFmt.NumPicturePattern = /^num\{([\w\W]*?)\}$/; 1859 1860 /** 1861 * Parses a given data source according to the given picture. 1862 * @param sSource {string} 1863 * @param sPicture {string} 1864 * @param sLocale {string} 1865 * @returns {object} 1866 */ 1867 PictureFmt.parse = function(sSource, sPicture,sLocale){ 1868 var PictureEngine = new xfalib.ut.PictureEngine({jsonModel:{locale:sLocale}}); 1869 1870 var match = PictureFmt.DatePicturePattern.exec(sPicture); 1871 if(match && match[1]){ 1872 return PictureEngine.parseDate(sSource, match[1]); 1873 } 1874 match = PictureFmt.TimePicturePattern.exec(sPicture); 1875 if(match && match[1]){ 1876 return PictureEngine.parseTime(sSource, match[1]); 1877 } 1878 match = PictureFmt.TextPicturePattern.exec(sPicture); 1879 if(match && match[1]){ 1880 return PictureEngine.parseText(sSource, match[1]); 1881 } 1882 match = PictureFmt.NumPicturePattern.exec(sPicture); 1883 if(match && match[1]){ 1884 return PictureEngine.parseNumeric(sSource, match[1]); 1885 } 1886 throw "Invalid picture clause "+sPicture; 1887 }; 1888 1889 /** 1890 * Formats a given data source according to the given picture. 1891 * @param date {object} 1892 * @param sPicture {string} 1893 * @param sLocale {string} 1894 * @returns {string} 1895 */ 1896 PictureFmt.format = function(sSource, sPicture, sLocale,bRelaxed,bFormatNumberFromasDefaultPC){ 1897 var PictureEngine = new xfalib.ut.PictureEngine({jsonModel:{locale:sLocale}}); 1898 1899 var match = PictureFmt.DatePicturePattern.exec(sPicture); 1900 if(match && match[1]){ 1901 return PictureEngine.formatDate(sSource, match[1]); 1902 } 1903 match = PictureFmt.TimePicturePattern.exec(sPicture); 1904 if(match && match[1]){ 1905 return PictureEngine.formatTime(sSource, match[1]); 1906 } 1907 match = PictureFmt.TextPicturePattern.exec(sPicture); 1908 if(match && match[1]){ 1909 return PictureEngine.formatText(sSource, match[1],bRelaxed); 1910 } 1911 match = PictureFmt.NumPicturePattern.exec(sPicture); 1912 if(match && match[1]){ 1913 return PictureEngine.formatNumeric(sSource, match[1],sLocale,bRelaxed,bFormatNumberFromasDefaultPC); 1914 } 1915 throw "Invalid picture clause "+sPicture; 1916 }; 1917 1918 /** 1919 * Checks if a given data source is formatted according to the given picture. 1920 * @param date {object} 1921 * @param sPicture {string} 1922 * @param sLocale {string} 1923 * @returns {boolean} 1924 */ 1925 PictureFmt.formatTest = function (sSource, sPicture, sLocale, bRelaxed, bFormatNumberFromasDefaultPC) { 1926 var formattedData; 1927 try { 1928 formattedData = PictureFmt.format(sSource, sPicture, sLocale, bRelaxed, bFormatNumberFromasDefaultPC); 1929 }catch(e) { 1930 return false;
1931 } 1932 1933 if(!_.isString(formattedData)) { 1934 return false; 1935 } else { 1936 var parsedData; 1937 try { 1938 parsedData = PictureFmt.parse(formattedData, sPicture, sLocale); 1939 } catch (e) { 1940 return false; 1941 } 1942 if(!_.isString(parsedData) && parsedData !== formattedData) { 1943 return false; 1944 } 1945 } 1946 return true; 1947 }; 1948 1949 /** 1950 * Parses a given data source according to the given date picture 1951 * under the given sLocale. 1952 * @param sSource {string} 1953 * @param sPicture {string} 1954 * @param sLocale {string} 1955 * @returns {string} 1956 */ 1957 PictureFmt.parseDate = function(sSource, sPicture,sLocale){ 1958 var picRegexp = PictureFmt.DatePicturePattern; 1959 var match = picRegexp.exec(sPicture); 1960 var PictureEngine = new xfalib.ut.PictureEngine({jsonModel:{locale:sLocale}}); 1961 if(match && match[1]){ 1962 return PictureEngine.parseDate(sSource, match[1]); 1963 }else{ 1964 return PictureEngine.parseDate(sSource, sPicture); 1965 } 1966 }; 1967 1968 1969 /** 1970 * Formats a given data source according to the given date picture 1971 * * under the given sLocale. 1972 * @param date {string} 1973 * @param sPicture {string} 1974 * @param sLocale {string} 1975 * @returns {string} 1976 */ 1977 PictureFmt.formatDate = function(date, sPicture, sLocale){ 1978 var picRegexp = PictureFmt.DatePicturePattern; 1979 var match = picRegexp.exec(sPicture); 1980 var PictureEngine = new xfalib.ut.PictureEngine({jsonModel:{locale:sLocale}}); 1981 if(match && match[1]){ 1982 return PictureEngine.formatDate(date, match[1]); 1983 }else{ 1984 return PictureEngine.formatDate(date, sPicture); 1985 } 1986 }; 1987 1988 /** 1989 * Parses a given data source according to the given date picture 1990 * under the given sLocale. 1991 * @param sSource {string} 1992 * @param sPicture {string} 1993 * @param sLocale {string} 1994 * @returns {date} 1995 */ 1996 PictureFmt.parseTime = function(sSource, sPicture,sLocale){ 1997 var picRegexp = PictureFmt.TimePicturePattern; 1998 var match = picRegexp.exec(sPicture); 1999 var PictureEngine = new xfalib.ut.PictureEngine({jsonModel:{locale:sLocale}}); 2000 if(match && match[1]){ 2001 return PictureEngine.parseTime(sSource, match[1]); 2002 }else{ 2003 return PictureEngine.parseTime(sSource, sPicture); 2004 } 2005 return null; 2006 }; 2007 2008 2009 /** 2010 * Formats a given data source according to the given date picture 2011 * * under the given sLocale. 2012 * @param date {string} 2013 * @param sPicture {string} 2014 * @param sLocale {string} 2015 * @returns {string} 2016 */ 2017 PictureFmt.formatTime = function(date, sPicture, sLocale){ 2018 var picRegexp = PictureFmt.TimePicturePattern; 2019 var match = picRegexp.exec(sPicture); 2020 var PictureEngine = new xfalib.ut.PictureEngine({jsonModel:{locale:sLocale}}); 2021 if(match && match[1]){ 2022 return PictureEngine.formatTime(date, match[1]); 2023 }else{ 2024 return PictureEngine.formatTime(date, sPicture); 2025 } 2026 }; 2027 2028 /** 2029 * Parses a given data source according to the given text picture 2030 * under the given sLocale. 2031 * @param sSource {string} 2032 * @param sPicture {string} 2033 * @param sLocale {string} 2034 * @returns {string} 2035 */ 2036 PictureFmt.parseText = function(sSource, sPicture,sLocale){ 2037 var picRegexp = PictureFmt.TextPicturePattern; 2038 var match = picRegexp.exec(sPicture); 2039 var PictureEngine = new xfalib.ut.PictureEngine({jsonModel:{locale:sLocale}}); 2040 if(match && match[1]){ 2041 return PictureEngine.parseText(sSource, match[1]); 2042 }else{ 2043 return PictureEngine.parseText(sSource, sPicture); 2044 } 2045 }; 2046 2047 /** 2048 * Formats a given data source according to the given text picture 2049 * under the given sLocale. 2050 * @param sSource {string} 2051 * @param sPicture {string} 2052 * @param sLocale {string} 2053 * @returns {string} 2054 */ 2055 PictureFmt.formatText = function(sSource, sPicture, sLocale,bRelaxed){ 2056 var picRegexp = PictureFmt.TextPicturePattern; 2057 var match = picRegexp.exec(sPicture); 2058 var PictureEngine = new xfalib.ut.PictureEngine({jsonModel:{locale:sLocale}}); 2059 if(match && match[1]){ 2060 return PictureEngine.formatText(sSource, match[1],bRelaxed); 2061 }else{ 2062 return PictureEngine.formatText(sSource, sPicture,bRelaxed); 2063 } 2064 return null; 2065 }; 2066 2067 /** 2068 * Parses a given data source according to the given numeric picture 2069 * under the given sLocale. 2070 * @param sSource {string} 2071 * @param sPicture {string} 2072 * @param sLocale {string} 2073 * @returns {string} 2074 */ 2075 PictureFmt.parseNumeric = function(sSource, sPicture,sLocale){ 2076 var picRegexp = PictureFmt.NumPicturePattern; 2077 var match = picRegexp.exec(sPicture); 2078 var PictureEngine = new xfalib.ut.PictureEngine({jsonModel:{locale:sLocale}}); 2079 if(match && match[1]){ 2080 return PictureEngine.parseNumeric(sSource, match[1]); 2081 }else{ 2082 return PictureEngine.parseNumeric(sSource, sPicture); 2083 } 2084 return null; 2085 }; 2086 2087 /** 2088 * Formats a given data source according to the given numeric picture 2089 * under the given sLocale. 2090 * @param sSource {string} 2091 * @param sPicture {string} 2092 * @param sLocale {string} 2093 * @returns {string} 2094 */ 2095 PictureFmt.formatNumeric = function(sSource, sPicture, sLocale){ 2096 var picRegexp = PictureFmt.NumPicturePattern; 2097 var match = picRegexp.exec(sPicture); 2098 var PictureEngine = new xfalib.ut.PictureEngine({jsonModel:{locale:sLocale}}); 2099 if(match && match[1]){ 2100 return PictureEngine.formatNumeric(sSource, match[1]); 2101 }else{ 2102 return PictureEngine.formatNumeric(sSource, sPicture); 2103 } 2104 }; 2105 2106 2107 2108 2109 /** 2110 * Parses a given data source according to the given datetime picture 2111 * under the given sLocale. 2112 * @param sSource {string} 2113 * the source data. 2114 * @param sPicture {string} 2115 * the datetime picture. 2116 * @param sDateMask {string} 2117 * the date sub-picture. 2118 * @param sTimeMask {string} 2119 * the time sub-picture. 2120 * @param sLocale 2121 * the locale name. 2122 * 2123 */ 2124 PictureFmt.parseDateTime = function(sSource, sPicture, sDateMask, sTimeMask, sLocale){ 2125 2126 }; 2127 /** 2128 * Formats a given data source according to the given datetime picture 2129 * under the given locale. 2130 * 2131 * @param sSource {string} 2132 * the source data. 2133 * @param sPicture {string} 2134 * the datetime picture. 2135 * @param sDateMask {string} 2136 * the date sub-picture. 2137 * @param sTimeMask {string} 2138 * the time sub-picture. 2139 * @param sLocale {string} 2140 * the locale name. 2141 */ 2142 PictureFmt.formatDateTime = function(sSource, sPicture, sDateMask, sTimeMask, sLocale){ 2143 2144 }; 2145 2146})(_,xfalib); 2147/** 2148 * @package xfalib.ut.PictureUtils 2149 * @fileOverview The file defines static utilities methods. 2150 * @version 0.0.1 2151 */ 2152 2153(function(_,xfalib){ 2154 var PictureUtils = xfalib.ut.PictureUtils = function() {} 2155 2156 PictureUtils.padding = function(number, digits, isFw, zero){ 2157 var leading = ["0","00","000","0000"]; 2158 var numStr = leading[digits-1] + number; 2159 return numStr.slice(- digits); 2160 }; 2161 2162 PictureUtils.parseIntAggressive = function(dateString, startPos,len){ 2163 var result = new Object(); 2164 var parsedNum = 0; //The number value parsed from dateString 2165 var parsedLen = -1; //How many chars parsed according to this pattern; 2166 for(var idx=0; idx<len && (startPos + idx) < dateString.length; idx++){ 2167 var chr = dateString.charAt(startPos + idx); 2168 if(chr >='0' && chr <='9'){ 2169 parsedNum = parsedNum *10 + (chr- '0'); 2170 }else{ 2171 parsedLen = idx; 2172 break; 2173 } 2174 } 2175 if(parsedLen == -1) { 2176 parsedLen = len; 2177 } 2178 result.value = parsedNum; 2179 result.len = parsedLen; 2180 return result; 2181 }; 2182 2183 PictureUtils.parseIntExact = function(dateString, startPos,len){ 2184 var result = 0; 2185 PictureUtils.assert(startPos+ len <= dateString.length, "mismatch"); 2186 for(var idx=0; idx<len ; idx++){ 2187 var chr = dateString.charAt(startPos + idx); 2188 if(chr >='0' && chr <='9'){ 2189 result = result *10 + (chr- '0'); 2190 }else{ 2191 throw "unexpected currentChar in PictureUtils.parseInt"; 2192 } 2193 } 2194 return result; 2195 }; 2196 2197 PictureUtils.isDigit = function(chr){ 2198 return /[0-9]/.test(chr) ; 2199 }; 2200 2201 PictureUtils.inString = function(chr,aString){ 2202 return (aString.indexOf(chr) >=0) ; 2203 }; 2204 2205 2206 var regExpIsLetter = /[\u0041-\u005a\u0061-\u007a\u00aa-\u00aa\u00b5-\u00b5\u00ba-\u00ba\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u0236\u0250-\u02
2206c1\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]/ 2207 2208 /** 2209 * TODO Implement method equivalent to Character.isLetter. 2210 */ 2211 PictureUtils.isLetter = function(chr){ 2212 return regExpIsLetter.test(chr); 2213 }; 2214 2215 PictureUtils.isLetterOrDigit = function(chr){ 2216 return this.isLetter(chr) || this.isDigit(chr); 2217 }; 2218 2219 /** 2220 * Scan this string for the first character in the given set. Similar to 2221 * strcspn(). 2222 * 2223 * @param src{String} 2224 * the string to scan 2225 * @param sSkip{String} 2226 * the characters to scan for 2227 * @param nOffset{number} 2228 * the position where to start the scan. Default = 0. 2229 * @return The position, relative to nOffset, for the first character found 2230 * in the given set 2231 */ 2232 PictureUtils.skipUntil = function(srcStr, sSkip, nOffset) { 2233 var nCharsSkipped = nOffset; 2234 2235 // starting at the offset position, scan the characters in this string 2236 // until it matches one of the characters in the given set. 2237 while (nCharsSkipped < srcStr.length) { 2238 var i = nCharsSkipped; 2239 if (sSkip.indexOf(srcStr.charAt(i++)) >= 0) 2240 break; 2241 nCharsSkipped = i; 2242 } 2243 2244 return nCharsSkipped - nOffset; 2245 }; 2246 2247 PictureUtils.matchString = function(str, startPos, target){ 2248 if(startPos + target.length > str.length){ 2249 return false;
2250 }else{ 2251 for(var idx = 0; idx<target.length; idx++){ 2252 if(target.charAt(idx) != str.charAt(startPos + idx)) return false; 2253 } 2254 return true; 2255 } 2256 }; 2257 2258 PictureUtils.assert = function(condition, message){ 2259 if(!condition){ 2260 throw message; 2261 } 2262 }; 2263 2264 PictureUtils.getLocaleObject = function(locale,property) { 2265 if(locale !== null && xfalib.runtime.xfa) { 2266 return xfalib.runtime.xfa._getLocaleSymbols(locale, property); 2267 } else { 2268 return xfalib.ut.XfaUtil.prototype.getDefaultLocaleProperty(property) 2269 } 2270 } 2271 2272 PictureUtils.getHashOfLocaleObject = function(locale,property) { 2273 if(!PictureUtils.getHashOfLocaleObject[locale+"_"+property]) { 2274 var hashObj = {}; 2275 _.each(PictureUtils.getLocaleObject(locale,property), function(val) { 2276 var sVal = (val+"").toLowerCase(); 2277 var hash = 0; 2278 for(var i =0;i<sVal.length;i++) { 2279 hash+=(i+1)*sVal.charCodeAt(i) 2280 } 2281 hashObj[hash] = hashObj[hash] || []; 2282 hashObj[hash].push(sVal); 2283 }) 2284 PictureUtils.getHashOfLocaleObject[locale+"_"+property] = hashObj; 2285 } 2286 return PictureUtils.getHashOfLocaleObject[locale+"_"+property] 2287 } 2288 2289 PictureUtils.convertNumberToLocale = function(locale,number) { 2290 var zero = PictureUtils.getLocaleObject(locale,"numberSymbols.zero"); 2291 var zeroCode = zero.charCodeAt(0); 2292 number += ""; 2293 var newNumber = []; 2294 for(var i = 0;i < number.length;i++) { 2295 newNumber.push(String.fromCharCode(zeroCode + parseInt(number.charAt(i)))); 2296 } 2297 return newNumber.join(""); 2298 } 2299 2300 PictureUtils.parsePictureClause = function (clause){ 2301 if(clause === null || clause === undefined) { 2302 return []; 2303 } 2304 var insidePattern = false, 2305 insideQuote=false, 2306 insideLocale = false, 2307 locale = "", 2308 type = "", 2309 pattern = "", 2310 flag = false, 2311 currentChar = "", 2312 result = [], 2313 matchType = /^num$|^text$|^date$/, 2314 matchLocale = /^[a-zA-Z]*_[a-zA-Z]*$/, 2315 i = 0, 2316 bracketOpenCount = 0; 2317 for(;i<clause.length;i++) { 2318 currentChar = clause.charAt(i); 2319 if(insideQuote && currentChar !== "'") { 2320 pattern += currentChar; 2321 continue; 2322 } 2323 switch(currentChar) { 2324 case "'": 2325 if(!insidePattern) { 2326 // ' is not allowed except insidePattern 2327 return null; 2328 } 2329 insideQuote = !insideQuote; 2330 pattern += currentChar; 2331 break; 2332 case "{": 2333 if(insidePattern || insideLocale || type === "") { 2334 // { is not allowed insidePattern or insideLocale 2335 return null; 2336 } 2337 insidePattern = true; 2338 break; 2339 case "}": 2340 if(!insidePattern || (insideLocale && pattern === "") || type === "") { 2341 // { is allowed only insidePattern and not insideLocale 2342 return null; 2343 } else { 2344 bracketOpenCount = 0; 2345 insidePattern = false; 2346 if(matchType.exec(type) === null) { 2347 return null; 2348 } 2349 if(locale !== "" && matchLocale.exec(locale) === null) { 2350 return null; 2351 } 2352 result.push({ 2353 category: type, 2354 mask: pattern, 2355 locale: locale 2356 }) 2357 } 2358 break; 2359 case "|": 2360 if(type === "" || insidePattern || insideLocale) { 2361 return null; 2362 } else { 2363 type = pattern = locale = ""; 2364 insidePattern = insideLocale = false;
2365 } 2366 break; 2367 case "(" : 2368 if(type === "" || bracketOpenCount === 1) { 2369 // ( is not allowed inside Locale 2370 return null; 2371 } else { 2372 if(!insidePattern) { 2373 insideLocale = true; 2374 } else { 2375 pattern += currentChar; 2376 } 2377 bracketOpenCount++; 2378 } 2379 break; 2380 case ")" : 2381 if((!insideLocale && !insidePattern) || bracketOpenCount === 0) { 2382 return null; 2383 } else { 2384 if(insidePattern) { 2385 pattern += currentChar; 2386 } 2387 insideLocale = false; 2388 bracketOpenCount--; 2389 } 2390 break; 2391 default: 2392 if(insidePattern) { 2393 pattern += currentChar; 2394 } else if(insideLocale) { 2395 locale += currentChar; 2396 } else if(type !== "" && (pattern !== "" || locale !== "")){ 2397 return null; 2398 } else { 2399 type += currentChar; 2400 } 2401 break; 2402 } 2403 } 2404 if(insidePattern || insideLocale || insideQuote || bracketOpenCount !== 0) { 2405 return null; 2406 } 2407 return result; 2408 } 2409 2410})(_,xfalib); 2411 2412/** 2413 * @package xfalib.ut.VisitorBase 2414 * @import xfalib.ut.Class 2415 * @fileOverview Base class for visitor 2416 * @version 0.0.1 2417 */ 2418 2419/** 2420 * @constructor 2421 * @param Object {jsonModel: {_sPicture: String}} 2422 */ 2423 2424(function(_,xfalib) { 2425 var VisitorBase = xfalib.ut.VisitorBase = xfalib.ut.Class.extend({ 2426 consume : function(token){ 2427 switch (token.type) 2428 { 2429 case 1: 2430 this.consumeStringLiteral(token); 2431 break; 2432 case 2: 2433 this.consumeSubPattern(token); 2434 break; 2435 case 3: 2436 this.consumeStringWildCard(token); 2437 break; 2438 case 4: 2439 this.consumeCharLiteral(token); 2440 break; 2441 } 2442 }, 2443 acceptPatternChar : function(chr){ 2444 return false; 2445 }, 2446 getPicture : function(){ 2447 return this.jsonModel._sPicture; 2448 }, 2449 abstractMethod : function(){ 2450 throw "Not implemented"; 2451 }, 2452 consumeStringWildCard : this.abstractMethod, 2453 consumeStringLiteral: this.abstractMethod, 2454 consumeCharLiteral: this.abstractMethod, 2455 consumeSubPattern: this.abstractMethod, 2456 getResult: this.abstractMethod 2457 }); 2458})(_,xfalib); 2459 2460/** 2461 * @package xfalib.ut.NumPictureDesc 2462 * @import xfalib.ut.Class 2463 * @fileOverview Pre-process Numeric Picture. 2464 * @version 0.0.1 2465 */ 2466 2467/** 2468 * @constructor 2469 * @param Object {jsonModel: {_sPicture: String}} 2470 */ 2471 2472(function(_,xfalib){ 2473 var NumPictureDesc = xfalib.ut.NumPictureDesc = xfalib.ut.Class.extend({ 2474 2475 initialize: function() { 2476 this.hasRadix = false; 2477 this.hasExpon = false; 2478 this.hasSign = false; 2479 this.hasPercent = false; 2480 this.fracDigit = 0; 2481 this.intDigit = 0; 2482 2483 this._mbLeftParenSeen = false; 2484 this._mbRightParenSeen = false; 2485 this._compactPattern(); 2486 this._xlatePattern(); 2487 NumPictureDesc._super.initialize.call(this); 2488 }, 2489 2490 getPicture : function(){ 2491 return this.jsonModel._sPicture; 2492 }, 2493 2494 _match2Char : function (char1, char2, idx){ 2495 if(idx+1 < this.jsonModel._sPicture.length){ 2496 return (this.jsonModel._sPicture.charAt(idx) ==char1 && this.jsonModel._sPicture.charAt(idx+1) ==char2); 2497 }else{ 2498 return false;
2499 } 2500 }, 2501 2502 _xlatePattern : function(){ 2503 var patPos = 0; 2504 for(var token = xfalib.ut.Scanner.lookupNext(this.jsonModel._sPicture, patPos, this._acceptPatternChar); token != null; ){ 2505 this._consume(token); 2506 patPos = patPos + token.len; 2507 token = xfalib.ut.Scanner.lookupNext(this.jsonModel._sPicture, patPos, this._acceptPatternChar); 2508 } 2509 }, 2510 2511 _compactPattern : function(){ 2512 var buf = new Array(); 2513 for(var index =0, len = this.jsonModel._sPicture.length; index <len; index++){ 2514 if(this._match2Char('D','B',index)){ 2515 buf.push('D'); 2516 index++; 2517 }else if(this._match2Char('d','b',index)){ 2518 buf.push('d'); 2519 index++; 2520 }else if(this._match2Char('C','R',index)){ 2521 buf.push('C'); 2522 index++; 2523 }else if(this._match2Char('c','r',index)){ 2524 buf.push('c'); 2525 index++; 2526 }else{ 2527 buf.push(this.jsonModel._sPicture.charAt(index)); 2528 } 2529 } 2530 this.jsonModel._sPicture = buf.join(""); 2531 }, 2532 2533 _acceptPatternChar : function(chr){ 2534 return xfalib.ut.PictureUtils.inString(chr, "(%$,.)89BCDERSVZbcdrsvzt"); 2535 }, 2536 2537 _consume : function(token){ 2538 if(token.type == 2){ 2539 this._subConsume(token.patChar, token.len); 2540 }// else not a pattern 2541 }, 2542 2543 _subConsume : function(chr, chrCnt){ 2544 switch (chr) { 2545 case'E' : 2546 if (chrCnt > 1 || this.hasExpon || (this.fracDigit + this.intDigit)==0) 2547 throw "Illegal Numeric Picture: more than one Expon"; 2548 this.hasExpon = true; 2549 break; 2550 case '(': 2551 if (chrCnt > 1 || this._mbLeftParenSeen || this.fracDigit + this.intDigit >0 ) 2552 throw "Illegal Numeric Picture: ()"; 2553 this._mbLeftParenSeen = true; 2554 break; 2555 2556 case ')': 2557 if (chrCnt > 1 || ! this._mbLeftParenSeen || this._mbRightParenSeen) 2558 throw "Illegal Numeric Picture: ()"; 2559 this._mbRightParenSeen = true; 2560 if(this.fracDigit + this.intDigit >0) this.hasSign = true; 2561 break; 2562 case 'S': 2563 case 's': 2564 case 'C': //CR 2565 case 'c': //cr 2566 case 'D': //DB 2567 case 'd': //db 2568 this.hasSign = true; 2569 break; 2570 case '%' : 2571 this.hasPercent = true; 2572 break; 2573 case '.': 2574 case 'V': 2575 case 'v': 2576 if (chrCnt > 1 || this.hasRadix) 2577 throw "Illegal Numeric Picture: too many vV."; 2578 this.hasRadix = true; 2579 this._mbFracStartSeen = true; 2580 break; 2581 case '8' : 2582 case '9' : 2583 case 'Z': 2584 case 'z': 2585 if (this.hasRadix){ 2586 this.fracDigit += chrCnt; 2587 } else{ 2588 this.intDigit += chrCnt; 2589 } 2590 break; 2591 } 2592 }, 2593 2594 parseNumberInfo : function(msText){ 2595 var text=msText, 2596 num = Number(text), 2597 negative = false 2598 if(num < 0){ 2599 negative = true; 2600 num = -num; 2601 text = text.replace("-",""); 2602 } 2603 if(this.hasPercent){ 2604 num *= 100; 2605 text = ""+num; 2606 } 2607 var shift = 0; 2608 if(this.hasExpon){ 2609 var threshold = Math.pow(10,this.intDigit); 2610 if(num < threshold){ 2611 while(num*10 < threshold) { 2612 num *= 10; 2613 shift--; 2614 } 2615 }else{ 2616 while(num > threshold){ 2617 num /= 10; 2618 shift++; 2619 } 2620 } 2621 text = num+""; 2622 } 2623 var radixPos = text.indexOf(".", 0), 2624 fractionDigit = radixPos<0 ? 0 : text.length - radixPos - 1 2625 2626 if(this.fracDigit < fractionDigit) { 2627 num = num.toFixed(this.fracDigit); 2628 text = num +"" 2629 } 2630 2631 if(text.indexOf("0") == 0 && msText.indexOf("0") != 0) { 2632 text = text.substring(1); 2633 } 2634 2635 radixPos = text.indexOf(".", 0) 2636 var integerDigit = radixPos < 0 ? text.length : radixPos, 2637 offset = this.intDigit - integerDigit 2638 2639 if(offset <0 ){ 2640 throw "Exit: most significant " + offset +" digit lost"; 2641 } 2642 return { 2643 "integerDigit" : integerDigit, 2644 "radixPos" : radixPos , 2645 "fractionDigit" : radixPos<0 ? 0 : text.length - radixPos - 1, 2646 "msText" : text, 2647 "shift" : shift, 2648 "isNegative" : negative, 2649 "padding" :offset 2650 }; 2651 } 2652 }); 2653 2654 NumPictureDesc.gsDB = "DB"; 2655 NumPictureDesc.gsCR = "CR"; 2656 NumPictureDesc.gsE = "E"; 2657 NumPictureDesc.gsDSP = " "; 2658 NumPictureDesc.gsSSP = " "; 2659 2660})(_,xfalib); 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 /** 2673 * @package xfalib.ut.TimeInfo 2674 * @import xfalib.ut.Class 2675 * @fileOverview A wrapper class for date related information. 2676 * @version 0.0.1 2677 */ 2678
2679/** 2680 * @constructor 2681 */ 2682(function(_,xfalib){ 2683 var TimeInfo = xfalib.ut.TimeInfo = xfalib.ut.Class.extend({ 2684 2685 initialize: function() { 2686 this.mHourOfMeriDiem = -1; 2687 this.mHourOfDay = -1; 2688 this.mMinuteOfHour = -1; 2689 this.mSecondOfMinute = -1; 2690 this.mThousandthOfSecond = -1; 2691 }, 2692 2693 getISOTime : function(){ 2694 var timeStr = ""; 2695 if(this.mThousandthOfSecond>0){ 2696 timeStr = "-" + this.formatNum(this.mThousandthOfSecond,3); 2697 } 2698 if(this.mSecondOfMinute>0 || timeStr!=""){ 2699 timeStr = this.formatNum(this.mSecondOfMinute,2)+timeStr; 2700 timeStr = ":"+timeStr; 2701 } 2702 if(this.mMinuteOfHour>0 || timeStr!=""){ 2703 timeStr = this.formatNum(this.mMinuteOfHour,2)+timeStr; 2704 timeStr = ":"+timeStr; 2705 } 2706 timeStr = this.formatNum(this.mHourOfDay,2) + timeStr; 2707 2708 return timeStr; 2709 }, 2710 2711 formatNum : function(num, digits){ 2712 if(num<0){ 2713 num = 0; 2714 } 2715 return xfalib.ut.PictureUtils.padding(num, digits); 2716 }, 2717 2718 getDate : function(){ 2719 var date = new Date(); 2720 this.setTime(date); 2721 return date; 2722 }, 2723 2724 setTime : function(date){ 2725 date.setHours(this.mHourOfDay); 2726 date.setMinutes(this.mMinuteOfHour); 2727 date.setSeconds(this.mSecondOfMinute); 2728 date.setMilliseconds(this.mThousandthOfSecond); 2729 } 2730 }); 2731 2732 /** 2733 * 2734 * <p>Valid ISO8601/XFA time strings are in any one 2735 * of the following time patterns: 2736 * <ul> 2737 * <li> HH[MM[SS[.FFF][z]]] 2738 * <li> HH[MM[SS[.FFF][+HH[MM]]]] 2739 * <li> HH[MM[SS[.FFF][-HH[MM]]]] 2740 * <li> HH[:MM[:SS[.FFF][z]]] 2741 * <li> HH[:MM[:SS[.FFF][+HH[:MM]]]] 2742 * <li> HH[:MM[:SS[.FFF][-HH[:MM]]]] 2743 * </ul> 2744 */ 2745 TimeInfo.Parse = function(isoDateStr, locale){ 2746 var scanner = new xfalib.ut.Scanner({jsonModel:{_str:isoDateStr}}); 2747 var hours = scanner.readInteger(2); 2748 var minitues = -1; 2749 if(!scanner.isEOF()){ 2750 scanner.optionalConsumeChar(':'); 2751 minitues = scanner.readInteger(2); 2752 } 2753 var seconds = -1; 2754 if(!scanner.isEOF()){ 2755 scanner.optionalConsumeChar(':'); 2756 seconds = scanner.readInteger(2); 2757 } 2758 var milliseconds = -1; 2759 if(!scanner.isEOF()){ 2760 scanner.optionalConsumeChar('-'); 2761 milliseconds = scanner.readInteger(3); 2762 } 2763 //TODO timezone 2764 var info = new xfalib.ut.TimeInfo(); 2765 TimeInfo.setPropertyIfNotNull(info,hours,"mHourOfDay"); 2766 TimeInfo.setPropertyIfNotNull(info,minitues,"mMinuteOfHour"); 2767 TimeInfo.setPropertyIfNotNull(info,seconds,"mSecondOfMinute"); 2768 TimeInfo.setPropertyIfNotNull(info,milliseconds,"mThousandthOfSecond"); 2769 return info; 2770 }; 2771 2772 /** 2773 * 2774 * static method 2775 */ 2776 TimeInfo.setPropertyIfNotNull = function(object, value, proName){ 2777 if(value!=null){ 2778 var d = Number(value); 2779 if(!isNaN(d)){ 2780 object[proName] = d; 2781 } 2782 } 2783 }; 2784 2785})(_,xfalib); 2786/** 2787 * @package xfalib.ut.DateInfo 2788 * @import xfalib.ut.Class 2789 * @fileOverview A wrapper class for date related information. 2790 * @version 0.0.1 2791 */ 2792 2793/** 2794 * @constructor 2795 */ 2796 2797(function(_,xfalib) { 2798 var DateInfo = xfalib.ut.DateInfo = xfalib.ut.Class.extend({ 2799 2800 initialize: function(options) { 2801 if (options && !options.isParsingCall ) { // skip setting internal values when called while parsing date formats 2802 this.date = new Date(); 2803 this._year = this.date.getFullYear(); 2804 this._month = this.date.getMonth() + 1; 2805 this._day = this.date.getDay(); 2806 } 2807 DateInfo._super.initialize.call(this); 2808 }, 2809 2810 formatNum : function(num, digits){ 2811 if(num<0) 2812 num = 0; 2813 return xfalib.ut.PictureUtils.padding(num, digits); 2814 }, 2815 2816 getDate : function(){ 2817 return this.date; 2818 }, 2819 setDate : function() { 2820 this.date = new Date(this._year,this._month-1,this._day) 2821 }, 2822 getISODate : function(){ 2823 var isoDate = []; 2824
2825 isoDate.push(this.formatNum(this._year, 4)); 2826 isoDate.push("-"); 2827 isoDate.push(this.formatNum(this._month, 2)); 2828 isoDate.push("-"); 2829 isoDate.push(this.formatNum(this._day, 2)); 2830 2831 return isoDate.join(""); 2832 }, 2833 2834 year : function(y) { 2835 if(y && y > 0 && y <= 9999) 2836 this._year = y; 2837 else 2838 throw "undefined year"; 2839 }, 2840 2841 month : function(m) { 2842 if(m && m>0 && m < 13) { 2843 this._month = m; 2844 } 2845 else 2846 throw "Invalid month " + m; 2847 }, 2848 2849 _leapYear : function() { 2850 var year = this._year; 2851 return year % 400 == 0 || (year % 100 != 0 && year % 4 == 0); 2852 }, 2853 2854 _maxDate : function(m) { 2855 if(this._leapYear() && m == 2) 2856 return 29; 2857 else return DateInfo.dates[m-1]; 2858 }, 2859 2860 day : function(d) { 2861 if(d && d > 0 && d <= this._maxDate(this._month || 0)) 2862 this._day = d; 2863 else 2864 throw "Invalid Date "+ d + " for the month "+(this._month); 2865 }, 2866 2867 validate : function(y, m, d) { 2868 this.year(y); 2869 this.month(m); 2870 this.day(d); 2871 } 2872 }); 2873 2874 DateInfo.ParseIsoString = function(isoDateStr, locale){ 2875 var isDateRegexp = /^(\d{4})(?:-?(\d{1,2})(?:-?(\d{1,2}))?)?(?:T((\d{2}):(\d{2}):(\d{2}))Z)?$/; 2876 var match = isDateRegexp.exec(isoDateStr); 2877 if(match && match.length >= 4){ 2878 var dateInfo = new DateInfo(); 2879 var date = new Date(isoDateStr); 2880 // TODO - check if date is invalid. 2881 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 2882 dateInfo.year(date.getFullYear()); 2883 dateInfo.month(date.getMonth()+1); 2884 dateInfo.day(date.getDate()); 2885 } else { 2886 try { 2887 dateInfo.year(Number(match[1])); 2888 dateInfo.month(Number(match[2])); 2889 dateInfo.day(Number(match[3])); 2890 } catch(e) { 2891 return null; 2892 } 2893 } 2894 dateInfo.setDate(); 2895 return dateInfo; 2896 } 2897 return null; 2898 }; 2899 2900 DateInfo.Parse = function(dateStr, locale, validateWithDefaultPatterns){ 2901 locale = locale || "en_US"; 2902 var patterns = xfalib.ut.PictureUtils.getLocaleObject(locale,"datePatterns"), 2903 isoDate = this.ParseIsoString(dateStr, locale); 2904 if(!_.isEmpty(isoDate)) { 2905 return isoDate; // in case edit pattern is present, it'll be parsed by the widget during input and return an iso date string. 2906 } 2907 //if edit pattern is present then don't try to match it from default locale patterns. 2908 if(validateWithDefaultPatterns === false){ 2909 _.find(patterns, function(pattern) { 2910 try { 2911 isoDate = xfalib.ut.PictureFmt.parseDate(dateStr,pattern,locale); 2912 return true; 2913 } catch(exception) { 2914 return false; 2915 } 2916 }); 2917 } 2918 isoDate = isoDate || dateStr; 2919 return DateInfo.ParseIsoString(isoDate); 2920 }; 2921 2922 DateInfo.dates = [31,28,31,30,31,30,31,31,30,31,30,31]; 2923 DateInfo.daysOfWeek = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]; 2924})(_,xfalib); 2925/** 2926 * @package xfalib.ut.PictureEngine 2927 * @import xfalib.ut.Scanner 2928 * @fileOverview The file is a facade to assembly all components together. 2929 * @version 0.0.1 2930 */ 2931(function(_,xfalib) { 2932 2933 var PictureEngine = xfalib.ut.PictureEngine = xfalib.ut.Class.extend({ 2934 2935 _lookupNext: xfalib.ut.Scanner.lookupNext, 2936 2937 MAX_XFA_PREC : 8, // Max no. of fractional digits in XFA. 2938 MAX_DBL_DIG :18, // Max no. of significant digits in a double. 2939 MAX_INT_DIG :10, // Max no. of significant digits in an integer. 2940 MAX_DBL_WIDTH :15, // Max width before precision loss in a double. 2941 INTEGRAL_FMT : 0, 2942 DECIMAL_FMT : 1, 2943 CURRENCY_FMT : 2, 2944 PERCENT_FMT : 3, 2945 2946 parseDate : function(sSource, sPicture, locale){ 2947 return this._acceptVisitor(new xfalib.ut.DateParsingVisitor({jsonModel:{_sPicture:sPicture,_dataString:sSource,_locale:this.jsonModel.locale}})); 2948 }, 2949 2950 formatDate : function(dDate, sPicture){
2951 var validateWithDefaultPatterns = typeof sPicture !== 'undefined'; 2952 var dateInfo = xfalib.ut.DateInfo.Parse(dDate, this.jsonModel.locale, validateWithDefaultPatterns); 2953 if(dateInfo == null){ 2954 return null; 2955 }else{ 2956 return this._acceptVisitor(new xfalib.ut.DateFormattingVisitor({jsonModel:{_sPicture:sPicture,_dateInfo:dateInfo,_locale:this.jsonModel.locale}})); 2957 } 2958 }, 2959 2960 parseTime : function(sSource, sPicture){ 2961 return this._acceptVisitor(new xfalib.ut.TimeParsingVisitor({jsonModel:{_sPicture:sPicture,_dataString:sSource}})); 2962 }, 2963 2964 formatTime : function(dDate, sPicture){ 2965 var timeInfo = xfalib.ut.TimeInfo.Parse(dDate, this.jsonModel.locale); 2966 if(timeInfo == null){ 2967 return null; 2968 }else{ 2969 return this._acceptVisitor(new xfalib.ut.TimeFormattingVisitor({jsonModel:{_sPicture:sPicture,_timeInfo:timeInfo}})); 2970 } 2971 }, 2972 2973 parseText : function(sSource, sPicture){ 2974 return this._acceptVisitor(new xfalib.ut.TextParsingVisitor({jsonModel:{_sPicture:sPicture,_dataString:sSource}})); 2975 }, 2976 2977 formatText : function(sSource, sPicture,bRelaxed){ 2978 return this._acceptVisitor(new xfalib.ut.TextFormattingVisitor({jsonModel:{_sPicture:sPicture,_text:sSource,relaxed:bRelaxed}})); 2979 }, 2980
2981 parseNumeric : function(sSource, sPicture){ 2982 var visitor = new xfalib.ut.NumParsingVisitor({jsonModel:{_sPicture:sPicture,_dataString:sSource,_locale:this.jsonModel.locale}}); // TODO : Is locale required 2983 visitor.parse(); 2984 return visitor.getResult(); 2985 }, 2986 2987 formatNumeric : function(sSource, sPicture,locale,bRelaxed,bFormatNumberFromasDefaultPC){ 2988 2989 var sFormatPicture =sPicture; 2990 if( bRelaxed && bFormatNumberFromasDefaultPC){ 2991 sFormatPicture = this.getNumberFormat(sPicture,1, {formatOption: "WITH_GROUPINGS", 2992 "precision" : this.getNumberPrecision(sSource), 2993 "width" : sSource.length 2994 }); 2995 } 2996 return this._acceptVisitor(new xfalib.ut.NumFormattingVisitor({jsonModel:{_sPicture:sFormatPicture,_locale:this.jsonModel.locale},text:sSource})); 2997 }, 2998 2999 _acceptVisitor : function(visitor){ 3000 this._scanPattern(visitor); 3001 return visitor.getResult(); 3002 }, 3003 3004 _scanPattern : function(visitor){ 3005 var patPos = 0; 3006 var sPicture = visitor.getPicture(); 3007 for(var token = this._lookupNext(sPicture, patPos, visitor.acceptPatternChar); token != null; ){ 3008 visitor.consume(token); 3009 patPos = patPos + token.len; 3010 token = this._lookupNext(sPicture, patPos, visitor.acceptPatternChar); 3011 } 3012 }, 3013 3014 /** 3015 * Removes n bytes from this string starting at position nOffset. 3016 * 3017 * @param nOffset - start position for the remove 3018 * @param nLength - the number of characters to remove 3019 * @return This string 3020 */ 3021 3022 _swallow : function(sString , nOffset, nLenToSwallow) 3023 { 3024 if(_.isEmpty(sString) || nLenToSwallow ==0){ 3025 return sString; 3026 } 3027 3028 if( (nOffset + nLenToSwallow)> sString.length ) { 3029 nLenToSwallow = (nOffset + nLenToSwallow) - sString.length; 3030 } 3031 var subStr = sString.substr(0,nOffset) + sString.substr(offset + nLenToSwallow); 3032 3033 return subStr 3034 }, 3035 /** 3036 * Replace some portion of one string with another String. 3037 * @param sString - the String where it has to be replaced. 3038 * @param sReplacement - the replacement string. 3039 * @param nOffset - start position for the replacement. Default value = 0. 3040 * @param nCutLength - the number of bytes to remove from the 3041 * original string. 3042 */ 3043 3044 _replaceAll : function(sString ,sReplacement , nOffset ,nCutlength) { 3045 return sString.substr(0,nOffset) + sReplacement + sString.substr(nOffset + nCutlength) 3046 }, 3047 3048 //---------------------------------------------------------------------- 3049 // SkipOver 3050 // 3051 // Scan this string for the first byte of the character not in the given set. 3052 // Similar to strspn(). 3053 //---------------------------------------------------------------------- 3054 _skipOver : function(fromString,sSkip, nOffset) 3055 { 3056 // starting at the offset position, scan the characters in this string 3057 // until it does not match any of the characters in the given set. 3058 var nCharsSkipped = nOffset; 3059 var i = 0; 3060 while (nCharsSkipped < fromString.length) 3061 { 3062 i = nCharsSkipped; 3063 if (sSkip.indexOf(fromString[i]) ==-1) { 3064 break; 3065 } 3066 i++; 3067 nCharsSkipped = i; 3068 } 3069 3070 return nCharsSkipped - nOffset; 3071 }, 3072 3073 /* 3074 * Get the numeric format in the given style. 3075 * @param style in the range of values 0-2, 3076 * where (0 = integral, 1 = decimal, 2 = currency). 3077 * @param option in the set of format options: 3078 */ 3079 getNumberFormat : function(format , style, option) 3080 { 3081 if (style < this.INTEGRAL_FMT || this.PERCENT_FMT < style) { 3082 style = this.DECIMAL_FMT; 3083 } 3084 3085 var sFormat = format; 3086 3087 // 3088 // Use any alternate part because they handle negative values. 3089 // 3090 var nBar = 0; 3091 if ((nBar = sFormat.indexOf('|')) != -1) { 3092 sFormat = this._swallow(sFormat, 0, nBar + 1); 3093 } 3094 // 3095 // Determine position of radix (or anything like it) 3096 // and the replicating part of the pattern, i.e., from 3097 // the separator to this radix. 3098 // 3099 var nDot; 3100 if ( (nDot = sFormat.indexOf('.')) == -1) { 3101 if ((nDot = sFormat.indexOf('v')) == -1) { 3102 if ((nDot = sFormat.indexOf('V')) == -1) { 3103 if ((nDot = sFormat.indexOf('E')) == -1) { 3104 if ((nDot = sFormat.indexOf(' ')) == -1) { 3105 if ((nDot = sFormat.indexOf('%')) == -1) { 3106 nDot = sFormat.length; 3107 } 3108 } 3109 } 3110 } 3111 } 3112 } 3113 if (nDot) { 3114 if (this._skipOver(sFormat,"89zZ", nDot - 1) != 1) { 3115 nDot = sFormat.length; 3116 } 3117 } 3118 var sZZZ; 3119 var nZed; 3120 if ( (nZed = sFormat.indexOf("z,")) != -1) { 3121 // 3122 // Watson 1230768. Handle locales, like India, that have 3123 // pictures with more than one grouping symbol. 3124 // 3125 var nSep = nDot; 3126 var nComma; 3127 if ((nComma = sFormat.indexOf(',', nZed + 2)) !=-1) { 3128 nSep = nComma; 3129 } 3130 if (nSep > nZed + 2) { 3131 sZZZ = Array(nSep - nZed).join('z'); 3132 } 3133 else { 3134 sZZZ = Array(1).join('z'); 3135 } 3136 } 3137 else { 3138 nZed = 0; 3139 } 3140 // 3141 // If non-integral styles Then determine width and precision. 3142 // 3143 var nPrec = 0; 3144 var nWidth = this.MAX_INT_DIG; 3145 if (style != this.INTEGRAL_FMT) { 3146 nPrec = option.precision; // (option >> 8) & 0xff;
3147 var trim = ((nPrec & 0x80) == 0); 3148 nPrec &= 0x7f; 3149 if (nPrec == 0x7f) { 3150 nPrec = this._skipOver(sFormat, "89zZ", nDot + 1); 3151 } 3152 if ((option.width) != undefined) { 3153 nWidth = option.width; 3154 } 3155 else { 3156 nWidth = this.MAX_DBL_DIG; 3157 } 3158 // 3159 // Fix for Watson 1229423. If the locale's format contains 3160 // any sign pictures Then widen accordingly. Also widen if 3161 // precision of locale's picture format is greater than requested. 3162 // 3163 if (sFormat.indexOf('s')!=-1) { 3164 nWidth += 1; 3165 } 3166 if (sFormat.indexOf('(')!=-1) { 3167 nWidth += 1; 3168 } 3169 if (sFormat.indexOf(')') !=-1) { 3170 nWidth += 1; 3171 } 3172 var nFmtPrec = this._skipOver(sFormat,"89zZ", nDot + 1); 3173 if (0 < nPrec && nPrec < nFmtPrec) { 3174 nWidth += nFmtPrec - nPrec; 3175 } 3176 3177 // 3178 // Pare down the precision if the width is big enough to yield 3179 // IEEE 754 64-bit double precision errors, which appears to be 3180 // anything over 14 significant digits. 3181 // 3182 if (trim && nPrec > 0 && nWidth > nPrec) { 3183 // 3184 // Fix for Watson 1211481. If the given precision is less 3185 // than what the locale's format dictates then widen the given 3186 // width. 3187 // 3188 if (nPrec <= sFormat.length - 1 - nDot) { 3189 nWidth += sFormat.length - 1 - nDot - nPrec; 3190 } 3191 for (var i = nWidth - 1; i > this.MAX_DBL_WIDTH; i--) { 3192 // 3193 // Never pare down the precision below what the locale's 3194 // format dictates. 3195 // 3196 if (nPrec <= sFormat.length - 1 - nDot) 3197 break; 3198 nPrec--; 3199 } 3200 } 3201 } 3202 //Watson 1483675 - If the locale's format contains 3203 // a dollar sign or a space then widen accordingly. 3204 if (style == this.CURRENCY_FMT) { 3205 if (sFormat.indexOf('$')!=-1) { 3206 nWidth++; 3207 } 3208 3209 if (sFormat.indexOf(' ')!=-1) { 3210 nWidth += 1; 3211 } 3212 } 3213 3214 // 3215 // If percent style was wanted Then truncate after the percent character. 3216 // 3217 if (style == this.PERCENT_FMT) { 3218 var nTrim = this._skipOver(sFormat,"89zZ", nDot + 1); 3219 sFormat = this._replaceAll(sFormat,"",nTrim,0) 3220 //sFormat.Replace(jfString::EmptyString(), nDot + 1, nTrim); 3221 3222 //Watson 1483675 - If the locale's format contains 3223 // a percent sign then widen accordingly. 3224 if (sFormat.indexOf('%')!=-1) { 3225 nWidth++; 3226 } 3227 } 3228 // 3229 // Else if integral style was wanted Then truncate at the radix character. 3230 // 3231 // 3232 // If integral style was wanted Then truncate at the radix character. 3233 // 3234 else if (style == this.INTEGRAL_FMT || nPrec == 0){// && option.formatOption == "WITHOUT_RADIX") { 3235 var nTrim = this._skipOver(sFormat,"89zZ", nDot + 1); 3236 sFormat = this._replaceAll(sFormat,"",nDot,nTrim+1); 3237 } 3238 // 3239 // Otherwise for decimal and currency styles Do 3240 // replace fractional 'z' pictures with '8's to requested precision, 3241 // 3242 else if (option.formatOption == "WITH_EIGHTS") { 3243 var nEight = nDot + 1; 3244 while ((nEight =sFormat.indexOf('z'))!=-1) { 3245 this._replaceAll(sFormat, '8', nEight,'8'.length); 3246 } 3247 while (sFormat.Length() - nDot <= nPrec) { 3248 sFormat = this._replaceAll(sFormat, "8", nDot + 1, 0); 3249 } 3250 } 3251 // 3252 // Or replace fractional '9' pictures with 'z's to requested precision 3253 // Watson 1322850 - add option to keep nines, previously this function 3254 // would force frac. digits to be either z's or 8's with no option for 9's. 3255 // 3256 else if ((option.formatOption) == "WITH_ZEDS" && !((option.formatOption) == "KEEP_NINES")) { 3257 var nNine = nDot + 1; 3258 while ((nNine = sFormat.indexOf('9'))!=-1) { 3259 this._replaceAll(sFormat, 'z', nNine,1); 3260 } 3261 while (sFormat.Length() - nDot <= nPrec) {
3262 this._replaceAll(sFormat, "z", nDot + 1, 0); 3263 } 3264 } 3265 // 3266 // Replicate section from separator to radix to requested width. 3267 // 3268 if (!sZZZ) { 3269 sZZZ = "z"; 3270 } 3271 else if ((option.formatOption) == "WITHOUT_GROUPINGS" ) { 3272 // 3273 // Watson 1230768. Handle locales, like India, that have 3274 // pictures with more than one grouping symbol. 3275 // 3276 var nComma = nZed + 1 ; 3277 this._replaceAll(sFormat, 'z' ,nComma,1); 3278 while ( nComma!= -1 && (nComma < nDot)) { 3279 nComma = sFormat.indexOf(','); 3280 sFormat = this._replaceAll(sFormat,'z',nComma,1); 3281 } 3282 } 3283 else if ((option.formatOption == "WITH_GROUPINGS")) { 3284 sZZZ = this._replaceAll(sZZZ,',',0,1); 3285 nWidth += (nWidth + sZZZ.length) / sZZZ.length; 3286 } 3287 while (sFormat.length < nWidth) { 3288 sFormat = this._replaceAll(sFormat, sZZZ, nZed + 1, 0); 3289 } 3290 return sFormat; 3291 }, 3292 3293 /** 3294 * Get the decimal precision of the given numeric string. 3295 * @return the decimal precision or 0 for integral values. 3296 */ 3297 getNumberPrecision: function(sVal) 3298 { 3299 var nRadix = 0; 3300 var i = -1; 3301 // Reason for not using the commented line. We are always storing the value in model with . as decimal separator 3302 // Passing field locale/ browser locale would lead to precision width being zero for non-english locales where 3303 // decimal separater may be different. 3304 // var rIndex = xfalib.ut.PictureUtils.getLocaleObject(this.jsonModel.locale,"numberSymbols").decimal; 3305 // so hardcoding . for now 3306 var rIndex = "."; 3307 if( (nRadix = sVal.indexOf(rIndex))!=-1) 3308 { 3309 for(; nRadix <=sVal.length ;nRadix++) { 3310 i++; 3311 } 3312 3313 return i; 3314 } 3315 return 0; 3316 } 3317 }) 3318})(_,xfalib); 3319/** 3320 * @package xfalib.ut.FormattingVisitorBase 3321 * @import xfalib.ut.VisitorBase 3322 * @fileOverview Base class for visitor 3323 * @version 0.0.1 3324 */ 3325 3326/** 3327 * @constructor 3328 * @param Object {jsonModel: {_sPicture: String]} 3329 */ 3330 3331(function(_,xfalib) { 3332 var FormattingVisitorBase = xfalib.ut.FormattingVisitorBase = xfalib.ut.VisitorBase.extend({ 3333 3334 initialize: function() { 3335 this._buffer = []; //TODO: ASK Ren where does this _buffer comes from 3336 FormattingVisitorBase._super.initialize.call(this); 3337 }, 3338 3339 consumeStringWildCard : function(token){ 3340 //'?' '*' '+ 3341 this._buffer.push(" "); 3342 }, 3343 3344 consumeStringLiteral : function(token){ 3345 this._buffer.push(this.jsonModel._sPicture.substr(token.startPos+1,token.len-2)); 3346 }, 3347 3348 consumeCharLiteral : function(token){ 3349 this._buffer.push(""+ this.jsonModel._sPicture.charAt(token.startPos)); 3350 } 3351 }) 3352 3353})(_,xfalib); 3354/** 3355 * @package xfalib.ut.ParsingVisitorBase 3356 * @import xfalib.ut.VisitorBase 3357 * @fileOverview Base class for visitor 3358 * @version 0.0.1 3359 */ 3360 3361/** 3362 * @constructor 3363 * @param Object {jsonModel: {_sPicture: String,_dataString: String}} 3364 */ 3365 3366(function(_,xfalib){ 3367 var ParsingVisitorBase = xfalib.ut.ParsingVisitorBase = xfalib.ut.VisitorBase.extend({ 3368 3369 initialize: function() { 3370 this._strLen = this.jsonModel._dataString.length; 3371 this._strPos = 0; 3372 ParsingVisitorBase._super.initialize.call(this); 3373 }, 3374 3375 consumeStringWildCard : function(token){ 3376 if (chr == '?') { 3377 if (this._strPos < this._strLen)//&& Character.isDefined(str.charAt(strPos)) 3378 this._strPos += 1; 3379 } else if (chr == '+') { 3380 if (this._strPos >= this._strLen)// || ! Character.isWhitespace(str.charAt(strPos))) 3381 throw "Mismatch"; 3382 this._strPos += 1; 3383 while (this._strPos < this._strLen)// && Character.isWhitespace(str.charAt(strPos))) 3384 this._strPos += 1; 3385 } else if (chr == '*') { 3386 while (this._strPos < this._strLen)// && Character.isWhitespace(str.charAt(strPos))) 3387 this._strPos += 1; 3388 } 3389 3390 }, 3391 3392 consumeStringLiteral : function(token){ 3393 for(var offset=0; offset<token.len-2 ;offset++){ //-2, heading and trailing quote 3394 if(this.jsonModel._sPicture.charAt(token.startPos+offset+1) != this.jsonModel._dataString.charAt(this._strPos+offset)){ 3395 throw ("Mismatch" + this.jsonModel._sPicture.substr(token.startPos, token.len)); 3396 } 3397 } 3398 this._strPos += token.len-2; 3399 3400 }, 3401 3402 consumeCharLiteral : function(token){ 3403 if(this.jsonModel._sPicture.charAt(token.startPos) == this.jsonModel._dataString.charAt(this._strPos)){ 3404 this._strPos += 1; 3405 }else{ 3406 throw "Mismatch"; 3407 } 3408 } 3409 }) 3410})(_,xfalib); 3411 3412/** 3413 * @package xfalib.ut.DateFormattingVisitor 3414 * @import xfalib.ut.FormattingVisitorBase 3415 * @fileOverview The file provides formating logic on date pattern characters. 3416 * @version 0.0.1 3417 */ 3418 3419 3420/** 3421 * @constructor 3422 * @param object {jsonModel: {_sPicture:String,_dateInfo: xfalib.ut.DateInfo}} 3423 */ 3424 3425(function(_,xfalib) { 3426 var PictureUtils = xfalib.ut.PictureUtils; 3427 var DateFormattingVisitor = xfalib.ut.DateFormattingVisitor = xfalib.ut.FormattingVisitorBase.extend({ 3428 3429 consumeSubPattern : function(token){ 3430 var chr = token.patChar; 3431 var chrCnt = token.len; 3432 3433 switch (chr) { 3434 case 'D': 3435 var dayOfMonth=this.jsonModel._dateInfo.date.getDate(); 3436 switch(chrCnt){ 3437 case 1: 3438 break; 3439 case 2: 3440 dayOfMonth = PictureUtils.padding(dayOfMonth,2); 3441 break; 3442 } 3443 this._buffer.push(PictureUtils.convertNumberToLocale(this.jsonModel._locale,dayOfMonth)); 3444 break; 3445 case 'J': 3446 3447 //this._mDayOfYear; 3448 break; 3449 case 'M': 3450 var monthOfYear = this.jsonModel._dateInfo.date.getMonth(); 3451 switch(chrCnt){ 3452 case 1: 3453 this._buffer.push(PictureUtils.convertNumberToLocale(this.jsonModel._locale,monthOfYear+1)); 3454 break; 3455 case 2: 3456 this._buffer.push(PictureUtils.convertNumberToLocale(this.jsonModel._locale,PictureUtils.padding(monthOfYear+1,2))); 3457 break; 3458 case 3: 3459 var monthNames = PictureUtils.getLocaleObject(this.jsonModel._locale,"calendarSymbols.abbrmonthNames"); 3460 this._buffer.push(monthNames[monthOfYear]); 3461 break; 3462 case 4: 3463 var monthNames = PictureUtils.getLocaleObject(this.jsonModel._locale,"calendarSymbols.monthNames"); 3464 this._buffer.push(monthNames[monthOfYear]); 3465 break; 3466 } 3467 3468 break; 3469 case 'E': 3470 var dayOfWeek = this.jsonModel._dateInfo.date.getDay(); 3471 var dayNames; 3472 switch(chrCnt) { 3473 case 1: 3474 this._buffer.push(dayOfWeek); 3475 break; 3476 case 3: 3477 dayNames = PictureUtils.getLocaleObject(this.jsonModel._locale,"calendarSymbols.abbrdayNames"); 3478 this._buffer.push(dayNames[dayOfWeek]); 3479 break; 3480 case 4: 3481 dayNames = PictureUtils.getLocaleObject(this.jsonModel._locale,"calendarSymbols.dayNames"); 3482 this._buffer.push(dayNames[dayOfWeek]); 3483 break; 3484 default: 3485 throw "unsupported Picture Clause "; 3486 } 3487 break; 3488 case 'e': 3489 break; 3490 case 'G': 3491 break; 3492 case 'Y': 3493 3494 var yearOfEra = this.jsonModel._dateInfo.date.getFullYear() 3495 switch(chrCnt){ 3496 case 2: 3497 if(yearOfEra>2029 || yearOfEra < 1930){ 3498 throw "unsupported " + yearOfEra + " by pattern YY"; 3499 } 3500 yearOfEra = PictureUtils.padding(yearOfEra % 100, 2); 3501 break; 3502 case 4: 3503 yearOfEra = PictureUtils.padding(yearOfEra, 4); // 2 digit(0000-9999) 3504 break; 3505 } 3506 this._buffer.push(PictureUtils.convertNumberToLocale(this.jsonModel._locale,yearOfEra)); 3507 break; 3508 case 'w': 3509 break; 3510 case 'W': 3511 break; 3512 default: throw "Unsupported pattern"; 3513 } 3514 3515 }, 3516 /** 3517 * 3518 * @override 3519 */ 3520 getResult : function(){ 3521 return this._buffer.join(""); 3522 } 3523 3524 }); 3525})(_,xfalib); 3526 3527 3528/** 3529 * @package xfalib.ut.TextFormattingVisitor 3530 * @import xfalib.ut.FormattingVisitorBase 3531 * @fileOverview Formats a string according to Text Picture. 3532 * @version 0.0.1 3533 */ 3534
3535/** 3536 * @constructor 3537 * @param Object { jsonModel:{_sPicture: String, _text: String}} 3538 */ 3539(function(_,xfalib){ 3540 var TextFormattingVisitor = xfalib.ut.TextFormattingVisitor = xfalib.ut.FormattingVisitorBase.extend({ 3541 3542 initialize: function() { 3543 this._textPos = 0; 3544 this._relaxed = typeof this.jsonModel.relaxed === "undefined" ? true: this.jsonModel.relaxed; 3545 TextFormattingVisitor._super.initialize.call(this); 3546 }, 3547 3548 consumeSubPattern : function(token){ 3549 var chr = token.patChar; 3550 var chrCnt = token.len; 3551 for(var index = 0; index < chrCnt && (!this._relaxed || this._textPos < this.jsonModel._text.length); index++){ 3552 switch (chr) { 3553 case '9': // Numeric 3554 var cUni = this.jsonModel._text.charAt(this._textPos++); 3555 if(!xfalib.ut.PictureUtils.isDigit(cUni)){ 3556 throw "TextFormatting: not a digit as expected"; 3557 } 3558 this._buffer.push(cUni); 3559 break; 3560 case 'A': // Alphebetic 3561 var cUni = this.jsonModel._text.charAt(this._textPos++); 3562 if(!xfalib.ut.PictureUtils.isLetter(cUni)){ 3563 throw "TextFormatting: not a character as expected"; 3564 } 3565 this._buffer.push(cUni); 3566 break; 3567 case 'O': // Alphanumeric 3568 case '0': 3569 var cUni = this.jsonModel._text.charAt(this._textPos++); 3570 // cUni === "" is a hack for LC-6152 3571 // To prevent extra loop[one more time than the length of the string] for which cUni was "" 3572 // which was neither a letter nor a digit 3573 // so we were getting textformatting error 3574 //which caused email id validation to fail for chars less than picture clause 3575 if(!(cUni ==="" || xfalib.ut.PictureUtils.isLetter(cUni) || xfalib.ut.PictureUtils.isDigit(cUni))){ 3576 throw "TextFormatting: not a character or digit as expected"; 3577 } 3578 this._buffer.push(cUni); 3579 break; 3580 case 'X': 3581 var cUni = this.jsonModel._text.charAt(this._textPos++); 3582 this._buffer.push(cUni); 3583 break; 3584 case 't': 3585 this._buffer.push("\t"); 3586 break; 3587 default: this._buffer.push(chr); 3588 } 3589 } 3590 3591 }, 3592 3593 /** 3594 * 3595 * @override 3596 */ 3597 getResult : function(){ 3598 if(this._textPos < this.jsonModel._text.length) 3599 throw "TextFormatting: picture clause smaller than input Text"; 3600 return this._buffer.join(""); 3601 }, 3602 3603 /** 3604 * 3605 * @override 3606 */ 3607 acceptPatternChar : function(chr){ 3608 return xfalib.ut.PictureUtils.inString(chr, "9AO0Xt"); 3609 }, 3610 3611 consumeCharLiteral : function(token){ 3612 this._buffer.push(""+ this.jsonModel._sPicture.charAt(token.startPos)); 3613 // LC-3869 : forward the text pointer after literal is present and matched with the picture. 3614 if(this.jsonModel._sPicture.charAt(token.startPos) == this.jsonModel._text.charAt(token.startPos)) 3615 this._textPos++; 3616 } 3617 }) 3618 3619})(_,xfalib); 3620 3621 3622/** 3623 * @package xfalib.ut.TextFormattingVisitor 3624 * @import xfalib.ut.FormattingVisitorBase 3625 * @fileOverview The file provides formating logic on date pattern characters. 3626 * @version 0.0.1 3627 */ 3628 3629/** 3630 * @constructor 3631 * @param object {jsonModel: {_sPicture:String,_timeInfo: xfalib.ut.TimeInfo}} 3632 */ 3633 3634(function(_,xfalib){ 3635 var TimeFormattingVisitor = xfalib.ut.TimeFormattingVisitor= xfalib.ut.FormattingVisitorBase.extend({ 3636 3637 consumeSubPattern : function(token){ 3638 var chr = token.patChar; 3639 var chrCnt = token.len; 3640 3641 switch (chr) { 3642 case 'H': 3643 case 'K': 3644 var hourOfDay = this.jsonModel._timeInfo.mHourOfDay; 3645 if(chr=='K'){ 3646 hourOfDay += 1; 3647 } 3648 switch(chrCnt){ 3649 case 1: 3650 this._buffer.push(hourOfDay); 3651 break; 3652 case 2: 3653 this._buffer.push(xfalib.ut.PictureUtils.padding(hourOfDay,2)); 3654 break; 3655 } 3656 break; 3657 3658 case 'M': 3659 var minuteOfHour = this.jsonModel._timeInfo.mMinuteOfHour; 3660 switch(chrCnt){ 3661 case 1: 3662 this._buffer.push(minuteOfHour); 3663 break; 3664 case 2: 3665 this._buffer.push(xfalib.ut.PictureUtils.padding(minuteOfHour,2)); 3666 break; 3667 } 3668 3669 break; 3670 case 'S': 3671 var secondOfMinute = this.jsonModel._timeInfo.mSecondOfMinute; 3672 switch(chrCnt){ 3673 case 1: 3674 this._buffer.push(secondOfMinute); 3675 break; 3676 case 2: 3677 this._buffer.push(xfalib.ut.PictureUtils.padding(secondOfMinute,2)); 3678 break; 3679 } 3680 break; 3681 case 'F': 3682 var Milliseconds =this.jsonModel._timeInfo.mThousandthOfSecond; 3683 this._buffer.push(xfalib.ut.PictureUtils.padding(Milliseconds,3)); 3684 break; 3685 3686 default: throw "Unsupported pattern"; 3687 }; 3688 3689 }, 3690 3691 /** 3692 * 3693 * @override 3694 */ 3695 getResult : function(){ 3696 return this._buffer.join(""); 3697 } 3698 3699 }); 3700 3701})(_,xfalib); 3702 3703 3704/** 3705 * @package xfalib.ut.NumFormattingVisitor 3706 * @import xfalib.ut.FormattingVisitorBase 3707 * @fileOverview Formats a string according to Text Picture. 3708 * @version 0.0.1 3709 */ 3710
3711/** 3712 * @constructor 3713 * @param Object { jsonModel:{_sPicture: String}, text: String} 3714 */ 3715 3716(function(_,xfalib){ 3717 var PictureUtils = xfalib.ut.PictureUtils; 3718 var NumFormattingVisitor = xfalib.ut.NumFormattingVisitor = xfalib.ut.FormattingVisitorBase.extend({ 3719 3720 initialize: function(options) { 3721 NumFormattingVisitor._super.initialize.call(this); 3722 this._textPos = 0; 3723 3724 //boolean value used for internal state track 3725 this._mbDigitAddedToOutput = false; // at least one digit has been added to output 3726 this._mbSignAddedToOutput = false; 3727 this._nScannedPatternDigit = 0; //how many digit(98Zz) characters scanned in pattern, reset to 0 after '.Vv' 3728 this._mbRadixSeen = false; 3729 3730 this._pictureDesc = new xfalib.ut.NumPictureDesc({jsonModel:{_sPicture:this.jsonModel._sPicture}}); 3731 this.jsonModel._sPicture= this._pictureDesc.getPicture(); 3732 this._numberInfo = this._pictureDesc.parseNumberInfo(options.text); 3733 3734 this._mbNegative = this._numberInfo.isNegative; 3735 this._msText = this._numberInfo.msText; 3736 this._leadingPadding = this._numberInfo.padding; 3737 // 3738 this._mNumberSymbols = xfalib.ut.PictureUtils.getLocaleObject(this.jsonModel._locale,"numberSymbols"); 3739 this._mCurrencySymbols = xfalib.ut.PictureUtils.getLocaleObject(this.jsonModel._locale,"currencySymbols"); 3740 }, 3741 3742 _checkAndAddDecimalPoint: function(fw) { 3743 if(this._mAddRadix) { 3744 this._buffer.push(this._fmtStr(this._mNumberSymbols.decimal, fw)); 3745 this._mAddRadix = false; 3746 } 3747 }, 3748 3749 consumeSubPattern : function(token){ 3750 var chr = token.patChar, 3751 chrCnt = token.len; 3752 switch (chr) { 3753 case '9': 3754 case '8': 3755 case 'Z': // Digit or space if zero. 3756 case 'z':// Digit or nothing if zero. 3757 if(!this._mbSignAddedToOutput) 3758 this._ensureSignIsAdded(); 3759 while (chrCnt-- > 0 ) { 3760 if(!this._mbRadixSeen){ 3761 if(this._leadingPadding > this._nScannedPatternDigit++){ 3762 var placeHolder = null; 3763 if(this._mbDigitAddedToOutput){ 3764 placeHolder = this._mNumberSymbols.zero; 3765 }else{ 3766 if(chr == '9' || chr =='8') { 3767 placeHolder = this._mNumberSymbols.zero; 3768 this._mbDigitAddedToOutput = true; 3769 }else if(chr == 'Z'){ 3770 placeHolder = " "; 3771 } 3772 } 3773 if(placeHolder){ 3774 this._buffer.push(this._matchChr(placeHolder)); 3775 } 3776 }else { 3777 var cValue = this._msText.charAt(this._textPos++); 3778 this._ensureCharIsDigit(cValue); 3779 this._buffer.push(PictureUtils.convertNumberToLocale(this.jsonModel._locale,cValue)); 3780 this._mbDigitAddedToOutput = true; 3781 } 3782 }else{ //handling fractional part 3783 if(this._nScannedPatternDigit++ < this._numberInfo.fractionDigit ){ 3784 var cValue = this._msText.charAt(this._textPos++); 3785 this._ensureCharIsDigit(cValue); 3786 this._checkAndAddDecimalPoint(); 3787 this._buffer.push(PictureUtils.convertNumberToLocale(this.jsonModel._locale,cValue)); 3788 this._mbDigitAddedToOutput = true; 3789 }else{ 3790 if(chr == '9'|| chr =='Z') { 3791 this._checkAndAddDecimalPoint(); 3792 this._buffer.push(this._matchChr(this._mNumberSymbols.zero)); 3793 } else if(chr == '8') { 3794 var cValue = this._msText.charAt(this._textPos++); 3795 if(cValue != '' && this._ensureCharIsDigit(cValue)) { 3796 this._checkAndAddDecimalPoint(); 3797 this._buffer.push(PictureUtils.convertNumberToLocale(this.jsonModel._locale,cValue)); 3798 this._mbDigitAddedToOutput = true; 3799 } 3800 } 3801 } 3802 } 3803 3804 } 3805 3806 break; 3807 case 'E': // Exponent. 3808 this._buffer.push('E'); 3809 this._buffer.push("" + this._numberInfo.shift); 3810 break; 3811 case 'C': // CR symbol if negative and spaces if positive. 3812 this._buffer.push((this._mbNegative) ? xfalib.ut.NumPictureDesc.gsCR : xfalib.ut.NumPictureDesc.gsDSP); 3813 break; 3814 case 'c': // CR symbol if negative and nothing if positive. 3815 if (this._mbNegative){ 3816 this._buffer.push(xfalib.ut.NumPictureDesc.gsCR); 3817 } 3818 break; 3819 case 'D': // DB symbol if negative and spaces if positive. 3820 this._buffer.push((this._mbNegative) ? xfalib.ut.NumPictureDesc.gsDB : xfalib.ut.NumPictureDesc.gsDSP); 3821 break; 3822 case 'd': // DB symbol if negative and nothing if positive. 3823 if (this._mbNegative){ 3824 this._buffer.push(xfalib.ut.NumPictureDesc.gsDB); 3825 } 3826 break; 3827 case 'S': // Minus sign if negative and a space if positive. 3828 case 's': 3829 if (this._mbNegative){ 3830 this._buffer.push(this._fmtStr( this._mNumberSymbols.minus)); 3831 }else{ 3832 if('S' == chr){ 3833 this._buffer.push(this._matchChr(' ')); 3834 } 3835 } 3836 break; 3837 case 'V': // Implied decimal sign if parsing. 3838 case '.': 3839 case 'v': // Implied decimal sign. 3840 if (this._textPos < this._msText.length && this._msText.charAt(this._textPos) == '.'){ 3841 this._textPos++; //consume a '.' 3842 } 3843 if (chr == 'V' || chr == '.'){ 3844 this._mAddRadix = true; 3845 //this._buffer.push(this._fmtStr(this._mNumberSymbols.decimal, )); 3846 } 3847 this._mbRadixSeen = true; 3848 this._nScannedPatternDigit = 0; 3849 break; 3850 3851 case 0xFF0C: // Fullwidth ','. 3852 case ',': // Grouping separator. 3853 while (chrCnt-- > 0) { 3854 if (this._mbDigitAddedToOutput){ 3855 this._buffer.push(this._fmtStr( this._mNumberSymbols.grouping )); 3856 } 3857 this._mbCommaSeen = true; 3858 } 3859 break; 3860 case 0xFF04: // Fullwidth '$'. 3861 case '$': // Currency name or symbol. 3862 while (chrCnt-- > 0) { 3863 this._buffer.push(this._fmtStr( this._mCurrencySymbol
3863s.symbol )); 3864 } 3865 break; 3866 case 0xFF05: // Fullwidth '%'. 3867 case '%': // Percent symbol. 3868 while (chrCnt-- > 0) { 3869 this._buffer.push(this._fmtStr( this._mNumberSymbols.percent)); 3870 } 3871 break; 3872 case 0xFF08: // Fullwidth '('. 3873 case 0xFF09: // Fullwidth ')'. 3874 case '(': // Left parenthesis. 3875 case ')': // Right parenthesis. 3876 this._buffer.push(this._matchChr((this._mbNegative) ? chr : ' ')); 3877 break; 3878 default: 3879 } 3880 }, 3881 3882 _ensureCharIsDigit : function(cValue){ 3883 if ('0' > cValue || cValue > '9'){ 3884 throw "Nuberic Formatting: not a digit as expected " + cValue; 3885 } 3886 }, 3887 3888 3889 _fmtStr : function(str){ 3890 return str; 3891 }, 3892 3893 _matchStr : function(str){ 3894 return str; 3895 }, 3896 3897 _matchChr : function(str){ 3898 return str; 3899 }, 3900 3901 _ensureSignIsAdded : function(){ 3902 if (this._mbNegative && ! this._mbDigitAddedToOutput && ! this._pictureDesc.hasSign) { 3903 this._buffer.push(this._mNumberSymbols.minus); 3904 this._mbSignAddedToOutput = true; 3905 } 3906 }, 3907 3908 /** 3909 * 3910 * @override 3911 */ 3912 getResult : function(){ 3913 return this._buffer.join(""); 3914 }, 3915 3916 /** 3917 * 3918 * @override 3919 */ 3920 acceptPatternChar : function(chr){ 3921 return xfalib.ut.PictureUtils.inString(chr, "(%$,.)89BCDERSVZbcdrsvzt"); 3922 } 3923 3924 }); 3925 3926})(_,xfalib); 3927 3928 3929/** 3930 * @package xfalib.ut.TimeParsingVisitor 3931 * @import xfalib.ut.ParsingVisitorBase 3932 * @fileOverview The file provides parsing/formating logic on date pattern characters. 3933 * @version 0.0.1 3934 */ 3935 3936/** 3937 * @constructor 3938 * @param Object {jsonModel: {_sPicture: String, _dataString: String]} 3939 */ 3940 3941(function(_,xfalib){ 3942 var TimeParsingVisitor = xfalib.ut.TimeParsingVisitor = xfalib.ut.ParsingVisitorBase.extend({ 3943 3944 initialize: function() { 3945 this._timeInfo = new xfalib.ut.TimeInfo(); 3946 TimeParsingVisitor._super.initialize.call(this); 3947 }, 3948 3949 consumeSubPattern : function(token){ 3950 var chr = token.patChar; 3951 var chrCnt = token.len; 3952 var curPos = this._strPos; 3953 var scannedChar = chrCnt; 3954 this._assert(curPos+chrCnt <=this.jsonModel._dataString.length, "Mismatch"); 3955 3956 switch (chr) { 3957 case 'h': 3958 if(this._timeInfo.mHourOfMeriDiem != -1 || this._timeInfo.mHourOfDay != -1){ 3959 throw "ambiguity time string"; 3960 } 3961 var hourOfMeriDiem=-1; 3962 switch(chrCnt){ 3963 case 1: 3964 var parsed = this.parseIntAggressive(this.jsonModel._dataString, curPos, 2); // 1-2 digit(1-12) 3965 hourOfMeriDiem = parsed.value; 3966 scannedChar = parsed.len; 3967 break; 3968 case 2: 3969 hourOfMeriDiem = this.parseIntExact(this.jsonModel._dataString, curPos, 2); // 1-2 digit(1-12) 3970 break; 3971 } 3972 3973 this._timeInfo.mHourOfMeriDiem = hourOfMeriDiem -1; 3974 this._assert(this._timeInfo.mHourOfMeriDiem>=0 && this._timeInfo.mHourOfMeriDiem<=11, "Invalid Hour Of MeriDiem value."); 3975 break; 3976 3977 case 'k': 3978 if(this._timeInfo.mHourOfMeriDiem != -1 || this._timeInfo.mHourOfDay != -1){ 3979 throw "ambiguity time string"; 3980 } 3981 var hourOfMeriDiem=-1; 3982 switch(chrCnt){ 3983 case 1: 3984 var parsed = this.parseIntAggressive(this.jsonModel._dataString, curPos, 2); // 1-2 digit(0-11) 3985 hourOfMeriDiem = parsed.value; 3986 scannedChar = parsed.len; 3987 break; 3988 case 2: 3989 hourOfMeriDiem = this.parseIntExact(this.jsonModel._dataString, curPos, 2); // 1-2 digit(0-11) 3990 break; 3991 } 3992 3993 this._timeInfo.mHourOfMeriDiem = hourOfMeriDiem; 3994 this._assert(this._timeInfo.mHourOfMeriDiem>=0 && this._timeInfo.mHourOfMeriDiem<=11, "Invalid hour of meriDiem value."); 3995 break; 3996 3997 case 'H': 3998 if(this._timeInfo.mHourOfMeriDiem != -1 || this._timeInfo.mHourOfDay != -1){ 3999 throw "ambiguity time string"; 4000 } 4001 var hourOfDay=-1; 4002 switch(chrCnt){ 4003 case 1: 4004 var parsed = this.parseIntAggressive(this.jsonModel._dataString, curPos, 2); // 1-2 digit(0-23) 4005 hourOfDay = parsed.value; 4006 scannedChar = parsed.len; 4007 break; 4008 case 2: 4009 hourOfDay = this.parseIntExact(this.jsonModel._dataString, curPos, 2); // 1-2 digit(0-23) 4010 break; 4011 } 4012 4013 this._timeInfo.mHourOfDay = hourOfDay; 4014 this._assert(this._timeInfo.mHourOfDay>=0 && this._timeInfo.mHourOfDay<=23, "Invalid hour of day value."); 4015 break; 4016 4017 case 'K': 4018 if(this._timeInfo.mHourOfMeriDiem != -1 || this._timeInfo.mHourOfDay != -1){ 4019 throw "ambiguity time string"; 4020 } 4021 var hourOfDay=-1; 4022 switch(chrCnt){ 4023 case 1: 4024 var parsed = this.parseIntAggressive(this.jsonModel._dataString, curPos, 2); // 1-2 digit(0-23) 4025 hourOfDay = parsed.value; 4026 scannedChar = parsed.len; 4027 break; 4028 case 2: 4029 hourOfDay = this.parseIntExact(this.jsonModel._dataString, curPos, 2); // 1-2 digit(0-23) 4030 break; 4031 } 4032 4033 this._timeInfo.mHourOfDay = hourOfDay - 1; 4034 this._assert(this._timeInfo.mHourOfDay>=0 && this._timeInfo.mHourOfDay<=23, "Invalid hour of day value."); 4035 break; 4036 case 'M': 4037 if(this._timeInfo.mMinuteOfHour != -1){ 4038 throw "ambiguity time string"; 4039 } 4040 var minuteOfHour=-1; 4041 switch(chrCnt){ 4042 case 1: 4043 var parsed = this.parseIntAggressive(this.jsonModel._dataString, curPos, 2); // 1-2 digit(0-59) 4044 minuteOfHour = parsed.value; 4045 scannedChar = parsed.len; 4046 break; 4047 case 2: 4048 minuteOfHour = this.parseIntExact(this.jsonModel._dataString, curPos, 2); // 1-2 digit(0-59) 4049 break; 4050 } 4051 4052 this._timeInfo.mMinuteOfHour = minuteOfHour; 4053 this._assert(this._timeInfo.mMinuteOfHour>=0 && this._timeInfo.mMinuteOfHour<=59, "Invalid minute of hour."); 4054 break; 4055 case 'S': 4056 if(this._timeInfo.mSecondOfMinute != -1){ 4057 throw "ambiguity time string"; 4058 } 4059 var secondOfMinute=-1; 4060 switch(chrCnt){ 4061 case 1: 4062 var parsed = this.parseIntAggressive(this.jsonModel._dataString, curPos, 2); // 1-2 digit(0-59) 4063 secondOfMinute = parsed.value; 4064 scannedChar = parsed.len; 4065 break; 4066 case 2: 4067 secondOfMinute = this.parseIntExact(this.jsonModel._dataString, curPos, 2); // 1-2 digit(0-59) 4068 break; 4069 } 4070 4071 this._timeInfo.mSecondOfMinute = secondOfMinute; 4072 this._assert(this._timeInfo.mSecondOfMinute>=0 && this._timeInfo.mSecondOfMinute<=59, "Invalid second of minute."); 4073 break; 4074 case 'F': 4075 4076 this._assert(chrCnt==3, "Invalid pattern F."); 4077 this._timeInfo.mThousandthOfSecond = this.parseIntExact(this.jsonModel._dataString, curPos, 3); 4078 this._assert(this._timeInfo.mThousandthOfSecond>=0 && this._timeInfo.mThousandthOfSecond<=999, "Invalid thousand of second."); 4079 break; 4080 4081 default: throw "Unsupported pattern"; 4082 } 4083 4084 this._strPos += scannedChar; 4085 }, 4086 4087 parseIntAggressive : xfalib.ut.PictureUtils.parseIntAggressive, 4088 4089 parseIntExact : xfalib.ut.PictureUtils.parseIntExact, 4090 4091 getResult : function(){ 4092 return this._timeInfo.getISOTime(); 4093 }, 4094 4095 getTimeInfo : function(){ 4096 return this._timeInfo; 4097 }, 4098 4099 _assert : function(condition, message){ 4100 if(!condition){ 4101 throw message; 4102 } 4103 } 4104 }); 4105})(_,xfalib); 4106 4107 4108 4109/** 4110 * @package xfalib.ut.TextParsingVisitor 4111 * @import xfalib.ut.ParsingVisitorBase 4112 * 4113 * @fileOverview Parses a string according to Text Picture. 4114 * @version 0.0.1 4115 */ 4116
4117/** 4118 * @constructor 4119 * @param Object {jsonModel: {_sPicture: String, _dataString: String]} 4120 */ 4121(function(_,xfalib){ 4122 var TextParsingVisitor = xfalib.ut.TextParsingVisitor = xfalib.ut.ParsingVisitorBase.extend({ 4123 4124 initialize: function() { 4125 TextParsingVisitor._super.initialize.call(this); 4126 this._buffer = []; 4127 }, 4128 4129 consumeSubPattern : function(token){ 4130 var chr = token.patChar; 4131 var chrCnt = token.len; 4132 for(var index = 0; index < chrCnt; index++){ 4133 switch (chr) { 4134 case '9': // Numeric 4135 var cUni = this.jsonModel._dataString.charAt(this._strPos++); 4136 if(!xfalib.ut.PictureUtils.isDigit(cUni)){ 4137 throw "TextParsing: not a digit as expected"; 4138 } 4139 this._buffer.push(cUni); 4140 break; 4141 case 'A': // Alphebetic 4142 var cUni = this.jsonModel._dataString.charAt(this._strPos++); 4143 if(!xfalib.ut.PictureUtils.isLetter(cUni)){ 4144 throw "TextParsing: not a character as expected"; 4145 } 4146 this._buffer.push(cUni); 4147 break; 4148 case 'O': // Alphanumeric 4149 case '0': 4150 var cUni = this.jsonModel._dataString.charAt(this._strPos++); 4151 if(!xfalib.ut.PictureUtils.isLetterOrDigit(cUni)){ 4152 throw "TextParsing: not a character or digit as expected"; 4153 } 4154 this._buffer.push(cUni); 4155 break; 4156 case 'X': 4157 var cUni = this.jsonModel._dataString.charAt(this._strPos++); 4158 this._buffer.push(cUni); 4159 break; 4160 case 't': 4161 if(this.jsonModel._dataString.charAt(this._strPos++)=="\t"){ 4162 this._buffer.push("\t"); 4163 }else{ 4164 throw "TextParsing: not a Tab as expected"; 4165 } 4166 break; 4167 default: 4168 if(this.jsonModel._dataString.charAt(this._strPos++)== chr){ 4169 this._buffer.push(chr); 4170 }else{ 4171 throw "TextParsing: not '" + chr+"' as expected"; 4172 } 4173 } 4174 } 4175 4176 }, 4177 /** 4178 * 4179 * @override 4180 */ 4181 getResult : function(){ 4182 if(this._strPos < this.jsonModel._dataString.length) 4183 throw "TextParsing: picture clause smaller than input Text"; 4184 return this._buffer.join(""); 4185 }, 4186 /** 4187 * 4188 * @override 4189 */ 4190 acceptPatternChar : function(chr){ 4191 return xfalib.ut.PictureUtils.inString(chr, "9AO0Xt"); 4192 } 4193 4194 }); 4195})(_,xfalib); 4196 4197 4198/** 4199 * @package xfalib.ut.NumParsingVisitor 4200 * @import xfalib.ut.ParsingVisitorBase 4201 * @fileOverview Parses a string according to Text Picture. 4202 * @version 0.0.1 4203 */ 4204 4205/** 4206 * @constructor 4207 * @param Object {jsonModel: {_sPicture: String,_dataString: String}} 4208 */ 4209 4210(function(_,xfalib){ 4211 var NumParsingVisitor = xfalib.ut.NumParsingVisitor = xfalib.ut.ParsingVisitorBase.extend({ 4212 4213 initialize: function(options) { 4214 this._pictureDesc = new xfalib.ut.NumPictureDesc({jsonModel:{_sPicture:this.jsonModel._sPicture}}); 4215 this.jsonModel._sPicture = this._pictureDesc.getPicture(); 4216 this._buffer = []; 4217 this._strPos = 0; 4218 this._hasRadix = false; 4219 this._mbNegative = false; 4220 this._mbDigitSeen = false; // at least one digit has been added to output 4221 this._mbSignSeen = false; 4222 this._mBacktrack = null; 4223 this._hasPercent = false; 4224 this._mbExponSeen = false; 4225 4226 this._mNumberSymbols = xfalib.ut.PictureUtils.getLocaleObject(this.options._locale,"numberSymbols");
4227 this._mCurrencySymbols = xfalib.ut.PictureUtils.getLocaleObject(this.options._locale,"currencySymbols"); 4228 }, 4229 4230 _lookupNext : xfalib.ut.Scanner.lookupNext, 4231 4232 parse : function(){ 4233 var patPos = 0; 4234 while(true){ 4235 try{ 4236 for(var token = this._lookupNext(this.jsonModel._sPicture, patPos, this.acceptPatternChar); token != null; ){ 4237 this.consume(token); 4238 patPos = patPos + token.len; 4239 token = this._lookupNext(this.jsonModel._sPicture, patPos, this.acceptPatternChar); 4240 } 4241 }catch(e){ 4242 //mismatch, try again! 4243 if(this._mBacktrack){ 4244 patPos = this._mBacktrack.patPos; 4245 this._buffer.length = 0; 4246 this._strPos = this._mBacktrack.strPos; 4247 this._mbDigitSeen = false; 4248 this._mBacktrack = null; 4249 continue; 4250 } 4251 } 4252 break; 4253 } 4254 }, 4255 consumeSubPattern : function(token){ 4256 4257 var chr = token.patChar; 4258 var chrCnt = token.len; 4259 var fw = false; 4260 switch (chr) { 4261 case '9': 4262 case '8': 4263 case 'Z': // Digit or space if zero. 4264 case 'z':// Digit or nothing if zero. 4265 while (chrCnt-- > 0 ) { 4266 if(!this._mbDigitSeen){ 4267 var cUni = this.jsonModel._dataString.charAt(this._strPos); 4268 if(cUni == '-'){ 4269 this._mbNegative = true; 4270 cUni = this.jsonModel._dataString.charAt(++this._strPos); 4271 } 4272 if(chr== '9' || chr == '8'){ 4273 if(!xfalib.ut.PictureUtils.isDigit(cUni)){ 4274 throw "TextParsing: not a digit as expected"; 4275 } 4276 this._buffer.push(cUni); 4277 this._mbDigitSeen =true; 4278 }else if(chr =='Z'){ 4279 if(xfalib.ut.PictureUtils.isDigit(cUni)){ 4280 this._buffer.push(cUni); 4281 this._mbDigitSeen =true; 4282 }else if(cUni != ' '){ 4283 throw "TextParsing: not a digit or space as expected"; 4284 } 4285 }else { 4286 // has to be 'z', eagerly try to match a digit, if a mismatch is latterly found, backtrack 4287 if(xfalib.ut.PictureUtils.isDigit(cUni)){ 4288 this._buffer.push(cUni); 4289 this._mbDigitSeen =true; 4290 this._mBacktrack = { 4291 "patPos" : token.patPos + token.len - chrCnt, //new position from next char after 'z' 4292 "strPos" : this._strPos 4293 }; 4294 }else { 4295 throw "TextParsing: not a digit or space as expected"; 4296 } 4297 } 4298 ++this._strPos; 4299 }else{ 4300 var cUni = this.jsonModel._dataString.charAt(this._strPos); 4301 if(xfalib.ut.PictureUtils.isDigit(cUni)){ 4302 this._buffer.push(cUni); 4303 ++this._strPos; 4304 }else{ 4305 if(chr !='z'){ 4306 throw "TextParsing: not a digit as expected"; 4307 }else{ 4308 ++this._strPos; 4309 } 4310 } 4311 } 4312 } 4313 4314 break; 4315 case 'V' : 4316 case 'v' : 4317 case '.' : 4318 if(this._matchStr(this._mNumberSymbols.decimal)){ 4319 this._hasRadix = true; 4320 this._buffer.push('.'); 4321 this._mbDigitSeen =true; 4322 }else{ 4323 throw "TextParsing: not a radix as expected"; 4324 } 4325 break; 4326 case 'E': // Exponent. 4327 if(this._matchStr('E')){ 4328 this._buffer.push('E'); 4329 if(this._matchStr('+')){ 4330 // 4331 }else if(this._matchStr('-')){ 4332 this.jsonModel._buffer.push('-'); 4333 } 4334 var strLen = this.jsonModel._dataString.length; 4335 while(this._strPos < strLen && 4336 xfalib.ut.PictureUtils.isDigit(this.jsonModel._dataString.charAt(this._strPos))){ 4337 this._buffer.push(this.jsonModel._dataString.charAt(this._strPos++)); 4338 } 4339 } 4340 break; 4341 4342 case 'C': // CR symbol if negative and spaces if positive. 4343 if(this._matchStr(xfalib.ut.NumPictureDesc.gsCR)){ 4344 this._mbNegative = true; 4345 }else if(!this._matchStr(xfalib.ut.NumPictureDesc.gsDSP)){ 4346 throw "TextParsing: not a CR as expected"; 4347 } 4348 break; 4349 case 'c': // CR symbol if negative and nothing if positive. 4350 if(this._matchStr(xfalib.ut.NumPictureDesc.gsCR)){ 4351 this._mbNegative = true; 4352 } 4353 break; 4354 case 'D': // DB symbol if negative and spaces if positive. 4355 if(this._matchStr(xfalib.ut.NumPictureDesc.gsDB)){ 4356 this._mbNegative = true; 4357 }else if(!this._matchStr(xfalib.ut.NumPictureDesc.gsDSP)){ 4358 throw "TextParsing: not a CR as expected"; 4359 } 4360 break; 4361 case 'd': // DB symbol if negative and nothing if positive. 4362 if(this._matchStr(xfalib.ut.NumPictureDesc.gsDB)){ 4363 this._mbNegative = true; 4364 } 4365 break; 4366 case 'S': // Minus sign if negative and a space if positive. 4367 if(this._matchStr(this._mNumberSymbols.negative,fw)){ 4368 this._mbNegative = true; 4369 }else if(!this._matchStr(" ")){ 4370 throw "TextParsing: not a CR as expected"; 4371 } 4372 break; 4373 case 's': 4374 if(this._matchStr(this._mNumberSymbols.negative,fw)){ 4375 this._mbNegative = true; 4376 } 4377 break; 4378 case 0xFF0C: // Fullwidth ','. 4379 case ',': // Grouping separator. 4380 while (chrCnt-- > 0) { 4381 if(!this._matchStr(this._mNumberSymbols.grouping, fw)){ 4382 throw "TextParsing: not a grouping symbol as expected"; 4383 } 4384 } 4385 break; 4386 case 0xFF04: // Fullwidth '$'. 4387 case '$': // Currency name or symbol. 4388 while (chrCnt-- > 0) { 4389 if(!this._matchStr(this._mCurrencySymbol
4389s.symbol, fw)){ 4390 throw "TextParsing: not a grouping symbol as expected"; 4391 } 4392 } 4393 break; 4394 case 0xFF05: // Fullwidth '%'. 4395 case '%': // Percent symbol. 4396 while (chrCnt-- > 0) { 4397 if(!this._matchStr(this._mNumberSymbols.percent, fw)){ 4398 throw "TextParsing: not a grouping symbol as expected"; 4399 } 4400 } 4401 this._hasPercent = true; 4402 break; 4403 case 0xFF08: // Fullwidth '('. 4404 case 0xFF09: // Fullwidth ')'. 4405 case '(': // Left parenthesis. 4406 case ')': // Right parenthesis. 4407 if(this._matchStr(chr,fw)){ 4408 this._mbNegative = true; 4409 }else if(!this._matchStr(" ")){ 4410 throw "TextParsing: not parentesis as expected"; 4411 } 4412 break; 4413 case 't': // tab. 4414 while (chrCnt-- > 0) this._matchStr('\t',fw); 4415 } 4416 }, 4417 getResult : function(){ 4418 var stringNum = this._buffer.join(""); 4419 if(this._hasPercent) { 4420 var buf = new Array(); 4421 stringNum = Number(stringNum).toString(); 4422 var dot = stringNum.indexOf('.'); 4423 4424 var pos = dot-2; 4425 if(pos ==0) buf.push("0"); 4426 else if(pos ==-1) buf.push("0.0"); 4427 else if(pos ==-3) pos = stringNum.length - 2; 4428 for(var index=0;index < stringNum.length; index++){ 4429 if(index == pos){ 4430 buf.push("."); 4431 } 4432 if(index != dot){ 4433 buf.push(stringNum.charAt(index)); 4434 } 4435 } 4436 stringNum = buf.join(""); 4437 } 4438 var number = Number(stringNum); 4439 if(this._mbNegative) number = -number; 4440 return number.toString(); 4441 }, 4442 4443 _matchStr : function(target){ 4444 if(xfalib.ut.PictureUtils.matchString(this.jsonModel._dataString, this._strPos, target)){ 4445 this._strPos+= target.length; 4446 return true; 4447 }else{ 4448 return false; 4449 } 4450 }, 4451 4452 /** 4453 * 4454 * @override 4455 */ 4456 acceptPatternChar : function(chr){ 4457 return xfalib.ut.PictureUtils.inString(chr, "(%$,.)89BCDERSVZbcdrsvzt"); 4458 } 4459 }); 4460})(_,xfalib); 4461/** 4462 * @package xfalib.ut.DateParsingVisitor 4463 * @import xfalib.ut.ParsingVisitorBase 4464 * @fileOverview The file provides parsing/formating logic on date pattern characters. 4465 * @version 0.0.1 4466 */ 4467 4468/** 4469 * @constructor 4470 * @param Object {jsonModel: {_sPicture: String, _dataString: String]} 4471 */ 4472 4473(function(_,xfalib) { 4474 var DateParsingVisitor = xfalib.ut.DateParsingVisitor = xfalib.ut.ParsingVisitorBase.extend({ 4475 4476 initialize: function() { 4477 this._dateInfo = new xfalib.ut.DateInfo({isParsingCall : true}); 4478 this._dayOfMonth = this._monthOfYear = this._yearOfEra = null; // used to validate date once all sub patterns are consumed 4479 DateParsingVisitor._super.initialize.call(this); 4480 }, 4481 4482 consumeSubPattern : function(token){ 4483 var chr = token.patChar; 4484 var chrCnt = token.len; 4485 var curPos = this._strPos; 4486 var scannedChar = chrCnt; 4487 4488 //TODO: need to remove this assert. 4489 this._assert(curPos+chrCnt <=this.jsonModel._dataString.length, "Mismatch"); 4490 4491 switch (chr) { 4492 case 'D': 4493 switch(chrCnt){ 4494 case 1: 4495 var parsed = xfalib.ut.PictureUtils.parseIntAggressive(this.jsonModel._dataString, curPos, 2); // 1-2 digit(1-31) 4496 this._dayOfMonth = parsed.value; 4497 scannedChar = parsed.len; 4498 break; 4499 case 2: 4500 this._dayOfMonth = xfalib.ut.PictureUtils.parseIntExact(this.jsonModel._dataString, curPos, 2); // 1-2 digit(1-31) 4501 break; 4502 } 4503 this._assert(this._dayOfMonth <= 31 && this._dayOfMonth >0, "Invalid date string1"); 4504 break; 4505 case 'J': 4506 4507 //this._mDayOfYear; 4508 break; 4509 case 'M': 4510 var symbol = ""; 4511 switch(chrCnt){ 4512 case 1: 4513 var parsed = xfalib.ut.PictureUtils.parseIntAggressive(this.jsonModel._dataString, curPos, 2); // 1-2 digit(1-12) 4514 this._monthOfYear = parsed.value; 4515 scannedChar = parsed.len; 4516 break; 4517 case 2: 4518 this._monthOfYear = xfalib.ut.PictureUtils.parseIntExact(this.jsonModel._dataString, curPos, 2); // 2 digit(01-12) 4519 break; 4520 case 3: 4521 symbol = "calendarSymbols.abbrmonthNames"; 4522 break; 4523 case 4: 4524 symbol = "calendarSymbols.monthNames" 4525 break; 4526 4527 } 4528 if(symbol) { 4529 var hashObj = xfalib.ut.PictureUtils.getHashOfLocaleObject(this.jsonModel._locale,symbol), 4530 str = this.jsonModel._dataString.toLowerCase(), 4531 hash = 0, 4532 curStr = "" 4533 scannedChar = 0; 4534 while(curPos+scannedChar < str.length) { 4535 hash += (scannedChar+1)*str.charCodeAt(curPos+scannedChar) 4536 curStr+= str.charAt(curPos+scannedChar); 4537 scannedChar++; 4538 if(hashObj[hash] && hashObj[hash].indexOf(curStr) > -1 ) break; 4539 } 4540 var monthNames = _.map(xfalib.ut.PictureUtils.getLocaleObject(this.jsonModel._locale, symbol), function (str) { 4541 return str.toLowerCase(); 4542 }); 4543 this._monthOfYear = monthNames.indexOf(curStr) + 1; // months are from 1 to 12 4544 } 4545 //TODO: remove this assert 4546 this._assert(this._monthOfYear <= 12 && this._monthOfYear >0, "Invalid date string2"); 4547 break; 4548 case 'E': 4549 var symbol = "" 4550 switch(chrCnt) { 4551 case 1: 4552 scannedChar = 1; 4553 break; 4554 case 3: 4555 symbol = "calendarSymbols.abbrdayNames"; 4556 break; 4557 case 4: 4558 symbol = "calendarSymbols.dayNames" 4559 break; 4560 default: 4561 throw "unsupported Picture Clause "; 4562 } 4563 if(symbol) { 4564 var hashObj = xfalib.ut.PictureUtils.getHashOfLocaleObject(this.jsonModel._locale,symbol); 4565 scannedChar = 0; 4566 var str = this.jsonModel._dataString.toLowerCase(); 4567 var hash = 0; 4568 var curStr = ""; 4569 while(curPos+scannedChar < str.length) { 4570 hash += (scannedChar+1)*str.charCodeAt(curPos+scannedChar) 4571 curStr+= str.charAt(curPos+scannedChar); 4572 scannedChar++; 4573 if(hashObj[hash] && hashObj[hash].indexOf(curStr) > -1) break; 4574 } 4575 } 4576 break; 4577 4578 case 'e': 4579 break; 4580 case 'G': 4581 break; 4582 case 'Y': 4583 4584 switch(chrCnt){ 4585 case 2: 4586 this._yearOfEra = xfalib.ut.PictureUtils.parseIntExact(this.jsonModel._dataString, curPos, 2); // 2 digit(00-99) 4587 this._yearOfEra+=2000; 4588 if(this._yearOfEra >= 2029){ 4589 this._yearOfEra -=100; 4590 } 4591 break; 4592 case 4: 4593 this._yearOfEra = xfalib.ut.PictureUtils.parseIntExact(this.jsonModel._dataString, curPos, 4); // 2 digit(0000-9999) 4594 break; 4595 } 4596 4597 this._assert(this._yearOfEra <= 9999 && this._yearOfEra >=0, "Invalid date string3"); 4598 break; 4599 case 'w': 4600 break; 4601 case 'W': 4602 break; 4603 default: throw "Unsupported pattern"; 4604 } 4605 4606 if(this._yearOfEra && this._monthOfYear && this._dayOfMonth){ 4607 this._dateInfo.validate(this._yearOfEra, this._monthOfYear, this._dayOfMonth); 4608 } 4609 4610 this._strPos += scannedChar; 4611 }, 4612 4613 getDate : function(){ 4614 return this._dateInfo.date; 4615 }, 4616 4617 getResult: function(){ 4618 if (this._strPos < this.jsonModel._dataString.length) { 4619 throw "DateParsing: picture clause smaller than input Date"; 4620 } 4621 return this._dateInfo.getISODate(); 4622 }, 4623 4624 _assert : function(condition, message){ 4625 if(!condition){ 4626 throw message; 4627 } 4628 } 4629 }); 4630})(_,xfalib); 4631 4632/************************************************************************* 4633 * 4634 * ADOBE CONFIDENTIAL 4635 * ___________________ 4636 * 4637 * Copyright 2013 Adobe Systems Incorporated 4638 * All Rights Reserved. 4639 *
4640 * NOTICE: All information contained herein is, and remains 4641 * the property of Adobe Systems Incorporated and its suppliers, 4642 * if any. The intellectual and technical concepts contained 4643 * herein are proprietary to Adobe Systems Incorporated and its 4644 * suppliers and are protected by trade secret or copyright law. 4645 * Dissemination of this information or reproduction of this material 4646 * is strictly forbidden unless prior written permission is obtained 4647 * from Adobe Systems Incorporated. 4648 **************************************************************************/ 4649 4650 4651 4652(function(_, $, xfalib){ 4653 4654 var LocalizationUtil = xfalib.ut.LocalizationUtil = xfalib.ut.Class.extend({ 4655 4656 getLocalizedMessage: function(category, message, snippets){ 4657 var resolvedMessage = message; 4658 if(snippets){ 4659 //resolve message with snippet 4660 resolvedMessage = resolvedMessage.replace(/{(\d+)}/g, function(match, number) { 4661 return typeof snippets[number] != 'undefined' 4662 ? snippets[number] 4663 : match 4664 ; 4665 }); 4666 } 4667 var text = ""; 4668 if (category) { 4669 text += " [" + category + "]"; 4670 } 4671 text += " " + resolvedMessage + "\r\n" ; 4672 return text; 4673 } 4674 4675 }); 4676})(_, $, xfalib); 4677 4678 4679/************************************************************************* 4680 * ADOBE CONFIDENTIAL 4681 * ___________________ 4682 * 4683 * Copyright 2013 Adobe Systems Incorporated 4684 * All Rights Reserved. 4685 *
4686 * NOTICE: All information contained herein is, and remains 4687 * the property of Adobe Systems Incorporated and its suppliers, 4688 * if any. The intellectual and technical concepts contained 4689 * herein are proprietary to Adobe Systems Incorporated and its 4690 * suppliers and are protected by all applicable intellectual property 4691 * laws, including trade secret and copyright laws. 4692 * Dissemination of this information or reproduction of this material 4693 * is strictly forbidden unless prior written permission is obtained 4694 * from Adobe Systems Incorporated. 4695 **************************************************************************/ 4696 4697 4698 4699 4700(function(_, $, xfalib){ 4701 xfalib.view.util.TextMetrics = { 4702 xfaUtil : xfalib.ut.XfaUtil.prototype, 4703 ERROR_MARGIN : 1, 4704 $measureEl : null, 4705 initialize : function(divEl){ 4706 if(!divEl){ 4707 var $div = $("<div></div>"); 4708 $div.attr("id", "textMetrics"); 4709 var divStyles = {}; 4710 divStyles.left = -1000; 4711 divStyles.top = -1000; 4712 divStyles.position = "absolute"; 4713 divStyles.visibility = "hidden"; 4714 this.xfaUtil.$css($div.get(0), divStyles); 4715 this.$measureEl = $div; 4716 $("body").append(this.$measureEl); 4717 }else{ 4718 this.$measureEl = divEl; 4719 } 4720 }, 4721 4722 measureExtent : function(text, options){ 4723 text = text + " "; 4724 if(!this.$measureEl){ 4725 this.initialize(); 4726 } 4727 options = options || {}; 4728 var textStyles = {}; 4729 var $refEl = $(options.refEl || "<div></div>") ; 4730 var refEl = $refEl.get(0); 4731 textStyles.fontSize = $refEl.css("fontSize") || options["font-size"] || options["fontSize"]; 4732 textStyles.fontStyle = $refEl.css("fontStyle") || options["font-style"] || options["fontStyle"]; 4733 textStyles.fontWeight = $refEl.css("fontWeight") || options["font-weight"] || options["fontWeight"]; 4734 textStyles.fontFamily = $refEl.css("fontFamily") || options["font-family"] || options["fontFamily"]; 4735 textStyles.lineHeight = refEl.style.lineHeight || options["line-height"] || options["lineHeight"]; 4736 textStyles.letterSpacing = $refEl.css("letterSpacing") || options["letter-spacing"] || options["letterSpacing"]; 4737 textStyles.whiteSpace = $refEl.css("whiteSpace") || options["white-space"] || options["whiteSpace"] || "pre-wrap"; 4738 if( $.browser.mozilla && $refEl.is("textarea")) // for Bug #3621180 4739 textStyles.whiteSpace = "pre-wrap"; 4740 textStyles.wordBreak = $refEl.css("wordBreak") || options["word-break"] || options["wordBreak"] || "break-all"; 4741 textStyles.wordWrap = $refEl.css("wordWrap") || options["word-wrap"] || options["wordWrap"] || "break-word"; 4742 textStyles.width = this._elWidth(refEl, options); 4743 textStyles.height = this._elHeight(refEl, options); 4744 textStyles.minWidth = this._elMinWidth(refEl, options); 4745 textStyles.minHeight = this._elMinHeight(refEl, options); 4746 textStyles.maxWidth = this._elMaxWidth(refEl, options); 4747 textStyles.maxHeight = this._elMaxHeight(refEl, options); 4748 this.xfaUtil.$css(this.$measureEl.get(0), textStyles); 4749 // for text fields/areas and draw requiring rich text support 4750 if(options.contentType === "text/html"){ 4751 // retaining for future use . If we use the above property for other rich text 4752 if(options.skipXSSProtection) { 4753 this.$measureEl.html(text); 4754 } else { 4755 this.$measureEl.html(xfalib.ut.XfaUtil.prototype.encodeScriptableTags(text)); 4756 } 4757 }else { 4758 text = text.replace(/\n\r/g,"\n").replace(/\r\n/g,"\n").replace(/\r/g, "\n"); 4759 this.$measureEl.text(text); 4760 } 4761 var measuredWidth = this.$measureEl.width(); 4762 var measuredHeight = this.$measureEl.height(); 4763 4764 if(measuredWidth == Math.ceil(options["width"]) || measuredWidth == Math.floor(options["width"])){ 4765 measuredWidth = options["width"]; 4766 } 4767 /* 4768 FORMS-11363 : fix for height calculation of table cell 4769 Enable this toggle for old behaviour (if any regression comes) 4770 */ 4771 else if ((window.FD && window.FD.isToggleEnabled("FT_FORMS-11363")) && (options["maxWidth"] > measuredWidth || (measuredWidth > options["minWidth"] > 0 && (options["maxWidth"] || -1) < 0))) { 4772 //complicated, please simplify if below hurts you: Add error margin if there is scope of further extension of extent 4773 measuredWidth = measuredWidth + 1; 4774 } else if (options["maxWidth"] > measuredWidth || (measuredWidth > options["minWidth"] > 0 && (options["maxWidth"] || -1) < 0)) { 4775 //complicated, please simplify if below hurts you: Add error margin if there is scope of further extension of extent 4776 measuredWidth = measuredWidth; 4777 } 4778 4779 if(measuredHeight == Math.ceil(options["height"]) || measuredHeight == Math.floor(options["height"])){ 4780 measuredHeight = options["height"]; 4781 } 4782 else if( $refEl.is("textarea") && (options["maxHeight"] > measuredHeight || (measuredHeight > options["minHeight"] > 0 && (options["maxHeight"] || -1) < 0))){ 4783 measuredHeight = measuredHeight +1; 4784 } 4785 this.$measureEl.empty(); 4786 return {width : measuredWidth, height : measuredHeight}; 4787 }, 4788 4789 _elWidth : function(refEl, options){ 4790 if(options["minWidth"] && options["minWidth"] > -1) 4791 return "auto"; 4792 else if(options["maxWidth"] && options["maxWidth"] > -1) 4793 return "auto"; 4794 else 4795 return options["width"] || "auto"; 4796 }, 4797 4798 _elHeight : function(refEl, options){ 4799 // TODO: check for calculations here for floating field and other cases. 4800 if(options["contentType"] === "text/html") 4801 return "auto"; 4802 if(options.isDraw) { // for handling the case of draw having floating fields 4803 return "auto"; 4804 } 4805 if(!$(refEl).is("textarea")) 4806 return options["height"] || "auto"; 4807 if(options["minHeight"] && options["minHeight"] > -1) 4808 return "auto"; 4809 else if(options["maxHeight"] && options["maxHeight"] > -1) 4810 return "auto"; 4811 else 4812 return options["height"] || "auto"; 4813 }, 4814 4815 _elMinWidth : function(refEl, options){ 4816 if(options["minWidth"] && options["minWidth"] > -1) 4817 return options["minWidth"]; 4818 else 4819 return "0"; //default css value 4820 }, 4821 4822 _elMinHeight : function(refEl, options){ 4823 if(options["minHeight"] && options["minHeight"] > -1) 4824 return options["minHeight"]; 4825 else 4826 return "0"; //default css value 4827 }, 4828 4829 _elMaxWidth : function(refEl, options){ 4830 if(options["maxWidth"] && options["maxWidth"] > -1) 4831 return options["maxWidth"]; 4832 else 4833 return "none"; //default css value 4834 }, 4835 4836 _elMaxHeight : function(refEl, options){ 4837 if(options["maxHeight"] && options["maxHeight"] > -1) 4838 return options["maxHeight"]; 4839 else 4840 return "none"; //default css value 4841 }, 4842 4843 _destroy : function() { 4844 $("#textMetrics").remove(); 4845 this.$measureEl = null; 4846 } 4847 } 4848})(_, $, xfalib); 4849(function($, _) { 4850 4851 $.alertBox = { 4852 4853 verticalOffset: -75, 4854 horizontalOffset: 0, 4855 repositionOnResize: true, 4856 overlayOpacity: 0.01,
4857 overlayColor: '#FFF', 4858 draggable: false, 4859 dialogClass: null, 4860 imageDirectory: "..", 4861 images: ["A_Warning_Lg_N.png", "A_Alert2_Lg_N.png", "C_QuestionBubble_Xl_N.png", "A_InfoBlue_32x32_N.png"], 4862 4863 alert: function(img, message, title, callback) { 4864 this._show(img, title, message, null, 'OK', function(result) { 4865 if( callback ) callback(result); 4866 }); 4867 }, 4868 4869 okCancel: function(img, message, title, callback) { 4870 this._show(img, title, message, null, 'OK-Cancel', function(result) { 4871 if( callback ) callback(result); 4872 }); 4873 }, 4874 yesNo: function(img, message, title, callback) { 4875 this._show(img, title, message, null, 'Yes-No', function(result) { 4876 if( callback ) callback(result); 4877 }); 4878 }, 4879 4880 yesNoCancel: function(img, message, title, callback) { 4881 this._show(img, title, message, null, 'Yes-No-Cancel', function(result) { 4882 if( callback ) callback(result); 4883 }); 4884 }, 4885 4886 _createBox: function(msgBox_message,buttons,callback) { 4887 var that = this; 4888 $("#"+msgBox_message).after("<div id='msgBox_panel'>"); 4889 _.each(buttons.split("-"),function(val,i) { 4890 var dispval = xfalib.locale.Strings[val.toLowerCase()] ? xfalib.locale.Strings[val.toLowerCase()] : val; // keys in loaclization files are in lower-case 4891 $("#msgBox_panel").append("<input type='button' value='"+dispval+"' id = 'msgBox_"+val+"' class=msgbox_input />"); 4892 $("#msgBox_"+val).click( function() { 4893 that._hide(); 4894 callback(!i); 4895 }); 4896 if(!i) $("msgBox_"+val).focus(); 4897 }); 4898 }, 4899 4900 _show: function(img, title, msg, value, type, callback) { 4901 4902 this._hide(); 4903 this._overlay('show'); 4904 4905 $("BODY").append( 4906 '<div id="msgBox_container">' + 4907 '<h1 id="msgBox_title"></h1>' + 4908 '<div id="msgBox_content">' + 4909 '<div id="msgBox_message"></div>' + 4910 '</div>' + 4911 '</div>'); 4912 4913 if( this.dialogClass ) $("#msgBox_container").addClass($.alertBox.dialogClass); 4914 4915 $("#msgBox_container").css({ 4916 position: 'absolute', 4917 zIndex: 99999, 4918 padding: 0, 4919 margin: 0 4920 }); 4921 4922 $("#msgBox_title").text(title); 4923 $("#msgBox_content").addClass("msgBoxType"+img);//css("background-image","url("+this.imageDirectory+ this.images[img]+")"); 4924 msg = xfalib.ut.XfaUtil.prototype.encodeScriptableTags(msg.replace(/\n/g, '<br />')); 4925 $("#msgBox_message").html(msg); 4926 4927 $("#msgBox_container").css({ 4928 minWidth: $("#msgBox_container").outerWidth(), 4929 maxWidth: $("#msgBox_container").outerWidth() 4930 }); 4931 4932 this._reposition(); 4933 this._maintainPosition(true); 4934 4935 this._createBox("msgBox_message",type,callback); 4936 4937 //TODO: Make keyboard input work 4938 /*$("#msgBox_ok").keypress( function(e) { 4939 if( e.keyCode == 13 || e.keyCode == 27 ) $("#msgBox_ok").trigger('click'); 4940 }); 4941 $("#msgBox_cancel").keypress( function(e) { 4942 if( e.keyCode == 13 ) $("#msgBox_ok").trigger('click'); 4943 if( e.keyCode == 27 ) $("#msgBox_cancel").trigger('click'); 4944 }); 4945 $("#msgBox_yes, #msgBox_no").keypress( function(e) { 4946 if( e.keyCode == 13 ) $("#msgBox_yes").trigger('click'); 4947 if( e.keyCode == 27 ) $("#msgBox_no").trigger('click'); 4948 });*/ 4949 4950 }, 4951 4952 _hide: function() { 4953 $("#msgBox_container").remove(); 4954 this._overlay('hide'); 4955 this._maintainPosition(false); 4956 }, 4957 4958 _overlay: function(status) { 4959 switch( status ) { 4960 case 'show': 4961 this._overlay('hide'); 4962 $("BODY").append('<div id="msgBox_overlay"></div>'); 4963 $("#msgBox_overlay").css({ 4964 position: 'absolute', 4965 zIndex: 99998, 4966 top: '0px', 4967 left: '0px', 4968 width: '100%', 4969 height: $(document).height(), 4970 background: this.overlayColor, 4971 opacity: this.overlayOpacity 4972 }); 4973 break; 4974 case 'hide': 4975 $("#msgBox_overlay").remove(); 4976 break; 4977 } 4978 }, 4979 4980 _reposition: function() { 4981 var windowHeight = $(window).height() / xfalib.ut.XfaUtil.prototype.formScaleFactor, 4982 windowWidth = $(window).width() / xfalib.ut.XfaUtil.prototype.formScaleFactor, 4983 windowScrollTop = $(window).scrollTop() / xfalib.ut.XfaUtil.prototype.formScaleFactor, 4984 windowScrollLeft = $(window).scrollLeft() / xfalib.ut.XfaUtil.prototype.formScaleFactor, 4985 top = ((windowHeight / 2) - ($("#msgBox_container").outerHeight() / 2)) + this.verticalOffset, 4986 left = ((windowWidth / 2) - ($("#msgBox_container").outerWidth() / 2)) + this.horizontalOffset; 4987 if( top < 0 ) top = 0; 4988 if( left < 0 ) left = 0; 4989 4990 // IE6 fix 4991 if( $.browser.msie && parseInt($.browser.version) <= 6 ) top = top + windowScrollTop; 4992 4993 $("#msgBox_container").css({ 4994 top: top + windowScrollTop + 'px', 4995 left: left + windowScrollLeft + 'px' 4996 }); 4997 $("#msgBox_overlay").height( $(document).height() ); 4998 }, 4999 5000 _maintainPosition: function(status) { 5001 if( this.repositionOnResize ) { 5002 switch(status) { 5003 case true: 5004 $(window).on('resize', this._reposition); 5005 break; 5006 case false: 5007 $(window).off('resize', this._reposition); 5008 break; 5009 } 5010 } 5011 } 5012 5013 }; 5014})($, window._);/************************************************************************* 5015 * ADOBE CONFIDENTIAL 5016 * ___________________ 5017 * 5018 * Copyright 2016 Adobe Systems Incorporated 5019 * All Rights Reserved. 5020 *
5021 * NOTICE: All information contained herein is, and remains 5022 * the property of Adobe Systems Incorporated and its suppliers, 5023 * if any. The intellectual and technical concepts contained 5024 * herein are proprietary to Adobe Systems Incorporated and its 5025 * suppliers and are protected by all applicable intellectual property 5026 * laws, including trade secret and copyright laws. 5027 * Dissemination of this information or reproduction of this material 5028 * is strictly forbidden unless prior written permission is obtained 5029 * from Adobe Systems Incorporated. 5030 **************************************************************************/ 5031 5032 5033(function(_, $, xfalib){ 5034 xfalib.view.util.HtmlUtil = { 5035 /* 5036 * Most of the time it returns undefined while accessing an undefined attribute of a dom element. 5037 * But some browsers can throw specific exceptions while accessing an attribute which is un-supported for a specific case. 5038 * This API is to make this behaviour consistent across browsers and return undefined for un-supported attributes. 5039 * */ 5040 getHTMLSupportedAttr : function($domElement, attr){ 5041 try{ 5042 return $domElement[attr]; 5043 } 5044 catch (err){ 5045 return undefined; 5046 } 5047 }, 5048 5049 /** 5050 * Checks if the attribute is supported for the given HTML element. 5051 * This is primarily useful to support HTML5 features in widgets 5052 * @param element name of HTML element 5053 * @param attribute attribute to check on the element 5054 * @returns {boolean} 5055 */ 5056 elementSupportsAttribute : function (element, attribute) { 5057 var test = document.createElement(element); 5058 if (attribute in test) { 5059 $(test).remove(); 5060 test = null; 5061 return true; 5062 } else { 5063 $(test).remove(); 5064 test = null; 5065 return false; 5066 } 5067 } 5068 } 5069})(_, $, xfalib); 5070/************************************************************************* 5071* 5072* ADOBE CONFIDENTIAL 5073* ___________________ 5074* 5075* Copyright 2013 Adobe Systems Incorporated 5076* All Rights Reserved. 5077*
5078* NOTICE: All information contained herein is, and remains 5079* the property of Adobe Systems Incorporated and its suppliers, 5080* if any. The intellectual and technical concepts contained 5081* herein are proprietary to Adobe Systems Incorporated and its 5082* suppliers and are protected by trade secret or copyright law. 5083* Dissemination of this information or reproduction of this material 5084* is strictly forbidden unless prior written permission is obtained 5085* from Adobe Systems Incorporated. 5086**************************************************************************/ 5087 5088 5089 5090(function(_, $, xfalib){ 5091 xfalib.view.util.Styles = { 5092 xfaUtil : xfalib.ut.XfaUtil.prototype, 5093 _deviceResolution : 144.0, //DPI 5094 _in2mmFactor : 25.4, 5095 _pdfResolution : 72.0 , 5096 getStyleForEdge : function (edgeElement, str, cssStyleObj){ 5097 var style = { "raised" : "outset" , 5098 "dashDot" : "dashed" , 5099 "dashDotDot" : "dashed" , 5100 "dashed" : "dashed" , 5101 "dotted" : "dotted" , 5102 "embossed" : "groove" , 5103 "etched" : "inset" , 5104 "lowered" : "ridge", 5105 "solid" : "solid"}; 5106 if(edgeElement && edgeElement.jsonModel.presence != "hidden" && edgeElement.jsonModel.presence !="invisible") { 5107 cssStyleObj['border'+str+'width'] = this._subPixelValue(this._convertToPx(edgeElement.getAttribute('thickness'))) || "1px"; 5108 if(edgeElement.getElement("color") && edgeElement.getElement("color").getAttribute("value") !="") { 5109 var color = edgeElement.getElement("color").getAttribute("value"); 5110 color = "rgb(" + color + ")"; 5111 cssStyleObj['border'+str+'color'] = color ; 5112 } 5113 else { 5114 cssStyleObj['border'+str+'color'] = "rgb(0,0,0)" ; 5115 } 5116 cssStyleObj['border'+str+'style'] = style[edgeElement.getAttribute('stroke')] || "solid" ; 5117 } else { 5118 cssStyleObj['border'+str+'width'] = "0px"; 5119 return 1; 5120 } 5121 5122 }, 5123 5124 getStyleForBorder : function (border) { 5125 if(border) { 5126 var edge = border.getElement('edge', 0, true), 5127 edge1 = border.getElement('edge', 1, true), 5128 edge2 = border.getElement('edge', 2, true), 5129 edge3 = border.getElement('edge', 3, true); 5130 if(edge || edge1 || edge2 || edge3) { 5131 var cssStyleObj = {} ; 5132 var e0 = this.getStyleForEdge(edge, "-top-",cssStyleObj); 5133 var e1 = this.getStyleForEdge(edge1 || edge,"-right-",cssStyleObj); 5134 var e2 = this.getStyleForEdge(edge2|| edge,"-bottom-",cssStyleObj); 5135 var e3 = this.getStyleForEdge(edge3 || edge,"-left-",cssStyleObj); 5136 if(e0 !=1|| e1 !=1|| e2 !=1|| e3!=1) 5137 return cssStyleObj ; 5138 } 5139 } 5140 return null; 5141 }, 5142 5143 _convertToPx : function(size){ 5144 if(!size) 5145 return 0; 5146 size = "" + size; 5147 var pxSize = size; 5148 if(size.indexOf("in") >=0){ 5149 pxSize = this._mm2px(parseFloat(size) * this._in2mmFactor); 5150 } 5151 else if(size.indexOf("mm") >=0){ 5152 pxSize = this._mm2px(size); 5153 } 5154 else if(size.indexOf("cm") >=0){ 5155 pxSize = this._mm2px(parseFloat(size) * 10); 5156 } 5157 else if(size.indexOf("pt") >=0){ 5158 pxSize = parseFloat(size) * (this._deviceResolution/this._pdfResolution); 5159 } 5160 else if(size.indexOf("px") >=0){ 5161 pxSize = parseFloat(size); 5162 } 5163 return pxSize; 5164 }, 5165 5166 _mm2px : function(mmSize){ 5167 var mmSizeNum = 0; 5168 if(_.isNumber(mmSize)) 5169 mmSizeNum = mmSize; 5170 else{ 5171 mmSizeNum = parseFloat(mmSize) 5172 } 5173 var mm2in = 1/25.4 ; 5174 var pxSize = mmSizeNum*mm2in*this._deviceResolution; 5175 return pxSize; 5176 }, 5177 5178 _subPixelValue : function(value){ 5179 if(value > 0.01) 5180 return Math.max(value, 1.0); 5181 else 5182 return value; 5183 } 5184 } 5185})(_, $, xfalib); 5186/************************************************************************* 5187 * ADOBE CONFIDENTIAL 5188 * ___________________ 5189 * 5190 * Copyright 2017 Adobe Systems Incorporated 5191 * All Rights Reserved. 5192 *
5193 * NOTICE: All information contained herein is, and remains 5194 * the property of Adobe Systems Incorporated and its suppliers, 5195 * if any. The intellectual and technical concepts contained 5196 * herein are proprietary to Adobe Systems Incorporated and its 5197 * suppliers and are protected by all applicable intellectual property 5198 * laws, including trade secret and copyright laws. 5199 * Dissemination of this information or reproduction of this material 5200 * is strictly forbidden unless prior written permission is obtained 5201 * from Adobe Systems Incorporated. 5202 **************************************************************************/ 5203 5204 5205 5206 5207(function(_, $, xfalib){ 5208 xfalib.view.util.traversalManager = { 5209 5210 // compute tabIndex for the provided page 5211 _computTabIndex : function (pageView) { 5212 var pageNum = pageView._pageNumber(), 5213 tabIndex = this._tabIndexBasedOnRange(pageNum); 5214 this.geographicalOrder = []; 5215 this._createGeographicalOrder(pageView); 5216 this._createFinalTraversalOrder(tabIndex); // assign tab index using traversal element and geographicalOrder 5217 // 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 5218 this._lastFieldTabbed = null; 5219 }, 5220 5221 _tabIndexBasedOnRange : function (pageNum) { 5222 var behaviorConfig = new xfalib.ut.Version(formBridge.userConfig["behaviorConfig"]), 5223 tabIndexConfig = (behaviorConfig.isOn('mfRangeTabIndex')|| behaviorConfig.isOn('rangeTabIndex')), 5224 /*assuming single page can not have more than 1000 fields.[index -> 0 to 999] 5225 this is also configurable by passing the maximum number of fields allowable in the page 5226 in the config parameter */ 5227 maxFieldInPageForTabIndex = tabIndexConfig? parseInt(tabIndexConfig):1000; 5228 5229 return pageNum * maxFieldInPageForTabIndex; 5230 }, 5231 5232 // to create geographical order array which will be containing all the views in the geographical order 5233 _createGeographicalOrder : function (currentView) { 5234 var sortedChildViewWrapper = this._sortViewGeographically(currentView.childViews); 5235 _.each(sortedChildViewWrapper, function (wrapper) { 5236 var currentView = wrapper.view, 5237 instanceCheckMap = this._getMapOfInstanceCheck(currentView), 5238 isViewEligibleForTabbing = this._isViewEligibleForTabbing(currentView); 5239 // If the child view is fieldView, drawView, exclGroupView or subformView then we will push these views in this.geographicalOrder array, 5240 // as we need their traverse object during final traversing 5241 if (((instanceCheckMap.isField && !instanceCheckMap.isChildOfExclGroup) || instanceCheckMap.isSubform || instanceCheckMap.isDraw 5242 || instanceCheckMap.isExclGroup) && isViewEligibleForTabbing) { 5243 this.geographicalOrder.push({ 5244 view : currentView, 5245 visited : false 5246 }); 5247 } 5248 if (instanceCheckMap.isContainer && isViewEligibleForTabbing) { 5249 this._createGeographicalOrder(currentView); 5250 } 5251 }, this); 5252 }, 5253 5254 // to sort provided views in geographical order 5255 _sortViewGeographically : function (views) { 5256 var viewsWrapper = []; // wrapper of view and their geographical reference 5257 _.each(views, function(view) { 5258 var position = view.$el.offset(), 5259 paddedX = xfalib.ut.XfaUtil.prototype.padString(parseInt(position.left), 5, '0'), 5260 marginTop = view._marginTop(), 5261 paddedY = position.top - parseFloat(marginTop), 5262 positionalReference = parseInt("" + parseInt(paddedY) + paddedX); 5263 viewsWrapper.push({ 5264 positionalReference: positionalReference, 5265 view: view 5266 }); 5267 }); 5268 return _.sortBy(viewsWrapper, function(viewWrapper){ return viewWrapper.positionalReference; }); 5269 }, 5270 5271 // Walk through views in geographical order and assign tab index honouring traversal object if present 5272 _createFinalTraversalOrder : function (tabIndex) { 5273 var geographicalOrderLength = this.geographicalOrder.length, 5274 currentWrappedObj = null, 5275 index = -1, 5276 traversalIndex = 0, // index of the element to be traversed 5277 viewTraversed = 0; // counter of view traversed 5278 5279 while (1) { 5280 if (traversalIndex >= geographicalOrderLength) { 5281 traversalIndex = 0; 5282 } 5283 currentWrappedObj = this.geographicalOrder[traversalIndex]; 5284 5285 if (!currentWrappedObj || currentWrappedObj.visited) { // if the wrapped object does not exist or it has been visited move to the next one 5286 traversalIndex++; 5287 } else { 5288 currentWrappedObj.visited = true; 5289 viewTraversed++; 5290 var currentView = currentWrappedObj.view, 5291 instanceCheckMap = this._getMapOfInstanceCheck(currentView), 5292 currentModel = currentView.model, 5293 nextView = null, 5294 nextViewSom = null; 5295 5296 // get the first traversal of the subform if traversal object is present, else move to the next geographical element 5297 // next of the subform will be taken care when we will be finding the next view to be traversed, 5298 // as we will be checking if the ancestor contain next before moving to geographically next view 5299 if (instanceCheckMap.isSubform) { 5300 if (currentModel && currentModel.getTraversalObject()) { 5301 // get the first element to be traversed and update traversalIndex 5302 nextViewSom = currentModel.getNextTraversalSom(xfalib.template.Constants.firstTraversal); 5303 index = this._findViewInGeographicalOrderArray(nextViewSom); 5304 traversalIndex = index != -1 ? index : traversalIndex + 1; 5305 } else { 5306 traversalIndex++; 5307 } 5308 // get the next traversal for the field/draw if traversal object is present, else move to the next geographical element 5309 // update the tabindex for the field 5310 } else if (instanceCheckMap.isField || instanceCheckMap.isDraw) { 5311 if (instanceCheckMap.isField) { 5312 currentView.updateTabIndex(tabIndex); 5313 this._lastFieldTabbed = currentView; 5314 tabIndex++; 5315 } 5316 if (currentModel && currentModel.getTraversalObject()) { 5317 //get next element to be traversed and update traversalIndex 5318 nextViewSom = currentModel.getNextTraversalSom(xfalib.template.Constants.nextTraversal); 5319 index = this._findViewInGeographicalOrderArray(nextViewSom); 5320 traversalIndex = index != -1 ? index : traversalIndex + 1; 5321 } else { 5322 traversalIndex = this._findNextViewToBeTraversed(traversalIndex); 5323 } 5324 // if traversal object present get the next element to be traversed, if first is also present then update tab index of the first element 5325 // else look for the traversal element in the children 5326 } else if (instanceCheckMap.isExclGroup) { 5327 if (currentModel && currentModel.getTraversalObject()) { 5328 // get next element to be traversed and update traversalIndex 5329 nextViewSom = currentModel.getNextTraversalSom(xfalib.template.Constants.nextTraversal); 5330 index = this._findViewInGeographicalOrderArray(nextViewSom); 5331 traversalIndex = index != -1 ? index : traversalIndex + 1; 5332 // if first is also present assign tab index to that referred child else assign same tab index to all child 5333 nextViewSom = currentModel.getNextTraversalSom(xfalib.template.Constants.firstTraversal); 5334 tabIndex = this._updateTabIndexOfExclGroupChildren(currentView, tabIndex, nextViewSom); 5335 } else { 5336 tabIndex = this._updateTabIndexOfExclGroupChildren(currentView, tabIndex); 5337 traversalIndex = this._findTraversalInExclGroupChildren(currentView, traversalIndex); 5338 } 5339 } else { 5340 traversalIndex++; 5341 } 5342 } 5343 5344 // if all the view are traversed, we have assigned tab index to all the views 5345 if (viewTraversed >= geographicalOrderLength) { 5346 this._renderNextPageFuture(); 5347 break; 5348 } 5349 } 5350 }, 5351 5352 // Check if the nextView is a sibling of the currentView (shares the same parent) 5353 // if it is not a sibling, check if the parent has a NEXT traversal. 5354 // if so get the node traversed to else recurse to see if nextView is a sibling of our parent 5355 // return -1 if the provided next node is sibling of current node or if no ancestor contain next traversal 5356 // else return index of the next traversal object of parent 5357 _getParentNextTraversal : function (currentView, nextView, traversalIndex) { 5358 var parentView = currentView.parentView, 5359 parentModel = parentView.model, 5360 nextViewParentModel = nextView.parentView.model, 5361 traversalObj = null, 5362 nextIndex = -1; 5363 5364 if (parentModel && nextViewParentModel && parentModel.somExpression != nextViewParentModel.somExpression) { 5365 if(parentView && parentView instanceof xfalib.view.SubformView) { 5366 if (parentModel.getTraversalObject()) { 5367 var nextViewSom = parentModel.getNextTraversalSom(xfalib.template.Constants.nextTraversal); 5368 nextIndex = this._findViewInGeographicalOrderArray(nextViewSom); 5369 if (nextIndex != -1 && !this.geographicalOrder[
5369nextIndex].visited) { 5370 return nextIndex; 5371 } else { 5372 return traversalIndex++; 5373 } 5374 } else { 5375 this._getParentNextTraversal(parentView, nextView, traversalIndex); 5376 } 5377 } else { // parentView is not a subform so skip up a level and re-check sibling 5378 this._getParentNextTraversal(parentView, nextView, traversalIndex); 5379 } 5380 } else { 5381 return -1; //provided currentView and nextView are sibling 5382 } 5383 return traversalIndex++; 5384 }, 5385 5386 // return the index of the view having provided somExpression in the geographicalOrder array 5387 _findViewInGeographicalOrderArray : function (somExpression) { 5388 return _.findIndex(this.geographicalOrder, function (viewWrapper) { 5389 var currentViewModel = viewWrapper.view.model; 5390 return (currentViewModel && currentViewModel.somExpression == somExpression); 5391 }); 5392 }, 5393 5394 // find the next element to be traversed based on the provided traversalIndex 5395 _findNextViewToBeTraversed : function (traversalIndex) { 5396 var currentView = this.geographicalOrder[traversalIndex].view, 5397 index = this._getNextUnvisited(traversalIndex), //get next unvisited based on geographical location 5398 nextView = null, 5399 nextIndex = -1; 5400 5401 if (index != -1) { 5402 nextView = this.geographicalOrder[index].view; 5403 //check if both are sibling and if not find the next of the parent and update traversalIndex 5404 nextIndex = this._getParentNextTraversal(currentView, nextView, traversalIndex); 5405 return nextIndex != -1 ? nextIndex : index; 5406 } 5407 return traversalIndex++; 5408 }, 5409 5410 // return the next unvisited node based on geographical location 5411 // starting from the traversalIndex and wraps around to check all the views 5412 _getNextUnvisited : function (traversalIndex) { 5413 var geographicalOrderLength = this.geographicalOrder.length, 5414 index = 0, 5415 actualIndex = 0; 5416 while(index < geographicalOrderLength) { 5417 actualIndex = (index + traversalIndex) % geographicalOrderLength; 5418 if(!this.geographicalOrder[actualIndex].visited) { 5419 return actualIndex; 5420 } 5421 index++; 5422 } 5423 return -1; 5424 }, 5425 5426 // assign same tab index to all the child of exclude group 5427 // if exclude group contain first traverse object, then the child being referred as first should have less tabindex 5428 // compared to other child 5429 _updateTabIndexOfExclGroupChildren : function (exclGroupView, tabIndex, firstChildSom) { 5430 _.each(exclGroupView.childViews, function(child){ 5431 if (this._isViewEligibleForTabbing(child)) { 5432 if(firstChildSom && child.model.somExpression == firstChildSom) { 5433 tabIndex++; 5434 child.updateTabIndex(tabIndex-1); 5435 this._lastFieldTabbed = child; 5436 } else { 5437 child.updateTabIndex(tabIndex); 5438 } 5439 } 5440 }, this); 5441 if (!firstChildSom) { 5442 this._lastFieldTabbed = exclGroupView.childViews[0]; 5443 } 5444 return ++tabIndex; 5445 }, 5446 5447 // find if any child contains next pointer and update traversal index 5448 // start with the last in the geographical order of the children and find child which have next traversal 5449 _findTraversalInExclGroupChildren : function (exclGroupView, traversalIndex) { 5450 var sortedChildView = this._sortViewGeographically(exclGroupView.childViews), 5451 tempObj = null, 5452 childView = null, 5453 childModel = null, 5454 traversalObj = null, 5455 nextViewSom = null, 5456 index = -1; 5457 5458 sortedChildView.reverse(); 5459 tempObj = _.find(sortedChildView, function(child) { 5460 childView = child.view; 5461 childModel = childView.model; 5462 if(childModel && (traversalObj = childModel.getTraversalObject())) { 5463 return traversalObj.length > 0; 5464 } 5465 }); 5466 5467 if (tempObj) { 5468 nextViewSom = tempObj.model.getNextTraversalSom(xfalib.template.Constants.nextTraversal); 5469 index = this._findViewInGeographicalOrderArray(nextViewSom); 5470 traversalIndex = index != -1 ? index : traversalIndex + 1; 5471 } else { // else get next unvisited based on geographical location 5472 traversalIndex = this._findNextViewToBeTraversed(traversalIndex); 5473 } 5474 return traversalIndex; 5475 }, 5476 5477 // check if the view is initialized and visible 5478 _isViewEligibleForTabbing : function (view) { 5479 if (view._initialized && view.$el.css("visibility") != "hidden") { 5480 return true; 5481 } 5482 return false;
5483 }, 5484 5485 // return map of whethter provided view is instance of the various views 5486 _getMapOfInstanceCheck : function (view) { 5487 var instanceCheckMap = {}; 5488 instanceCheckMap.isSubform = view instanceof xfalib.view.SubformView; 5489 instanceCheckMap.isField = view instanceof xfalib.view.FieldView; 5490 instanceCheckMap.isDraw = view instanceof xfalib.view.XfaDrawView; 5491 instanceCheckMap.isExclGroup = view instanceof xfalib.view.ExclGroupView; 5492 instanceCheckMap.isChildOfExclGroup = view.parentView instanceof xfalib.view.ExclGroupView; 5493 instanceCheckMap.isContainer = view instanceof xfalib.view.ContainerView; 5494 5495 return instanceCheckMap; 5496 }, 5497 5498 // add event handler for rendering next page on tabbing on last field of the page 5499 _renderNextPageFuture : function () { 5500 if (this._lastFieldTabbed) { 5501 this._lastFieldTabbed.$el.one('focusin.traversalManager', function() { 5502 var pagingManager = window.formBridge ? window.formBridge.pagingManager() : null; 5503 $(window).on( "keyup.traversalManager", function (e) { 5504 var code = (e.keyCode ? e.keyCode : e.which); 5505 if (code == 9 && pagingManager && pagingManager.hasMorePages()) { 5506 pagingManager.renderNextPage(); 5507 $(window).off("keyup.traversalManager"); 5508 } 5509 }); 5510 }); 5511 } 5512 }, 5513 _destroy : function() { 5514 this.geographicalOrder = null; 5515 } 5516 } 5517})(_, $, xfalib); 5518/************************************************************************* 5519* 5520* ADOBE CONFIDENTIAL 5521* ___________________ 5522* 5523* Copyright 2013 Adobe Systems Incorporated 5524* All Rights Reserved. 5525*
5526* NOTICE: All information contained herein is, and remains 5527* the property of Adobe Systems Incorporated and its suppliers, 5528* if any. The intellectual and technical concepts contained 5529* herein are proprietary to Adobe Systems Incorporated and its 5530* suppliers and are protected by trade secret or copyright law. 5531* Dissemination of this information or reproduction of this material 5532* is strictly forbidden unless prior written permission is obtained 5533* from Adobe Systems Incorporated. 5534**************************************************************************/ 5535 5536 5537 5538(function(_, $, xfalib){ 5539 5540 var ErrorManager = xfalib.view.util.ErrorManager = xfalib.ut.Class.extend({ 5541 5542 options: { 5543 warningMessageVisible:false, 5544 errorMessageVisible: false 5545 }, 5546 5547 initialize: function () { 5548 $(window).on("destroy.xfa", function () { 5549 $("#error-msg").hide(); 5550 $("#warning-msg").hide(); 5551 }); 5552 }, 5553 5554 onFieldEnter: function (jqWidget) { 5555 var element = jqWidget.element; 5556 if (jqWidget.option("errorMessage")|| jqWidget.option("warningMessage")) { 5557 var pos = $(element).offset(), 5558 styles = {}; 5559 styles.left = (pos.left * (1 / xfalib.ut.XfaUtil.prototype.formScaleFactor) + element.width() + 5) + "px"; 5560 styles.top = pos.top * (1 / xfalib.ut.XfaUtil.prototype.formScaleFactor) + "px"; 5561 if (jqWidget.option("errorMessage")) { 5562 jqWidget.$css($("#error-msg").get(0), styles); 5563 $("#error-msg").text(jqWidget.option("errorMessage")).show(); 5564 jqWidget.option("errorMessageVisible",true); 5565 } 5566 else if (jqWidget.option("warningMessage")) { 5567 jqWidget.$css($("#warning-msg").get(0), styles); 5568 $("#warning-msg").text(jqWidget.option("warningMessage")).show(); 5569 jqWidget.option("warningMessageVisible",true); 5570 } 5571 } 5572 }, 5573 5574 onFieldExit: function (jqWidget) { 5575 if (jqWidget.option("errorMessageVisible")) { 5576 $("#error-msg").hide(); 5577 jqWidget.option("errorMessageVisible",false); 5578 } else if (jqWidget.option("warningMessageVisible")) { 5579 $("#warning-msg").hide(); 5580 jqWidget.option("warningMessageVisible",false); 5581 } 5582 }, 5583 5584 markError: function (jqWidget, msg, type) { 5585 // assigning role="alert" so that JAWS reads-out the validation message 5586 if (type != "warning") { 5587 if ($("#error-msg").length < 1) 5588 $("<div id='error-msg' role='alert'></div>").appendTo('body'); 5589 jqWidget.option("errorMessage",msg); 5590 jqWidget.element.addClass("dataInvalid"); 5591 } else { 5592 if ($("#warning-msg").length < 1) 5593 $("<div id='warning-msg' role='alert'></div>").appendTo('body'); 5594 jqWidget.option("warningMessage",msg); 5595 } 5596 5597 }, 5598 5599 clearError: function (jqWidget) { 5600 this.onFieldExit(jqWidget); 5601 jqWidget.element.removeClass("dataInvalid"); 5602 jqWidget.option("errorMessage",null); 5603 jqWidget.option("warningMessage",null); 5604 } 5605 }); 5606})(_, $, xfalib); 5607(function(_,$, xfalib) { 5608 var xfaUtil = xfalib.ut.XfaUtil.prototype, 5609 BUFFER_SPC = 20; 5610 5611 /* template for the clear Button */ 5612 var clearButtonTemplate = '<div class="dp-clear">' + 5613 '<a></a>' + 5614 '</div>'; 5615 5616 /* template for the calendar 5617 * header contains the navigation icons (left and right arrows) 5618 * and the current caption (which can be date, year or month) 5619 * 5620 * monthview displays the grid for showing the dates for a particular 5621 * month 5622 * 5623 * yearview displays all the months of that year 5624 * 5625 * yearsetview displays a grid of 16 years. This can be configured 5626 * through the option: yearsPerView 5627 * 5628 */ 5629 var calendarTemplate = '<div class="dp-header">' + 5630 '<div class="dp-leftnav"></div>' + 5631 '<div class="dp-caption"></div>' + 5632 '<div class="dp-rightnav"></div>' + 5633 '</div>' + 5634 '<div role="table" class="view dp-monthview"></div>' + 5635 '<div role="table" class="view dp-yearview"></div>' + 5636 '<div role="table" class="view dp-yearsetview"></div>'; 5637 5638 /*template for the timer: not implemented yet */ 5639 var watchTemplate = '<div class="dp-header">' + 5640 '<div class="dp-leftnav"></div>' + 5641 '<div class="dp-caption"></div>' + 5642 '<div class="dp-rightnav"></div>' + 5643 '</div>' + 5644 '<div class="view dp-monthview"></div>' + 5645 '<div class="view dp-yearview"></div>' + 5646 '<div class="view dp-yearsetview"></div>'; 5647 5648 /** default configuration options 5649 * 5650 * container: the html element where the datepicker template will be added 5651 *
5652 * yearsPerView: number of years to show in the yearset view 5653 * 5654 * width: with of the widget 5655 * 5656 * viewHeight: Height of the month,year and yearset view. This doesn't include 5657 * the height of the header 5658 * 5659 * locale: locale information for the locale in which to show the datepicker which comprises of 5660 * days: day names to display in the monthview 5661 * months: month names to display in the yearview 5662 * zero: string representation of zero in the locale. Numbers will be 5663 * displayed in that locale only 5664 * clearText: Text to display for the reset button 5665 * name: name of the locale 5666 * 5667 * format: input format for the datepicker (not implemented) 5668 * 5669 * pickerType: type of the datetimepicker (date, datetime and time) 5670 * 5671 * positioning: element around which datepicker will be displayed. if null then it 5672 * will be displayed around the input element 5673 * 5674 * showCalendarIcon: to show the Calendar on the right of the text field or not 5675 */ 5676 5677 var defaults = { 5678 container: "body", 5679 yearsPerView: 16, 5680 width: 340, 5681 viewHeight: 248, 5682 locale: { 5683 days:["S","M","T","W","T","F","S"], 5684 months: ["January","February","March","April","May","June","July","August","September","October","November","December"], 5685 zero: "0", 5686 clearText: "Clear", 5687 name:"en_US" 5688 }, 5689 format:"YYYY-MM-DD", 5690 pickerType:"date", 5691 positioning: null, 5692 showCalendarIcon: false 5693 }, 5694 dates = [31,28,31,30,31,30,31,31,30,31,30,31], 5695 /* 5696 * Actions to perform when clicked on the datepicker buttons 5697 * for different views 5698 * caption: view to show when clicked on caption 5699 * (Year/YearSet/Month/null) null means don't change the view 5700 * li: view to show when clicked on date, month or year element 5701 * upDown: add(up key) or subtract(down key) current date (for monthview), 5702 * month(Year View) or year(YearSetView) with the number provided 5703 * key: identifies the key that needs to be changed for that view 5704 */ 5705 viewAction = { 5706 Month: { 5707 caption: 'Year', 5708 li: null, 5709 key:"day", 5710 upDown:7 5711 }, 5712 Year: { 5713 caption: "Yearset", 5714 li: "Month", 5715 key:"month", 5716 upDown:3 5717 }, 5718 Yearset: { 5719 caption: null, 5720 li: "Year", 5721 key:"year", 5722 upDown:4 5723 } 5724 }, 5725 headerClass = "header", 5726 5727 DateTimePicker = function() { 5728 this.initialized = false; 5729 } 5730 5731 $.extend(DateTimePicker.prototype, { 5732 /* 5733 * create the widget using the provided options 5734 */ 5735 create: function(options) { 5736 var $dp,self = this,html="",prevNavWidth,nextNavWidth; 5737 if (window.FD && window.FD.isToggleEnabled("FT_FORMS-13599")) { 5738 defaults.width = 433; 5739 } 5740 this.options = $.extend({},defaults,options); 5741 // prevent memory leak since options.positioning holds reference to HTML DOM 5742 this.options.positioning = null; 5743 // If width of date-picker exceeds screen width then it'll take up the entire screen width in AF 5744 if(window.guideBridge && this.options.width > window.innerWidth && window.innerWidth > 0) { 5745 this.options.width=window.innerWidth - BUFFER_SPC; // buffer 5746 } 5747 if(this.options.pickerType.match(/date/)) { 5748 html += calendarTemplate; 5749 } 5750 5751 if(this.options.pickerType.match(/time/)) { 5752 html += watchTemplate; 5753 } 5754 5755 html += clearButtonTemplate; 5756 5757 $.extend(this, { 5758 selectedDay:0, 5759 selectedMonth:0, 5760 selectedYear:0, 5761 currentDay:0, 5762 currentMonth:0, 5763 currentYear:0, 5764 touchSupported : xfalib.ut.TouchUtil.TOUCH_ENABLED, 5765 _visible:false, 5766 _defaultView:"Month", 5767 _keysEnabled:false, 5768 focusedOnDatepickerItem : false, 5769 keyboardAccessibility : true, 5770 $dp:$("<div></div>").addClass("datetimepicker") 5771 .width(this.options.width) 5772 .append(html) 5773 .addClass("datePickerTarget") 5774 .appendTo(this.options.container) 5775 .toggleClass("datetimepicker-notouch",this.touchSupported), 5776 $month: $(".dp-monthview",this.$dp).height(this.options.viewHeight),
5777 $year: $(".dp-yearview",this.$dp).height(this.options.viewHeight), 5778 $yearset : $(".dp-yearsetview",this.$dp).height(this.options.viewHeight) 5779 }); 5780 this.actualWidth = Math.floor(this.$dp.width()); 5781 this.$clear = $('.dp-clear a', this.$dp).on("click", $.proxy(this._clearDate, this)); 5782 this.$prevNavWidthBtn = $(".dp-leftnav", this.$dp).on("click", 5783 function(evnt) { 5784 self._adjustDate(-1, self.view, false) 5785 }); 5786 this.$nextNavWidthBtn = $(".dp-rightnav", this.$dp).on("click", 5787 function(evnt) { 5788 self._adjustDate(1, self.view, false) 5789 }); 5790 prevNavWidth = this.$prevNavWidthBtn.outerWidth(true); 5791 nextNavWidth = this.$nextNavWidthBtn.outerWidth(true); 5792 this.$caption = $(".dp-caption", this.$dp).width(this.actualWidth - prevNavWidth - nextNavWidth) 5793 .on("click", 5794 function(evnt) { 5795 if(!self.$caption.hasClass("disabled")) { 5796 self._layout(viewAction[self.view].caption); 5797 } 5798 }); 5799 if (this.keyboardAccessibility) { 5800 _.each([this.$prevNavWidthBtn, this.$caption, this.$nextNavWidthBtn, this.$clear], function (elem, i) { 5801 elem.attr("tabIndex", i + 1); 5802 }); 5803 } 5804 // attach click event on entire datePicker popup 5805 $(this.$dp).on("click", 5806 function(evnt) { 5807 //focus only if the device doesn't support touch 5808 // input otherwise on screen keyboard will popup 5809 if(!self.touchSupported) 5810 self._curInstance.$field.focus(); 5811 }); 5812 5813 $(window).on("touchstart.datetimepicker mousedown.datetimepicker",self._checkWindowClicked); 5814 this._curInstance = null; 5815 }, 5816 5817 /* 5818 * attaches the date picker to the field. This is a one time operation 5819 * First creates a configuration object and stores it in the field data attributes 5820 * then attaches event handlers on click, focus (to show the picker) and blur (to hide) events 5821 */ 5822 _attachField: function($field,options, value) { 5823 var inst = this._newInst($field,options, value), 5824 self = this, 5825 activateField = function(evnt) { 5826 var data = xfaUtil.$data(evnt.target,"datetimepicker"); 5827 if(self._isFieldDisabled(data)) { 5828 return; 5829 } 5830 if(!self._curInstance) 5831 self._activateField(evnt); 5832 5833 if(self.options.showCalendarIcon) { 5834 if (evnt.type === self.getEvent()) { 5835 if (self._iconClicked) { 5836 self._iconClicked = false; 5837 if (self._visible) { 5838 self._hide(); // hide the calendar popup if visible when calendar icon is clicked 5839 self._curInstance.$field.focus(); // bring back focus in field 5840 } else { 5841 self._show(); //// show the calendar popup if not visible when calendar icon is clicked 5842 } 5843 } 5844 } 5845 } else { 5846 /*show the popup only if 5847 1. click/touch event 5848 2. focus event in case of non-touch devices and focus is not done using script 5849 */ 5850 if (evnt.type === self.getEvent() || (evnt.type === "focus" && !self.touchSupported && !self.scriptFocus)) { 5851 self._show(evnt); 5852 } 5853 } 5854 5855 self._clickedWindow = true; 5856 self.scriptFocus = false;
5857 }, 5858 deactivateField = function(evnt) { 5859 //deactivate only if clicked outside window 5860 // on touch devices only keyboard or calander should be active at once, touching keyboard should deactivate calendar 5861 if ((self._clickedWindow && !self.focusedOnDatepickerItem) && (self.options.showCalendarIcon || !self.touchSupported)) { 5862 self._hide(); 5863 self._deactivateField(); 5864 self._clickedWindow = true; 5865 } 5866 }; 5867 5868 xfaUtil.$data($field[0],"datetimepicker",inst); 5869 5870 $field.on(this.getEvent(),activateField) 5871 .focus(activateField) 5872 .blur(deactivateField); 5873 if(options.showCalendarIcon) { 5874 var calendarIcon = $("<div></div>") 5875 .addClass("datepicker-calendar-icon") 5876 .css({ 5877 "width": options.iconWidth + "px", 5878 "height": options.iconHeight + "px" 5879 }); 5880 calendarIcon.insertAfter($field); 5881 5882 if (this.keyboardAccessibility) { 5883 calendarIcon.attr("tabindex", 0); 5884 } 5885 5886 calendarIcon.on(this.getEvent(), function (evnt) { 5887 self._iconClicked = true; 5888 $field.click(); 5889 }) 5890 .on("keydown", function (event) { 5891 if (event.keyCode === 32 || event.keyCode === 13) { 5892 // Check if field is disabled before triggering click 5893 var data = xfaUtil.$data($field[0], "datetimepicker"); 5894 if (data && !self._isFieldDisabled(data)) { 5895 $field.click(); 5896 } 5897 } 5898 }); 5899 } 5900 }, 5901 5902 _newInst: function($f,options, value) { 5903 return { 5904 $field:$f, 5905 locale: options.locale, 5906 positioning: options.positioning || $f, 5907 access:options.access, 5908 selectedDate:options.value, 5909 editValue :options.editValue, 5910 minValidDate : options.minValidDate, 5911 maxValidDate : options.maxValidDate, 5912 exclMinDate : options.exclMinDate, 5913 exclMaxDate : options.exclMaxDate 5914 } 5915 }, 5916 5917 /* 5918 * To check where the click happened, if happened outside the datepicker 5919 * then hide the picker. This is checked whether any ancestor of clicked target 5920 * has a class datePickerTarget. This class is added to the attached element as well 5921 */ 5922 _checkWindowClicked : function(evnt) { 5923 var self = adobeDateTimePicker; 5924 if(self._curInstance) { 5925 // datepickerTarget class depicts that the component is a part of the Date Field 5926 // and on click of that class, we should not hide the datepicker or fire exit events. 5927 if(!$(evnt.target).closest(".datePickerTarget").length) { 5928 //non-touch devices do not deactivate on blur. Hence needs to be done here 5929 if(self.touchSupported) { 5930 self._hide() 5931 //clicking outside a field doesn't blur the field in IPad. Doing it by script 5932 self._curInstance.$field[0].blur() 5933 self._deactivateField() 5934 } else{ 5935 self._clickedWindow = true; 5936 // set focusedOnDatepickerItem to false, it hides the datepicker see method deactivateField. 5937 self.focusedOnDatepickerItem = false; 5938 self._curInstance.$field.blur() 5939 } 5940 } 5941 else { 5942 self._clickedWindow = false;
5943 } 5944 } 5945 }, 5946 5947 /** 5948 * Checks if the current datepicker field is disabled. 5949 * 5950 * Fields marked as "readOnly" or with access set to false are considered 5951 * disabled and should not allow datepicker interaction. 5952 * 5953 * @param {Object} [data] - Optional data object to check. If not provided, uses current instance. 5954 * @returns {boolean} True if the field is disabled (access is "readOnly" or false), false otherwise. 5955 * Returns false if no current instance exists. 5956 */ 5957 _isFieldDisabled: function(data) { 5958 if (data) { 5959 return data.access === false || data.access === "readOnly"; 5960 } 5961 return this._curInstance && (this._curInstance.access === false || this._curInstance.access === "readOnly"); 5962 }, 5963 5964 /* 5965 * handling of key strokes. All the key strokes prevent the default browser action 5966 * unless specified otherwise 5967 * tab: set focus on calendar icon when dateinput field is active, navigates through date picker buttons when datepicker is open, 5968 * otherwise perform default browser action 5969 * escape: hides the datepicker 5970 * down arrow key: navigate the picker downwards by the number specified in actionView.upDown of the current View 5971 * up arrow key: navigate the picker upwards by the number specified in actionView.upDown of the current View 5972 * left arrow key: navigate the picker one unit of that view backward 5973 * right arrow key: navigate the picker one unit of that view forward 5974 * shift + up: perform the action that happens on clicking the caption (as specified in actionView.caption) 5975 * shift + left: perform the action that happens on clicking the left navigation button 5976 * shift + right: perform the action that happens on clicking the right navigation button 5977 * space/enter: triggers the click event for the current focused element from datepicker/ opens datepicker when calendar icon is focused. 5978 */ 5979 _hotKeys: function(evnt) { 5980 var handled = false, date; 5981 switch(evnt.keyCode) { 5982 case 9: //tab 5983 // CQ-4239352 : Setting clickedWindow property to true on tabbing so that deactivateField logic gets executed 5984 // When clicking on "x" on input field in in IE and when selecting the content and releasing the mouse select outside the field 5985 // the click event is not trigerred on the field and hence activateField is not executed, so clickedWindow remains as false 5986 adobeDateTimePicker._clickedWindow = true; 5987 handled = false; 5988 break; 5989 case 27://escape 5990 if(this._visible) { 5991 adobeDateTimePicker._hide(); 5992 this._curInstance.$field.focus(); 5993 handled = true; 5994 } 5995 break; 5996 case 32: //space 5997 case 13: // enter 5998 if($(evnt.target).hasClass("datepicker-calendar-icon")){ 5999 // Check if field is disabled before showing datepicker 6000 // disabled fields are marked as readOnly in the form 6001 if(this._isFieldDisabled()) { 6002 return; 6003 } 6004 if(!this._visible) { 6005 this._show(); 6006 return; 6007 } 6008 this.$focusedDate.addClass("dp-focus"); 6009 } 6010 break; 6011 case 40: //down arrow key 6012 if(!this._visible) { 6013 // Check if field is disabled before showing datepicker 6014 if(this._isFieldDisabled()) { 6015 return; 6016 } 6017 this._show(); 6018 return; 6019 } 6020 this.$focusedDate.addClass("dp-focus"); 6021 break; 6022 } 6023 6024 if(adobeDateTimePicker._visible && this._keysEnabled) { 6025 var v = viewAction[this.view].key, 6026 updown=viewAction[this.view].upDown; 6027 switch(evnt.keyCode) { 6028 case 9: // tab
6029 if (evnt.shiftKey) { 6030 if ($(evnt.target).hasClass("dp-leftnav") || $(evnt.target).hasClass("dp-focus")) { 6031 this._hide(); 6032 this._curInstance.$field.focus(); 6033 handled = true; 6034 } else { 6035 handled = false; 6036 } 6037 } else { 6038 var buttonTabindex = $(evnt.target).attr("tabindex"); 6039 if (buttonTabindex === '0') { 6040 if (evnt.target.tagName.toLocaleLowerCase() === "input") { 6041 this._hide(); 6042 handled = false; 6043 } else { 6044 this.$prevNavWidthBtn.focus(); 6045 handled = true; 6046 } 6047 } else if (buttonTabindex === '4') { 6048 this._hide(); 6049 this._curInstance.$field.focus(); 6050 handled = true; 6051 } else { 6052 handled = false; 6053 } 6054 } 6055 break; 6056 case 32: //select on space 6057 case 13: // select on enter 6058 this.hotKeyPressed = true; 6059 this.focusedOnDatepickerItem = false; 6060 if (!this.focusedOnDatepickerItem) { 6061 $(evnt.target, this.$dp).triggerHandler("click"); 6062 } else { 6063 if (this.$focusedDate) { 6064 this.$focusedDate.trigger("click"); 6065 } 6066 } 6067 this.hotKeyPressed = false; 6068 handled = true; 6069 break; 6070 case 37: //left arrow key 6071 if (evnt.shiftKey) { 6072 $(".dp-leftnav", this.$dp).triggerHandler("click"); 6073 } else { 6074 this._adjustDate(-1, v, true); 6075 } 6076 handled = true; 6077 break; 6078 case 38: //up arrow key 6079 if (evnt.shiftKey) { 6080 this.$caption.triggerHandler("click"); 6081 } else { 6082 this._adjustDate(-updown, v, true); 6083 } 6084 handled = true; 6085 break; 6086 case 39: //right arrow key 6087 if (evnt.shiftKey) { 6088 $(".dp-rightnav", this.$dp).triggerHandler("click"); 6089 } else { 6090 this._adjustDate(+1, v, true); 6091 } 6092 handled = true; 6093 break; 6094 case 40: //down arrow key 6095 this._adjustDate(updown, v, true); 6096 handled = true; 6097 break; 6098 default: 6099 } 6100 } 6101 if(handled) { 6102 evnt.preventDefault(); 6103 } 6104 }, 6105 6106 /* 6107 * show the datepicker. 6108 */ 6109 _show: function() { 6110 if(this._isFieldDisabled()) 6111 return; 6112 this.options.locale = this._curInstance.locale; 6113 if(!this._visible) { 6114 var self = this, 6115 date = new Date(), 6116 val, 6117 maxDateInfo, 6118 minDateInfo, 6119 validDate; 6120 //Bug#3607735: 6121 // Date constructor in ipad 5.1 doesn't support "YYYY-MM-DD", hence parsing the date on our own 6122 validDate = xfalib.ut.DateInfo.ParseIsoString(this._curInstance.selectedDate); 6123 date = (validDate != null)? validDate.getDate(): new Date(); 6124 this.selectedDay = this.currentDay = date.getDate(); 6125 this.selectedMonth = this.currentMonth = date.getMonth(); 6126 this.selectedYear = this.currentYear = date.getFullYear(); 6127 maxDateInfo = this.options.maxValidDate ? xfalib.ut.DateInfo.ParseIsoString(this._curInstance.maxValidDate) : null; 6128 this.maxValidDate = maxDateInfo ? maxDateInfo.getDate() : null; 6129 minDateInfo = this.options.minValidDate ? xfalib.ut.DateInfo.ParseIsoString(this._curInstance.minValidDate) : null; 6130 this.minValidDate = minDateInfo ? minDateInfo.getDate() : null; 6131 this.exclMaxDate = this._curInstance.exclMaxDate; 6132 this.exclMinDate = this._curInstance.exclMinDate; 6133 $('.dp-clear a',this.$dp).text(this.options.locale.clearText); 6134 this._layout('Month'); 6135 this._position(); 6136 this.$dp.show(); 6137 // if li element of datepicker is focused then set focusedOnDatepickerItem to true, it manages the visibility of the datepicker. 6138 this.focusedOnDatepickerItem = false;
6139 this._visible = true; 6140 if (this.options.showCalendarIcon) { 6141 this._curInstance.$field.attr('readonly', true); // when the datepicker is active, deactivate the field 6142 } 6143 } 6144 6145 // Disabling the focus on ipad due to a bug where value of 6146 // date picker is not being set 6147 // Removing this code will only hamper one use case 6148 // where on ipad if you click on the calander then 6149 // the field becomes read only so 6150 // there is no indication where the current focus is 6151 // And if you remove this foucs code all together 6152 // then what happens is that on desktop MF in iframe the exit event 6153 // is not getting called hence calander getting remained open even 6154 // when you click somewhere on window or focus into some other field 6155 if (this.options.showCalendarIcon && !this.touchSupported) { 6156 if(this.$focusedDate.length > 0) { 6157 this.$focusedDate.focus(); // shift focus on current date or selected date. 6158 } else { 6159 this._curInstance.$field.focus(); // field loses focus after being marked readonly, causing blur event not to be fired later 6160 } 6161 } 6162 }, 6163 6164 /* 6165 * position the datepicker around the positioning element 6166 * provided in the options 6167 */ 6168 _position: function() { 6169 var $elem = this._curInstance.positioning, 6170 windowScrollX = window.scrollX/ xfalib.ut.XfaUtil.prototype.formScaleFactor, 6171 windowScrollY = window.scrollY/ xfalib.ut.XfaUtil.prototype.formScaleFactor, 6172 windowInnerHeight = window.innerHeight/ xfalib.ut.XfaUtil.prototype.formScaleFactor, 6173 windowInnerWidth = window.innerWidth/ xfalib.ut.XfaUtil.prototype.formScaleFactor, 6174 height = $elem.outerHeight(true), 6175 width = $elem.outerWidth(true), 6176 top = $elem.offset().top / xfalib.ut.XfaUtil.prototype.formScaleFactor + height, 6177 left = $elem.offset().left / xfalib.ut.XfaUtil.prototype.formScaleFactor, 6178 styles = {"top": (top+"px"), "left": (left+"px")}, 6179 diffBottom = top + this.$dp.outerHeight(true) - windowInnerHeight - windowScrollY, 6180 newLeft, 6181 newTop; 6182 if(diffBottom > 0) { 6183 //can't appear at the bottom 6184 //check top 6185 newTop = top - height - this.$dp.outerHeight(true) - BUFFER_SPC; 6186 if(newTop < windowScrollY) { 6187 //can't appear at the top as well ... the datePicker pop up overlaps the date field 6188 newTop = top - diffBottom; 6189 // Fix for BUG #3626974 6190 if(xfaUtil.isWebkit() && !this.options.showCalendarIcon) { 6191 this._curInstance.$field.trigger("onoverlap.datetimepicker"); 6192 } 6193 } 6194 styles.top = newTop + "px"; 6195 } 6196 if(left + this.$dp.outerWidth(true) > windowScrollX + windowInnerWidth ) { 6197 //align with the right edge 6198 newLeft = windowScrollX + windowInnerWidth - this.$dp.outerWidth(true) - BUFFER_SPC; 6199 styles.left = newLeft + "px"; 6200 } 6201 xfaUtil.$css(this.$dp.get(0), styles); 6202 return this; 6203 }, 6204 6205 /* 6206 * layout the nextView. if nextView is null return 6207 * 6208 */ 6209 _layout: function(nextView) { 6210 if(nextView == null) { 6211 this._hide(); 6212 } else { 6213 if(this.view) 6214 this['$'+this.view.toLowerCase()].hide(); 6215 this.view = nextView; 6216 this.$caption.toggleClass("disabled",!viewAction[this.view].caption); 6217 this['$'+this.view.toLowerCase()].show(); 6218 this["show"+this.view](); 6219 } 6220 return this; 6221 }, 6222 6223 /* 6224 * show the month view 6225 */ 6226 showMonth: function() { 6227 var self = this, 6228 curDate = new Date(this.currentYear, this.currentMonth), 6229 maxDay = this._maxDate(this.currentMonth), 6230 prevMaxDay = this._maxDate((this.currentMonth + 11)%12), 6231 day1 = new Date(this.currentYear,this.currentMonth,1).getDay(), 6232 data,display; 6233 6234 this.tabulateView( 6235 { 6236 caption: this.options.locale.months[this.currentMonth] + ", "+ this._convertNumberToLocale(this.currentYear), 6237 header:this.options.locale.days, 6238 numRows:7, 6239 numColumns:7, 6240 elementAt: function(row,col) { 6241 var day = (row-1)*7 + col - day1 + 1; 6242 var monthVal = self.currentMonth + 1; 6243 display = self._convertNumberToLocale(day); 6244 data = day; 6245 if(day < 1) { 6246 display = self._convertNumberToLocale(prevMaxDay + day); 6247 data = -1; 6248 monthVal = self.currentMonth; 6249 } 6250 else if(day > maxDay) { 6251 display = self._convertNumberToLocale(day-maxDay); 6252 data = -1; 6253 monthVal = self.currentMonth + 2; 6254 } 6255 else { 6256 curDate.setDate(day); 6257 var compareFn = xfalib.ut.XfaUtil.prototype._compareVal; 6258 // check if the currentdate is valid based on max and min valid date 6259 if(compareFn(curDate, self.maxValidDate, self.exclMaxDate) || compareFn(self.minValidDate, curDate, self.exclMinDate)) { 6260 data = -1; 6261 } 6262 } 6263 return { 6264 data : data, 6265 display : display, 6266 ariaLabel : self.options.editValue(self.currentYear+"-"+self._pad2(monthVal)+"-"+self._pad2(display)) 6267 }; 6268 } 6269 }); 6270 }, 6271 6272 6273 6274 /* 6275 * show the year view 6276 */ 6277 showYear: function() { 6278 var self = this, 6279 minDate = this.minValidDate ? new Date(this.minValidDate.getFullYear(), this.minValidDate.getMonth()) : null, 6280 maxDate = this.maxValidDate ? new Date(this.maxValidDate.getFullYear(), this.maxValidDate.getMonth()) : null, 6281 curDate = new Date(this.currentYear, 0), //can't omit month, if only one param present it is treated as millisecond 6282 data, 6283 month; 6284 this.tabulateView( 6285 { 6286 caption : this._convertNumberToLocale(this.currentYear), 6287 numRows : 4, 6288 numColumns : 3, 6289 elementAt : function(row,col) { 6290 data = month = row*3 + col; 6291 curDate.setMonth(month); 6292 if ((minDate && curDate < minDate) || (maxDate && curDate > maxDate)) { 6293 data = -1; 6294 } 6295 return { 6296 data : data, 6297 display : self.options.locale.months[month], 6298 ariaLabel : self.options.locale.months[month] + " " +self.currentYear 6299 }; 6300 } 6301 }); 6302 }, 6303 6304 /* 6305 * show the year set view 6306 */ 6307 showYearset: function() { 6308 var year, 6309 minDate = this.minValidDate ? new Date(this.minValidDate.getFullYear(), 0
6309) : null , 6310 maxDate = this.maxValidDate ? new Date(this.maxValidDate.getFullYear() + 1, 0) : null, 6311 curDate = new Date(), 6312 data, 6313 self = this; 6314 this.tabulateView( 6315 { 6316 caption: this._convertNumberToLocale(this.currentYear - this.options.yearsPerView/2) +"-"+this._convertNumberToLocale(this.currentYear - this.options.yearsPerView/2 + this.options.yearsPerView - 1), 6317 numRows:4, 6318 numColumns:4, 6319 elementAt: function(row,col) { 6320 data = year = self.currentYear - 8 + (row*4 + col); 6321 curDate.setFullYear(year); 6322 if ((minDate && curDate < minDate) || (maxDate && curDate > maxDate)) { 6323 data = -1; 6324 } 6325 return { 6326 "data" : data, 6327 "display" : self._convertNumberToLocale(year), 6328 ariaLabel : year 6329 }; 6330 } 6331 }); 6332 }, 6333 6334 insertRow : function(rowNum,rowArray,isHeader,height) { 6335 var $view = this["$"+this.view.toLowerCase()], 6336 width = (this.actualWidth)/rowArray.length, 6337 $row = $("ul",$view).eq(rowNum), 6338 items,$li,element,$tmp, 6339 self= this; 6340 if(!$row.length) 6341 $row = $("<ul></ul>").attr("aria-label", "").attr("role", "row").appendTo($view).toggleClass(headerClass,isHeader); 6342 $row.height(height); 6343 items = $("li",$row).length; 6344 while(items++ < rowArray.length) { 6345 $tmp = $("<li></li>").attr("role", "cell").appendTo($row); 6346 if(!isHeader) 6347 $tmp.on("click", $.proxy(this._selectDate,this)); 6348 } 6349 6350 _.each(rowArray, function(el,index) { 6351 $li = $("li",$row).eq(index); 6352 if(isHeader) 6353 $li.text(rowArray[index]); 6354 else { 6355 element = rowArray[index]; 6356 xfaUtil.$data($li.get(0), "value", element.data); 6357 if(self._checkDateIsFocussed(element.data)) { 6358 if(self.$focusedDate) { 6359 self.$focusedDate.removeClass("dp-focus"); 6360 self.$focusedDate.attr("tabindex", "-1"); 6361 } 6362 self.$focusedDate = $li; 6363 if(self._keysEnabled) 6364 self.$focusedDate.addClass("dp-focus") 6365 } 6366 $li.toggleClass("dp-selected",self._checkDateIsSelected(element.data)) 6367 .toggleClass("disabled", element.data == -1).text(element.display) 6368 .attr("title", element.ariaLabel) 6369 .attr("aria-label", element.ariaLabel) 6370 .attr("tabindex", -1); 6371 } 6372 $li.css( {"height":height+"px","width":width+"px","line-height":height+"px"}); 6373 }); 6374 return $row; 6375 }, 6376 6377 /* 6378 * creates a tabular view based on the options provided. The options that can be passed are 6379 * numRows: number of rows that needs rendering 6380 * numCols: number of columns that needs rendering 6381 * caption: text for the datepickers caption element 6382 * header: an array of elements that identifies the header row 6383 * elementAt: a function(row, column) that returns an object (data: <data>, display: <display>) where 6384 * <data> is the value to set for that view when the element at (row,column) is clicked and 6385 * <display> is the value that will be visible to the user 6386 */ 6387 tabulateView : function(options) { 6388 var r = 0,rows = 0, 6389 row = [], 6390 ht = this.options.viewHeight/options.numRows, 6391 c; 6392 this.$caption.text(options.caption); 6393 if(options.header) { 6394 this.insertRow(r++,options.header,true,ht); 6395 } 6396 while(r < options.numRows) { 6397 c = 0; 6398 while(c < options.numColumns) { 6399 row[c] = options.elementAt(r,c); 6400 c++; 6401 } 6402 this.insertRow(r++,row,false,ht); 6403 } 6404 }, 6405 6406 _activateField : function(evnt) { 6407 this._curInstance = xfaUtil.$data(evnt.target,"datetimepicker"); 6408 this._curInstance.$field.trigger("onfocus1.datetimepicker").addClass("datePickerTarget"); 6409 // Issue LC-7049: 6410 // datepickerTarget should be added when activate the field and should be removed 6411 // after the fields gets deactivated. 6412 if (this.options.showCalendarIcon) { 6413 this._curInstance.$field.parent().addClass("datePickerTarget"); 6414 } 6415 //enable hot keys only for non touch devices 6416 if(!this.touchSupported && !this._keysEnabled) { 6417 $(window).on("keydown.datetimepicker", $.proxy(this._hotKeys,this)); 6418 this._keysEnabled = true; 6419 } 6420 }, 6421 6422 _deactivateField: function() { 6423 if(this._curInstance) { 6424 if(this._keysEnabled) { 6425 $(window).off("keydown.datetimepicker") 6426 this._keysEnabled = false;
6427 } 6428 //Bug#3607499: on deactivate check the value in the input box, if that is 6429 // different than the selected Date, change the selectedDate 6430 //if (this._curInstance.selectedDate != this._curInstance.$field.val()) { 6431 // this._curInstance.selectedDate = this._curInstance.$field.val(); 6432 //} 6433 this._curInstance.$field.trigger("onfocusout.datetimepicker").removeClass("datePickerTarget"); 6434 // Issue LC-7049: 6435 // datepickerTarget should be added when activate the field and should be removed 6436 // after the fields gets deactivated. Otherwise clicking on any other datefield 6437 // will not hide the existing datepicker 6438 if (this.options.showCalendarIcon) { 6439 this._curInstance.$field.parent().removeClass("datePickerTarget"); 6440 } 6441 this._curInstance = null; 6442 } 6443 }, 6444 6445 _hide: function() { 6446 if(this._visible) { 6447 this.$dp.hide(); 6448 this._curInstance.$field.trigger("onclose.datetimepicker"); 6449 this._visible = false; 6450 if (this.options.showCalendarIcon) { 6451 this._curInstance.$field.attr('readonly', false); // when the datepicker is deactivated, activate the field 6452 } 6453 } 6454 }, 6455 6456 _adjustDate: function(step, view, focus) { 6457 var maxDate,prevMaxDate; 6458 var _focus = focus || false; 6459 switch(view.toLowerCase()) { 6460 case "day": 6461 this.currentDay += step; 6462 maxDate = this._maxDate(this.currentMonth) 6463 if(this.currentDay < 1) { 6464 prevMaxDate = this._maxDate((this.currentMonth - 1 + 12)%12); 6465 this.currentDay = prevMaxDate + this.currentDay; 6466 return this._adjustDate(-1, "month", _focus); 6467 } 6468 if(this.currentDay > maxDate) { 6469 this.currentDay -= maxDate; 6470 return this._adjustDate(+1, "month", _focus); 6471 } 6472 break; 6473 case "month": 6474 this.currentMonth += step; 6475 if(this.currentMonth > 11) { 6476 this.currentYear++; 6477 this.currentMonth = 0; 6478 } 6479 if(this.currentMonth < 0) { 6480 this.currentYear--; 6481 this.currentMonth = 11; 6482 } 6483 break; 6484 case "year": 6485 this.currentYear += step; 6486 break;
6487 case "yearset": 6488 this.currentYear += step*this.options.yearsPerView; 6489 break; 6490 } 6491 this._layout(this.view); 6492 if (_focus) { 6493 this.focusedOnDatepickerItem = true; 6494 this.$focusedDate.attr("tabindex", 0)[0].focus(); 6495 } 6496 }, 6497 6498 _checkDateIsSelected: function(data) { 6499 switch(this.view.toLowerCase()) { 6500 case "month": 6501 return this.currentYear == this.selectedYear && this.currentMonth == this.selectedMonth && data == this.selectedDay; 6502 case "year": 6503 return this.currentYear == this.selectedYear && this.selectedMonth == data; 6504 case "yearset": 6505 return this.selectedYear == data; 6506 } 6507 }, 6508 6509 _checkDateIsFocussed: function(data) { 6510 switch(this.view.toLowerCase()) { 6511 case "month": 6512 return data == this.currentDay; 6513 case "year": 6514 return this.currentMonth == data;
6515 case "yearset": 6516 return this.currentYear == data; 6517 } 6518 }, 6519 6520 _convertNumberToLocale : function(number) { 6521 var zeroCode = this.options.locale.zero.charCodeAt(0); 6522 number += ""; 6523 var newNumber = []; 6524 for(var i = 0;i < number.length;i++) { 6525 newNumber.push(String.fromCharCode(zeroCode + parseInt(number.charAt(i)))); 6526 } 6527 return newNumber.join(""); 6528 }, 6529 6530 _clearDate: function() { 6531 var isDateEmpty = this._curInstance.$field.val() ? false : true; 6532 this.selectedYear 6533 = this.selectedMonth 6534 = this.selectedYear 6535 = -1; 6536 this._curInstance.selectedDate = ""; 6537 this._curInstance.$field.val(""); 6538 if (!isDateEmpty) { 6539 this._curInstance.$field.trigger("onvaluechange.datetimepicker", [ 6540 {selectedDate: ""} 6541 ]); 6542 } 6543 $(".dp-selected",this['$'+this.view.toLowerCase()]).removeClass("dp-selected"); 6544 }, 6545 6546 getEvent : function() { 6547 return "click";//this.touchSupported ? "touchstart" : "click"; 6548 }, 6549 6550 _pad2: function(m) { 6551 return m = m < 10 ?"0"+m:m; 6552 }, 6553 6554 toString : function() { 6555 return this.selectedYear +"-"+this._pad2(this.selectedMonth + 1)+"-"+this._pad2(this.selectedDay); 6556 }, 6557 6558 _selectDate : function(evnt) { 6559 var val = xfaUtil.$data(evnt.target, "value"), 6560 nextView = viewAction[this.view].li, 6561 editVal; 6562 //disabled dates have a value of -1. Do nothing in that case 6563 if(val == -1) 6564 return; 6565 switch(this.view.toLowerCase()) { 6566 case "month": 6567 this.selectedMonth = this.currentMonth; 6568 this.selectedYear = this.currentYear; 6569 this.selectedDay = val; 6570 this._curInstance.selectedDate = this.toString(); 6571 editVal = this._curInstance.editValue(this.toString()); 6572 this._curInstance.$field.val(editVal).focus(); 6573 this._curInstance.$field.trigger("onvaluechange.datetimepicker", [ 6574 {selectedDate: editVal} 6575 ]); 6576 $(".dp-selected",this['$'+this.view.toLowerCase()]).removeClass("dp-selected"); 6577 $(evnt.target).addClass("dp-selected"); 6578 break; 6579 case "year": 6580 this.currentMonth = val; 6581 break;
6582 case "yearset": 6583 this.currentYear = val; 6584 break; 6585 } 6586 this._layout(nextView); 6587 //manually focus on the field if clicked on the popup buttons for non-touch device 6588 if(!this.touchSupported) { 6589 //No need to focus if selection is made by pressing space. 6590 if(!this.hotKeyPressed) { 6591 this.scriptFocus = true; 6592 if(nextView == null) { 6593 this.focusedOnDatepickerItem = false; 6594 } 6595 } 6596 } else if(nextView == null){ 6597 //For touch devices, deactivate the field if a selection is made 6598 this.focusedOnDatepickerItem = false; 6599 this._deactivateField() 6600 } 6601 }, 6602 6603 _leapYear : function() { 6604 return this.currentYear % 400 == 0 || (this.currentYear % 100 != 0 && this.currentYear % 4 == 0); 6605 }, 6606 6607 _maxDate : function(m) { 6608 if(this._leapYear() && m == 1) 6609 return 29; 6610 else return dates[m]; 6611 }, 6612 6613 _access: function(val) { 6614 if(typeof val == "undefined") 6615 return this.access 6616 this.access = val; 6617 }, 6618 6619 _value:function(val) { 6620 if(typeof val == "undefined") 6621 return this.$field.val() 6622 else { 6623 this.selectedDate = val; 6624 var editValue = this.editValue(val); 6625 // update the field val with provided value instead of null 6626 if (!editValue) { 6627 editValue = val; 6628 } 6629 this.$field.val(editValue); 6630 } 6631 } 6632 }); 6633 6634 var adobeDateTimePicker = new DateTimePicker(); 6635 6636 $.fn.adobeDateTimePicker = function(options, value) { 6637 if(!adobeDateTimePicker.initialized) { 6638 adobeDateTimePicker.create(options); 6639 adobeDateTimePicker.initialized = true; 6640 } 6641 if(typeof options === "object") { 6642 adobeDateTimePicker._attachField(this, options); 6643 } 6644 else if(typeof options === "string") { 6645 if(arguments.length == 2) 6646 adobeDateTimePicker["_"+options].apply(xfaUtil.$data(this[0],"datetimepicker"),[value]) 6647 else 6648 return adobeDateTimePicker["_"+options].apply(xfaUtil.$data(this[0],"datetimepicker")) 6649 } 6650 return this; 6651 } 6652})(_, $, xfalib); 6653(function (xfalib) { 6654 xfalib.ut.TouchUtil = (function () { 6655 var touchAvailable = !!("ontouchstart" in window || window.DocumentTouch && document instanceof DocumentTouch) , 6656 pointerEnabled = !!(window.MSPointerEvent || window.PointerEvent) , 6657 POINTER_DOWN_EVENT = "mousedown", 6658 POINTER_MOVE_EVENT = "mousemove", 6659 POINTER_UP_EVENT = "mouseup", 6660 EVENT_TYPE = "MouseEvent"; 6661 6662 if (window.PointerEvent) { //> IE11 6663 POINTER_DOWN_EVENT = "pointerdown"; 6664 POINTER_MOVE_EVENT = "pointermove"; 6665 POINTER_UP_EVENT = "pointerup"; 6666 EVENT_TYPE = "PointerEvent"; 6667 6668 } else if (window.MSPointerEvent) { // IE10 6669 POINTER_DOWN_EVENT = "MSPointerDown"; 6670 POINTER_MOVE_EVENT = "MSPointerMove"; 6671 POINTER_UP_EVENT = "MSPointerUp"; 6672 EVENT_TYPE = "MSPointerEvent" ; 6673 6674 } else if (touchAvailable) { // other touch devices 6675 POINTER_DOWN_EVENT = "touchstart"; 6676 POINTER_MOVE_EVENT = "touchmove"; 6677 POINTER_UP_EVENT = "touchend"; 6678 EVENT_TYPE = "TouchEvent"; 6679 } 6680 return { 6681 TOUCH_ENABLED: touchAvailable, 6682 // new MS Pointer Events 6683 POINTER_EVENT: EVENT_TYPE, 6684 POINTER_ENABLED: pointerEnabled, 6685 POINTER_DOWN: POINTER_DOWN_EVENT, 6686 POINTER_MOVE: POINTER_MOVE_EVENT, 6687 POINTER_UP: POINTER_UP_EVENT, 6688 getTouchEvent: function (evt) { 6689 var target; 6690 if (pointerEnabled) { 6691 target = evt.originalEvent; 6692 } else if (touchAvailable) { 6693 target = evt.originalEvent || evt; 6694 target = target.touches[0]; 6695 //if (evt.originalEvent && evt.originalEvent.changedTouches && evt.originalEvent.changedTouches[0]) { 6696 // te = evt.originalEvent.changedTouches[0]; 6697 //} 6698 } 6699 6700 return target || evt; 6701 }, 6702 getPointerEvent: function (eventType) { 6703 var event = null; 6704 if ((typeof PointerEvent) === "function") { 6705 event = new PointerEvent(eventType, { 6706 bubbles: true, 6707 cancelable: true 6708 }); 6709 } else { 6710 event = document.createEvent(EVENT_TYPE); 6711 event.initEvent(eventType, true, true); 6712 } 6713 return event; 6714 }, 6715 getTouches:function(evt){ 6716 var touches = []; 6717 if(touchAvailable && evt.originalEvent && evt.originalEvent.touches ){ 6718 touches = evt.originalEvent.touches; 6719 } 6720 return touches; 6721 } 6722 }; 6723 })(); 6724})(xfalib); 6725(function ($, _) { 6726 $.widget("xfaWidget.abstractWidget", { 6727 6728 $userControl: null, 6729 6730 $data: xfalib.ut.XfaUtil.prototype.$data, 6731 6732 $css: xfalib.ut.XfaUtil.prototype.$css, 6733 6734 getOrElse: xfalib.ut.Class.prototype.getOrElse, 6735 6736 dIndexOf: xfalib.ut.XfaUtil.prototype.dIndexOf, 6737 6738 btwn: xfalib.ut.XfaUtil.prototype.btwn, 6739 6740 logger: xfalib.ut.XfaUtil.prototype.getLogger, 6741
6742 localeStrings: xfalib.ut.XfaUtil.prototype.getLocaleStrings, 6743 6744 logMsgs: xfalib.ut.XfaUtil.prototype.getLogMessages, 6745 6746 errorManager: xfalib.ut.XfaUtil.prototype.getErrorManager, 6747 6748 _widgetName: "abstractWidget", 6749 6750 // if there are any specific black listed attributes, each widget should define their own 6751 _blackListedAttributes : ["type"], 6752 6753 options: { 6754 name: "", 6755 value: null, 6756 commitProperty: "value", 6757 displayValue: null, 6758 screenReaderText: null, 6759 tabIndex: 0, 6760 role: null, 6761 paraStyles: null, 6762 dir: null, 6763 errorMessage: null, 6764 warningMessage: null, 6765 hScrollDisabled: false, 6766 placeholder:"", 6767 isValid:true, 6768 mandatory: false 6769 }, 6770 6771 getOptionsMap: function () { 6772 return { 6773 "tabIndex": function (val) { 6774 this.$userControl.attr("tabindex", val); 6775 }, 6776 "role": function (val) { 6777 if (val) 6778 this.$userControl.attr("role", val); 6779 }, 6780 "screenReaderText": function (val) { 6781 if (val) 6782 this.$userControl.attr("aria-label", val) 6783 }, 6784 "paraStyles": function (val) { 6785 if (val) 6786 this.$css(this.$userControl.get(0), val); 6787 }, 6788 "dir": function (val) { 6789 if (val) 6790 this.$userControl.attr("dir", this.options.dir); 6791 }, 6792 "height": function (val) { 6793 if (val) { 6794 this.$css(this.$userControl[0], {"height": val}) 6795 } 6796 }, 6797 "width": function (val) { 6798 if (val) 6799 this.$css(this.$userControl[0], {"width": val}) 6800 }, 6801 "isValid": function (val) { 6802 if(val){ 6803 this.$userControl.removeAttr("aria-invalid"); 6804 } else { 6805 this.$userControl.attr("aria-invalid",true); 6806 } 6807 }, 6808 "color" : function(value) { 6809 if(!_.isEmpty(value)) { 6810 var color = "rgb(" + value + ")"; 6811 this.$css(this.$userControl[0], {"color": color}); 6812 } 6813 }, 6814 "font-style" : function (value) { 6815 if (!_.isEmpty(value)) { 6816 this.$css(this.$userControl[0], {"font-style": value}); 6817 } 6818 }, 6819 "mandatory" : function (value) { 6820 if(value){ 6821 this.$userControl.attr("aria-required", true); 6822 } else { 6823 this.$userControl.removeAttr("aria-required"); 6824 } 6825 } 6826 }; 6827 }, 6828 6829 getEventMap: function () { 6830 return { 6831 "focus": xfalib.ut.XfaUtil.prototype.XFA_ENTER_EVENT, 6832 "blur": xfalib.ut.XfaUtil.prototype.XFA_EXIT_EVENT, 6833 "click": xfalib.ut.XfaUtil.prototype.XFA_CLICK_EVENT 6834 }; 6835 }, 6836 6837 /** 6838 * Copies all the attributes from source jquery object to destination jquery object 6839 * @param $src source jquery object 6840 * @param $dest destination jquery object 6841 */ 6842 copyAttributesFromSrcToDest : function($src, $dest){ 6843 var that = this; 6844 // let's get all the attribute from the src element and copy it to dest jquery object 6845 if($src != null && $src[0] && $src[0].attributes && $dest != null){ 6846 $.each($src[0].attributes, function() { 6847 // we don't add the black listed set of attributes 6848 if(this.specified && this.value != null && _.isString(this.value) && this.value.length > 0 && that._blackListedAttributes.indexOf(this.name) === -1) { 6849 $dest.attr(this.name, this.value); 6850 } 6851 }); 6852 } 6853 }, 6854 6855 _create: function () { 6856 this.widgetEventPrefix = ""; 6857 this.element.addClass(this._widgetName); 6858 this.$userControl = this.render(); 6859 this.optionsHandler = this.getOptionsMap(); 6860 this.eventMap = this.getEventMap(); 6861 this._initializeOptions(); 6862 this._initializeEventHandlers(); 6863 this.errObj = this.errorManager(); 6864 //call it only after render 6865 // Dirty hack to prevent this being called in Guide 6866 if (typeof guidelib === "undefined") { 6867 this.$css(this.$userControl.get(0), { 6868 "box-sizing": "border-box", 6869 "position": "absolute" 6870 }); 6871 } 6872 }, 6873 6874 _initializeEventHandlers: function () { 6875 xfalib.ut.XfaUtil.prototype.getLogger().debug("xfa", "initialize event handlers for " + this._widgetName); 6876 _.each(this.eventMap, function (xfaevent, htmlevent) { 6877 var self = this; 6878 if (xfaevent) { 6879 if (!(xfaevent instanceof Array)) { 6880 xfaevent = [xfaevent]; 6881 } 6882 for (var i = 0; i < xfaevent.length; i++) { 6883 xfalib.ut.XfaUtil.prototype.getLogger().debug("xfa", "binding " + htmlevent + " with " + xfaevent[i]); 6884 this.$userControl.on(htmlevent, 6885 (function (xfevnt) { 6886 return function (evnt) { 6887 xfalib.ut.XfaUtil.prototype.getLogger().debug("xfa", "trigger " + evnt.type + 6888 " xfa-event " + xfevnt); 6889 self._preProcessEvent.apply(self, [xfevnt, evnt]); 6890 //since the fix https://github.com/jquery/jquery/pull/972, Fix for keeping namespace when triggering an event using an Event #972 6891 //we need to clear the namespace and its regular expression of triggering event, as the listeners are registered on un-namespaced events 6892 evnt.namespace = ""; 6893 evnt.namespace_re = ""; 6894 self._trigger(xfevnt, evnt); 6895 self._postProcessEvent.apply(self, [xfevnt, evnt]); 6896 } 6897 })(xfaevent[i]) 6898 ) 6899 6900 } 6901 } 6902 }, this) 6903 }, 6904 6905 _preProcessEvent: function (xfaevent, htmlevent) { 6906 if (xfaevent == this.options.commitEvent) { 6907 this.preProcessCommit(htmlevent); 6908 } 6909 switch (xfaevent) { 6910 case xfalib.ut.XfaUtil.prototype.XFA_ENTER_EVENT: 6911 this.preProcessEnter(htmlevent); 6912 break; 6913 case xfalib.ut.XfaUtil.prototype.XFA_EXIT_EVENT: 6914 this.preProcessExit(htmlevent); 6915 break; 6916 case xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT: 6917 this.preProcessChange(htmlevent); 6918 break; 6919 case xfalib.ut.XfaUtil.prototype.XFA_CLICK_EVENT: 6920 this.preProcessClick(htmlevent); 6921 break; 6922 } 6923 6924 }, 6925 6926 _postProcessEvent: function (xfaevent, htmlevent) { 6927 if (xfaevent == this.options.commitEvent) { 6928 this.postProcessCommit(htmlevent); 6929 } 6930 switch (xfaevent) { 6931 case xfalib.ut.XfaUtil.prototype.XFA_ENTER_EVENT: 6932 this.postProcessEnter(htmlevent); 6933 break; 6934 case xfalib.ut.XfaUtil.prototype.XFA_EXIT_EVENT: 6935 this.postProcessExit(htmlevent); 6936 break; 6937 case xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT: 6938 this.postProcessChange(htmlevent); 6939 break; 6940 case xfalib.ut.XfaUtil.prototype.XFA_CLICK_EVENT: 6941 this.postProcessClick(htmlevent); 6942 break; 6943 } 6944 }, 6945 6946 _initializeOptions: function () { 6947 _.each(this.optionsHandler, function (value, key) { 6948 if (typeof value === "function") 6949 value.apply(this, [this.options[key]]); // TODO: check whether it is needed for initialization or not 6950 }, this) 6951 }, 6952 6953 _setOption: function (key, value) { 6954 if (this.options[key] != value) { 6955 this.options[ key ] = value; 6956 if (typeof this.optionsHandler[key] === "function") { 6957 this.optionsHandler[key].apply(this, [this.options[key]]) 6958 } 6959 } 6960 }, 6961 6962 /** 6963 * @override 6964 */ 6965 option: function (key, value) { 6966 if (arguments.length === 1 && 6967 typeof key === "string" && 6968 this.options.hasOwnProperty(key) && 6969 this.options[key] === undefined) { 6970 return undefined; 6971 } 6972 return $.Widget.prototype.option.apply(this, arguments) 6973 }, 6974 6975 destroy: function () { 6976 this.$userControl.removeClass(this._widgetName); 6977 }, 6978 6979 6980 render: function () { 6981 var control; 6982 if (this.element.children().length > 0) { 6983 control = $(this.element.children().get(0)); 6984 } 6985 else 6986 control = this.element; 6987 control.attr("name", this.options.name) 6988 return control; 6989 }, 6990 6991 6992 preProcessCommit: function (evnt) { 6993 this.options.value = this.getCommitValue(); 6994 xfalib.ut.XfaUtil.prototype.getLogger().debug("xfa", "passing commit value " + this.options.value + 6995 "to model "); 6996 }, 6997 6998 getCommitValue: function () { 6999 7000 }, 7001 7002 preProcessExit: function (evnt) { 7003 7004 }, 7005 7006 preProcessEnter: function (evnt) { 7007 //Only focus the enabled widgets 7008 if (this.options.access === "open") { 7009 this._showError(); 7010 this.showValue(); 7011 } 7012 }, 7013 7014 preProcessChange: function (evnt) { 7015 7016 }, 7017 7018 preProcessClick: function (evnt) { 7019 7020 }, 7021 7022 postProcessCommit: function (evnt) { 7023 this.showDisplayValue(); 7024 }, 7025 7026 postProcessExit: function (evnt) { 7027 //Only for the enabled widgets 7028 if (this.options.access === "open") { 7029 this.showDisplayValue(); 7030 this._hideError(); 7031 } 7032 }, 7033 7034 postProcessEnter: function (evnt) { 7035 }, 7036 7037 postProcessChange: function (evnt) { 7038 7039 }, 7040 7041 postProcessClick: function (evnt) { 7042 7043 }, 7044 7045 showDisplayValue: function () { 7046 this.$userControl.val(this.options.displayValue) 7047 }, 7048 7049 /** 7050 * Checks if the edit value is same as value present in the user control(html form element) 7051 * @returns {boolean} 7052 */ 7053 _isValueSame : function(){ 7054 return (((this.options.value === null) && (this.$userControl.val() === "")) || (this.options.value === this.$userControl.val())); 7055 }, 7056 7057 showValue: function () { 7058 // May be $userControl doesn't have val(), using it as of now 7059 // If the value of the field is not same as edit value, only then set the value, this also solves IE bug of cursor 7060 // moving to the end of field on click 7061 if(!this._isValueSame()) { 7062 this.$userControl.val(this.options.value) 7063 } 7064 }, 7065 7066 focus: function () { 7067 var that = this; 7068 // setTimeout added to fix CQ-51141 7069 // While using setFocus API in adaptive form, the focus was not being set in TextBox on chrome 7070 // and also on click of caption of RadioButton/Checkbox, due to fast event execution, he
7070nce adding delay during focus. 7071 setTimeout(function(){ 7072 that.$userControl[0].focus(); 7073 }, 1); 7074 }, 7075 7076 click: function () { 7077 this.focus(); 7078 this.$userControl.triggerHandler("click"); // we do not want the exact click as might bubble up to the field. 7079 }, 7080 7081 /* widget specific code */ 7082 7083 _showError: function () { 7084 if(this.errObj && _.isFunction(this.errObj.onFieldEnter)) { 7085 this.errObj.onFieldEnter(this); 7086 } 7087 }, 7088 7089 _calculatePaddingForVAlign:function(diff){ 7090 var flagForMoz = $.browser.mozilla && !xfalib.ut.Utilities.isIE11() && 7091 this.options.multiLine, 7092 vAlignBottomOrTop = this.options.paraStyles && 7093 (this.options.paraStyles["vertical-align"] == "bottom" || 7094 this.options.paraStyles["vertical-align"] == "top"); 7095 7096 if(flagForMoz && vAlignBottomOrTop || $.browser.msie && this.options.multiLine) { 7097 return; 7098 } 7099 // to handle the edge cases, if the diff is like -0.01 the whole operation is getting aborted 7100 // this diff comes mainly due to scroll height getting rounded off when widgetHeight is like x.999999 7101 diff = (diff > -0.01) ? Math.abs(diff) : diff; 7102 if (this.options.paraStyles && diff > 0) { 7103 var vAlign = this.options.paraStyles["vertical-align"]; 7104 if (vAlign == "bottom") { 7105 diff = diff - this.options.paraStyles["padding-bottom"]; 7106 this.$userControl.css("padding-top", diff); 7107 this.padding = this.$userControl.css("padding-top"); 7108 } 7109 else if (vAlign == "top" || (vAlign != "middle" && vAlign == undefined)) { 7110 if (this.options.paraStyles["padding-top"]) 7111 diff = diff - this.options.paraStyles["padding-top"]; 7112 this.$userControl.css("padding-bottom", diff); 7113 this.padding = this.$userControl.css("padding-bottom"); 7114 } 7115 else if (this.options.multiLine && vAlign == "middle") { 7116 var newDiff = diff / 2; 7117 newDiff = newDiff - this.options.paraStyles["padding-bottom"]; 7118 if (this.options.paraStyles["padding-top"]) 7119 newDiff = newDiff + this.options.paraStyles["padding-top"]; 7120 this.$userControl.css("padding-top", newDiff); 7121 } 7122 } 7123 }, 7124 7125 _handleVAlignOnExit: function (evnt) { 7126 7127 if (!this.options.paraStyles) { 7128 //vAlign has to be handled only if there is paraStyles 7129 return; 7130 } 7131 var value = this.options.displayValue, 7132 lineHeight = xfalib.view.util.TextMetrics.measureExtent(value, {refEl: this.$userControl.get(0), maxHeight: -1}).height, 7133 widgetHeight = this.options.height, 7134 diff = widgetHeight - lineHeight; 7135 this._calculatePaddingForVAlign(diff); 7136 7137 }, 7138 7139 _handleVAlignOnEnter: function (evnt) { 7140 //Only align the enabled widgets 7141 var flagForIE = $.browser.msie && this.options.multiLine; 7142 if (this.options.paraStyles && !flagForIE) { 7143 var vAlign = this.options.paraStyles["vertical-align"]; 7144 if (vAlign == "bottom" && this.padding) 7145 this.$userControl.css("padding-top", this.padding); 7146 else if (vAlign == "top" && this.padding) 7147 this.$userControl.css("padding-bottom", this.padding); 7148 } 7149 }, 7150 7151 _hideError: function () { 7152 if(this.errObj && _.isFunction(this.errObj.onFieldExit)) { 7153 this.errObj.onFieldExit(this); 7154 } 7155 }, 7156 7157 markError: function (msg, type) { 7158 if(this.errObj && _.isFunction(this.errObj.markError)) { 7159 this.errObj.markError(this, msg, type); 7160 } 7161 }, 7162 7163 clearError: function () { 7164 if(this.errObj && _.isFunction(this.errObj.clearError)) { 7165 this.errObj.clearError(this); 7166 } 7167 }, 7168 7169 getEditValue: function(value) { 7170 if(this.options.editPattern == null) { 7171 return value; 7172 } 7173 try { 7174 return xfalib.ut.PictureFmt.format(value, this.options.editPattern); 7175 } catch(e) { 7176 return null; 7177 } 7178 }, 7179 7180 parseEditValue: function(value) { 7181 if(this.options.editPattern == null) { 7182 return value; 7183 } 7184 try { 7185 return xfalib.ut.PictureFmt.parse(value, this.options.editPattern); 7186 } catch(e) { 7187 return value; 7188 } 7189 } 7190 }); 7191})($, window._); 7192(function($) { 7193 $.widget( "xfaWidget.defaultWidget", $.xfaWidget.abstractWidget, { 7194 7195 _widgetName: "defaultWidget", 7196 7197 getOptionsMap: function() { 7198 var parentOptionsMap = $.xfaWidget.abstractWidget.prototype.getOptionsMap.apply(this,arguments); 7199 return $.extend({},parentOptionsMap,{ 7200 "access": function(val) { 7201 switch(val) { 7202 case "open" : 7203 this.$userControl.removeAttr("readOnly"); 7204 this.$userControl.removeAttr("aria-readonly"); 7205 this.$userControl.removeAttr("disabled"); 7206 this.$userControl.removeAttr("aria-disabled"); 7207 break; 7208 case "nonInteractive" : 7209 case "protected" : 7210 this.$userControl.attr("disabled", "disabled"); 7211 this.$userControl.attr("aria-disabled", "true"); 7212 break; 7213 case "readOnly" : 7214 this.$userControl.attr("readOnly", "readOnly"); 7215 this.$userControl.attr("aria-readonly", "true"); 7216 break; 7217 default : 7218 this.$userControl.removeAttr("disabled"); 7219 this.$userControl.removeAttr("aria-disabled"); 7220 break; 7221 } 7222 }, 7223 7224 "displayValue": function(val) { 7225 if(this.options.commitProperty) { 7226 if($.browser.mozilla && this.options.commitProperty == "value") { 7227 // on submitting form firefox does not remember autocomplete values, if updated through attr() 7228 this.$userControl.val(this._displayEmptyStringForIE(this.options.displayValue)); 7229 } else { 7230 this.$userControl.prop(this.options.commitProperty, this._displayEmptyStringForIE(this.options.displayValue)); 7231 this.$userControl.attr(this.options.commitProperty, this._displayEmptyStringForIE(this.options.displayValue)); 7232 } 7233 } else { 7234 this.logger().debug("xfaView", "[DefaultWidget._update], User Control or Commit Property is null"); 7235 } 7236 }, 7237 7238 "placeholder": function(value){ 7239 this.$userControl.attr("placeholder", value); 7240 } 7241 }); 7242 }, 7243 7244 _displayEmptyStringForIE: function(value){ 7245 /*CQ-69417: By default "null" is displayed in the comments text box 7246 "null" values shown in IE */ 7247 // CQ-69107 included check for edge as well 7248 return (value == null && xfalib.ut.XfaUtil.prototype.detectIE()) ? '' : value; 7249 }, 7250 7251 render : function() { 7252 var control = $.xfaWidget.abstractWidget.prototype.render.apply(this,arguments) 7253 this._attachEventHandlers(control) 7254 return control 7255 }, 7256 7257 getCommitValue: function() { 7258 var value = this.$userControl.val(); 7259 if(this.options.hScrollDisabled && !this.options.multiLine) 7260 var value = xfalib.ut.XfaUtil.prototype.splitStringByWidth(this.$userControl.val(),this.$userControl.width(),this.$userControl.get(0)) ; 7261 return value; 7262 }, 7263 7264 _attachEventHandlers: function($control) {
7265 $control.keydown($.proxy(this._handleKeyDown,this)); 7266 $control.keypress($.proxy(this._handleKeyPress,this)); 7267 $control.on('paste',$.proxy(this._handlePaste,this)); 7268 $control.on('cut',$.proxy(this._handleCut,this)); 7269 }, 7270 7271 _compositionUpdateCallback : function (event) { 7272 return false; 7273 }, 7274 7275 _attachCompositionEventHandlers : function($control) { 7276 var isComposing = false; // IME Composing going on 7277 var hasCompositionJustEnded = false; // Used to swallow keyup event related to compositionend 7278 // IME specific handling, to handle japanese languages max limit 7279 // since enter can also be invoked during composing, a special handling is done here 7280 var that = this, 7281 changeCaratPosition = function() { 7282 // change the carat selection position to further limit input of characters 7283 var range = window.getSelection(); 7284 range.selectAllChildren(that.$userControl[0]); 7285 range.collapseToEnd(); 7286 }; 7287 $control.keyup(function(event) { 7288 if (/*isComposing || */hasCompositionJustEnded) { 7289 if (that._compositionUpdateCallback(event)) { 7290 changeCaratPosition(); 7291 } 7292 // IME composing fires keydown/keyup events 7293 hasCompositionJustEnded = false; 7294 } 7295 }); 7296 $control.on("compositionstart", 7297 function(event) { 7298 isComposing = true; 7299 }) 7300 .on("compositionupdate", 7301 function(event) { 7302 // event.originalEvent.data refers to the actual content 7303 if (that._compositionUpdateCallback(event)) { 7304 changeCaratPosition(); 7305 } 7306 }) 7307 .on("compositionend", 7308 function(event) { 7309 isComposing = false; 7310 // some browsers (IE, Firefox, Safari) send a keyup event after 7311 // compositionend, some (Chrome, Edge) don't. This is to swallow 7312 // the next keyup event, unless a keydown event happens first 7313 hasCompositionJustEnded = true; 7314 }) 7315 .on("keydown", 7316 function(event) { 7317 // Safari on OS X may send a keydown of 229 after compositionend 7318 if (event.which !== 229) { 7319 hasCompositionJustEnded = false; 7320 } 7321 }); 7322 }, 7323 7324 _handleKeyDown : function(event){ 7325 if(event.keyCode == 13 || event.charCode == 13 || event.which == 13) // touch devices may return charCode 7326 event.preventDefault(); 7327 }, 7328 7329 _handleKeyPress : function(event){ 7330 if(event.keyCode == 13 || event.charCode == 13 || event.which == 13) // touch devices may return charCode 7331 event.preventDefault(); 7332 } 7333 }); 7334})($); 7335(function($, _) { 7336 var xfaUtil = xfalib.ut.XfaUtil.prototype; 7337 $.widget( "xfaWidget.dateTimeEdit", $.xfaWidget.defaultWidget, { 7338 7339 _widgetName : "dateTimeEdit", 7340 7341 getEventMap: function() { 7342 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getEventMap.apply(this,arguments); 7343 if(this._nativeWidget === false) { 7344 return $.extend({}, parentOptionsMap, { 7345 "onfocus1.datetimepicker": xfalib.ut.XfaUtil.prototype.XFA_ENTER_EVENT, 7346 "onvaluechange.datetimepicker": xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT, 7347 "onfocusout.datetimepicker": xfalib.ut.XfaUtil.prototype.XFA_EXIT_EVENT, 7348 "onoverlap.datetimepicker": xfalib.ut.XfaUtil.prototype.XFA_CLICK_EVENT, // Custom Event to fix BUG #3626974 7349 "input": xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT, // TODO : add handler for xfa.event.change 7350 "focus": null, 7351 "blur": null 7352 }) 7353 } else { 7354 return $.extend({}, parentOptionsMap, { 7355 "change": xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT 7356 }) 7357 } 7358 }, 7359 7360 _getAdobeDatePickerOptionsMap : function(parentOptionsMap) { 7361 return { 7362 "access" : function (val) { 7363 switch (val) { 7364 case "open" : 7365 this.$userControl.adobeDateTimePicker("access", true); 7366 break; 7367 case "nonInteractive" : 7368 case "protected" : 7369 case "readOnly" : 7370 this.$userControl.adobeDateTimePicker("access", false); 7371 break; 7372 } 7373 parentOptionsMap.access.apply(this, arguments); 7374 }, 7375 "displayValue" : function (val) { 7376 // set the value in the datepicker plugin 7377 this.$userControl.adobeDateTimePicker("value", this.options.value); 7378 // show the display value 7379 this.showDisplayValue(); 7380 } 7381 } 7382 }, 7383 7384 _getNativeDatePickerOptionsMap: function (parentOptionsMap) { 7385 return { 7386 "displayValue": function (val) { 7387 this.showDisplayValue(); 7388 } 7389 } 7390 }, 7391 7392 7393 getOptionsMap: function() { 7394 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this,arguments), 7395 datePickerOptions = this._nativeWidget === false ? this._getAdobeDatePickerOptionsMap(parentOptionsMap) 7396 : this._getNativeDatePickerOptionsMap(parentOptionsMap), 7397 commonOptions = { 7398 "paraStyles": function (paraStyles) { 7399 parentOptionsMap.paraStyles.apply(this, arguments); 7400 this._handleVAlignOnExit(); 7401 }, 7402 7403 "access": function(val) { 7404 // update width on change of access (as width of widget is dependent on access) 7405 // The calender icon should be hidden, and widget should take full space when readOnly 7406 parentOptionsMap.access.apply(this, arguments); 7407 this.getOptionsMap().width.apply(this,[this.options.width]); 7408 }, 7409 "width": function (val) { 7410 parentOptionsMap.width.apply(this, arguments); 7411 if (this.options.showCalendarIcon && val && this.options.access == "open") { 7412 var effectiveWidth = val > this.options.calendarIconWidth ? val - this.options.calendarIconWidth : val; 7413 this.$userControl.width(effectiveWidth); // leave space for the cal icon 7414 } 7415 }, 7416 7417 "height": function(val) { 7418 parentOptionsMap.height.apply(this, arguments); 7419 this._handleVAlignOnExit(); 7420 }, 7421 "screenReaderText": function (val) { 7422 var editPattern = this.options.editPattern; 7423 var defaultEditPattern = this._nativeWidget ? "mm/dd/yyyy" : "YYYY-MM-DD"; 7424 var regex = /(?:date){0,1}{(.*)}/;
7424 // date{<pattern>} or {<pattern>} both are valid as per xfa spec 7425 editPattern = typeof editPattern === "string" ? editPattern.match(regex)[1] : defaultEditPattern; 7426 var defaultLabel = "Please Enter date in {0} format only"; 7427 if (editPattern) { 7428 var ariaLabel = xfalib.ut.LocalizationUtil.prototype.getLocalizedMessage("", 7429 xfalib.locale.Strings.datePickerAriaLabel || defaultLabel, [editPattern]) 7430 } 7431 var finalVal = val !== undefined ? val + " " + ariaLabel : val; 7432 this.$userControl.attr("aria-label", finalVal); 7433 } 7434 }; 7435 return $.extend({},parentOptionsMap,datePickerOptions, commonOptions); 7436 }, 7437 7438 postProcessExit: function(evnt) { 7439 $.xfaWidget.defaultWidget.prototype.postProcessExit.apply(this,arguments); 7440 this._handleVAlignOnExit (); 7441 }, 7442 7443 preProcessEnter: function(evnt) { 7444 $.xfaWidget.defaultWidget.prototype.preProcessEnter.apply(this,arguments); 7445 this._handleVAlignOnEnter(); 7446 }, 7447 7448 preProcessChange: function(evnt) { 7449 //CQ-46332:loss of date value in date-picker , setting the value here or else 7450 //it gets lost during focus 7451 if(this._nativeWidget === true){ 7452 this.options.value = this.$userControl.val(); 7453 } 7454 }, 7455 7456 showDisplayValue: function() { 7457 if(this._nativeWidget === false) { 7458 $.xfaWidget.defaultWidget.prototype.showDisplayValue.apply(this, arguments); 7459 } else { 7460 this.showValue(); 7461 } 7462 }, 7463 7464 7465 showValue: function () { 7466 if (this._nativeWidget == false) { 7467 this.$userControl.adobeDateTimePicker("value", this.options.value); 7468 } else { 7469 $.xfaWidget.defaultWidget.prototype.showValue.apply(this, arguments); 7470 } 7471 $.xfaWidget.textField.prototype._selectOnFocusInIE.apply(this, arguments); 7472 }, 7473 7474 getCommitValue: function() { 7475 if (this._nativeWidget === false) { 7476 var value = this.$userControl.adobeDateTimePicker("value"), 7477 parsedValue = this.parseEditValue(value); 7478 return parsedValue; 7479 } 7480 return $.xfaWidget.defaultWidget.prototype.getCommitValue.apply(this, arguments); 7481 }, 7482 7483 render: function() { 7484 var self = this, 7485 textStyle = this.getOrElse(this.$data(this.element.get(0), "xfamodel"), "textstyle", ""), 7486 $control = $.xfaWidget.abstractWidget.prototype.render.apply(this, arguments), 7487 $source = $control, 7488 id, 7489 existingInlineStyleAttributeValues, 7490 newInlineStyleAttributeValues, 7491 combinedInlineStyleAttributeValues; 7492 existingInlineStyleAttributeValues = this.element.find("input").attr("style") || ''; 7493 this._nativeWidget = true; 7494 if(this.options.useNativeWidget === false || $control[0].type !== "date") { 7495 this._nativeWidget = false; 7496 id = this.element.find("input")[0].id; 7497 this.element.children().remove(); 7498 $("<div></div>").css({position: "relative", width: "100%", height: "100%"}) // want to fill entire width of containing table cell 7499 .append($("<input type='text'/>")) 7500 .appendTo(this.element); 7501 $control = $("input", this.element). 7502 attr("style", textStyle). 7503 attr("name", this.options.name). 7504 attr("id", id). 7505 adobeDateTimePicker({ 7506 positioning: this.element, 7507 locale: { 7508 months: this.options.months, 7509 days: this.options.days, 7510 zero: this.options.zero, 7511 clearText: this.options.clearText 7512 }, 7513 access: this.options.access, 7514 value: this.options.value, 7515 showCalendarIcon: this.options.showCalendarIcon, 7516 iconWidth: this.options.calendarIconWidth, 7517 minValidDate : this.options.minValidDate, 7518 maxValidDate : this.options.maxValidDate, 7519 exclMinDate : this.options.exclMinDate, 7520 exclMaxDate : this.options.exclMaxDate, 7521 editValue: function (value) { 7522 return self.getEditValue(value); 7523 } 7524 }); 7525 } 7526 this._attachEventHandlers($control); 7527 newInlineStyleAttributeValues = this.element.find("input").attr("style") || ''; 7528 //append the previous inlineStyleAttributeValues to newInlineStyleAttributeValues so that the inline styles 7529 //added from the dialog are applied. 7530 combinedInlineStyleAttributeValues = newInlineStyleAttributeValues + existingInlineStyleAttributeValues; 7531 this.element.find("input").attr("style", combinedInlineStyleAttributeValues); 7532 // only in case of adaptive form, we would copy the attributes back 7533 if(window.guideBridge) { 7534 // restore the original attribute back to destination object 7535 this.copyAttributesFromSrcToDest($source, this.element.find("input")); 7536 } 7537 return $control; 7538 } 7539 }) ; 7540 7541})($, _); 7542(function($, _) { 7543$.widget("xfaWidget.numericInput", $.xfaWidget.defaultWidget, { 7544 7545 _widgetName: "numericInput", 7546 7547 options : { 7548 value : null, 7549 curValue: null, 7550 pos: 0, 7551 lengthLimitVisible: true, 7552 zero:"0",
7553 decimal:".", 7554 minus:"-" 7555 }, 7556 7557 //TODO: to support writing in different locales \d should be replaced by [0-9] for different locales 7558 _matchArray : { 7559 "integer":"^[+-]?{digits}*$", 7560 "decimal":"^[+-]?{digits}{leading}({decimal}{digits}{fraction})?$", 7561 "float":"^[+-]?{digits}*({decimal}{digits}*)?$" 7562 }, 7563 7564 _regex : null, 7565 7566 _engRegex : null, 7567 7568 _writtenInLocale : false, 7569 7570 _previousCompositionVal : "", 7571 7572 7573 _toLatinForm : function (halfOrFullWidthStr) { 7574 // refer http://www.fileformat.info/info/unicode/block/halfwidth_and_fullwidth_forms/utf8test.htm 7575 return halfOrFullWidthStr.replace( 7576 /[\uff00-\uffef]/g, 7577 function(ch) { return String.fromCharCode(ch.charCodeAt(0) - 0xfee0); } 7578 ); 7579 }, 7580 7581 getOptionsMap: function() { 7582 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this,arguments); 7583 return $.extend({},parentOptionsMap,{ 7584 "paraStyles": function(paraStyles){ 7585 parentOptionsMap.paraStyles.apply(this,arguments); 7586 this._handleVAlignOnExit (); 7587 } , 7588 7589 "height": function(val) { 7590 if(val) { 7591 this.$css(this.$userControl[0],{"height" :val}); 7592 this._handleVAlignOnExit(); // To Handle the case of expandable Fields 7593 } 7594 } 7595 7596 }) 7597 }, 7598 7599 getEventMap: function() { 7600 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getEventMap.apply(this,arguments); 7601 return $.extend({},parentOptionsMap,{ 7602 "onKeyInput.numericInput" : xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT 7603 }) 7604 }, 7605 7606 _getDigits: function() { 7607 var zeroCode = this.options.zero.charCodeAt(0), 7608 digits = ""; 7609 for(var i = 0;i < 10;i++) { 7610 digits += String.fromCharCode(zeroCode + i); 7611 } 7612 return "["+digits+"]" 7613 }, 7614 7615 _escape: function(str) { 7616 return str.replace(".","\\.") 7617 }, 7618 7619 postProcessExit: function(evnt) { 7620 $.xfaWidget.defaultWidget.prototype.postProcessExit.apply(this,arguments); 7621 this._handleVAlignOnExit (); 7622 }, 7623 7624 preProcessEnter: function(evnt) { 7625 $.xfaWidget.defaultWidget.prototype.preProcessEnter.apply(this,arguments); 7626 this._handleVAlignOnEnter(); 7627 }, 7628 7629 render : function() { 7630 var matchStr = this._matchArray[this.options.dataType]; 7631 if(matchStr) { 7632 var ld = this.options.leadDigits, 7633 fd = this.options.fracDigits, 7634 ldstr = ld && ld != -1 ? "{0,"+ld+"}" 7635 : "*", 7636 fdstr = fd && fd != -1 ? "{0,"+fd+"}" 7637 : "*", 7638 matchStr = matchStr.replace("{leading}",ldstr) 7639 .replace("{fraction}",fdstr), 7640 localeStr = matchStr.replace(/{digits}/g,this._getDigits()) 7641 .replace("{decimal}",this._escape(this.options.decimal)), 7642 engStr = matchStr.replace(/{digits}/g,"[0-9]") 7643 .replace("{decimal}","\\.") 7644 this._processValue = !(this._getDigits() == "[0123456789]" && this.options.decimal == ".") 7645 this._regex = new RegExp(localeStr, "g"); 7646 this._engRegex = new RegExp(engStr, "g"); 7647 } 7648 return $.xfaWidget.defaultWidget.prototype.render.apply(this, arguments); 7649 }, 7650 7651 getCommitValue: function() { 7652 var value = $.xfaWidget.defaultWidget.prototype.getCommitValue.apply(this, arguments); 7653 // we support full width, half width and locale specific numbers 7654 value = this._toLatinForm(value); 7655 if(value.length > 0 && this._processValue && !value.match(this._engRegex)) { 7656 this._writtenInLocale = true; 7657 value = this._convertValueFromLocale(value); 7658 } else { 7659 this._writtenInLocale = false 7660 } 7661 if(value && value.length >= this.options.combCells ) 7662 value = value.slice(0,this.options.combCells); 7663 this._previousCompositionVal = value; 7664 return value; 7665 }, 7666 7667 _compositionUpdateCallback : function (event) { 7668 var that = this; 7669 var flag = false;
7670 var leadDigits = that.options.leadDigits; 7671 var fracDigits = that.options.fracDigits; 7672 // we don't check use-case where just fracDigits is set since in case of composition update, the value to update is not known 7673 if (leadDigits !== -1) { 7674 var val = that.$userControl.val(); 7675 if (event.type === "compositionupdate" && event.originalEvent.data) { 7676 val = val + event.originalEvent.data.substr(event.originalEvent.data.length - 1); 7677 } 7678 // can't use the existing regex (since current regex checks for english digits), rather doing leadDigit compare 7679 var totalLength = leadDigits + (fracDigits !== -1 ? (fracDigits + that.options.decimal.length) : 0); 7680 if (val.indexOf(that.options.decimal) === -1) { 7681 totalLength = leadDigits; 7682 } 7683 var latinVal = this._toLatinForm(val); 7684 // match both since we support full width, half width and locale specific input 7685 var match = latinVal.match(that._regex)|| latinVal.match(this._engRegex); 7686 flag = !match; 7687 if (match === null) { 7688 // entered invalid character, revert to previous value 7689 that.$userControl.val(that._previousCompositionVal); 7690 flag = true; 7691 } else if (flag) { 7692 // if max reached 7693 var newVal = val.substr(0, totalLength); 7694 that.$userControl.val(newVal); 7695 that._previousCompositionVal = newVal; 7696 flag = true; 7697 } else { 7698 that._previousCompositionVal = val; 7699 } 7700 } 7701 return flag; 7702 }, 7703 7704 _attachEventHandlers : function($control) { 7705 $.xfaWidget.defaultWidget.prototype._attachEventHandlers.apply(this, arguments); 7706 // IME specific handling, to handle japanese languages max limit 7707 $.xfaWidget.defaultWidget.prototype._attachCompositionEventHandlers.apply(this, arguments); 7708 }, 7709 7710 _handleKeyInput : function(event, character, code){ 7711 if(event.ctrlKey && !_.contains(['paste', 'cut'], event.type)) { 7712 return true; 7713 } 7714 7715 $.xfaWidget.defaultWidget.prototype._handleKeyDown.apply(this,arguments); 7716 this.options.lengthLimitVisible = true; 7717 7718 var val = this.$userControl.prop(this.options.commitProperty) || '', 7719 // if selectionStart attribute isn't supported then its value will be undefined 7720 selectionStart = xfalib.view.util.HtmlUtil.getHTMLSupportedAttr(this.$userControl[0], "selectionStart"), 7721 isSelectionAttrSupported = !(selectionStart === undefined || selectionStart === null), 7722 selectionStart = selectionStart || 0, 7723 selectionEnd = xfalib.view.util.HtmlUtil.getHTMLSupportedAttr(this.$userControl[0], "selectionEnd") || 0, 7724 combCells = parseInt(this.options.combCells) || 0, 7725 current, 7726 change = character; 7727 7728 if (combCells > 0 ) { 7729 change = character.substr(0, combCells - val.length + selectionEnd - selectionStart); 7730 } 7731 7732 current = val.substr(0, selectionStart) + change + val.substr(selectionEnd); 7733 // done to handle support for both full width, half width or mixed input in number field 7734 var latinCurrentValue = this._toLatinForm(current); 7735 7736 // we want to check regex first and then see whether it was numeric or not. 7737 if (!(this._regex == null || latinCurrentValue.match(this._regex) || latinCurrentValue.match(this._engRegex))) { 7738 event.preventDefault(); 7739 return false; 7740 } 7741 7742 // CQ-4245407 : selectionStart and selectionEnd attributes aren't supported in case of input type = number 7743 // it is used for providing native HTML5 implementation for numeric field, so no further processing is required 7744 // As it is specific to AF and AF doesn't support change event on each keypress, so this change should be fine 7745 if (!isSelectionAttrSupported) { 7746 return true; 7747 } 7748 7749 if (!_.contains(['keydown', 'cut'], event.type) && combCells && (val.length >= combCells || current.length > combCells) && selectionStart === selectionEnd) { 7750 event.preventDefault(); 7751 return false;
7752 } 7753 7754 this.options.curValue = val; 7755 this._previousCompositionVal = val; 7756 this.options.pos = selectionStart; 7757 7758 if(this.options.hScrollDisabled && !_.contains(['keydown', 'cut'], event.type)) { 7759 var expectedWidth = xfalib.view.util.TextMetrics.measureExtent(current, {refEl: this.$userControl[0], maxWidth:-1}).width; 7760 if(!event.ctrlKey && expectedWidth > this.$userControl.width() - 5){ 7761 event.preventDefault(); 7762 this.options.lengthLimitVisible = false; 7763 } 7764 } 7765 7766 this.$userControl.trigger({ 7767 type : "onKeyInput.numericInput", 7768 originalType : event.type, 7769 character : character, // contains the pasted string or pressed key 7770 keyCode : event.keyCode || 0, 7771 charCode : event.charCode || 0, 7772 which : event.which || 0, 7773 ctrlKey : event.ctrlKey || event.metaKey || false, 7774 shiftKey : event.shiftKey || false, 7775 keyDown : false, // This property is available only for list boxes and drop-down lists 7776 selectionStart: selectionStart, 7777 selectionEnd: selectionEnd 7778 }); 7779 }, 7780 7781 _handleKeyDown : function(event){ 7782 if (event) { 7783 var code = event.charCode || event.which || event.keyCode || 0; 7784 if(code == 8 || code == 46) // backspace and del 7785 this._handleKeyInput(event, "", code); 7786 else if(code == 32) { // suppress space 7787 event.preventDefault(); 7788 return false; 7789 } 7790 } 7791 }, 7792 7793 _isValidChar: function (character) { 7794 character = this._toLatinForm(character); 7795 var lastSingleDigitChar = String.fromCharCode(this.options.zero.charCodeAt(0) + 9); 7796 // we only full width, half width and also locale specific if customer has overlayed the i18n file 7797 return (character >= "0" && character <= "9") || (character>=this.options.zero && character<=lastSingleDigitChar) || character===this.options.decimal || character===this.options.minus; 7798 }, 7799 7800 _handleKeyPress : function(event){ 7801 if (event) { 7802 var code = event.charCode || event.which || event.keyCode || 0, 7803 character = String.fromCharCode(code); 7804 7805 if(xfalib.ut.XfaUtil.prototype.isNonPrintableKey(event.key)) { // mozilla also generates a keypress, along with keydown 7806 return true; // for all keys, so only handling printable keys in keypress 7807 } 7808 7809 if (this._isValidChar(character)) 7810 this._handleKeyInput(event, character, code); 7811 else if (!event.ctrlKey){ 7812 event.preventDefault(); 7813 return false; 7814 } 7815 } 7816 }, 7817 7818 _handlePaste : function(event){ 7819 if (event) { 7820 var pastedChar = undefined; 7821 if (window.clipboardData && window.clipboardData.getData) { // IE 7822 pastedChar = window.clipboardData.getData('Text'); 7823 } else if (event.originalEvent.clipboardData && event.originalEvent.clipboardData.getData) { 7824 pastedChar = event.originalEvent.clipboardData.getData('text/plain'); 7825 } 7826 7827 if(pastedChar) { 7828 var allPastedCharsValid = _.every(pastedChar.split(''), function (character) { 7829 return this._isValidChar(character); 7830 }, this); 7831 if (allPastedCharsValid) { 7832 // during paste we support both half width, full width and locale specific numbers 7833 pastedChar = this._toLatinForm(pastedChar); 7834 this._handleKeyInput(event, pastedChar, 0); 7835 } 7836 else if (!event.ctrlKey) { 7837 event.preventDefault(); 7838 return false; 7839 } 7840 } 7841 } 7842 }, 7843 7844 _handleCut : function(event) { 7845 if (event) { 7846 this._handleKeyInput(event, "", 0); 7847 } 7848 }, 7849 // CQ-107886 : added handling for negative values, as for '-', '-3' was getting returned 7850 _convertValueToLocale: function(val) { 7851 var zeroCode = this.options.zero.charCodeAt(0); 7852 return _.map(val,function(c) { 7853 if(c == ".") { 7854 return this.options.decimal; 7855 } else if(c == "-") { 7856 return this.options.minus; 7857 } else { 7858 return String.fromCharCode(parseInt(c) + zeroCode); 7859 } 7860 },this).join(""); 7861 }, 7862 7863 _convertValueFromLocale: function(val) { 7864 val = this._toLatinForm(val); 7865 var zeroCode = this.options.zero.charCodeAt(0); 7866 return _.map(val,function(c) { 7867 if(c == this.options.decimal) { 7868 return "."; 7869 } else if(c == this.options.minus) { 7870 return "-"; 7871 } else { 7872 return (c.charCodeAt(0) - zeroCode).toString(); 7873 } 7874 },this).join(""); 7875 }, 7876 7877 showValue : function() { 7878 // if the value is same, don't do anything 7879 if(!this._isValueSame()){ 7880 if(this.options.value && this._writtenInLocale) { 7881 this.$userControl.val(this._convertValueToLocale(this.options.value)) 7882 } else { 7883 this.$userControl.val(this.options.value) 7884 } 7885 } 7886 //IE doesn't show selected text if we focus and set its value all the time so force selection 7887 $.xfaWidget.textField.prototype._selectOnFocusInIE.apply(this, arguments); 7888 } 7889}); 7890})($, window._);(function ($, _) { 7891 $.widget("xfaWidget.dropDownList", $.xfaWidget.defaultWidget, { //commitEvent: change; commitProperty: value<Array> 7892 7893 _widgetName: "dropDownList", 7894 7895 options: { 7896 value: [], 7897 items: [], 7898 editable: false, 7899 placeholder: "", 7900 displayValue: [] 7901 }, 7902 7903 widgetSkeleton: '<select name="" style="" size = "1"></select>', 7904 optionSkeleton: '<option data-user-option></option>', 7905 optGroupSkeleton: '<optgroup label=""></optgroup>', 7906 AF_OPTGROUP_NAME: "afOptGroupName", 7907 PLACE_HOLDER_STYLE_CLASS : "placeHolder", 7908 7909 getOptionsMap: function () { 7910 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this, arguments); 7911 return $.extend({}, parentOptionsMap, { 7912 "value": function (val) { 7913 if (!_.isArray(val)) { 7914 val = [val]; 7915 } 7916 var selectedOptionFound = false, 7917 that = this; 7918 //sync option selection as per new values 7919 $("option", this.$userControl).each(function (index) { 7920 var selectValue = $(this).val(); 7921 //Check if this value is present in options value array 7922 if (_.contains(val, selectValue)) { 7923 $(this).prop("selected", true); 7924 selectedOptionFound = true; 7925 } else { 7926 $(this).prop("selected", false); 7927 if (this.id === "emptyValue") { 7928 $(this).val("").html(that.options.placeholder); 7929 //Hiding emptyValue with no placeholder text configured. 7930 if(that.options.placeholder.length == 0) { 7931 $(this).hide(); 7932 } 7933 } 7934 } 7935 }); 7936 7937 /* Add default option if : 7938 / 1. If placeholder add an extra option 7939 / 2. If the value is set anything other than the options (and null/"") create a new option 7940 */ 7941 if ((!selectedOptionFound && val.length != 0 && val[0] != null) || that.options.placeholder.length != 0) { 7942 if (this.$userControl.children('[data-empty-option]').length == 0) { 7943 var extraOption = document.createElement("option"); 7944 extraOption.setAttribute("data-empty-option", ""); 7945 extraOption.setAttribute("role", "none"); 7946 extraOption.setAttribute("value", "") 7947 this.$userControl[0].insertBefore(extraOption, this.$userControl[0].firstChild); 7948 } 7949 // If placeholder is present the set value of empty option to placeholder 7950 if (that.options.placeholder.length != 0) { 7951 this.$userControl.children('[data-empty-option]').text(that.options.placeholder); 7952 } 7953 // If placeholder is present and value is not present then select placeholder 7954 if (val.length == 0 || val[0] == null) { 7955 this.$userControl.children('[data-empty-option]').prop("selected", true); 7956 } // If value is set anything other than option then set empty option to value 7957 else if (!selectedOptionFound && val.length != 0 && val[0] != null) { 7958 this.$userControl.children('[data-empty-option]').text(val[0]). 7959 prop("selected", true). 7960 val(_.escape(val[0])). 7961 show(); 7962 } 7963 7964 } 7965 else if (that.options.placeholder.length == 0) { 7966 // Delete default option if value is found in options while adding options 7967 if (selectedOptionFound && this.$userControl.children('[data-empty-option]').val() != that.options.displayValue) { 7968 if (this.$userControl.children('[data-empty-option]').length > 0) { 7969 this.$userControl[0].removeChild(this.$userControl.children('[data-empty-option]')[0]); 7970 } 7971 } 7972 // Reset the value of dropdown based on rule 7973 else if (!selectedOptionFound && (val.length == 0 || val == null || val[0] == null)) { 7974 this.$userControl[0].value = ""; 7975 } 7976 } 7977 this.$userControl.toggleClass(this.PLACE_HOLDER_STYLE_CLASS, val.length == 0 || val == null); 7978 }, 7979 7980 "items": function (val) { 7981 if (!_.isArray(val)) { 7982 val = [val]; 7983 } 7984 7985 var AF_OPTGROUP_NAME = "afOptGroupName"; 7986 var i, j, optgroupOptions = [], element, $viewOptgroup, $preOptgroup; 7987 var viewOptgroups = $("optgroup", this.$userControl); 7988 // Removes all options which earlier didn't belong to any optgroup. 7989 if (viewOptgroups.length == 0) { 7990 // save selected value because when value is set before items in setWidgetOptions 7991 // the selected value would get lost in html 7992 var selectedOption = this.$userControl.find('[selected]'); 7993 this.$userControl.children("option[data-user-option]").remove(); 7994 } 7995 for (i = 0, j = 0; j < val.length; j++) { 7996 element = val[j]; 7997 if (element.save != AF_OPTGROUP_NAME) { 7998 // Add options to String[] which will be later synced to the optgroup. 7999 optgroupOptions.push(element); 8000 } else { 8001 $viewOptgroup = viewOptgroups[i++]; 8002 // When optgroup is less than the required optgroups. 8003 if (i > viewOptgroups.length) { 8004 $viewOptgroup = this.addGroup(element.display); 8005 } 8006 // Undefined as it may not occur even once when list is purely of options. 8007 if (!_.isUndefined($viewOptgroup) && $viewOptgroup.label != element.display) { 8008 $viewOptgroup.label = element.display || ''; 8009 } 8010 // Check to skip the first optgroup. 8011 if (j != 0) { 8012 // Syncs options to the prev optgroup. 8013 // Prev optgroup because current optgroup marks the end of options of prev. 8014 this.handleOptions($preOptgroup, optgroupOptions); 8015 // Clear options of the optgroup for next optgroup. 8016 optgroupOptions = []; 8017 } 8018 $preOptgroup = $viewOptgroup; 8019 } 8020 } 8021 // Removes all extra optgroups. 8022 while (i < viewOptgroups.length) { 8023 $viewOptgroup = viewOptgroups[i++]; 8024 this.deleteGroup($viewOptgroup.label); 8025 } 8026 //Add remaining options to respective optgroup. 8027 if (optgroupOptions.length != 0) { 8028 this.handleOptions($preOptgroup, optgroupOptions, selectedOption); 8029 } 8030 8031 //Intentionally left the selection check -> I am relying on the fact that "value" sync event is called after "items" sync. 8032 }, 8033 8034 "displayValue": function () { 8035 }, 8036 "placeholder": function(value){ 8037 // overriding the default handling of place holder options setter 8038 }, 8039 "access": function (val) { 8040 switch (val) { 8041 case "open" : 8042 this.$userControl.removeAttr("disabled"); 8043 this.$userControl.removeAttr("aria-disabled"); 8044 this.$userControl.removeAttr("aria-readonly"); 8045 var options = this.$userControl[0]; 8046 if(options && options.length > 0) { 8047 _.each(this.$userControl[0], function (element) { 8048 element.removeAttribute("disabled"); 8049 }); 8050 } 8051 break; 8052 case "nonInteractive" : 8053 case "protected" : 8054 // In case of nonInteractive and protected, field should be disabled and cannot be tabbed. 8055 this.$userControl.attr("disabled", "disabled"); 8056 case "readOnly" : 8057 this.$userControl.attr("aria-disabled", "true"); 8058 this.$userControl.attr("aria-readonly", "true"); 8059 var options = this.$userControl[0]; 8060 if(options && options.length > 0) { 8061 _.each(this.$userControl[0], function (element) { 8062 element.disabled = true; 8063 }); 8064 } 8065 break; 8066 default : 8067 this.$userControl.removeAttr("disabled"); 8068 this.$userControl.removeAttr("aria-disabled"); 8069 this.$userControl.removeAttr("aria-readonly"); 8070 break; 8071 } 8072 } 8073 }) 8074 }, 8075 8076 getEventMap: function () { 8077 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getEventMap.apply(this, arguments); 8078 return $.extend({}, parentOptionsMap, { 8079 "focus": [xfalib.ut.XfaUtil.prototype.XFA_ENTER_EVENT, xfalib.ut.XfaUtil.prototype.XFA_PREOPEN_EVENT], 8080 "change": xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT 8081 }) 8082 }, 8083 8084 render: func
8084tion () { 8085 var existingInlineStyleAttributeValues = this.element.find("select").attr("style"), 8086 newInlineStyleAttributeValues, 8087 combinedInlineStyleAttributeValues, 8088 size = 1; 8089 8090 this.element.addClass(this._widgetName); 8091 this.element.children().remove(); 8092 8093 var inputName = _.uniqueId("select"), //Unique Id 8094 textStyle = this.getOrElse(this.$data(this.element.get(0), "xfamodel"), "textstyle", ""), 8095 $widgetSkeleton = $(this.widgetSkeleton) 8096 .attr('style', textStyle) 8097 .attr('name', inputName); 8098 if(this.options.editable) { 8099 $widgetSkeleton.addClass('combobox'); 8100 } 8101 8102 if(this.options.items && this.options.items.length>0){ 8103 size = this.options.items.length 8104 } 8105 if(this.options.multiSelect) { 8106 $widgetSkeleton.addClass('multiDropdown'); 8107 $widgetSkeleton.attr('multiple','multiple'); 8108 $widgetSkeleton.attr('size',size); 8109 $widgetSkeleton.attr('data-multiple-selection',"true"); 8110 } 8111 8112 var $parEl = $widgetSkeleton; 8113 _.each(this.options.items, function(item){ 8114 var saveItem = _.isString(item.save) ? item.save.replace(/\"/g, """) : ""; 8115 if (saveItem === this.AF_OPTGROUP_NAME){ // assuming optgroups appear before options 8116 $parEl = $(this.optGroupSkeleton).attr('label', item.display).appendTo($widgetSkeleton); 8117 } else { 8118 $(this.optionSkeleton).val(saveItem).text(item.display).appendTo($parEl); 8119 } 8120 },this); 8121 8122 this.element.append($widgetSkeleton); 8123 8124 var control = this.element.children().eq(0).attr("name", this.options.name); 8125 this._attachEventHandlers(control); 8126 newInlineStyleAttributeValues = this.element.find("select").attr("style"); 8127 //append the previous inlineStyleAttributeValues to newInlineStyleAttributeValues so that the inline styles 8128 //added from the dialog are applied. 8129 combinedInlineStyleAttributeValues = newInlineStyleAttributeValues + existingInlineStyleAttributeValues; 8130 this.element.find("select").attr("style", combinedInlineStyleAttributeValues); 8131 return control; 8132 }, 8133 8134 //syncs the options to the optgroup dynamically. 8135 handleOptions : function ($viewOptgroup, val, selectedOption) { 8136 //When the list so far consists purely of options. 8137 if (_.isUndefined($viewOptgroup)) { 8138 $viewOptgroup = this.$userControl[0]; 8139 } 8140 var viewOptions = $("option[data-user-option]", $viewOptgroup); 8141 //Syncs the value of options. 8142 for (var i = 0, j = 0; i < viewOptions.length && j < val.length; i++, j++) { 8143 var $viewOption = viewOptions[i]; 8144 var element = val[j]; 8145 if ($viewOption.text != element.display) { 8146 $viewOption.text = element.display || ''; 8147 } 8148 if ($viewOption.value != element.save) { 8149 $viewOption.value = element.save || ''; 8150 } 8151 } 8152 //Deletes options if count is more than required. 8153 while (i < viewOptions.length) { 8154 this.deleteOption(viewOptions[i++]) 8155 } 8156 //Add options if count is less than required. 8157 while (j < val.length) { 8158 this.addOption($viewOptgroup, val[j++], selectedOption); 8159 } 8160 // Set empty value to dropdown if placeholder and default value is not present 8161 if (this.options.placeholder.length == 0) { 8162 if (this.checkForEmptyValue(this.options.value)) { 8163 this.$userControl[0].value = ""; 8164 } 8165 } 8166 // since options are removed and added again during items we need to set the access again options. 8167 this.optionsHandler["access"].apply(this, [this.options["access"]]); 8168 }, 8169 8170 addOption : function ($viewOptgroup, element, selectedOption) { 8171 var $newOption = $(this.optionSkeleton).val(element.save).text(element.display); 8172 $newOption.appendTo($viewOptgroup); 8173 if(selectedOption) { 8174 if(element.save === selectedOption.val() && element.display === selectedOption.text()) { 8175 $newOption.prop("selected", true); 8176 } 8177 } 8178 // Since the displayValue is a '\n' separated string of selected values in case of multiSelect, 8179 // we convert it to an array and check whether that array contains the save value of the element 8180 var values; 8181 if (this.options.value && _.isString(this.options.value)) { 8182 values = this.options.value.split('\n'); 8183 } else if (_.isArray(this.options.value)) { 8184 // In the case of AF we have value/displayValue as an array 8185 values = this.options.value 8186 } 8187 if (values && values.indexOf(element.save) >= 0) { 8188 //Delete emptyValue with no placeholder text configured and value is found in options 8189 if (this.options.placeholder.length == 0 && this.$userControl.children('[data-empty-option]').length > 0) { 8190 this.$userControl[0].removeChild(this.$userControl.children('[data-empty-option]')[0]); 8191 } 8192 this.$userControl.children().filter(function() { 8193 return this.value == element.save; 8194 }).prop("selected", true); 8195 } 8196 }, 8197 8198 deleteOption: function ($viewOption) { 8199 this.$userControl.find('option[value='+$viewOption.value+']').remove(); 8200 }, 8201 8202 checkForEmptyValue: function(value) { 8203 if ((value && _.isArray(value) && value[0] == null) || (this.options.value == null)) 8204 return true; 8205 else 8206 return false;
8207 }, 8208 8209 addGroup: function(label) { 8210 //Creates a optgroup Node. 8211 var optionGroup = document.createElement("OPTGROUP"); 8212 optionGroup.label = label; 8213 this.$userControl[0].appendChild(optionGroup); 8214 return optionGroup; 8215 }, 8216 8217 deleteGroup: function(label) { 8218 this.$userControl.children().remove('optgroup[label='+label+']'); 8219 }, 8220 8221 addItem: function(itemValues) { 8222 var newOption = new Option(itemValues.sDisplayVal || '', itemValues.sSaveVal || ''), 8223 val = this.options.value; 8224 this.$userControl[0].add(newOption, null); 8225 // if item has same value as present in options then mark it as selected 8226 if (_.contains(val, itemValues.sSaveVal)) { 8227 this.$userControl.find("option[value=" + itemValues.sSaveVal + "]").prop("selected", true); 8228 var emptyValue = this.$userControl.children('[data-empty-option]'); 8229 if (emptyValue.length > 0 && emptyValue.val() === itemValues.sSaveVal) { 8230 this.$userControl[0].removeChild(emptyValue[0]); 8231 } 8232 } else if ((val == null || val.length == 0 || val[0] == null) && this.options.placeholder.length == 0) { 8233 // Value should remain empty if option is not already selected & placeholder is empty 8234 this.$userControl[0].value = ""; 8235 } 8236 }, 8237 8238 clearItems: function () { 8239 //Deleting all the options including optGroup except the empty value. 8240 this.$userControl.children().not('[data-empty-option]').remove(); 8241 }, 8242 8243 deleteItem: function (nIndex) { 8244 //check for emptyValue instead of blindly doing + 1 8245 if (this.$userControl[0].item(0) && this.$userControl[0].item(0).id == "emptyValue") 8246 nIndex = nIndex + 1; 8247 //if there is emptyValue element then just delete one index higher 8248 //this check is must instead of blindly increasing the index by 1 because NWKListBox extends this class and that doesn't maintain emptyValue 8249 this.$userControl[0].remove(nIndex); 8250 }, 8251 8252 getCommitValue: function (event) { 8253 var value = $("option:selected", this.$userControl).map(function () { 8254 return $(this).val(); 8255 }).get(); 8256 return value; 8257 }, 8258 8259 showDisplayValue: function () { 8260 }, 8261 8262 destroy: function () { 8263 this.element. 8264 removeClass(this._widgetName). 8265 children().remove(). 8266 text(""); 8267 8268 // call the base destroy function 8269 $.xfaWidget.defaultWidget.prototype.destroy.apply(this, arguments); 8270 }, 8271 8272 _handleKeyDown: function (event) { 8273 8274 if (event.keyCode == 13) { 8275 //do nothing 8276 //just override the return key behaviour and over to defaultWidget for rest of the stuff. 8277 //return key is intercepted to avoid submission of form which is default behavior of html form element 8278 //but as a side effect it also stops the closing of drop down only in IE -> probably I should use IE condition but 8279 // this code works fine in chrome as well so keeping it that way. 8280 //watson bug#3675141 8281 } 8282 else 8283 $.xfaWidget.defaultWidget.prototype._handleKeyDown.apply(this, arguments); 8284 }, 8285 8286 // CQ-51462 : focus and commit event (change) happen together hence first selection was modifying the value 8287 // we do not want focus to modify the value that is about to be committed 8288 showValue : function() { 8289 8290 } 8291 }); 8292})($, _); 8293(function($, _){ 8294 $.widget( "xfaWidget.listBox", $.xfaWidget.defaultWidget, { 8295 8296 _widgetName: "listBoxWidget", 8297 8298 options : { 8299 value : [], 8300 items : [], 8301 multiSelect : false 8302 }, 8303 8304 getOptionsMap: function() { 8305 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this,arguments); 8306 return $.extend({},parentOptionsMap,{ 8307 "width" : function(val) { 8308 //Bug#3597771. setting the height more than 0.95 brings scrollbar 8309 this.options.width = val*0.95 8310 parentOptionsMap.width.apply(this,[this.options.width]) 8311 }, 8312 "access" : function() {}, 8313 "value": function(val) { 8314 var newValues = this.options.value, 8315 self = this, 8316 tabSet = false;
8317 if(!_.isArray(newValues)) 8318 newValues = [newValues]; 8319 var tabSet 8320 this.$userControl.children().each(function(){ 8321 var saveVal = $(this).attr("data-save"); 8322 8323 // Check if this value is present in options value array 8324 if(newValues && _.contains(newValues, saveVal)){ 8325 self._selectListItem($(this)); 8326 tabSet = true; 8327 8328 // Set the selected data attribute to true. 8329 if (!$.data(this, "_xfaInitialized")) { 8330 //Initialized data- attributes parse for once using this call. 8331 // Next onward don't use this. Instead use $.data which is cheap/ 8332 $(this).data(); 8333 $.data(this, "_xfaInitialized", true); //Mark the element to say that data has been initialized. 8334 } 8335 $.data(this, "selected", true); 8336 8337 } 8338 else{ 8339 $(this).removeClass("item-selected"); 8340 $(this).addClass("item-selectable"); 8341 $(this).attr("tabIndex", "-1"); 8342 } 8343 }); 8344 if(!tabSet) { 8345 $(this.$userControl.children().get(0)).attr("tabIndex", this.options.tabIndex); 8346 } 8347 }, 8348 8349 "items" : function(val) { 8350 if(!_.isArray(val)) 8351 val = [val]; 8352 var viewItems = this.$userControl.children(); 8353 8354 //if number of items are not same in model and view then balance it 8355 if((viewItems.length) > val.length){ 8356 for(var i=viewItems.length; i > val.length; i--){ 8357 this.deleteItem(i-1); 8358 } 8359 } 8360 else if((viewItems.length) < val.length){ 8361 for(var i=viewItems.length; i < (val.length); i++){ 8362 this.addItem({sDisplayVal: val[i].display, sSaveVal: val[i].save}); 8363 } 8364 } 8365 8366 _.each(val, function(element, index){ 8367 var $viewItem = $(viewItems[index]); 8368 if( $viewItem.text() != element.display){ 8369 $viewItem.text(element.display || ''); 8370 } 8371 8372 if( $viewItem.attr("data-save") != element.save){ 8373 $viewItem.attr("data-save", element.save || ''); 8374 } 8375 }); 8376 8377 //Intentionally left the selection check -> I am relying on the fact that "value" sync event is called after "items" sync. 8378 }, 8379 8380 "displayValue" : function(){;}, 8381 8382 "tabIndex": function() { 8383 var selectedItem = this.$userControl.children(".item-selected"), 8384 children =this.$userControl.children() 8385 if(selectedItem.length) { 8386 selectedItem.eq(0).attr("tabIndex", this.options.tabIndex); 8387 } 8388 else if(children.length > 0) { 8389 children.eq(0).attr("tabIndex", this.options.tabIndex); 8390 } 8391 } 8392 }) 8393 }, 8394 8395 getEventMap: function() { 8396 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getEventMap.apply(this,arguments); 8397 return $.extend({},parentOptionsMap,{ 8398 "listboxenter":xfalib.ut.XfaUtil.prototype.XFA_ENTER_EVENT, 8399 "listboxexit":xfalib.ut.XfaUtil.prototype.XFA_EXIT_EVENT, 8400 "listboxchange":xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT, 8401 "focus":null, 8402 "blur":null 8403 }) 8404 }, 8405 8406 showDisplayValue : function() { 8407 }, 8408 8409 render : function() { 8410 this.element.addClass( this._widgetName); 8411 this.element.children().remove(); 8412 8413 //TODO: add a function for geting textStyle 8414 var textStyle = this.getOrElse(this.$data(this.element.get(0), "xfamodel"), "textstyle", ""), 8415 that = this, 8416 //Bug#3597771 width and height are provided by the view itself. 8417 listElTemplate = 8418 '<ol style="position:absolute;<%=textStyle%>" role="listbox">' + 8419 '<% _.each(items, function(item){ %>' + 8420 '<% var saveItem = item.save ? item.save.replace(/\"/g,"""):null %>'+ 8421 '<li role="option" data-save="<% print(saveItem) %>" data-selected="false"><% print(item.display) %></li>'+ 8422 '<%})%>'+ 8423 '</ol>', 8424 compiledListElTemplate = _.template(listElTemplate), 8425 templateOptions = _.extend({ 8426 "textStyle" : textStyle 8427 }, this.options), 8428 resolvedListEl = compiledListElTemplate(templateOptions); 8429 that.element.html(xfalib.ut.XfaUtil.prototype.encodeScriptableTags(resolvedListEl)); 8430 var control = $(that.element.children().get(0)).attr("name",this.options.name); 8431 this._attachEventHandlers(control); 8432 return control 8433 }, 8434 8435 focus: function() { 8436 if(this.$userControl.children(".item-selected").length > 0) { 8437 this.$userControl.children(".item-selected")[0].focus(); 8438 } 8439 else if(this.$userControl.children().length > 0) { 8440 this.$userControl.children()[0].focus(); 8441 } 8442 }, 8443 8444 addItem : function(itemValues){ 8445 $("<li></li>") 8446 .attr("data-save", itemValues.sSaveVal || '') 8447 .text(itemValues.sDisplayVal || '') 8448 .appendTo(this.$userControl)
8449 .click($.proxy(this._handleItemClick, this)) 8450 .focus($.proxy(this._handleItemFocus, this)); 8451 8452 // add new item as selected if the value is already present in options 8453 if (_.contains(this.options.value, itemValues.sSaveVal)) { 8454 this._selectListItem(this.$userControl.find("[data-save=" + itemValues.sSaveVal+ "]")); 8455 } 8456 }, 8457 8458 clearItems : function(){ 8459 $(this.$userControl).empty(); 8460 }, 8461 8462 deleteItem : function(nIndex){ 8463 $(this.$userControl).children('li').each(function(index,element){ 8464 if(index==nIndex){ 8465 $(element).off("click").off("focus").remove(); 8466 } 8467 }) 8468 }, 8469 8470 8471 _attachEventHandlers : function($control){ 8472 var self = this; 8473 $control.keydown($.proxy(this._hotKeys,this)) 8474 .children().on("mousedown",function() { 8475 if(self.inFocus == true) { 8476 self.mouseDown = true; 8477 } 8478 }) 8479 .click($.proxy(this._handleItemClick, this)) 8480 .focus($.proxy(this._handleItemFocus, this)) 8481 .blur($.proxy(this._handleFocusOut,this)) 8482 8483 }, 8484 8485 _hotKeys : function(event){ 8486 if(this.options.access != "open") 8487 return; 8488 if(this.itemInFocus){ 8489 switch(event.which) { 8490 case 38: //arrow up 8491 var prevSibling = $(this.itemInFocus).prev(); 8492 if(prevSibling){ 8493 this.keyDown = true; 8494 prevSibling.focus(); 8495 this.keyDown = false; 8496 } 8497 event.preventDefault(); 8498 break; 8499 case 40: //arrow down 8500 var nextSibling = $(this.itemInFocus).next(); 8501 if(nextSibling){ 8502 this.keyDown = true; 8503 nextSibling.focus(); 8504 this.keyDown = false; 8505 } 8506 event.preventDefault(); 8507 break; 8508 case 91: //left arrow 8509 case 92: //right arrow 8510 event.preventDefault(); 8511 break; 8512 case 32: 8513 this._toggleItem(this.itemInFocus); 8514 event.preventDefault(); 8515 break; 8516 default: 8517 } 8518 } 8519 }, 8520 8521 _toggleItem: function(item) { 8522 var $item = $(item), 8523 multiMode = this.options.multiSelect, // && event.ctrlKey ; 8524 that = this; 8525 //toggle selected state of this item 8526 this.$data(item, "selected", !this.$data(item, "selected")); 8527 var state = this.$data(item, "selected") 8528 8529 if(!multiMode) { 8530 var $selectedItem = this.$userControl.children(".item-selected") 8531 if($selectedItem.length) {
8532 this.$data($selectedItem[0],"selected",false) 8533 $selectedItem.removeClass("item-selected").addClass("item-selectable") 8534 } 8535 } 8536 $item.toggleClass("item-selectable",!state). 8537 toggleClass("item-selected",state) 8538 8539 this.$userControl.trigger("listboxchange"); 8540 }, 8541 8542 getCommitValue: function() { 8543 var that = this, 8544 multiMode = this.options.multiSelect; 8545 8546 8547 return this.$userControl.children().map(function(){ 8548 // intentionally using $this.attr("data-save") instead of $this.data("data") 8549 return that.$data(this, "selected") ? $(this).attr("data-save") : null; 8550 }).get(); 8551 }, 8552 8553 _handleItemFocus : function(event){ 8554 if(this.options.access != "open") 8555 return; 8556 var item = event.target; 8557 this.itemInFocus = item; 8558 8559 // overriding default widgets handleFocus 8560 if(!(this.keyDown || this.mouseDown)) { //we do not need to fire focus event if 8561 this.$userControl.trigger("listboxenter") // clicked on another li element or pressed a key to move the selectio 8562 } 8563 this.mouseDown = false; 8564 this.inFocus = true; 8565 }, 8566 8567 _handleItemClick : function(event){ 8568 // Bug#3501811 If clicked onlistbox entry more than once, exit event is not fired 8569 // Clicking on the same entry does not call focus and hence we were not resetting the state. Doing it in onClick 8570 if(this.mouseDown == true) 8571 this.mouseDown = false; 8572 if(this.options.access != "open") 8573 return; 8574 this._toggleItem(event.target) 8575 }, 8576 8577 _handleFocusOut: function(){ 8578 if(!(this.keyDown || this.mouseDown)) { 8579 this.$userControl.trigger("listboxexit"); 8580 this.inFocus = false 8581 } 8582 }, 8583 8584 _selectListItem : function ($elem) { 8585 if ($elem && $elem.length) { 8586 $elem.removeClass("item-selectable") 8587 .addClass("item-selected") 8588 .attr("tabIndex", this.options.tabIndex); 8589 } 8590 }, 8591 8592 destroy: function() { 8593 this.element. 8594 removeClass(this._widgetName). 8595 children().remove(). 8596 text(""); 8597 8598 $.xfaWidget.defaultWidget.prototype.destroy.apply(this, arguments); 8599 } 8600}); 8601})($, window._); 8602(function($) { 8603 $.widget( "xfaWidget.nwkListBox", $.xfaWidget.dropDownList, { //non-webkit listbox 8604 8605 _widgetName : "nwkListBox", 8606 8607 options : { 8608 value : [], 8609 multiSelect : false 8610 }, 8611 8612 render : function() { 8613 var $control = $.xfaWidget.dropDownList.prototype.render.apply(this, arguments); 8614 if($control){ 8615 $control.children("#emptyValue").remove(); 8616 if(this.options.multiSelect) 8617 $control.attr("multiple", "multiple"); 8618 } 8619 this._updateSelectSize($control); 8620 return $control; 8621 }, 8622 8623 addItem : function(itemValues){ 8624 $.xfaWidget.dropDownList.prototype.addItem.apply(this, arguments); 8625 this._updateSelectSize(); 8626 }, 8627 8628 clearItems : function(){ 8629 $.xfaWidget.dropDownList.prototype.clearItems.apply(this, arguments); 8630 this._updateSelectSize(); 8631 }, 8632 8633 deleteItem : function(nIndex){ 8634 $.xfaWidget.dropDownList.prototype.deleteItem.apply(this, arguments); 8635 this._updateSelectSize(); 8636 }, 8637 8638 _updateSelectSize : function($control){ 8639 $control = $control || this.$userControl; 8640 $control.attr("size", (this.options.items || []).length); 8641 }, 8642 8643 // Bug#3597771 8644 // focus and commit event happen together hence first selection was modifying the value 8645 // we do not want focus to modify the value that is about to be committed 8646 showValue : function() { 8647 8648 } 8649 8650 }); 8651})($); 8652(function ($) { 8653 $.widget("xfaWidget.xfaButton", $.xfaWidget.defaultWidget, { //commitEvent: change; commitProperty: value<Array> 8654 8655 _widgetName: "xfaButton", 8656 8657 options: { 8658 value: null, 8659 svgCaption: false //option to indicate if button already has an SVG caption 8660 }, 8661 8662 getOptionsMap: function () { 8663 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this, arguments); 8664 return $.extend({}, parentOptionsMap, { 8665 "access": function (val) { 8666 switch (val) { 8667 case "open" : 8668 this.$userControl.removeAttr("disabled"); 8669 this.$userControl.removeAttr("aria-disabled"); 8670 break; 8671 case "nonInteractive" : 8672 case "protected" : 8673 case "readOnly" : 8674 this.$userControl.attr("disabled", "disabled"); 8675 this.$userControl.attr("aria-disabled", "true"); 8676 break; 8677 default : 8678 this.$userControl.removeAttr("disabled"); 8679 this.$userControl.removeAttr("aria-disabled"); 8680 break; 8681 } 8682 }, 8683 "value": function () { 8684 }, 8685 "displayValue": function () { 8686 }, 8687 "svgCaption": function (val) { 8688 if (val) { 8689 this.$userControl.removeAttr("value"); 8690 } 8691 } 8692 }) 8693 }, 8694 8695 _attachEventHandlers: function ($control) { 8696 $control.click(function () { 8697 this.focus() 8698 }); 8699 }, 8700 8701 getCommitValue: function () { 8702 return this.options.value; 8703 }, 8704 8705 showValue: function () { 8706 }, 8707 8708 showDisplayValue: function () { 8709 } 8710 }); 8711})($);(function ($) { 8712 $.widget("xfaWidget.XfaCheckBox", $.xfaWidget.defaultWidget, { //commitEvent: change; commitProperty: value<Array> 8713 8714 _widgetName: "XfaCheckBox", 8715 8716 options: { 8717 value: null, 8718 state: -1, 8719 states: 2, 8720 values: [], 8721 mandatory: false 8722 }, 8723 8724 checkedState: false, 8725 clickPending: false, 8726 8727 getOptionsMap: function () { 8728 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this, arguments); 8729 return $.extend({}, parentOptionsMap, { 8730 "access": function (val) { 8731 switch (val) { 8732 case "open" : 8733 this.$userControl.removeAttr("disabled"); 8734 this.$userControl.removeAttr("aria-disabled"); 8735 break; 8736 case "nonInteractive" : 8737 case "protected" : 8738 case "readOnly" : 8739 this.$userControl.attr("disabled", "disabled"); 8740 this.$userControl.attr("aria-disabled", "true"); 8741 break; 8742 default : 8743 this.$userControl.removeAttr("disabled"); 8744 this.$userControl.removeAttr("aria-disabled"); 8745 break; 8746 } 8747 }, 8748 8749 "displayValue": function (val) { 8750 this.$userControl.attr(this.options.commitProperty, this.options.value); 8751 this._state(this.dIndexOf(this.options.values, this.options.value)); 8752 this.$userControl.attr("checked", this.checkedState ? "checked" : null); 8753 this.$userControl.prop("checked", this.checkedState ? "checked" : null); 8754 //for accessibility 8755 this.$userControl.attr("aria-checked", this.checkedState); 8756 if (this.options.state == 2) 8757 this.$userControl.addClass("neutral"); 8758 else if (this.options.states == 3) 8759 this.$userControl.removeClass("neutral"); // since current state != neutral 8760 }, 8761 8762 "allowNeutral": function (val) { 8763 var intVal = parseInt(val); 8764 if (intVal == 0 || intVal == 1) { 8765 this.options.states = 2 + intVal; 8766 } 8767 }, 8768 8769 "paraStyles": function (paraStyles) { 8770 parentOptionsMap.paraStyles.apply(this, arguments); 8771 this._handleVAlignOnExit(); 8772 } 8773 }) 8774 }, 8775 8776 getEventMap: function () { 8777 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getEventMap.apply(this, arguments); 8778 return $.extend({}, parentOptionsMap, { 8779 "xfacheckboxchange" : xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT, 8780 "xfacheckboxclick" : xfalib.ut.XfaUtil.prototype.XFA_CLICK_EVENT, 8781 "change": null, 8782 "click" : null 8783 }) 8784 }, 8785 8786 _attachEventHandlers: function ($control) { 8787 var that = this; 8788 var focusFunc = function (evnt) { 8789 if (!that.inFocus) { 8790 that.focus(); 8791 that.inFocus = true; 8792 } 8793 } 8794 var focusOutFunc = function (evnt) { 8795 that.inFocus = false;
8796 } 8797 $control.click(focusFunc).change(focusFunc).blur(focusOutFunc); 8798 $control.change($.proxy(this._handleChange,this)).click($.proxy(this._handleClick,this)); //LC-5106 8799 }, 8800 8801 getCommitValue: function () { 8802 this._state((this.options.state + 1) % this.options.states); 8803 this.$userControl.attr("checked", this.checkedState ? "checked" : null); 8804 //for accessibility 8805 this.$userControl.attr("aria-checked", this.checkedState) 8806 if (this.options.state == 2) { 8807 this.$userControl.addClass("neutral"); 8808 } 8809 else if (this.options.states == 3) 8810 this.$userControl.removeClass("neutral"); // since current state != neutral 8811 8812 return this.options.values[this.options.state]; 8813 }, 8814 8815 _handleVAlignOnExit: function (evnt) { 8816 //--this is being kept empty as no other browser (i.e Mozilla and Chrome) take the padding-bottom or padding-top into account. 8817 // the only browser to take it into consideration is IE. And moreover the alignment and padding considerations have already been taken into account in 8818 // calculations in CheckButtonFieldView.js. And on removing the entire function it takes up the _handleVAlignOnExit() of AbstractWidget. 8819 8820 }, 8821 8822 _handleChange: function (evnt) { 8823 this.$userControl.trigger("xfacheckboxchange"); //change is always fired 8824 if(this.clickPending === true) { 8825 this.clickPending = false; 8826 this.$userControl.trigger("xfacheckboxclick"); 8827 } else { 8828 // handling of this.clickPending is added to handle the case when clicked on checkbox/radiobutton label/caption 8829 this.clickPending = true; 8830 } 8831 }, 8832 8833 _handleClick: function (evnt) { 8834 var isChrome = xfalib.ut.XfaUtil.prototype.detectChrome(), 8835 isIE = xfalib.ut.XfaUtil.prototype.detectIE(), 8836 isSafari = xfalib.ut.XfaUtil.prototype.isSafari(), 8837 userControlType = this.$userControl.attr("type"); 8838 // click will not be fired if the previous state of the radiobutton is 'on'. 8839 // NPR-35652 : Checkbox movement - Click event works fine on chrome but not in iOS safari for collapsible fields 8840 // CQ-103023 : Click Event on Radio Button not working correctly in Chrome 53 8841 // CQ-103715 : CQ-103715 : Click Event on Check Box not working correctly in Chrome and Firefox, added handling for checkbox also 8842 // handling of this.clickPending is added to handle the case when clicked on checkbox/radiobutton label/caption 8843 if(($.browser.mozilla || isChrome || isSafari) && !isIE && this.clickPending === false && ((userControlType === "radio" && this.checkedState === false) || (userControlType === "checkbox"))) { 8844 this.clickPending = true; 8845 } 8846 else { 8847 this.$userControl.trigger("xfacheckboxclick"); 8848 this.clickPending = false; 8849 } 8850 }, 8851 8852 _state: function (newState) { 8853 if (newState == undefined) 8854 return this.options.state; 8855 else 8856 this.options.state = newState; 8857 this.checkedState = (newState == 0 || newState == 2); 8858 }, 8859 8860 click: function () { 8861 // trigger change for check box and for radio only if it is not selected 8862 // otherwise radio button will go in deselected state 8863 if (this.$userControl.attr("type") !== "radio" || this.options.state !== 0) { 8864 this.$userControl.trigger("change"); 8865 } 8866 //we should call only the handler since calling click will trigger change. 8867 this.$userControl.triggerHandler("click"); 8868 } 8869 }); 8870})($); 8871(function($, _){ 8872 $.widget( "xfaWidget.textField", $.xfaWidget.defaultWidget, { 8873 8874 _widgetName: "textField", 8875 8876 options: { 8877 curValue : null , 8878 pos:0, 8879 lengthLimitVisible: true, 8880 maxChars:0 , 8881 flag:"", 8882 // by default html5Type is set to true 8883 // we leverage pattern, maxLength support from HTML5 browser for mobile forms 8884 html5Type : "text", 8885 length : null, 8886 minLength : 0, 8887 totalLengthMessage : "", 8888 minimumLengthMessage : "", 8889 }, 8890 8891 getOptionsMap: function() { 8892 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this,arguments); 8893 return $.extend({},parentOptionsMap,{ 8894 "maxChars": function(maxchars) { 8895 if(this._maxCharsReached(this.options.value)) { 8896 var value = this.options.value.slice(0,maxchars) 8897 this._setOption("value", value); 8898 this._setOption("displayValue", value); 8899 } 8900 8901 }, 8902 8903 "multiLine ": function(val) { 8904 if(this.options.multiLine) 8905 this.$userControl.attr("aria-multiline", "true"); 8906 else 8907 this.$userControl.removeAttr("aria-multiline", "false"); 8908 }, 8909 8910 "height": function(val) { 8911 if(val) {
8912 this.$css(this.$userControl[0],{"height" :val}) 8913 this._handleVAlignOnExit(); // To Handle the case of expandable Fields 8914 } 8915 }, 8916 "width": function(val){ 8917 parentOptionsMap.width.apply(this,arguments); 8918 // handle valign on width change as well 8919 // as content height(scrollHeight) varies according to width 8920 this._handleVAlignOnExit(); 8921 }, 8922 "paraStyles": function(paraStyles){ 8923 parentOptionsMap.paraStyles.apply(this,arguments); 8924 this._handleVAlignOnExit(); 8925 } 8926 8927 }) 8928 }, 8929 8930 render : function() { 8931 var control = $.xfaWidget.defaultWidget.prototype.render.apply(this, arguments); 8932 // use the control to set HTML5 attributes 8933 if (control && control.length > 0 && this.options.html5Type) { 8934 var minLength = this.options.minLength, 8935 maxLength = this.options.maxChars, 8936 length = this.options.length; 8937 isMinLengthSet = minLength != null && minLength > 0, 8938 isMaxLengthSet = maxLength != null && maxLength > 0, 8939 isLengthSet = length != null && length > 0, 8940 isMultiline = this.options.multiLine, 8941 minLengthMsg = this.options.minimumLengthMessage, 8942 totLengthMsg = this.options.totalLengthMessage, 8943 pattern = ""; // html5 pattern is not supported for textarea 8944 8945 // order of execution matters for the below code snippet 8946 if (isMinLengthSet) { 8947 // add minLength though it is not fully supported in all browsers 8948 // hence also adding pattern attribute 8949 control.attr("minlength", parseInt(minLength)); 8950 if(minLengthMsg && minLengthMsg.length > 0) { 8951 control.attr("title", this.options.minimumLengthMessage); // html5 supported message on pattern validation failure 8952 } 8953 } 8954 8955 if (isMaxLengthSet) { 8956 control.attr("maxlength", parseInt(maxLength)); 8957 } 8958 8959 // if both min and max length is set 8960 if(isMinLengthSet && isMaxLengthSet){ 8961 pattern += ".{" + minLength + "," + maxLength + "}"; 8962 } else if(isMinLengthSet) { 8963 // if only min length set 8964 pattern += ".{" + minLength + ",}"; 8965 } 8966 8967 // if length is set then set min and max length in pattern equal to length 8968 if (isLengthSet) { 8969 if(isMultiline){ // set both min and maxlength as pattern is not supported 8970 control.attr("minlength", parseInt(length)); 8971 control.attr("maxlength", parseInt(length)); 8972 } 8973 if(totLengthMsg && totLengthMsg.length > 0) { 8974 control.attr("title", this.options.totalLengthMessage); 8975 } 8976 // reset the pattern string 8977 pattern = ".{" + length + "," + length + "}"; 8978 } 8979 // if required is set, set the required attribute, it is necessary else an empty value will be excluded from constraint validation 8980 if (this.options.required) { 8981 control.attr("required", true); 8982 } 8983 // set the pattern if not empty and check if this is not multiline, since pattern is not supported for textarea 8984 if (pattern && pattern.length > 0 && !isMultiline) { 8985 control.attr("pattern", pattern); 8986 } 8987 } 8988 return control; 8989 }, 8990 8991 /* This function aligns vAlign when: 8992 1. parastyles is present and the widget contains a value. 8993 2. During initial rendering if no content present fallback to the previous logic. 8994 3. Presence of content in widget. 8995 */ 8996 _handleVAlignOnExit: function(){ 8997 var value = this.options.displayValue, 8998 noContentPresent = _.isEmpty(this.$userControl.val() || this.options.displayValue), 8999 contentHeight,widgetHeight,diff,tempCSS; 9000 9001 //the widget doesn't have value as yet but content exists [ Rendering of widget] 9002 if (!this.options.paraStyles || noContentPresent) { 9003 //vAlign has to be handled only if there is paraStyles and widget has content 9004 return; 9005 } 9006 9007 // mozilla results in vAlign regression hence made this change only for textarea 9008 if($(this.element[0]).find("textarea").length >0 && !noContentPresent) { 9009 /* measureExtent not returning correct height of content in textarea even with all 9010 css values */ 9011 tempCSS={'height':this.$userControl.css('height'),'padding':this.$userControl.css('padding')};
9012 this.$css(this.$userControl[0],{'height':'1px','padding':'0px'}); 9013 9014 contentHeight = this._getContentHeight(); 9015 this.$css(this.$userControl[0],tempCSS); 9016 widgetHeight = this.options.height; 9017 diff = widgetHeight - contentHeight; 9018 this._calculatePaddingForVAlign(diff); 9019 } else { 9020 // widget has no initial content or is a textfield.Proceed as before. 9021 $.xfaWidget.defaultWidget.prototype._handleVAlignOnExit.apply(this,arguments); 9022 } 9023 }, 9024 9025 getEventMap: function() { 9026 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getEventMap.apply(this,arguments); 9027 return $.extend({},parentOptionsMap,{ 9028 "onKeyInput.textField" : xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT 9029 }) 9030 }, 9031 9032 _maxCharsReached: function(val) { 9033 var isMaxLengthSupported = false, 9034 elementName = this.options.multiLine ? "textarea" : "input"; 9035 // in browsers, where max length is supported, we don't custom javascript checks, we let HTML do the validation of max length 9036 if(this.options.html5Type && xfalib.view.util.HtmlUtil.elementSupportsAttribute(elementName, "maxLength")){ 9037 isMaxLengthSupported = true; 9038 } 9039 return !isMaxLengthSupported && this.options.maxChars 9040 && this.options.maxChars!=="0" 9041 && val 9042 && val.length >= this.options.maxChars 9043 }, 9044 9045 _handleKeyInput : function(event, character, code) { 9046 if(event.ctrlKey && !_.contains(['paste', 'cut'], event.type)) { 9047 return true; 9048 } 9049 9050 if(!this.options.multiLine) { 9051 $.xfaWidget.defaultWidget.prototype._handleKeyDown.apply(this, arguments); 9052 character = (code == 13) ? '' : character ; 9053 } 9054 9055 var val = this.$userControl.val(), 9056 selectionStart = xfalib.view.util.HtmlUtil.getHTMLSupportedAttr(this.$userControl[0], "selectionStart") || 0, 9057 selectionEnd = xfalib.view.util.HtmlUtil.getHTMLSupportedAttr(this.$userControl[0], "selectionEnd") || 0, 9058 pos = selectionStart, 9059 // CQ-4260239 : " " taking space of 5 chars for restricting the length to visible area 9060 newVal = (val.substr(0, selectionStart) + character + val.substr(selectionEnd)); 9061 this.options.curValue = val; 9062 if(!this.options.multiLine) { //TODO:looks like a bug 9063 this.options.lengthLimitVisible = true; 9064 this.options.pos = pos; 9065 if(this.options.hScrollDisabled && !_.contains(['keydown', 'cut'], event.type)) { 9066 var expectedWidth = xfalib.view.util.TextMetrics.measureExtent(newVal, {refEl: this.$userControl[0], maxWidth:-1}).width; 9067 if(!event.ctrlKey && expectedWidth > this.$userControl.width()){ // Why allowance of 5 required?? 9068 this.options.lengthLimitVisible = false; 9069 event.preventDefault(); 9070 return false; 9071 } 9072 } 9073 } else if (this.options.multiLine && this.options.hScrollDisabled) { // LC-4656 : wait till user input, if it causes an overflow revert to old text 9074 var $textArea = this.$userControl; 9075 $textArea.css("padding", "0px 0px 0px"); // TODO : take care of multiline selection & padding later 9076 9077 // TODO : find a scheme to avoid attaching and detaching listeners, currently $.val() causes 'input' to fire, resulting in an infinite loop 9078 $textArea.one("input", function () { 9079 if ($textArea.prop('scrollHeight') > $textArea.prop('offsetHeight')) { 9080 $textArea.val(val) 9081 .prop("selectionStart", selectionEnd) 9082 .prop("selectionEnd", selectionEnd); // LC-4656 : reset the cursor pos, afterwards 9083 character = null; 9084 code = 0; 9085 } 9086 }); 9087 } 9088 9089 if (!_.contains(['keydown', 'cut'], event.type) && this._maxCharsReached(val) && selectionStart === selectionEnd) { 9090 event.preventDefault(); 9091 return false;
9092 } 9093 9094 this.$userControl.trigger({ 9095 type : "onKeyInput.textField", 9096 originalType : event.type, 9097 character : character, // contains the pasted string or pressed key 9098 keyCode : event.keyCode || 0, 9099 charCode : event.charCode || 0, 9100 which : event.which || 0, 9101 ctrlKey : event.ctrlKey || event.metaKey || false, 9102 shiftKey : event.shiftKey || false, 9103 keyDown: false, // This property is available only for list boxes and drop-down lists 9104 selectionStart: selectionStart, 9105 selectionEnd: selectionEnd 9106 }); 9107 }, 9108 9109 _handleKeyDown : function(event){ 9110 if (event) { 9111 var code = event.charCode || event.which || event.keyCode || 0; 9112 if(code == 8 || code == 46) // backspace and del 9113 this._handleKeyInput(event, "", code); 9114 } 9115 }, 9116 9117 _handleKeyPress : function(event){ 9118 if (event) { 9119 var code = event.charCode || event.which || event.keyCode || 0, 9120 character = (code == 13) ? "\n" : String.fromCharCode(code); // modified '\r\n' -> '\n' 9121 9122 if(xfalib.ut.XfaUtil.prototype.isNonPrintableKey(event.key)) { // mozilla also generates a keypress, along with keydown 9123 return true; // for all keys, so only handling printable keys in keypress 9124 } 9125 9126 this._handleKeyInput(event, character, code); 9127 } 9128 }, 9129 9130 _compositionUpdateCallback : function (event) { 9131 var that = this; 9132 var val = that.$userControl.val(); 9133 if (event.type === "compositionupdate" && event.originalEvent.data) { 9134 // this has been deliberately done to get the actual data in case of max character. 9135 if (that.options.maxChars) { 9136 val = event.originalEvent.data; 9137 } else { 9138 val = val + event.originalEvent.data.substr(event.originalEvent.data.length - 1); 9139 } 9140 } 9141 var flag = that._maxCharsReached(val); 9142 if (flag) { 9143 // if max reached 9144 var newVal = val.substr(0, that.options.maxChars); 9145 //in case the value is not changed then we do not need to update value and close the android keyboard. 9146 if (val === newVal) { 9147 return false; 9148 } 9149 that.$userControl.val(newVal); 9150 } 9151 return flag; 9152 }, 9153 9154 _attachEventHandlers: function($control) { 9155 $.xfaWidget.defaultWidget.prototype._attachEventHandlers.apply(this, arguments); 9156 // IME specific handling, to handle japanese languages max limit 9157 $.xfaWidget.defaultWidget.prototype._attachCompositionEventHandlers.apply(this, arguments); 9158 }, 9159 9160 _handlePaste : function(event){ 9161 if (event) { 9162 var pastedChar = undefined; 9163 if (window.clipboardData && window.clipboardData.getData) { // IE 9164 pastedChar = window.clipboardData.getData('Text'); 9165 } else if (event.originalEvent.clipboardData && event.originalEvent.clipboardData.getData) { 9166 pastedChar = event.originalEvent.clipboardData.getData('text/plain'); 9167 } 9168 if(pastedChar) { 9169 this._handleKeyInput(event, pastedChar, 0); 9170 } 9171 } 9172 }, 9173 9174 _handleCut : function(event) { 9175 if (event) { 9176 this._handleKeyInput(event, "", 0); 9177 } 9178 }, 9179 9180 postProcessExit: function(evnt) { 9181 $.xfaWidget.defaultWidget.prototype.postProcessExit.apply(this,arguments); 9182 if (this.options.multiLine && this.options.hScrollDisabled) { 9183 return; 9184 } 9185 this._handleVAlignOnExit(); 9186 }, 9187 9188 preProcessEnter: function(evnt) { 9189 $.xfaWidget.defaultWidget.prototype.preProcessEnter.apply(this,arguments); 9190 if(this.options.multiLine && this.options.hScrollDisabled) 9191 return; 9192 this._handleVAlignOnEnter(); 9193 }, 9194 9195 /** 9196 * @brief: Select the given field on focus in Internet Explorer 9197 * 9198 */ 9199 _selectOnFocusInIE : function(){ 9200 // if the value is not same only then do selection in IE 9201 // For Issue: LC-9895, we check if value not same 9202 if($.browser.msie && !this._isValueSame()) { 9203 this.$userControl.select(); 9204 } 9205 else { 9206 //all other browsers behave like a good boy 9207 } 9208 }, 9209 9210 showValue : function() { 9211 $.xfaWidget.defaultWidget.prototype.showValue.apply(this,arguments); 9212 //IE doesn't show selected text if we focus and set its value all the time so force selection 9213 this._selectOnFocusInIE(); 9214 }, 9215 9216 getCommitValue: function() { 9217 var value = $.xfaWidget.defaultWidget.prototype.getCommitValue.apply(this, arguments); 9218 9219 if(this._maxCharsReached(value)) { 9220 value = value.slice(0,this.options.maxChars); 9221 } 9222 9223 this.$userControl.val(this.options.value); 9224 9225 //TODO: ask Sharad whether it is right 9226 if(this.options.multiLine && this.options.hScrollDisabled) { 9227 //var str= this._checkLines(value); 9228 //if(value != str) { 9229 return value; 9230 //} 9231 } 9232 return value; 9233 }, 9234 9235 /* 9236 ** returns the contentHeight which needs to be considered for padding for valign, 9237 ** if no contentHeight is present then fontSize is returned. 9238 */ 9239 _getContentHeight: function () {
9240 var contentHeight = Math.ceil(this.$userControl.get(0).scrollHeight); 9241 return contentHeight ? contentHeight : this.options.fontSize; 9242 } 9243 }); 9244})($, window._); 9245/************************************************************************* 9246 * 9247 * ADOBE CONFIDENTIAL 9248 * __________________ 9249 * 9250 * Copyright 2019 Adobe Systems Incorporated 9251 * All Rights Reserved. 9252 * 9253 * NOTICE: All information contained herein is, and remains 9254 * the property of Adobe Systems Incorporated and its suppliers, 9255 * if any. The intellectual and technical concepts contained 9256 * herein are proprietary to Adobe Systems Incorporated and its 9257 * suppliers and may be covered by U.S. and Foreign Patents, 9258 * patents in process, and are protected by trade secret or copyright law. 9259 * Dissemination of this information or reproduction of this material 9260 * is strictly forbidden unless prior written permission is obtained 9261 * from Adobe Systems Incorporated. 9262 **************************************************************************/ 9263 9264(function ($) { 9265 $.widget("xfaWidget.richTextField", $.xfaWidget.textField, { 9266 9267 _widgetName : "richTextField", 9268 9269 _richTextWidget : null, 9270 9271 _changeAccess : function (val) { 9272 switch (val) { 9273 case "open": 9274 if (this._richTextWidget) { 9275 this._richTextWidget.editor.enable(); 9276 this._richTextWidget.$toolbar.removeClass("hideToolbar"); 9277 } 9278 break; 9279 case "readOnly": 9280 if (this._richTextWidget) { 9281 this._richTextWidget.editor.disable(); 9282 this._richTextWidget.$toolbar.addClass("hideToolbar"); 9283 } 9284 break; 9285 } 9286 }, 9287 9288 getOptionsMap : function () { 9289 var parentOptionsMap = $.xfaWidget.textField.prototype.getOptionsMap.apply(this, arguments); 9290 return $.extend({}, parentOptionsMap, { 9291 "value" : function (val) { 9292 if (this._richTextWidget) { 9293 this._richTextWidget.setRichTextEditorContent(val); 9294 } 9295 }, 9296 "access" : function (val) { 9297 this._changeAccess(val); 9298 } 9299 }); 9300 }, 9301 9302 getEventMap : function () { 9303 // in case of IE browsers, focus event is delayed, hence adding activate method for content editable 9304 if (xfalib.ut.XfaUtil.prototype.isIE()) { 9305 var parentOptionsMap = $.xfaWidget.textField.prototype.getEventMap.apply(this, arguments); 9306 return $.extend({}, parentOptionsMap, { 9307 "activate.richTextField" : xfalib.ut.XfaUtil.prototype.XFA_ENTER_EVENT 9308 }); 9309 } else { 9310 return $.xfaWidget.textField.prototype.getEventMap.apply(this, arguments); 9311 } 9312 }, 9313 9314 render : function () { 9315 var $richTextWidget = this.element.find("div.richTextWidget").eq(0); 9316 if(!$richTextWidget.length){ 9317 var attachedTextareaClasses = this.element.children().attr('class'); 9318 var richTextWidgetElement = '<div class="richTextWidget ' + attachedTextareaClasses + '" id="richTextField_' + this.options.name + '_' + attachedTextareaClasses + '"></div>'; 9319 this.element.children().remove(); 9320 this.element.append(richTextWidgetElement); 9321 $richTextWidget = this.element.find("div.richTextWidget").eq(0); 9322 }else{ 9323 $richTextWidget.children().remove(); 9324 } 9325 $richTextWidget.append(this.options.value); 9326 return $.xfaWidget.defaultWidget.prototype.render.apply(this, arguments); 9327 }, 9328 9329 getCommitValue : function () { 9330 var value = ""; 9331 if (this._richTextWidget) { 9332 value = this._richTextWidget.getRichTextEditorContent(); 9333 } 9334 return value; 9335 }, 9336 9337 preProcessEnter : function (evnt) { 9338 $.xfaWidget.textField.prototype.preProcessEnter.apply(this, arguments); 9339 var $richTextDiv = this.$userControl.find("div.richTextWidget").eq(0); 9340 if(!$richTextDiv.length){ 9341 $richTextDiv = this.element.find("div.richTextWidget").eq(0); 9342 this.changeDefaultToolbarConfig();
9343 this.$userControl.parents('.richtextsupport').css('z-index', 'auto'); 9344 } 9345 if (window.Form === undefined || window.Form.rte === undefined) { 9346 /* Forms RTE is part of Forms Addon package only. Dont do anything if addon is not installed.*/ 9347 return; 9348 } else if (this._richTextWidget === null) { 9349 this._initializeRTEToolbar(); 9350 this._richTextWidget = new window.Form.rte.RichTextEditor({ 9351 selector : $richTextDiv.attr("id"), 9352 toolbar : window.Form.rte.RichTextEditor.MFToolbar, 9353 data : this.options.value, 9354 locale : $richTextDiv.data("locale") 9355 }); 9356 var that = this; 9357 this._richTextWidget.editor.on("blur:composer", function () { 9358 that.$userControl.trigger("blur"); 9359 }); 9360 // initialize the access 9361 if (this.options.access) { 9362 this._changeAccess(this.options.access); 9363 } 9364 } 9365 }, 9366 9367 changeDefaultToolbarConfig: function(){ 9368 if(window.Form && window.Form.rte){ 9369 var toolbarDefaultConfigData = window.Form.rte.DefaultConfig; 9370 toolbarDefaultConfigData.fontSize.defaultValue = this.options.fontSize; 9371 toolbarDefaultConfigData.fontFamily.defaultValue = this.options.fontFamily; 9372 9373 // Adding 'isFontInPx' flag and overriding two utility functions 9374 // 'getDefaultParaStyle' and 'getMissingParaStyle' are responsible for adding RTE font styling attributes to rich text elements 9375 toolbarDefaultConfigData.isFontInPx = true; 9376 this.changeDefaultParaStyleUtility(); 9377 this.changeMissingParaStyleUtility(); 9378 9379 // Adding dropdown values in default config if not available in options 9380 if(toolbarDefaultConfigData.fontSize.options.indexOf(this.options.fontSize) === -1){ 9381 toolbarDefaultConfigData.fontSize.options.push(this.options.fontSize); 9382 } 9383 if(toolbarDefaultConfigData.fontFamily.options.indexOf(this.options.fontFamily) === -1){ 9384 toolbarDefaultConfigData.fontFamily.options.push(this.options.fontFamily); 9385 } 9386 } 9387 }, 9388 9389 changeDefaultParaStyleUtility: function(){ 9390 Form.rte.util.HtmlUtils.getDefaultParaStyle = function (config) { 9391 var style = ""; 9392 if (config) { 9393 style += 'font-family:' + config.fontFamily.defaultValue + ';'; 9394 if(config.isFontInPx){ 9395 style += 'font-size:' + config.fontSize.defaultValue + 'px;'; 9396 style += 'letter-spacing:' + config.letterSpacing.defaultValue + 'px;'; 9397 }else{ 9398 style += 'font-size:' + config.fontSize.defaultValue + 'pt;'; 9399 style += 'letter-spacing:' + config.letterSpacing.defaultValue + 'pt;'; 9400 } 9401 style += 'color:#000000;'; 9402 style += 'text-align:left;'; 9403 } 9404 9405 return style; 9406 }; 9407 }, 9408 9409 changeMissingParaStyleUtility : function(){ 9410 Form.rte.util.HtmlUtils.getMissingParaStyle = function (style, config) { 9411 if (style && style.length > 0) { 9412 if (config) { 9413 if (!Form.rte.util.StringHelper.endsWith(style, ";")) { 9414 style += ";"; 9415 } 9416 if (style.indexOf("font-family") < 0) { 9417 style += 'font-family:' + config.fontFamily.defaultValue + ';'; 9418 } 9419 if (style.indexOf("font-size") < 0) { 9420 if(config.isFontInPx){ 9421 style += 'font-size:' + config.fontSize.defaultValue + 'px;'; 9422 }else{ 9423 style += 'font-size:' + config.fontSize.defaultValue + 'pt;'; 9424 } 9425 } 9426 if (style.indexOf("letter-spacing") < 0) { 9427 if(config.isFontInPx){ 9428 style += 'letter-spacing:' + config.letterSpacing.defaultValue + 'px;'; 9429 }else{ 9430 style += 'letter-spacing:' + config.letterSpacing.defaultValue + 'pt;'; 9431 } 9432 } 9433 if (style.indexOf("color") < 0) { 9434 style += 'color:#000000;'; 9435 } 9436 if (style.indexOf("text-align") < 0) { 9437 style += 'text-align:left;'; 9438 } 9439 } 9440 } else { 9441 style = Form.rte.util.HtmlUtils.getDefaultParaStyle(config); 9442 } 9443 return style; 9444 }; 9445 }, 9446 9447 _initializeRTEToolbar : function () { 9448 window.Form.rte.RichTextEditor.MFToolbar = window.Form.rte.RichTextEditor.MFToolbar || { 9449 defaultMode : 'basic', 9450 toolbars : { 9451 basic : { 9452 layout : [ 9453 { 9454 items : [Form.rte.Commands.HEADER] 9455 }, 9456 { 9457 items : [Form.rte.Commands.BOLD, Form.rte.Commands.ITALIC, Form.rte.Commands.UNDERLINE] 9458 }, 9459 { 9460 command : 'lists', 9461 icon : 'list', 9462 title : "List Type", 9463 type : 'popover', 9464 placement : 'bottom', 9465 items : [Form.rte.Commands.INSERT_UNORDERED_LIST, 9466 Form.rte.Commands.INSERT_ORDERED_LIST, 9467 Form.rte.Commands.INSERT_LOWERCASE_ALPHABET_LIST] 9468 }, 9469 { 9470 title : 'Expand', 9471 command : Form.rte.Commands.MODE, 9472 value : Form.rte.ToolbarMode.FULL, 9473 icon : 'resize-full' 9474 } 9475 ], 9476 floating : true 9477 }, 9478 full : { 9479 layout : [ 9480 { 9481 items : [Form.rte.Commands.BOLD, Form.rte.Commands.ITALIC, Form.rte.Commands.UNDERLINE] 9482 }, 9483 { 9484 items : [Form.rte.Commands.SUPERSCRIPT, Form.rte.Commands.SUBSCRIPT] 9485 }, 9486 { 9487 items : [ 9488 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 9489 ] 9490 }, 9491 { 9492 items : [Form.rte.Commands.INSERT_UNORDERED_LIST, Form.rte.Commands.INSERT_ORDERED_LIST, Form.rte.Commands.INSERT_LOWERCASE_ALPHABET_LIST 9493 ] 9494 }, 9495 { 9496 title : 'Collapse', 9497 command : Form.rte.Commands.MODE, 9498 value : Form.rte.ToolbarMode.BASIC, 9499 icon : 'resize-small', 9500 selected : true 9501 } 9502 ] 9503 } 9504 } 9505 }; 9506 } 9507 }); 9508 9509})($);(function($){ 9510 $.widget( "xfaWidget.imageField", $.xfaWidget.defaultWidget, { 9511 9512 _widgetName:"imageField", 9513 9514 options: { 9515 tabIndex: 0, 9516 "role": "img" 9517 }, 9518 9519 getEventMap: function () { 9520 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getEventMap.apply(this, arguments); 9521 return $.extend({}, parentOptionsMap, { 9522 "imagechange": xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT 9523 }) 9524 }, 9525 9526 getOptionsMap: function() { 9527 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this,arguments); 9528 return $.extend({},parentOptionsMap,{ 9529 "screenReaderText": function(val) { 9530 if(val) 9531 this.$userControl.attr("alt", val) 9532 }, 9533 "displayValue": function(val) { 9534 var widgetValue; 9535 if (this.options.value) { 9536 widgetValue = "data:;base64," + this.options.value; 9537 } else { 9538 widgetValue = ""; 9539 } 9540 this.$userControl.prop(this.options.commitProperty, widgetValue); 9541 this.$userControl.attr(this.options.commitProperty, widgetValue); 9542 }, 9543 "access" : function() {}, 9544 9545 // CQ-85514 : use max-ht & max-wd to honor image's intrinsic ht & wd attributes & prevent distortion 9546 "height" : function (val) { 9547 // in case aspect is actual then we need to crop the image, which will be not possible if max height and width are set 9548 if (val && this.options.aspect != "actual") { 9549 this.$css(this.$userControl[0], {"max-height": val}); 9550 } 9551 }, 9552 "width" : function (val) { 9553 if (val && this.options.aspect != "actual") { 9554 this.$css(this.$userControl[0], {"max-width": val}); 9555 } 9556 }, 9557 "aspect" : function (val) { 9558 // value of actual turns off scaling, causing the image to be drawn at its native size, 9559 // as per xfa spec Adobe implementations crop the image 9560 if(this.options.aspect == "actual") { 9561 var right = this.$userControl.attr("width"), 9562 bottom = this.$userControl.attr("height"); 9563 right = right.indexOf("px") >= 0 ? right : right + "px"; 9564 bottom = bottom.indexOf("px") >= 0 ? bottom : bottom + "px"; 9565 this._cropImage("0px", right, bottom, "0px"); 9566 this.$userControl.removeAttr("height width"); 9567 // value of none indicates no aspect ratio 9568 // as per xfa spec image is independently scaled in the horizontal and vertical directions to exactly f
9568ill the field, 9569 // which are already set to fill the field 9570 } else if (this.options.aspect != "none") { 9571 // 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 9572 // without overflowing it in either dimension. 9573 this.$userControl.attr({"height" : "auto", "width" : "auto"}); 9574 } 9575 } 9576 }); 9577 }, 9578 9579 // crop the image using top,right, bottom, left coordiantes of the image 9580 _cropImage : function (top, right, bottom, left) { 9581 var clipRect = "rect(" + top + "," + right + "," + bottom + "," + left + ")"; 9582 var clipPathPolygon = "polygon( 0px 0px, 0px " + bottom + "," + right + " " + bottom +"," + right + " 0px)"; 9583 // clip property is deprecated but still supported by all the major browsers 9584 // clip-path replaces the deprecated clip property but still is not fully supported by all major browser 9585 this.$userControl.css({"clip" : clipRect, "clip-path" : clipPathPolygon}); 9586 }, 9587 9588 render : function() { 9589 var self = this; 9590 if (typeof FileReader !== "undefined") { 9591 this.reader = new FileReader(); 9592 } else { 9593 xfalib.ut.XfaUtil.prototype.getLogger().error("Image Field is supported only for HTML5 supported browsers."); 9594 } 9595 if (this.element) { 9596 // change event triggered when new image is selected 9597 this.$widgetInput = this.element.find("input").on("change.imageField", function() { 9598 self._handleInputChange(); 9599 }).click(function(event) { 9600 // to stop bubbling of event from input to widget 9601 event.stopPropagation(); 9602 }); 9603 this.$widgetImg = this.element.on("click.imageField", function() { 9604 self._imageClick(); 9605 }).find("img"); 9606 } 9607 if (this.reader) { 9608 //load event is triggered each time the reading operation is successfully completed 9609 this.reader.addEventListener("load", function () { 9610 self.$widgetImg.attr("src",self.reader.result); 9611 self.$widgetImg.trigger("imagechange"); 9612 }, false); 9613 } 9614 return $.xfaWidget.defaultWidget.prototype.render.apply(this, arguments); 9615 }, 9616 9617 getCommitValue: function() { 9618 return this._extractData(this.$userControl.attr("src")); 9619 }, 9620 9621 // hidden input change handler, input change will be triggered on selecting a new image 9622 _handleInputChange : function() { 9623 this._displayImage(); 9624 }, 9625 9626 _imageClick : function(clickEvent) { 9627 //as the input button is hidden we trigger click explicitly on click of the widget 9628 this.$widgetInput.trigger("click"); 9629 }, 9630 9631 // removes "data\:.*\;base64," from the image base64 string 9632 _extractData : function(value) { 9633 return value.replace(/data\:.*\;base64,/, ""); 9634 }, 9635 9636 // previews image in the imagefield widget 9637 _displayImage : function() { 9638 var imageFile = this.$widgetInput.get(0).files ? this.$widgetInput.get(0).files[0] : null; 9639 if (imageFile && this._isFileOfImageType(imageFile.name)) { 9640 if (this.reader) { 9641 //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 9642 this.reader.readAsDataURL(imageFile); 9643 } 9644 } 9645 }, 9646 9647 // Test for supported image file(jpg,jpeg,png,gif,tif,bmp) 9648 _isFileOfImageType : function(fileName) { 9649 if (fileName) { 9650 return (/\.(jpe?g|png|gif|tif|bmp)$/i.test(fileName)); 9651 } 9652 return false; 9653 } 9654}); 9655})($); 9656/** 9657 * Created with IntelliJ IDEA. 9658 * User: rpandey 9659 * Date: 12/24/12 9660 * Time: 8:06 PM 9661 * To change this template use File | Settings | File Templates. 9662 */ 9663 9664 9665(function($){ 9666 $.widget( "xfaWidget.signatureField", $.xfaWidget.defaultWidget, { 9667 9668 _widgetName:"signatureField", 9669 9670 getOptionsMap: function() { 9671 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this,arguments); 9672 return $.extend({},parentOptionsMap,{ 9673 "displayValue": function(val) {}, 9674 "access": function(val) {} 9675 }) 9676 }, 9677 9678 render : function() { 9679 var $control = $.xfaWidget.defaultWidget.prototype.render.apply(this, arguments); 9680 //pessimistic checks 9681 if($control) { 9682 $control.attr("readOnly","readonly").attr("disabled", true); 9683 } 9684 return $control; 9685 } 9686 }); 9687})($); 9688/* 9689 * ADOBE CONFIDENTIAL 9690 * ___________________ 9691 * 9692 * Copyright 2011-2012 Adobe Systems Incorporated 9693 * All Rights Reserved. 9694 *
9695 * NOTICE: All information contained herein is, and remains 9696 * the property of Adobe Systems Incorporated and its suppliers, 9697 * if any. The intellectual and technical concepts contained 9698 * herein are proprietary to Adobe Systems Incorporated and its 9699 * suppliers and may be covered by U.S. and Foreign Patents, 9700 * patents in process, and are protected by trade secret or copyright law. 9701 * Dissemination of this information or reproduction of this material 9702 * is strictly forbidden unless prior written permission is obtained 9703 * from Adobe Systems Incorporated. 9704 */ 9705 9706/** 9707 * widget definition for scribbleable field 9708 */ 9709(function($,xfalib){ 9710 9711 var TouchUtil=xfalib.ut.TouchUtil; 9712 var ScribbleUtil=(function(){ 9713 return { 9714 localeString:function(id){ 9715 return xfalib.ut.XfaUtil.prototype.encodeScriptableTags($.xfaWidget.abstractWidget.prototype.localeStrings()[id]) || id; 9716 } 9717 }; 9718 })(); 9719 var DELETE_KEY = 46; 9720 var ESC_KEY = 27; 9721 var ENTER_KEY = 13; 9722/** 9723 * Scribble class definition, used for drawing on canvas using mouse or touch 9724 */ 9725function Scribble( canvasID,image,_width,_height, callback) { 9726 this._callback = callback; 9727 this.canvasID = canvasID; 9728 this._lineWidth=5; 9729 this.canvas = $("#"+canvasID); 9730 this.context = this.canvas.get(0).getContext("2d"); 9731 this.context.clearRect(0,0,this.canvas.width,this.canvas.height); 9732 this._enabled=true; 9733 this.context.strokeStyle = "#000000"; 9734 this.canvasBorderWidth = parseInt(this.canvas.css('border-left-width'),10); // assuming top and left borders are same width 9735 this.context.lineWidth = this._lineWidth; 9736 this.lastMousePoint = {x:0, y:0}; 9737 9738 this.canvas[0].width = _width;// this.canvas.parent().innerWidth(); 9739 this.canvas[0].height = _height;//this.canvas.parent().innerHeight(); 9740 if(!image){ 9741 this.context.fillStyle = '#ffffff'; 9742 this.context.clearRect(0,0,_width,_height); 9743 } else {
9744 this.context.drawImage(image,0,0); 9745 } 9746 this.canvas.on( TouchUtil.POINTER_DOWN, this.onCanvasMouseDown() ); 9747} 9748Scribble.prototype.setLineWidth=function(w){ 9749 this._lineWidth=w; 9750}; 9751Scribble.prototype.onCanvasMouseDown = function () { 9752 var self = this; 9753 return function(event) { 9754 if(TouchUtil.getTouches(event).length < 2){ 9755 self.mouseMoveHandler = self.onCanvasMouseMove(); 9756 self.mouseUpHandler = self.onCanvasMouseUp(); 9757 //CQ-4261765 : Scribble sign scroll issue with ios 9758 //https://stackoverflow.com/questions/49500339/cant-prevent-touchmove-from-scrolling-window-on-ios 9759 //https://github.com/jquery/jquery/issues/2871 9760 document.addEventListener(TouchUtil.POINTER_MOVE, self.mouseMoveHandler,{ passive: false }); 9761 $(document).on(TouchUtil.POINTER_UP, self.mouseUpHandler ); 9762 self.updateMousePosition( event ); 9763 self.updateCanvas( event ); 9764 } 9765 } 9766}; 9767 9768Scribble.prototype.onCanvasMouseMove = function () { 9769 var self = this; 9770 return function(event) { 9771 if(TouchUtil.getTouches(event).length < 2){ 9772 self.updateCanvas( event ); 9773 event.preventDefault(); 9774 return false; 9775 } 9776 } 9777}; 9778 9779Scribble.prototype.onCanvasMouseUp = function (event) { 9780 var self = this; 9781 return function(event) { 9782 document.removeEventListener(TouchUtil.POINTER_MOVE, self.mouseMoveHandler,{ passive: false }); 9783 $(document).off(TouchUtil.POINTER_UP, self.mouseUpHandler ); 9784 self.mouseMoveHandler = null; 9785 self.mouseUpHandler = null; 9786 } 9787}; 9788 9789Scribble.prototype.updateMousePosition = function (event) { 9790 if(!this._enabled) return ; 9791 var target = TouchUtil.getTouchEvent(event); 9792 9793 var offset = this.canvas.offset(); 9794 /* In IE>=10 pageX values are incorrect when using zoom 9795 so calculate them using clientX and scrollLeft */ 9796 this.lastMousePoint.x = target.clientX + $(window).scrollLeft() - offset.left - this.canvasBorderWidth; 9797 this.lastMousePoint.y = target.clientY + $(window).scrollTop() - offset.top - this.canvasBorderWidth; 9798 9799}; 9800Scribble.prototype._isInsideCanvas = function(x,y){ 9801 return y>=0 && y<this.canvas[0].height && x>=0 && x < this.canvas[0].width; 9802}; 9803 Scribble.prototype.updateCanvas = function (event) { 9804 if(!this._enabled) { 9805 return; 9806 } 9807 var oldX,oldY,dX,dY,canDraw,scaleX,scaleY,cssWidth,cssHeight; 9808 cssWidth = parseInt(this.canvas[0].style.width,10); 9809 cssHeight = parseInt(this.canvas[0].style.height,10); 9810 scaleX = cssWidth?this.canvas[0].width/cssWidth:1; 9811 scaleY = cssHeight?this.canvas[0].height/cssHeight:1; 9812 9813 scaleX /= xfalib.ut.XfaUtil.prototype.formScaleFactor; 9814 scaleY /= xfalib.ut.XfaUtil.prototype.formScaleFactor; 9815 9816 oldX = this.lastMousePoint.x*scaleX; 9817 oldY = this.lastMousePoint.y*scaleY; 9818 9819 this.updateMousePosition( event ); 9820 9821 var newX = this.lastMousePoint.x*scaleX; 9822 var newY = this.lastMousePoint.y*scaleY; 9823 9824 dX = Math.abs(newX - oldX ); 9825 dY = Math.abs(newY - oldY ); 9826 9827 canDraw = ( dX > 0 || dY > 0 ) && this._isInsideCanvas(oldX,oldY) && this._isInsideCanvas(newX,newY);; 9828 9829 if(canDraw){ 9830 this.context.beginPath(); 9831 this.context.moveTo( oldX, oldY ); 9832 this.context.lineTo(newX, newY ); 9833 this.context.lineWidth=this._lineWidth; 9834 this.context.lineCap='round'; 9835 this.context.stroke(); 9836 9837 this._callback(); 9838 9839 } 9840}; 9841 9842Scribble.prototype.toString = function () { 9843 9844 var dataString = this.canvas.get(0).toDataURL("image/png"); 9845 //var index = dataString.indexOf( "," )+1; 9846 //dataString = dataString.substring( index ); 9847 9848 return dataString; 9849}; 9850Scribble.prototype.setEnabled=function(enable){ 9851 this._enabled=enable; 9852}; 9853Scribble.prototype.clear = function () { 9854 9855 var c = this.canvas[0]; 9856 this.context.clearRect( 0, 0, c.width, c.height ); 9857}; 9858 9859 9860// ImageEdit dialog box 9861var imageEditDialog=(function(_){ 9862 9863 // html used to construct dialog box 9864 var htmlStr=(function(){ 9865 var html=[ 9866 '<div id="iEBox_container" tabindex="0" role="dialog" aria-label="'+ScribbleUtil.localeString("pleaseSignText")+'">', 9867 '<div id="iEBox_panel">', 9868 '<div id = "iEBox_Cancel" class="iEBox_button" tabindex="0" role="button" aria-label="'+ScribbleUtil.localeString("cancel")+'" title="'+ScribbleUtil.localeString("cancel")+'" ></div>', 9869 '</div>', 9870 '<div id="iEBox_content">', 9871 '<div id="iEBox_canvases" align=center>', 9872 '<div style="display:inline-block; vertical-align:top;">', 9873 '<canvas id="iEBox_canvas" style="margin:0px;border-bottom:0px;" width="696" height="390" ></canvas>' , 9874 '<input type="text" id="keyboard_Sign_Box" name="signatureText" placeholder="'+ScribbleUtil.localeString("typeYourSignatureHere")+'">', 9875 '<fieldset id="iEBox_caption"><legend align="center">
9875'+ScribbleUtil.localeString("pleaseSignText")+'</legend></fieldset>', 9876 '</div>', 9877 '<canvas id="iEBox_geoCanvasRight" width="0" height="0" ></canvas>', 9878 '<div><canvas id="iEBox_geoCanvasBottom" width="0" height="0" ></canvas></div>', 9879 '</div>', 9880 '<div>', 9881 '<div id="iEBox_Brush" class="iEBox_button" tabindex="0" role="button" aria-label="'+ScribbleUtil.localeString("brushes")+'" title="'+ScribbleUtil.localeString("brushes")+'"></div>', 9882 '<div id="iEBox_Clear" class="iEBox_button" tabindex="0" role="button" aria-label="'+ScribbleUtil.localeString("clear")+'" title="'+ScribbleUtil.localeString("clear")+'" ></div>', 9883 '<div id="iEBox_Geo" class="iEBox_button" tabindex="0" role="button" aria-label="'+ScribbleUtil.localeString("geolocation")+'" title="'+ScribbleUtil.localeString("geolocation")+'" ></div>', 9884 '<div id="iEBox_Text" class="iEBox_button" tabindex="0" role="button" aria-label="'+ScribbleUtil.localeString("typeYourName")+'" title="'+ScribbleUtil.localeString("typeYourName")+'"></div>', 9885 '<div id="iEBox_title"></div>', 9886 '<div id="iEBox_Ok" class="iEBox_button" tabindex="0" role="button" aria-label="'+ScribbleUtil.localeString("ok")+'" title="'+ScribbleUtil.localeString("ok")+'" ></div>', 9887 '</div>' , 9888 '</div>' , 9889 '<div id="iEBox_moveframe" ></div>', 9890 '<div id="iEBox_brushList" ></div>', 9891 '</div>'].join(""); 9892 return function(){ 9893 return html; 9894 }; 9895 }); 9896 9897 /** 9898 * 9899 */ 9900 9901 var dialogObj = { 9902 verticalOffset: 0, // removing the magic value of -75 since it was not causing any impact 9903 horizontalOffset: 0, 9904 repositionOnResize: true, 9905 overlayOpacity: .75, 9906 overlayColor: '#CCCCCC', 9907 draggable: true, 9908 _brushes:[2,3,4,5,6,7,8,9,10], 9909 _buttonsEnabled:{}, 9910 _isOpen:false, 9911 show:function(title,callback){ 9912 this._show(callback); 9913 this._buttonsEnabled={Geo:true,Clear:true,Ok:true,Cancel:true,Brush:true,Text:true}; 9914 }, 9915 setEnabled:function(button,enable){ 9916 if(this._buttonsEnabled[button]!=enable){ 9917 this._buttonsEnabled[button]=enable; 9918 if(enable){ 9919 $('#iEBox_'+button).empty('<div style="background:white;width:100%;height:100%;opacity:0.75;"></div>'). 9920 removeClass("disable_button"); 9921 } else { 9922 $('#iEBox_'+button).append('<div style="background:white;width:100%;height:100%;opacity:0.75;"></div>'). 9923 addClass("disable_button"); 9924 } 9925 9926 } 9927 }, 9928 enableButtons:function(buttons){ 9929 for(var k in buttons){ 9930 this.setEnabled(k,buttons[k]); 9931 } 9932 }, 9933 toggleBrushList:function(event){ 9934 var that = this; 9935 if($('#iEBox_brushList').css('display')!='none'){ 9936 $('#iEBox_brushList').css({display:'none'}); 9937 return; 9938 } 9939 var tmpFn = document.onselectstart; 9940 document.onselectstart=function(){return false;}; 9941 $('#iEBox_brushList').css({display:'block',visibility:'hidden'}); 9942 $('#iEBox_brushList').offset($('#iEBox_Brush').offset()); 9943 $('#iEBox_brushList').offset({top:$('#iEBox_Brush').offset().top-$('#iEBox_brushList').height()}); 9944 $('#iEBox_brushList').css({display:'block',visibility:'visible'}); 9945 // $('#iEBox_brushList').focus(); 9946 $('#iEBox_brushList').one('mouseleave',function(event){ 9947 $('#iEBox_brushList').css({display:'none'}); 9948 document.onselectstart=tmpFn; 9949 }); 9950 }, 9951 _attachCallbacks: function(callback) { 9952 var that = this; 9953 var sigCanvas = $('#iEBox_canvas')[0]; 9954 var ctx=sigCanvas.getContext("2d"); 9955 var minSigCanvasFontSize=10; 9956 var maxSigCanvasFontSize=70;
9957 var sigCanvasFontSize=minSigCanvasFontSize; 9958 var initialSigCanvasFontSize=sigCanvasFontSize; 9959 var initialFontCalculatedFlag=false; 9960 var sigCanvasFontFamily="sans-serif, Georgia"; 9961 var sigCanvasFontStyle="italic"; 9962 _.each("Cancel-Clear-Geo-Ok-Brush-Text".split("-"),function(val,idx){ 9963 $("#iEBox_"+val).click( function(event) { 9964 if(that._buttonsEnabled[val]){ 9965 event.stopPropagation(); 9966 callback(val); 9967 } 9968 }); 9969 $("#iEBox_"+val).keydown( function(event) { 9970 if(that._buttonsEnabled[val] && (event.keyCode == ENTER_KEY || event.charCode == ENTER_KEY || event.which == ENTER_KEY) ){ 9971 event.stopPropagation(); 9972 callback(val); 9973 } 9974 }); 9975 }); 9976 _.each($("#iEBox_brushList").children(),function(itm,idx){ 9977 $(itm).on(TouchUtil.POINTER_UP,function(event){ 9978 callback("BrushSelect",that._brushes[idx]); 9979 $('#iEBox_brushList').css({display:'none'}); 9980 // $(itm).css({backgroundColor:'#FFFFFF'}); 9981 }); 9982 $(itm).on(TouchUtil.POINTER_DOWN,function(event){ 9983 // $(itm).css({backgroundColor:'#AAAAAA'}); 9984 event.preventDefault(); 9985 }); 9986 }); 9987 9988 $('#keyboard_Sign_Box').keydown(function (event){ 9989 var inputSign=$('#keyboard_Sign_Box')[0].value; 9990 9991 if(event.key==="Backspace") { 9992 ctx.font=sigCanvasFontStyle+sigCanvasFontSize+"px "+sigCanvasFontFamily; 9993 sigCanvasFontSize=dialogObj._increaseFontForSignature(ctx.measureText(inputSign).width,sigCanvas.width, 9994 sigCanvasFontSize,initialSigCanvasFontSize); 9995 ctx.font=sigCanvasFontStyle+" "+sigCanvasFontSize+"px "+sigCanvasFontFamily; 9996 ctx.clearRect(0, 0, sigCanvas.width, sigCanvas.height); 9997 ctx.fillText(inputSign, 3, sigCanvasFontSize, sigCanvas.width-5); 9998 } 9999 event.stopPropagation(); 10000 }); 10001 10002 $("#keyboard_Sign_Box").keyup(function (event){ 10003 var inputSign=$('#keyboard_Sign_Box')[0].value; 10004 if(inputSign.length==0) { 10005 dialogObj.enableButtons({Ok: false, Clear: false}); 10006 } 10007 if(inputSign.length>=1 && inputSign.trim().length!=0) { 10008 dialogObj.enableButtons({Ok: true, Clear: true}); 10009 } 10010 if(initialFontCalculatedFlag===false){ 10011 sigCanvasFontSize=sigCanvas.height-20; 10012 sigCanvasFontSize=sigCanvasFontSize<minSigCanvasFontSize?minSigCanvasFontSize:sigCanvasFontSize; 10013 sigCanvasFontSize=sigCanvasFontSize>maxSigCanvasFontSize?maxSigCanvasFontSize:sigCanvasFontSize; 10014 initialSigCanvasFontSize=sigCanvasFontSize; 10015 $('#keyboard_Sign_Box')[0].style.font=sigCanvasFontStyle+" 2rem "+sigCanvasFontFamily; 10016 initialFontCalculatedFlag=true; 10017 } 10018 ctx.font=sigCanvasFontStyle+sigCanvasFontSize+"px "+sigCanvasFontFamily; 10019 sigCanvasFontSize=dialogObj._decreaseFontForSignature(ctx,inputSign,sigCanvas.width, 10020 sigCanvasFontSize,sigCanvasFontFamily); 10021 ctx.font=sigCanvasFontStyle+" "+sigCanvasFontSize+"px "+sigCanvasFontFamily; 10022 ctx.clearRect(0, 0, sigCanvas.width, sigCanvas.height); 10023 ctx.fillText(inputSign,3,sigCanvasFontSize,sigCanvas.width-5); 10024 event.stopPropagation(); 10025 }); 10026 10027 // capture tab key and escape 10028 $('#iEBox_container').keydown(function(event){ 10029 var firstFocusableItem = document.querySelector("#iEBox_container"); 10030 var lastFocusableItem = document.querySelector("#iEBox_Ok"); 10031 var KEYCODE_TAB = 9; 10032 var isTabPressed = (event.key === 'Tab' || event.keyCode === KEYCODE_TAB); 10033 if((event.keyCode == ESC_KEY || event.charCode == ESC_KEY || event.which == ESC_KEY)) { 10034 event.stopPropagation(); 10035 event.preventDefault(); 10036 callback("Cancel"); 10037 } else if (isTabPressed) { 10038 // Trap focus inside the dialog box 10039 if (event.shiftKey && document.activeElement === firstFocusableItem) { 10040 // when shift + tab key is pressed 10041 lastFocusableItem.focus(); 10042 event.preventDefault(); 10043 } else if (document.activeElement === lastFocusableItem) { 10044 // when tab key is pressed 10045 firstFocusableItem.focus(); 10046 event.preventDefault(); 10047 } 10048 } 10049 10050 }); 10051 10052 if(this.draggable){ 10053 this._makeDraggable(TouchUtil.TOUCH_ENABLED); 10054 } 10055 }, 10056 10057 _decreaseFontForSignature:function(ctx,inputSign,sigCanvasWidth,fontSize,sigCanvasFontFamily){ 10058 while(ctx.measureText(inputSign).width>sigCanvasWidth-5 && fontSize>20){ 10059 fontSize=fontSize-10; 10060 ctx.font=fontSize+"px "+sigCanvasFontFamily; 10061 } 10062 return fontSize 10063 }, 10064 _increaseFontForSignature:function(textWidth,sigCanvasWidth,fontSize,initialSigCanvasFontSize){ 10065 if(sigCanvasWidth-textWidth>0){ 10066 fontSize=initialSigCanvasFontSize; 10067 } 10068 return fontSize; 10069 }, 10070 _makeDraggable:function(touchEnabled){ 10071 var _isMouseDown=false; 10072 var _that=this; 10073 var dX; 10074 var dY; 10075 var offsetPos; 10076 var _mouseMovFun; 10077 var _mouseUpFun; 10078 $('#iEBox_panel').on(TouchUtil.POINTER_DOWN,function( event ){ 10079 10080 if(TouchUtil.getTouches(event).length < 2){ 10081 if($(event.target).is('#iEBox_panel')){ 10082 $('body')[0].addEventListener(TouchUtil.POINTER_MO
10082VE,_mouseMovFun=function( event ){ 10083 if(TouchUtil.getTouches(event).length < 2 && _isMouseDown){ 10084 event.preventDefault(); 10085 var evt = TouchUtil.getTouchEvent(event); 10086 var delX = evt.pageX - dX; 10087 var delY = evt.pageY - dY; 10088 $('#iEBox_moveframe').offset({ 10089 top: offsetPos.top+delY, 10090 left: offsetPos.left+delX 10091 }); 10092 } 10093 }, { passive: false }); 10094 $('body').on(TouchUtil.POINTER_UP,_mouseUpFun=function(event){ 10095 if(_isMouseDown){ 10096 var offsetMove = $('#iEBox_moveframe').offset(); 10097 var topEdge = $(window).scrollTop(); 10098 var bottomEdge = topEdge + $(window).height(); 10099 if(offsetMove.top - topEdge < 1){ 10100 offsetMove.top = topEdge; 10101 } 10102 if(offsetMove.top - bottomEdge + $('#iEBox_panel').height() > 0 ){ 10103 offsetMove.top = bottomEdge - $('#iEBox_panel').height(); 10104 } 10105 $('#iEBox_container').offset(offsetMove ); 10106 $('#iEBox_moveframe').css({display:'none'}).offset(offsetMove); 10107 _isMouseDown=false; 10108 $('body')[0].removeEventListener(TouchUtil.POINTER_MOVE,_mouseMovFun,{ passive: false }); 10109 $('body').off(TouchUtil.POINTER_UP,_mouseUpFun); 10110 } 10111 }); 10112 10113 var evt = TouchUtil.getTouchEvent(event); 10114 _isMouseDown=true; dX = evt.pageX;dY=evt.pageY; 10115 offsetPos = $('#iEBox_container').offset(); 10116 $('#iEBox_moveframe').css({display:'block'}); 10117 $('#iEBox_moveframe').offset(offsetPos); 10118 $('#iEBox_moveframe').css('width',$('#iEBox_container').css('width')); 10119 $('#iEBox_moveframe').css('height',$('#iEBox_container').css('height')); 10120 } 10121 } 10122 }); 10123 10124 }, 10125 _createBrushes:function(){ 10126 var _that=this; 10127 _.each(this._brushes,function(val,idx){ 10128 var divel = document.createElement('DIV'); 10129 var cnv = document.createElement('CANVAS'); 10130 var ctx = cnv.getContext('2d'); 10131 cnv.style.border='1px solid #AAAAAA'; 10132 cnv.width=TouchUtil.TOUCH_ENABLED?200:100; 10133 cnv.height=TouchUtil.TOUCH_ENABLED?40:20;; 10134 ctx.lineWidth=val; 10135 ctx.beginPath(); 10136 ctx.moveTo(10,cnv.height/2); 10137 ctx.lineTo(cnv.width-10,cnv.height/2); 10138 ctx.stroke(); 10139 divel.appendChild(cnv); 10140 $('#iEBox_brushList').append(divel); 10141 }); 10142 }, 10143 getIsOpen:function(){ 10144 return dialogObj._isOpen; 10145 }, 10146 setIsOpen:function(open){ 10147 dialogObj._isOpen = open; 10148 }, 10149 _show: function(callback) { 10150 dialogObj.hide(); 10151 dialogObj._overlay('show'); 10152 10153 $("BODY").append(htmlStr()); 10154 dialogObj.setIsOpen(true); 10155 $('#iEBox_container').focus(); 10156 dialogObj._createBrushes(); 10157 10158 dialogObj._reposition(); 10159 10160 // calculate spacing around canvas area 10161 // this will be used to find canvas dimensions based on available screen area. 10162 var container_el = $('#iEBox_container'); 10163 var canvas_el = $('#iEBox_canvas'); 10164 var container_width = $('#iEBox_container').outerWidth(true);
10165 var container_height = $('#iEBox_container').outerHeight(true); 10166 var canvas_width = canvas_el[0].width; 10167 var canvas_height = canvas_el[0].height; 10168 dialogObj.canvas_spacing = { x:container_width - canvas_width, y:container_height-canvas_height}; 10169 10170 dialogObj._maintainPosition(true); 10171 10172 dialogObj._attachCallbacks(callback); 10173 }, 10174 10175 hide: function() { 10176 $("#iEBox_container").remove(); 10177 this._overlay('hide'); 10178 dialogObj.setIsOpen(false); 10179 this._maintainPosition(false); 10180 }, 10181 _overlayResize:function(event) { 10182 if($("#iEBox_overlay").height()!= $(document).height()){ 10183 $("#iEBox_overlay").height( $(document).height() ); 10184 } 10185 10186 }, 10187 _disableMove:function(event) { 10188 event.preventDefault(); 10189 }, 10190 _overlay: function(status) { 10191 switch( status ) { 10192 case 'show': 10193 this._overlay('hide'); 10194 $("BODY").append('<div id="iEBox_overlay"></div>'); 10195 $("#iEBox_overlay").css({ 10196 position: 'fixed', 10197 zIndex: 99997, 10198 top: '0px', 10199 left: '0px', 10200 width: '100%', 10201 height: $(document).height(), 10202 background: this.overlayColor, 10203 opacity: this.overlayOpacity 10204 }); 10205 if(xfalib.ut.XfaUtil.prototype.isSafari()) { 10206 $("#iEBox_overlay").on('touchmove', this._disableMove); 10207 } 10208 $(document).on('scroll',this._overlayResize); 10209 break; 10210 case 'hide': 10211 if(xfalib.ut.XfaUtil.prototype.isSafari()) { 10212 $("#iEBox_overlay").off('touchmove'); 10213 } 10214 $("#iEBox_overlay").remove(); 10215 $(document).off('scroll',this._overlayResize); 10216 break; 10217 } 10218 }, 10219 /** 10220 * resize dialog based on available screen area 10221 */ 10222 _resize:function(){ 10223 // available screen area 10224 var aWidth = $(window).width(); 10225 var aHeight = $(window).height(); 10226 10227 var sigCnv = $('#iEBox_canvas')[0]; 10228 var sigTextBox = $('#keyboard_Sign_Box')[0]; 10229 var bGeoCnv = $('#iEBox_geoCanvasBottom')[0]; 10230 var rGeoCnv = $('#iEBox_geoCanvasRight')[0]; 10231 10232 // calculate amount of width height we need to reduce 10233 10234 var totalCnvWidth = sigCnv.width + rGeoCnv.width; 10235 var totalCnvHeight = sigCnv.height + bGeoCnv.height; 10236 10237 10238 10239 10240 10241 var diffW = totalCnvWidth + dialogObj.canvas_spacing.x - aWidth; 10242 if(diffW < 0) { 10243 diffW = 0; 10244 } 10245 var diffH = totalCnvHeight + dialogObj.canvas_spacing.y - aHeight; 10246 if(diffH < 0){ 10247 diffH = 0; 10248 } 10249 10250 var newTotalCnvHeight, newTotalCnvWidth; 10251 if( diffW > 0 || diffH > 0 ){ // does any side need resize 10252 10253 if(diffH * totalCnvWidth > totalCnvHeight * diffW){ // need to reduce height 10254 newTotalCnvHeight = totalCnvHeight - diffH; 10255 newTotalCnvWidth = (newTotalCnvHeight * totalCnvWidth)/ totalCnvHeight; 10256 } else { 10257 newTotalCnvWidth = totalCnvWidth - diffW; 10258 newTotalCnvHeight = (newTotalCnvWidth * totalCnvHeight)/ totalCnvWidth; 10259 } 10260 10261 // distribute evenly the new dimensions 10262 10263 10264 var newSigCnvWidth = (newTotalCnvWidth*sigCnv.width)/totalCnvWidth; 10265 var newSigCnvHeight = (newTotalCnvHeight*sigCnv.height)/totalCnvHeight; 10266 10267 sigCnv.style.width = newSigCnvWidth + "px"; 10268 sigCnv.style.height = newSigCnvHeight + "px"; 10269 10270 sigTextBox.style.width = newSigCnvWidth + "px"; 10271 sigTextBox.style.height = newSigCnvHeight + "px"; 10272 10273 10274 bGeoCnv.style.width = newSigCnvWidth +"px"; 10275 bGeoCnv.style.height = (newTotalCnvHeight - newSigCnvHeight) +"px"; 10276 10277 rGeoCnv.style.width = (newTotalCnvWidth - newSigCnvWidth) +"px"; 10278 rGeoCnv.style.height = newSigCnvHeight + "px"; 10279 10280 10281 $('#iEBox_caption').width(Math.floor(newSigCnvWidth)); 10282 10283 } else { 10284 sigCnv.style.width = sigCnv.width + "px"; 10285 sigCnv.style.height = sigCnv.height + "px"; 10286 10287 sigTextBox.style.width = sigCnv.width + "px"; 10288 sigTextBox.style.height = sigCnv.height + "px"; 10289 10290 bGeoCnv.style.width = bGeoCnv.width + "px"; 10291 bGeoCnv.style.height = bGeoCnv.height + "px"; 10292 10293 rGeoCnv.style.width = rGeoCnv.width + "px"; 10294 rGeoCnv.style.height = rGeoCnv.height + "px"; 10295 10296 $('#iEBox_caption').width(sigCnv.width); 10297 10298 } 10299 }, 10300 _reposition: function() { 10301 var top = (($(window).height() * (1 / xfalib.ut.XfaUtil.prototype.formScaleFactor) / 2) - ($("#iEBox_container").outerHeight() / 2)) + dialogOb
10301j.verticalOffset; 10302 var left = (($(window).width() * (1 / xfalib.ut.XfaUtil.prototype.formScaleFactor) / 2) - ($("#iEBox_container").outerWidth() / 2)) + dialogObj.horizontalOffset; 10303 if( top < 0 ) top = 0; 10304 if( left < 0 ) left = 0; 10305 10306 $("#iEBox_container").css({ 10307 top: top + $(window).scrollTop() * (1 / xfalib.ut.XfaUtil.prototype.formScaleFactor) + 'px', 10308 left: left + $(window).scrollLeft() * (1 / xfalib.ut.XfaUtil.prototype.formScaleFactor) + 'px' 10309 }); 10310 $("#iEBox_container").focus(); // scroll up to the canvas 10311 $("#iEBox_overlay").height( $(document).height() ); 10312 }, 10313 _maintainDialog:function(){ 10314 dialogObj._resize(); 10315 dialogObj._reposition(); 10316 }, 10317 _maintainPosition: function(status) { 10318 if(dialogObj.repositionOnResize ) { 10319 switch(status) { 10320 case true: 10321 $(window).on('orientationchange', dialogObj._maintainDialog); // also reposition if device is tilted 10322 break; 10323 case false: 10324 $(window).off('orientationchange', dialogObj._maintainDialog); 10325 break; 10326 } 10327 } 10328 } 10329 10330 }; 10331 return dialogObj; 10332})(window._); 10333 10334/** 10335 * class definition for GeoLocationQueryRequest 10336 * encapsulated success and error handlers 10337 */ 10338function GeoLocQuery(){} 10339GeoLocQuery.prototype={ 10340 init:function(success,failure){ 10341 this._successHandler = success; 10342 this._errorHandler = failure; 10343 this._active=true; 10344 return this; 10345 }, 10346 _handleSuccess:function(data){ 10347 this._successHandler(data); 10348 }, 10349 _handleError:function(err){ 10350 this._errorHandler(err); 10351 }, 10352 query:function(){ 10353 _that=this; 10354 navigator.geolocation.getCurrentPosition(function(pos){ 10355 if(_that._active){ 10356 _that._handleSuccess(pos); 10357 } 10358 _that._active=false; 10359 },function(err){ 10360 if(_that._active){ 10361 _that._handleError(err); 10362 } 10363 _that._active=false; 10364 },{timeout:10000}); 10365 }, 10366 cancel:function(){ 10367 _that._active=false; 10368 } 10369 10370}; 10371// GeoLocQuery definition ends here 10372 10373/** 10374* 10375* Base64 encode / decode 10376* http://www.webtoolkit.info/ 10377* 10378**/ 10379 10380var Base64 = { 10381 10382 // private property 10383 _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", 10384 10385 // public method for encoding 10386 encode : function (input) { 10387 var output = ""; 10388 var chr1, chr2, chr3, enc1, enc2, enc3, enc4; 10389 var i = 0; 10390 10391 while (i < input.length) { 10392 10393 chr1 = input.charCodeAt(i++); 10394 chr2 = input.charCodeAt(i++); 10395 chr3 = input.charCodeAt(i++); 10396 10397 enc1 = chr1 >> 2; 10398 enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); 10399 enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); 10400 enc4 = chr3 & 63; 10401 10402 if (isNaN(chr2)) { 10403 enc3 = enc4 = 64; 10404 } else if (isNaN(chr3)) { 10405 enc4 = 64; 10406 } 10407 10408 output = output + 10409 this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) + 10410 this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4); 10411 10412 } 10413 10414 return output; 10415 }, 10416 10417 // public method for decoding 10418 decode : function (input) { 10419 var output = ""; 10420 var chr1, chr2, chr3; 10421 var enc1, enc2, enc3, enc4; 10422 var i = 0; 10423 10424 input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); 10425 10426 while (i < input.length) { 10427 10428 enc1 = this._keyStr.indexOf(input.charAt(i++)); 10429 enc2 = this._keyStr.indexOf(input.charAt(i++)); 10430 enc3 = this._keyStr.indexOf(input.charAt(i++)); 10431 enc4 = this._keyStr.indexOf(input.charAt(i++)); 10432 10433 chr1 = (enc1 << 2) | (enc2 >> 4); 10434 chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); 10435 chr3 = ((enc3 & 3) << 6) | enc4; 10436 10437 output = output + String.fromCharCode(chr1); 10438 10439 if (enc3 != 64) { 10440 output = output + String.fromCharCode(chr2); 10441 } 10442 if (enc4 != 64) { 10443 output = output + String.fromCharCode(chr3); 10444 } 10445 10446 } 10447 10448 return output; 10449 10450 } 10451 10452 10453 10454}; 10455 10456/** 10457 * Utility Singleton for handling PNG Data 10458 */ 10459var PNGUtil=(function(){ 10460 var slf={ 10461 _LC_Scribble_MetaDataKey:"LC_SCIBBLE_METADATA", 10462 _isPng:function(b64data){ 10463 return b64data && b64data.replace(/\s+/g, "").indexOf("iVBORw0KGgo") == 0; // LC-5711 : trim any leading WhiteSpace
10464 // 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 10465 }, 10466 _update_crc:function(crc,data){ 10467 var c = crc; 10468 var n; 10469 for(n=0;n<data.length;n++){ 10470 c = this._XOR(slf._crc_table[(this._XOR(c,data.charCodeAt(n))&0xff)>>>0],(c>>>8)); 10471 } 10472 return c; 10473 }, 10474 _XOR:function(a,b){ 10475 return (a^b)>>>0; 10476 }, 10477 _U32Int2Str:function(n){ 10478 return String.fromCharCode((n>>>24)&0xFF)+String.fromCharCode((n>>>16)&0xFF)+String.fromCharCode((n>>>8)&0xFF)+String.fromCharCode(n>>>0&0xFF); 10479 }, 10480 _init_crc_table:function(){ 10481 var c=0; 10482 var n,k; 10483 slf._crc_table=[]; 10484 for(n=0;n<256;n++){ 10485 c = n; 10486 for(k=0;k<8;k++){ 10487 if(((c&1)>>>0)>0){ 10488 c = slf._XOR(0xedb88320 , (c>>>1)); 10489 } else { 10490 c = c>>>1; 10491 } 10492 } 10493 slf._crc_table[n]=c; 10494 } 10495 }, 10496 _CRC:function(data){ 10497 if(!this._crc_table) this._init_crc_table(); 10498 return this._XOR(this._update_crc(0xffffffff,data) , 0xffffffff); 10499 }, 10500 _prepareTextChunk:function(content,pad){ 10501 // pad the data appropriately 10502 var len = content.length; 10503 var lenStr = slf._U32Int2Str(len); 10504 var chunkType="tEXt"; 10505 var checkSumStr = slf._U32Int2Str(slf._CRC(chunkType+content)); 10506 return lenStr+chunkType+content+checkSumStr; 10507 }, 10508 _start:function(str){ 10509 slf._startTime = new Date().getTime(); 10510 slf._startFun=str; 10511 }, 10512 _end:function(){ 10513 var str = "Time "+slf._startFun+": "+(new Date().getTime()-slf._startTime); 10514 // $('BODY').append("<p>"+str+"</p><br/>"); 10515 }, 10516 _readU32Int:function(ctx){ 10517 var val=0; 10518 var d=ctx.d; 10519 val=((d.charCodeAt(ctx.p++)<<24)|(d.charCodeAt(ctx.p++)<<16)|(d.charCodeAt(ctx.p++)<<8)|(d.charCodeAt(ctx.p++)))>>>0; 10520 return val; 10521 }, 10522 _readChunkType:function(ctx){ 10523 var d = ctx.d; 10524 var str = d[ctx.p++]+d[ctx.p++]+d[ctx.p++]+d[ctx.p++]; 10525 return str; 10526 }, 10527 _makeReadOnly:function(b64data){ 10528 slf._start("_makeReadOnly"); 10529 // assume a valid png image encoded in base64; 10530 var bindata = slf._atob(b64data.replace(/\s+/g, '')); // remove white spaces that might have been inserted 10531 var pngctx={p:0,d:bindata}; 10532 pngctx.p+=8;// skip pngheader 10533 // read IHDR 10534 var size = slf._readU32Int(pngctx); 10535 slf._readChunkType(pngctx); //IHDR 10536 pngctx.p+=size; //Data 10537 slf._readU32Int(pngctx);//CRC 10538 var metadataChunk = slf._prepareTextChunk(slf._LC_Scribble_MetaDataKey+String.fromCharCode(0)+"true"); 10539 var newdata = pngctx.d.substring(0,pngctx.p)+metadataChunk+pngctx.d.substring(pngctx.p); 10540 var ret= slf._btoa(newdata); 10541 slf._end(); 10542 return ret; 10543 }, 10544 _atob:function(inp){ 10545 if(window.atob){ return atob(inp); } 10546 return Base64.decode(inp); 10547 }, 10548 _btoa:function(inp){ 10549 if(window.btoa){ return btoa(inp); } 10550 return Base64.encode(inp); 10551 }, 10552 _isReadOnly:function(b64data){ 10553 slf._start("_isReadOnly"); 10554 if(slf._isPng(b64data)){ 10555 var testStr = slf._LC_Scribble_MetaDataKey+String.fromCharCode(0)+"true"; 10556 var bindata = slf._atob(b64data.replace(/\s+/g, ''));
10556 // strip white spaces 10557 var pngctx={p:0,d:bindata}; 10558 pngctx.p+=8;// skip header 10559 while(pngctx.p<pngctx.d.length){ 10560 var size = slf._readU32Int(pngctx); 10561 var type = slf._readChunkType(pngctx); 10562 if(type=="tEXt"){ 10563 if(pngctx.d.indexOf(testStr,pngctx.p)==pngctx.p){ 10564 slf._end(); 10565 return true; 10566 } 10567 10568 } 10569 pngctx.p+=size; 10570 slf._readU32Int(pngctx);// 10571 }// while end 10572 } 10573 slf._end(); 10574 return false; 10575 } 10576 }; 10577 return slf; 10578})(); 10579 10580/** 10581 * JQuery widget definition starts here 10582 */ 10583$.widget( "xfaWidget.ScribbleImageField", $.xfaWidget.imageField, { 10584 10585 _widgetName:"ScribbleImageField", 10586 _geoLocQuery:null, 10587 _emptyImageVal:null,// should be null, but for now 10588 _extraInfo:null, 10589 _defaultStatus:" ", 10590 _enforceGeoLoc:!!navigator.userAgent.match(/iPad/i), 10591 _sigCanvasWidth:696, 10592 _sigCanvasHeight:390, 10593 _geoCanvId:null, 10594 _geoLocAtBottom:false, 10595 _geoCanvasHeight:100, 10596 _geoCanvasWidth:696, 10597 10598 _is_readonly:false, 10599 10600 options: { 10601 tabIndex: 0, 10602 "role": "img" 10603 }, 10604 10605 getOptionsMap: function() { 10606 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this,arguments); 10607 return $.extend({},parentOptionsMap,{ 10608 "displayValue": function(val) { 10609 if(this.options.commitProperty) { 10610 if(!val){ 10611 this._displayValue(this._extractData(this._createEmptyImageData())); 10612 this.$userControl.addClass("emptyScribble"); 10613 this._is_readonly=false; 10614 } else { 10615 this.$userControl.removeClass("emptyScribble"); 10616 if(PNGUtil._isPng(val)){ 10617 var widgetValue = "data:image/png;base64,"+this.options.value; 10618 }else { 10619 var widgetValue = "data:;base64," + this.options.value; 10620 } 10621 this._setValue(widgetValue); 10622 } 10623 } 10624 } 10625 }) 10626 }, 10627 10628 getEventMap: function() { 10629 var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getEventMap.apply(this,arguments); 10630 return $.extend({},parentOptionsMap,{ 10631 "scribblefocus":xfalib.ut.XfaUtil.prototype.XFA_ENTER_EVENT, 10632 "click":null, 10633 "scribbleclick":xfalib.ut.XfaUtil.prototype.XFA_CLICK_EVENT, 10634 "change":null, 10635 "scribblechange":xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT, 10636 "blur":null, 10637 "scribbleclose":xfalib.ut.XfaUtil.prototype.XFA_EXIT_EVENT 10638 }) 10639 }, 10640 10641 /** 10642 * This function achieves following 10643 * 1. Calculate dimensions of canvases to be used 10644 * 2. Findout if right or bottom canvas is to be used for geo location 10645 */ 10646 10647 aspectRatioToBeUsed :function(){ 10648 var aspectRatio ; 10649 if(this.options.aspectRatio && parseFloat(this.options.aspectRatio) > 0){ 10650 aspectRatio = 1/parseFloat(this.options.aspectRatio); //--in MF ratio is computed as height/width instead of width/height 10651 } else { 10652 var imgEl = this.element.children("img"), 10653 width = imgEl.attr('width'), 10654 height = imgEl.attr('height'), 10655 fieldWidth, 10656 fieldHeight; 10657 10658 if(width){ 10659 fieldWidth = parseInt(width,10); 10660 } else { 10661 fieldWidth = imgEl.width(); 10662 } 10663 if(height){ 10664 fieldHeight = parseInt(height,10); 10665 } else { 10666 fieldHeight = imgEl.height(); 10667 } 10668 aspectRatio = fieldHeight/fieldWidth; 10669 } 10670 return aspectRatio; 10671 }, 10672 10673 _setUpCanvas:function(){ 10674 var aspectRatio ; 10675 aspectRatio = this.aspectRatioToBeUsed(); 10676 10677 // max width, height of generated image 10678 var maxWidth = 640; 10679 var maxHeight = 480; 10680 10681 // width of field scaled to fit max image size 10682 var scaledWidth; 10683 var scaledHeight; 10684 10685 10686 // approx pixels required for rendering geo loc info in 12pt Arial font 10687 var approxGeoLocWidth=250; 10688 var approxGeoLocHeight=84; 10689 10690 scaledWidth = maxWidth; 10691 scaledHeight = maxWidth*aspectRatio; 10692 if(scaledHeight>maxHeight){ 10693 scaledHeight = maxHeight; 10694 scaledWidth = maxHeight/aspectRatio; 10695 } 10696 10697 // set canvas dimensions 10698 if(aspectRatio>=1){ 10699 this._geoCanvId='iEBox_geoCanvasBottom'; 10700 this._geoLocAtBottom=true; 10701 10702 10703 this._geoCanvasWidth = scaledWidth; 10704 // limit height to 30% of full height; 10705 this._geoCanvasHeight=Math.min(approxGeoLocHeight,scaledHeight/3);
10706 this._sigCanvasWidth = scaledWidth; 10707 this._sigCanvasHeight= scaledHeight-(this._enforceGeoLoc?this._geoCanvasHeight:0); 10708 } else { 10709 this._geoCanvId='iEBox_geoCanvasRight'; 10710 this._geoLocAtBottom=false; 10711 10712 10713 this._geoCanvasHeight = scaledHeight; 10714 // limit width to 30% of full width; 10715 this._geoCanvasWidth=Math.min(approxGeoLocWidth,scaledWidth/3); 10716 this._sigCanvasHeight= scaledHeight; 10717 this._sigCanvasWidth= scaledWidth-(this._enforceGeoLoc?this._geoCanvasWidth:0); 10718 } 10719 10720 }, 10721 10722 render : function() { 10723 var geoLocMandatoryOnIpad = this.options.geoLocMandatoryOnIpad; 10724 if(typeof(geoLocMandatoryOnIpad)!="undefined"){ 10725 this._enforceGeoLoc= this._enforceGeoLoc && (/^(true|1)$/i).test($.trim(geoLocMandatoryOnIpad)); 10726 } 10727 this._wgtId="wid"+~~(Math.random()*2000)+"_"+new Date().getTime(); 10728 10729 var $control = $.xfaWidget.defaultWidget.prototype.render.apply(this, arguments) 10730 10731 if(this.options.value || this.options.value != this._emptyImageVal){ 10732 this._is_readonly=!!PNGUtil._isReadOnly(this.options.value); 10733 } 10734 10735 if(this._is_readonly){ 10736 $control.after("<div id='"+this._wgtId+"' class='sc_popUpMenu'></div>"); 10737 } else { 10738 $control.after("<div id='"+this._wgtId+"' style='display:none;' class='sc_popUpMenu'></div>"); 10739 } 10740 10741 this._setUpCanvas(); 10742 return $control; 10743 }, 10744 10745 click: function() { 10746 this.focus(); 10747 var tmpEl = this.element.length?this.element[0]:this.element; 10748 if(this.options.access != "open") 10749 return; 10750 if (TouchUtil.POINTER_ENABLED || TouchUtil.TOUCH_ENABLED) { 10751 // simulate a click event 10752 tmpEl.dispatchEvent(TouchUtil.getPointerEvent(TouchUtil.POINTER_DOWN)); 10753 tmpEl.dispatchEvent(TouchUtil.getPointerEvent(TouchUtil.POINTER_UP)); 10754 } 10755 else { 10756 this.$userControl.triggerHandler("click"); 10757 } 10758 }, 10759 10760 _attachEventHandlers:function($control){ 10761 if(TouchUtil.POINTER_ENABLED || TouchUtil.TOUCH_ENABLED){ 10762 this._attachTouchEventHandlers($control); 10763 } else { 10764 this._attachMouseEventHandlers($control); 10765 } 10766 $control.keydown($.proxy(this._handleKeyDown,this)); 10767 }, 10768 _attachEventHandlerForCrossIcon:function($control){ 10769 var _that = this; 10770 $control.mouseenter(function(event){ 10771 if(_that.options.access != "open") 10772 return; 10773 event.stopPropagation(); 10774 if(_that._is_readonly){ 10775 $('#'+_that._wgtId).css({display:'block'}); 10776 var bodyMoveHandler; 10777 $('body').on('mousemove',bodyMoveHandler=function(event){ 10778 if(event.target!=$('#'+_that._wgtId)[0]&&event.target!=_that.$userControl[0]){ 10779 $('#'+_that._wgtId).css({display:'none'}); 10780 $('body').off('mousemove',bodyMoveHandler); 10781 } 10782 }); 10783 } 10784 }); 10785 10786 setTimeout(function(){ $("#"+_that._wgtId).click($.proxy(_that._onCrossClick,_that));},50); 10787 }, 10788 _attachTouchEventHandlers:function($control){ 10789 var _timer,_that=this; 10790 var tmpEl = this.element.length?this.element[0]:this.element; 10791 tmpEl.addEventListener(TouchUtil.POINTER_DOWN,function(event){ 10792 if(_that.options.access != "open") 10793 return; 10794 event.preventDefault(); 10795 _timer = setTimeout(function(){ 10796 _timer=0; 10797 _that._onCrossClick(event); 10798 },1000); 10799 }); 10800 tmpEl.addEventListener(TouchUtil.POINTER_UP,function(event){ 10801 if(_that.options.access != "open") 10802 return; 10803 event.preventDefault(); 10804 if(_timer){ 10805 clearTimeout(_timer); 10806 _that._onImageClick(event); 10807 } 10808 }); 10809 10810 if(TouchUtil.POINTER_ENABLED){ 10811 this._attachEventHandlerForCrossIcon($control); 10812 setTimeout(function(){ $("#"+_that._wgtId).on(TouchUtil.POINTER_UP,function(event){ 10813 event.stopPropagation(); 10814 });},50); 10815 } 10816 }, 10817 10818 _attachMouseEventHandlers:function($control){ 10819 var _timer=0,_that=this,_hoverTimer=0; 10820 $control.dblclick(function(event){ 10821 if(_that.options.access != "open") 10822 return; 10823 event.preventDefault();event.stopPropagation(); 10824 if(_timer.val){ 10825 clearTimeout(_timer);_timer =0; 10826 } 10827 _that._onCrossClick(event); 10828 }).click(function(event){ 10829 _that.$userControl.trigger("scribbleclick",event); 10830 if(_that.options.access != "open") 10831 return; 10832 event.preventDefault(); 10833 event.stopPropagation(); 10834 if(_timer){ 10835 clearTimeout(_timer);_timer=0; 10836 } else { 10837 _timer = setTimeout(function(){ 10838 _timer=0; 10839 _that._onImageClick(event); 10840 },500); 10841 } 10842 }); 10843 10844 this._attachEventHandlerForCrossIcon($control); 10845 10846 }, 10847 10848 _onCrossClick:function(event){ 10849 if(!this._is_readonly) return; 10850 this.$userControl.trigger("scribblefocus",event); 10851 this.$userControl.trigger("scribbleclick",event); 10852 event.stopPropagation(); 10853 $.alertBox.yesNo(null, 10854 this.localeStrings().clearSignatureConfirm, 10855 this.localeStrings().clearSignature, 10856 $.proxy(this._removeSigConfirmationHandler,this)); 10857 }, 10858 10859 _removeSigConfirmationHandler:function(isYes){ 10860 if(isYes){ 10861 this._saveValue(this._emptyImageVal); 10862 this._displayValue(this._extractData(this._createEmptyImageData())); 10863 this.$userControl.addClass("emptyScribble").trigger("scribbleclose",{}); 10864 this._is_readonly=false; 10865 } 10866 }, 10867 10868 _createEmptyImageData:function(){ 10869 if(!this._emptyImageData){ 10870 var emptyCanvasObj = document.createElement('canvas');
10871 emptyCanvasObj.style.width=this._sigCanvasWidth+'px'; 10872 emptyCanvasObj.style.height=this._sigCanvasHeight+'px'; 10873 emptyCanvasObj.width=this._sigCanvasWidth; 10874 emptyCanvasObj.height=this._sigCanvasHeight; 10875 var ctx = emptyCanvasObj.getContext('2d'); 10876 ctx.fillStyle='#ffffff'; 10877 ctx.clearRect(0,0,this._sigCanvasWidth,this._sigCanvasHeight); 10878 this._emptyImageData = emptyCanvasObj.toDataURL("image/png"); 10879 } 10880 return this._emptyImageData; 10881 }, 10882 10883 getCommitValue: function() { 10884 return this.options.value 10885 }, 10886 10887 _saveValue:function(val){ 10888 this.options.value=val; 10889 this.$userControl.trigger('scribblechange'); 10890 }, 10891 10892 _displayValue:function(val){ 10893 if(this.options.commitProperty) { 10894 //hardcode the widget VALUE by unknown image type 10895 if(val){ 10896 var widgetValue = "data:image/png;base64,"+val; 10897 this._setValue(widgetValue); 10898 } 10899 } 10900 else 10901 this.logger().debug("xfaView","[DefaultWidget._update], User Control or Commit Property is null" ); 10902 }, 10903 10904 _doOk:function(){ 10905 var mainCanvas = document.createElement('CANVAS'); 10906 var geoCnv = $('#'+this._geoCanvId)[0]; 10907 var sigCnv = $('#iEBox_canvas')[0]; 10908 var ctx = mainCanvas.getContext('2d'); 10909 10910 if(geoCnv.width>0&&geoCnv.height>0){ 10911 10912 if(this._geoLocAtBottom){ 10913 mainCanvas.width=sigCnv.width; 10914 mainCanvas.height =sigCnv.height+geoCnv.height; 10915 ctx.drawImage(sigCnv,0,0); 10916 ctx.drawImage(geoCnv,0,sigCnv.height); 10917 } else { 10918 mainCanvas.width=sigCnv.width+geoCnv.width; 10919 mainCanvas.height =sigCnv.height; 10920 ctx.drawImage(sigCnv,0,0); 10921 ctx.drawImage(geoCnv,sigCnv.width,0); 10922 } 10923 } else { 10924 mainCanvas.width=sigCnv.width; 10925 mainCanvas.height =sigCnv.height; 10926 ctx.drawImage(sigCnv,0,0); 10927 } 10928 imageEditDialog.hide(); 10929 var newdata = mainCanvas.toDataURL("image/png");//(this.myScribbleHandle||"").toString(); 10930 10931 var val,val1; 10932 if((val=/*=*/this._extractData(newdata))){ 10933 // val1 = PNGUtil._makeReadOnly(val); 10934 val = PNGUtil._makeReadOnly(val); 10935 this._saveValue(val); 10936 this._is_readonly=true; 10937 } 10938 this._geoLocQuery&&this._geoLocQuery.cancel();// cancel current geo loc request; 10939 this.$userControl.trigger("scribbleclose") 10940 }, 10941 _handleOk:function(){ 10942 if(this._enforceGeoLoc){ 10943 this._geoLocQuery = new GeoLocQuery().init($.proxy(function(data){ 10944 this._geoQuerySuccessHandler(data); 10945 this._doOk(); 10946 },this),$.proxy(this._geoQueryErrorHandler,this)); 10947 this._geoLocQuery.query(); 10948 this._showMessage(this.localeStrings().fetchGeoLocation); 10949 } else { 10950 this._doOk(); 10951 } 10952 }, 10953 10954 _handleCancel:function(){ 10955 imageEditDialog.hide(); 10956 this._geoLocQuery&&this._geoLocQuery.cancel();// cancel current geo loc request; 10957 this.$userControl.trigger("scribbleclose") 10958 }, 10959 10960 _handleClear:function(){ 10961 this.myScribbleHandle.setEnabled(true); 10962 this._is_readonly=false; 10963 this._makeReadOnly(this._is_readonly); 10964 $('#iEBox_canvas')[0].width=this._sigCanvasWidth; 10965 $('#iEBox_caption').width(this._sigCanvasWidth); 10966 $('#iEBox_canvas')[0].height=this._sigCanvasHeight; 10967 $('#keyboard_Sign_Box')[0].value=""; 10968 var geoCanv = $('#'+this._geoCanvId)[0]; 10969 imageEditDialog.enableButtons({Ok:false,Clear:false}); 10970 geoCanv.width=0; 10971 geoCanv.height=0; 10972 imageEditDialog._resize(); 10973 this._geoLocQuery&&this._geoLocQuery.cancel();// cancel current geo loc request; 10974 }, 10975 _makeReadOnly:function(readonly){ 10976 imageEditDialog.enableButtons({Ok:false,Clear:false,Geo:!readonly,Brush:!readonly,Text:!readonly}); 10977 if(readonly){ 10978 $('#iEBox_canvas').css({border:'1px solid gray'}); 10979 $('#iEBox_caption').css({display:'none'}); 10980 10981 } 10982 this._defaultStatus = " "; 10983 this._showMessage(this._defaultStatus); 10984 }, 10985 10986 _showMessage:function(msg){ 10987 var _that = this; 10988 if(this._msgTimeout) { clearTimeout(this._msgTimeout); this._msgTimeout=0; } 10989 $("#iEBox_title").replaceWith('<div id="iEBox_title">'+msg+'</div>'); 10990 this._msgTimeout = window.setTimeout(function(){ 10991 $("#iEBox_title").replaceWith('<div id="iEBox_title">'+_that._defaultStatus+'</div>'); 10992 },15000); 10993 }, 10994 10995 _geoQueryErrorHandler:function(err){ 10996 this._showMessage(this.localeStrings().errorFetchGeoLocation); 10997 }, 10998
10999 _getLogMessage:function(key){ 11000 return this.logMsgs()[key]||key; 11001 }, 11002 11003 _handleGeo:function(){ 11004 // initiate geolocation 11005 if(navigator.geolocation){ 11006 this._geoLocQuery = new GeoLocQuery().init($.proxy(this._geoQuerySuccessHandler,this),$.proxy(this._geoQueryErrorHandler,this)); 11007 this._geoLocQuery.query(); 11008 this._showMessage(this.localeStrings().fetchGeoLocation); 11009 } else { 11010 this.logger().debug("xfaView",this._getLogMessage("ALC-FRM-901-011")); 11011 } 11012 }, 11013 11014 // This Function is used to fetch the geolocation. 11015 calculateGeolocation: function(){ 11016 this._handleGeo(); 11017 }, 11018 11019 _handleText:function(){ 11020 var signBoxEl=document.getElementById("keyboard_Sign_Box"); 11021 var signCanvasEl=document.getElementById("iEBox_canvas"); 11022 if(signBoxEl.value.length==0){ 11023 this._handleClear(); 11024 } 11025 this._disableSignatureCanvas(); 11026 this._enableSignatureTextBox(); 11027 signBoxEl.focus(); 11028 }, 11029 11030 _disableSignatureTextBox:function(){ 11031 document.getElementById("keyboard_Sign_Box").style.display = "none"; 11032 }, 11033 11034 _enableSignatureTextBox:function(){ 11035 document.getElementById("keyboard_Sign_Box").style.display = "inline-block"; 11036 }, 11037 11038 _disableSignatureCanvas:function(){ 11039 document.getElementById("iEBox_canvas").style.display = "none"; 11040 }, 11041 11042 _enableSignatureCanvas:function(){ 11043 document.getElementById("iEBox_canvas").style.display = "inline-block"; 11044 }, 11045 11046 _handleBrushSelect:function(w){ 11047 if(this.myScribbleHandle&&!this._is_readonly) { 11048 this.myScribbleHandle.setLineWidth(w); 11049 } 11050 }, 11051 11052 _handleBrush:function(evt){ 11053 if($('#keyboard_Sign_Box')[0].value.length>0){ 11054 this._handleClear(); 11055 } 11056 this._disableSignatureTextBox(); 11057 this._enableSignatureCanvas(); 11058 imageEditDialog.toggleBrushList(evt); 11059 }, 11060 _handleKeyDown:function(event){ 11061 if(event.keyCode == ENTER_KEY || event.charCode == ENTER_KEY || event.which == ENTER_KEY) { // touch devices may return charCode 11062 event.preventDefault(); 11063 this._onImageClick(event); 11064 } else if(event.keyCode == DELETE_KEY || event.charCode == DELETE_KEY || event.which == DELETE_KEY) { 11065 this._onCrossClick(event); 11066 } 11067 }, 11068 _dialogCallback:function(button_val,arg1){ 11069 // add back on click handler 11070 // this.$userControl.click($.proxy(this._onImageClick, this)); 11071 11072 switch(button_val){ 11073 case "Ok": 11074 this._handleOk(); 11075 break; 11076 case "Cancel": 11077 this._handleCancel(); 11078 break; 11079 case "Clear": 11080 this._handleClear(); 11081 break; 11082 case "Geo": 11083 this.calculateGeolocation(); 11084 break; 11085 case "BrushSelect": 11086 this._handleBrushSelect(arg1); 11087 break; 11088 case "Brush": 11089 this._handleBrush(arg1); 11090 break; 11091 case "Text": 11092 this._handleText(); 11093 break; 11094 11095 } 11096 }, 11097 11098 _geoQuerySuccessHandler:function(data){ 11099 this._renderPosition(data); 11100 }, 11101 11102 _fitGeoLocText:function(latStr,longStr,timeStr,ctx,maxWidth,maxHeight){ 11103 var fontSize=12; 11104 ctx.font="bold "+fontSize+"pt Arial"; 11105 var width = Math.max(ctx.measureText(latStr).width,ctx.measureText(longStr).width,ctx.measureText(timeStr).width); 11106 var lineHeight = ctx.measureText("m").width*1.5; 11107 while((width>maxWidth||3*lineHeight>maxHeight)&&fontSize>1){ 11108 fontSize--; 11109 ctx.font="bold "+fontSize+"pt Arial"; 11110 width = Math.max(ctx.measureText(latStr).width,ctx.measureText(longStr).width,ctx.measureText(timeStr).width); 11111 lineHeight = ctx.measureText("m").width*1.5; 11112 } 11113 return {width:width,lineHeight:lineHeight,fontSize:fontSize}; 11114 }, 11115 11116 _renderPosition:function(position){ 11117 if(position&&position.coords){ 11118 this._showMessage(" "); 11119 var latStr = this.localeStrings().latitude+": " + position.coords.latitude; 11120 var longStr = this.localeStrings().longitude+": " + position.coords.longitude; 11121 var dateObj = new Date(); 11122 var tZone = (dateObj.getTimezoneOffset()/60*-1); 11123 11124 var timeStr = this.localeStrings().time+": "+(dateObj.getMonth()+1)+"/"+dateObj.getDate()+"/"+dateObj.getFullYear()+" "+dateObj.getHours()+":"+dateObj.getMinutes()+":"+dateObj.getSeconds()+((tZone>0)?" +":" ")+(tZone); 11125 var canvasObj = $('#'+this._geoCanvId)[0];
11126 var sigCanvas = $('#iEBox_canvas')[0]; 11127 var sigTextBox = $('#keyboard_Sign_Box')[0]; 11128 var dummyCanvas = document.createElement('canvas'); 11129 if(canvasObj){ 11130 var ctx = canvasObj.getContext('2d'); 11131 ctx.font="bold 12pt Arial"; 11132 11133 canvasObj.width=this._geoCanvasWidth; 11134 canvasObj.height=this._geoCanvasHeight; 11135 var layout = this._fitGeoLocText(latStr,longStr,timeStr,ctx,canvasObj.width,canvasObj.height); 11136 var aspectRatio ; 11137 aspectRatio = this.aspectRatioToBeUsed(); 11138 if(!this._enforceGeoLoc){ 11139 if(this._geoLocAtBottom){ 11140 dummyCanvas.height = this._sigCanvasHeight-canvasObj.height; 11141 dummyCanvas.width = dummyCanvas.height/aspectRatio; 11142 } else { 11143 dummyCanvas.width = this._sigCanvasWidth-canvasObj.width; 11144 dummyCanvas.height = dummyCanvas.width*aspectRatio; 11145 } 11146 // move drawn signature to a temporary canvas and scale it to new dimension 11147 dummyCanvas.getContext('2d').drawImage(sigCanvas,0,0,dummyCanvas.width,dummyCanvas.height); 11148 if(this._geoLocAtBottom){ 11149 sigCanvas.height = dummyCanvas.height; 11150 sigTextBox.height = dummyCanvas.height; 11151 sigCanvas.getContext('2d').drawImage(dummyCanvas,(sigCanvas.width-dummyCanvas.width)/2,0); 11152 } else { 11153 sigCanvas.width = dummyCanvas.width; 11154 sigTextBox.width = dummyCanvas.width; 11155 sigCanvas.getContext('2d').drawImage(dummyCanvas,0,(sigCanvas.height-dummyCanvas.height)/2); 11156 } 11157 $('#iEBox_caption').width(sigCanvas.width); 11158 imageEditDialog.enableButtons({Clear:true}); 11159 } 11160 11161 var fwidth = layout.width; 11162 var fheight = layout.lineHeight; 11163 var bottomMargin=2; 11164 ctx.fillStyle='#555555'; 11165 ctx.font="bold "+layout.fontSize+"pt Arial"; 11166 ctx.fillText(latStr,0,canvasObj.height-2*fheight-bottomMargin); 11167 ctx.fillText(longStr,0,canvasObj.height-fheight-bottomMargin); 11168 ctx.fillText(timeStr,0,canvasObj.height-bottomMargin); 11169 11170 imageEditDialog._resize(); 11171 } 11172 } 11173 }, 11174 _scribbleCallback:function(){ 11175 imageEditDialog.enableButtons({Clear:true,Ok:true}); // enable clear and ok buttons 11176 }, 11177 _onImageClick:function(){ 11178 if(!imageEditDialog.getIsOpen()){ 11179 var _that = this; 11180 imageEditDialog.show(" ",$.proxy(this._dialogCallback, this)); 11181 if(!this._enforceGeoLoc){ 11182 $('#iEBox_Geo').css({display:'inline-block'}); 11183 } 11184 var image = new Image(); 11185 image.onload=function(){ 11186 _that.myScribbleHandle = new Scribble("iEBox_canvas",image,image.width,image.height,$.proxy(_that._scribbleCallback,_that)); 11187 _that.myScribbleHandle.setEnabled(!_that._is_readonly); 11188 $('#iEBox_caption').width(image.width); 11189 $('#iEBox_container').css({display:'table'}); 11190 if($('#iEBox_container').length == 1){ 11191 $('#iEBox_container')[0].focus(); 11192 } 11193 imageEditDialog._resize(); 11194 imageEditDialog._reposition(); // recalculate position, so that the values are updated, esp. in iPad 11195 } 11196 if(!this.options.value||this.options.value==this._emptyImageVal){ 11197 this._is_readonly=false; 11198 this.$userControl.addClass("emptyScribble"); 11199 image.src = this._createEmptyImageData(); 11200 } else { 11201 this.$userControl.removeClass("emptyScribble"); 11202 if(PNGUtil._isPng(this.options.value)){ 11203 this._is_readonly = !!PNGUtil._isReadOnly(this.options.value); 11204 image.src = "data:image/png;base64,"+this.options.value;//this.createBl _that.$userControl.attr(_that.options.commitProperty); 11205 } else { 11206 image.src = "data:;base64," + this.options.value;//this.createBl _that.$userControl.attr(_that.options.commitProperty); 11207 } 11208 } 11209 this._makeReadOnly(this._is_readonly); 11210 } 11211 }, 11212 11213 _extractData:function(datauri){ 11214 var idx; 11215 if(datauri!=null&&datauri.length>0&&datauri.indexOf("data:")==0){ 11216 if((idx=datauri.indexOf(","))>0){ 11217 return datauri.substr(idx+1); 11218 } 11219 } 11220 }, 11221 11222 _setValue:function(val){ 11223 this.$userControl.prop(this.options.commitProperty, val); 11224 this.$userControl.attr(this.options.commitProperty, val); 11225 if(this._dummyImg){ 11226 this._dummyImg.setAttribute(this.options.commitProperty,val); 11227 } 11228 } 11229}); 11230 //hack for IOS5 touch bug 11231 $(function(){ 11232 $('body').on('touchstart', function(e) {}); 11233 }); 11234 11235})($,xfalib); 11236(function ($, window, _) { 11237 11238 var _defaults = { 11239 placeHolderText : "Enter comments here" 11240 }; 11241 11242 var AdobeFileAttachment = function (element, options) { 11243 this.options = options; 11244 this.$elementFileUploadBtn = []; 11245 this.$elementFileList = []; 11246 this.$element = $(element); 11247 if (this.$element.attr("multiple") && !xfalib.ut.Utilities._isDataContainerSupported()) { 11248 // remove multiple attribute if multi file selection in one go is not supported 11249 this.$element.removeAttr("multiple"); 11250 } 11251 this.$parent = this.$element.parent(); 11252 this.invalidFeature = { 11253 "SIZE":1, 11254 "NAME":2, 11255 "MIMETYPE":3 11256 }; 11257 Object.freeze(this.invalidFeature); 11258 // initialize the regex initially 11259 this.regexMimeTypeList = this.options.mimeType.map(function (value, i) { 11260 try { 11261 return new RegExp(value.trim()); 11262 } catch (e) { 11263 // failure during regex parsing, don't return anything specific to this value since the value contains 11264 // incorrect regex string 11265 if(window.console) { 11266 console.log(e); 11267 } 11268 } 11269 }); 11270 }; 11271 11272 var isBrowserIE9OrIE10 = ($.browser.msie && ($.browser.version === '9.0' || $.browser.version === '10.0')), 11273 fileLabelsCount = 0; 11274 11275 11276 AdobeFileAttachment.prototype = { 11277 _fileIframeName : "guide-fu-iframe", 11278 _addFile : "Add File", 11279 11280 clear: function () { 11281 this.$element.val(''); 11282 this.$elementFileList.empty(); 11283 }, 11284 11285 destroy: function () { 11286 this.$fileDomElements = $.map(this.$fileDomElements, function(item){ 11287 // since item can be null or object, doing this check 11288 if(_.isObject(item) && item.val().length === 0) { 11289 //TODO: remove item from dom, since there is a memory leak 11290 return item; 11291 } 11292 }); 11293 this.values = []; 11294 if(isBrowserIE9OrIE10){ 11295 if(_.last(this.$fileDomElements) == null){ 11296 this.cloneFileInputAndUpdateIdForIE9(); 11297 } else { 11298 this.updateLabelForAttr(_.last(this.$fileDomElements).attr("id")); 11299 } 11300 } 11301 this.$element.trigger("change.fileupload"); 11302 }, 11303 11304 _setUrl : function(url, index){ 11305 this.$elementFileList.find("span.guide-fu-fileName").eq(index).data("key", url); 11306 }, 11307 11308 _getUrl : function(index) { 11309 return this.$elementFileList.find("span.guide-fu-fileName").eq(index).data("key"); 11310 }, 11311 getSetFilePathAndReturnNamePathMap: function(valueList) { 11312 11313 var mapOfObjectsHavingTempPathAndFileNames = {}, 11314 $temp, 11315 tempPath; 11316 11317 $.each(this.$elementFileList.children(), function ( index, childLiElement) { 11318 $temp = $(childLiElement).find("span.guide-fu-fileName"); 11319 tempPath = $temp.data("key"); 11320 if(!tempPath && valueList && valueList[index]) { 11321 $temp.data("key", valueList[index]); 11322 } 11323 mapOfObjectsHavingTempPathAndFileNames[$temp.html()] = tempPath || $temp.data("key"); 11324 }); 11325 return mapOfObjectsHavingTempPathAndFileNames; 11326 }, 11327 11328 11329 value : function(value) { 11330 if(!_.isUndefined(value)) { 11331 var _self = this, 11332 comments = this.comment(), 11333 isChange = false, 11334 fileNames = _.isArray(this.options.fileNames) ? this.options.fileNames : null, 11335 oldUrls = {};
11336 // Cache the url before deletion 11337 this.$elementFileList.children().find("span.guide-fu-fileName").each(function(){ 11338 var url = $(this).data("key"); 11339 if(!_.isUndefined(url)){ 11340 var fileName = url.substring(url.lastIndexOf("/") + 1); 11341 oldUrls[fileName] = url; 11342 } 11343 }); 11344 this.$elementFileList.empty(); 11345 if(value != null) { 11346 var arr = value.split("\n"); 11347 // contruct initial file name and value map 11348 // this is done only once in entire live cycle, its done here, since we get value here 11349 if (fileNames && _.isEmpty(this._initialFileValueFileNameMap)) { 11350 for (var index = 0; index < fileNames.length; index++) { 11351 _self._initialFileValueFileNameMap[arr[index]] = fileNames[index] 11352 } 11353 } 11354 // Update the value array with the file 11355 this.values = _.map(arr, function(fileName, index){ 11356 // Check if file Name is a path, if yes get the last part after "/" 11357 var slash = fileName.lastIndexOf("/"), 11358 fileUrl = fileName, 11359 fileUploadUrl = null; 11360 if(slash !== -1) { 11361 // Store the cached url here 11362 fileUrl = fileUploadUrl = fileName; 11363 fileName = fileName.substring(slash + 1); 11364 // case: when you click on save second time 11365 if((_.isObject(_self.$fileDomElements[index]) && _self.$fileDomElements[index].val().length > 0) || _.isString(_self.$fileDomElements[index])){ 11366 isChange = true; 11367 _self.$fileDomElements[index] = null; 11368 } else if(_self.$fileDomElements[index] !== null) { // create a dummy file dom for the cached value 11369 isChange = true; 11370 _self.$fileDomElements.splice(index, 0, null); 11371 } 11372 } else if (oldUrls[fileName]) { 11373 fileUploadUrl = oldUrls[fileName]; 11374 } 11375 // if fileNames options is explicitly passed, use it 11376 if (fileNames && _self._initialFileValueFileNameMap[fileUrl]) { 11377 fileName = _self._initialFileValueFileNameMap[fileUrl]; 11378 } 11379 _self.showFileList(fileName, comments[index], fileUploadUrl); 11380 return fileUrl; 11381 }); 11382 if(isChange){ 11383 this.$element.trigger("change.fileupload"); 11384 } 11385 } else { 11386 if(_.isArray(this.values) && this.values.length !== 0){ 11387 this.destroy(); 11388 } 11389 } 11390 } 11391 else { 11392 return this.values; 11393 } 11394 }, 11395 11396 fileAttachment: function(){ 11397 return this.values; 11398 }, 11399 11400 comment : function(value){ 11401 var _self = this, 11402 $elem = null, 11403 comments; 11404 if (!_.isUndefined(value)) { 11405 if(value != null) { 11406 comments = value.split("\n"); 11407 $elem = this.$elementFileList.find('div.guide-fu-comment'); 11408 $elem.each(function(index){ 11409 $(this).text(comments[index]); 11410 }); 11411 } 11412 } 11413 else { 11414 $elem = this.$elementFileList.find('div.guide-fu-comment'); 11415 comments = []; 11416 $elem.each(function(){ 11417 comments.push($(this).text()); 11418 }); 11419 return comments; 11420 } 11421 }, 11422 11423 multiSelect : function(value){ 11424 if(value !== undefined) 11425 this.options.multiSelect = value; 11426 else 11427 return this.options.multiSelect; 11428 }, 11429 11430 fileSizeLimit : function(value){ 11431 if(value !== undefined) 11432 this.options.fileSizeLimit = value; 11433 else 11434 return this.options.fileSizeLimit; 11435 }, 11436 11437 mimeType : function(value){ 11438 if(value !== undefined) 11439 this.options.mimeType = value; 11440 else 11441 return this.options.mimeType; 11442 }, 11443 11444 access : function(value){ 11445 if(value == "readOnly") { 11446 this.$element.attr("disabled", "disabled"); 11447 //for readOnly hide the delete icon in file list
11448 $(this.$parent).addClass('guide-fu-disabled'); 11449 } 11450 else if(value == "open") { 11451 this.$element.removeAttr("disabled"); 11452 $(this.$parent).removeClass('guide-fu-disabled'); 11453 } 11454 }, 11455 11456 fileList : function(value) { 11457 var filtered, 11458 _self = this; 11459 if(value !== undefined){ 11460 this.$fileDomElements = []; 11461 _.each(value, function(item, index){ 11462 if((_.isObject(item) && (isBrowserIE9OrIE10 || item.val().length > 0)) || (_.isString(item))){ 11463 // check if index is within the length 11464 // this is written for delete case 11465 // if item is a string, then it should be set null 11466 if(_.isString(item)){ 11467 item = null; 11468 } 11469 _self.$fileDomElements[index] = item; 11470 } 11471 }); 11472 filtered = this.$fileDomElements; 11473 // In case of IE9, get the last element of fileDom and update the id for label 11474 if(isBrowserIE9OrIE10 && value !== null){ 11475 // Case: if it is single select, and then we do a restore and then after attaching another file we click save 11476 if(_.last(this.$fileDomElements) == null){ 11477 this.cloneFileInputAndUpdateIdForIE9(); 11478 } else { 11479 this.updateLabelForAttr(_.last(this.$fileDomElements).attr("id")); 11480 } 11481 } 11482 } 11483 else { 11484 // here filtered is a new array 11485 // A new array is returned over here so that the user of this API doesn't try to change the widget array directly 11486 filtered = $.map(this.$fileDomElements, function(item, index){ 11487 if(!item) { 11488 return _self._getUrl(index); 11489 } else if((item[0].files && item[0].files.length !== 0) 11490 || (_self.options.multiSelect || item[0].value.length > 0)) { 11491 return item; 11492 } 11493 }); 11494 } 11495 return filtered; 11496 }, 11497 11498 // file preview html 11499 fileItemPreview: function(){ 11500 return $("<span></span>").addClass("guide-fu-filePreview glyphicon glyphicon-ok"); 11501 }, 11502 11503 // force flag indicates that forcefully set the dom but don't update the options 11504 buttonText: function (value, force) { 11505 if (value !== undefined) { 11506 if(!force) 11507 this.options.buttonText = value; 11508 this.$elementFileUploadBtn.find('span.guide-fu-label').html(value); 11509 } else { 11510 return this.options.buttonText; 11511 } 11512 }, 11513 11514 // To change the icon of the button, the user should customize the class 11515 btnIcon: function () { 11516 return $("<span></span>").addClass("guide-fu-icon glyphicon glyphicon-folder-open"); 11517 }, 11518 11519 btnLabel: function(){ 11520 return $("<span></span>").addClass("guide-fu-label").html(this.options.buttonText); 11521 }, 11522 11523 fileItemList: function(){ 11524 return this.$parent.find(this.options.fileItemListClass); 11525 }, 11526 11527 getNewCommentElementSummary : function(text){ 11528 return $("<div title='Click to edit' tabindex='0'></p>").addClass("guide-fu-comment").text(text || _defaults.placeHolderText); 11529 }, 11530 11531 getNewCommentElement : function(text){ 11532 return $("<div contenteditable='true' tabindex='0'></div>").addClass("guide-fu-comment").text(text || ""); 11533 }, 11534 11535 fileItem: function(fileName, comment, fileUrl){ 11536 var $fileItem = $("<li></li>").addClass("guide-fu-fileItem"); 11537 var nameWithoutMarker = xfalib.ut.Utilities._getNameWithoutMarker(fileName); 11538 var $elem = $("<span tabindex='0'></span>").addClass("guide-fu-fileName").attr("aria-label", nameWithoutMarker).text(nameWithoutMarker).appendTo($fileItem).keypress(function(e) { 11539 if (e.keyCode === 13 || e.charCode === 32) { 11540 $(e.target).click(); 11541 } 11542 }).click($.proxy(this.handleFilePreview, this)); 11543 if(this.options.disablePreview) { 11544 $elem.addClass('non-preview-fileName'); 11545 } 11546 if(fileUrl != null){ 11547 $elem.attr("data-key", fileUrl); 11548 } 11549 $("<span tabindex='0'></span>").addClass("guide-fu-fileClose close").attr("role", "button").attr("aria-label", xfalib.locale.Strings.FileCloseAccessText
11549+ nameWithoutMarker).text("x").appendTo($fileItem).keypress(function(e) { 11550 if (e.keyCode === 13 || e.charCode === 32) { 11551 $(e.target).click(); 11552 } 11553 }) 11554 .click($.proxy(this.handleClick, this)); 11555 11556 this.fileItemPreview().appendTo($fileItem); 11557 11558 if(this.options.showComment){ 11559 this.getNewCommentElementSummary(comment).appendTo($fileItem).focus($.proxy(this.handleCommentClick, this)).click($.proxy(this.handleCommentClick, this)); 11560 } 11561 return $fileItem; 11562 }, 11563 11564 toggleFileUploadBtn: function(){ 11565 if(this.options.multiSelect) { 11566 // Change the look of file upload button 11567 if(this.$elementFileList.children().length > 0){ 11568 // Change the text 11569 this.buttonText(this._addFile, true); 11570 // Change the icon too 11571 this.$elementFileUploadBtn.find('span.guide-fu-icon').removeClass("glyphicon-folder-open").addClass("glyphicon-plus"); 11572 } else { 11573 this.buttonText(this.options.buttonText); 11574 this.$elementFileUploadBtn.find('span.guide-fu-icon').removeClass("glyphicon-plus").addClass("glyphicon-folder-open"); 11575 } 11576 } 11577 }, 11578 11579 showInvalidMessage: function(fileName, invalidFeature){ 11580 var that = this; 11581 var IS_IPAD = navigator.userAgent.match(/iPad/i) !== null, 11582 IS_IPHONE = (navigator.userAgent.match(/iPhone/i) !== null); 11583 if(IS_IPAD || IS_IPHONE){ 11584 setTimeout(function() { 11585 that.invalidMessage(that,fileName, invalidFeature); 11586 }, 0); 11587 } 11588 else { 11589 this.invalidMessage(this,fileName, invalidFeature); 11590 } 11591 }, 11592 11593 invalidMessage: function(refObj,fileName, invalidFeature){ 11594 if(invalidFeature === refObj.invalidFeature.SIZE) { 11595 alert(xfalib.ut.LocalizationUtil.prototype.getLocalizedMessage("", xfalib.locale.Strings["FileSizeGreater"], [fileName, refObj.options.fileSizeLimit])); 11596 } else if (invalidFeature === refObj.invalidFeature.NAME) { 11597 alert(xfalib.ut.LocalizationUtil.prototype.getLocalizedMessage("", xfalib.locale.Strings["FileNameInvalid"], [fileName])); 11598 } else if (invalidFeature === refObj.invalidFeature.MIMETYPE) { 11599 alert(xfalib.ut.LocalizationUtil.prototype.getLocalizedMessage("", xfalib.locale.Strings["FileMimeTypeInvalid"], [fileName])); 11600 } 11601 }, 11602 11603 /*** 11604 * 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 11605 * This is done since our model stores the URL too in case of draft restore or clicking on save in guide 11606 * @param text string representing the text of which the index is to be found 11607 * @param $elem reference to the jquery element. This is used if there are duplicate file names present in the file upload. 11608 * @returns {number} 11609 * @private 11610 */ 11611 _getIndexOfText : function(text, $elem){ 11612 var index = -1, 11613 self = this, 11614 isDuplicatePresent = false; 11615 _.find(this.values, function(value, iter){ 11616 // if value is a url, then compare with last 11617 var tempValue = value, 11618 // can't use getOrElse here since value can have "." in URL and getOrElse splits based on period to find key inside object 11619 fileName = (_.isObject(self._initialFileValueFileNameMap) && typeof self._initialFileValueFileNameMap[value] !== undefined) ? self._initialFileValueFileNameMap[value] : null; 11620 if(tempValue.match(/\//g) && tempValue.match(/\//g).length > 1){ 11621 tempValue = value.substring(value.lastIndexOf("/")+1); 11622 tempValue = xfalib.ut.Utilities._getNameWithoutMarker(tempValue); 11623 } 11624 // we pass file name explicityly as options, if passed use that as fallback to find the URL 11625 if(tempValue === text || fileName === text){ 11626 index = iter; 11627 isDuplicatePresent = self.values.indexOf(value, index + 1) !== -1; 11628 if($elem && isDuplicatePresent){ 11629 // now check if duplicate present and get its correct index 11630 // today all files are wrapped under .guide-fu-fileItem node 11631 index = $elem.closest(".guide-fu-fileItem").index(); 11632 } 11633 // check if there is a duplicate 11634 // this is to just break the loop 11635 return value; 11636 } 11637 }); 11638 return index; 11639 }, 11640 11641 11642 /* 11643 * Since input file element might contain multiple files. 11644 * This function takes absolute file index as parameter & returns position of the file w.r.t input file elt 11645 */ 11646 _getFileObjIdx : function (index) { 11647 if (index >= 0) { 11648 var currentIdx = 0; 11649 for (var fileInputEltIdx = 0; fileInputEltIdx < this.$fileDomElements.length; fileInputEltIdx++) { 11650 if (this.$fileDomElements[fileInputEltIdx]) { 11651 var files = this.$fileDomElements[fileInputEltIdx][0].files; 11652 if (files) { 11653 var filesLength = files.length; 11654 if ( index <= currentIdx + filesLength - 1 ) { 11655 return [fileInputEltIdx, index - currentIdx]; 11656 } 11657 currentIdx+=files.length; 11658 } 11659 } else { 11660 if (index == currentIdx) { 11661 return [fileInputEltIdx,0]; 11662 } 11663 currentIdx++; 11664 } 11665 } 11666 } 11667 return null; 11668 }, 11669 11670 /* 11671 * This function returns FileList object of the passed file array 11672 */ 11673 _getFileListItem : function (files) { 11674 try { 11675 var dataContainer = new DataTransfer() || (new ClipboardEvent("")).clipboardData; 11676 _.each(files, function (file) { 11677 dataContainer.items.add(file); 11678 }); 11679 return dataContainer.files; 11680 } catch(err) { 11681 console.error(err); 11682 throw err; 11683 } 11684 }, 11685 11686 _updateFilesInDom : function($fileDom, files) { 11687 // in safari, a change event is trigged if files property is changed dynamically 11688 // hence adding this check to clear existing state only for safari browsers 11689 this._isFileUpdate = true; 11690 $fileDom[0].files = this._getFileListItem(files); 11691 this._isFileUpdate = false;
11692 }, 11693 11694 /* 11695 * This function deletes files at specified indexes from input dom elt 11696 */ 11697 _deleteFilesFromInputDom : function ($fileDomElt, deletedIndexes) { 11698 var remainingFiles = []; 11699 _.each($fileDomElt[0].files, function(file,idx){ 11700 if(!deletedIndexes.includes(idx)){ 11701 remainingFiles.push(file); 11702 } 11703 }); 11704 try { 11705 // in safari, a change event is trigged if files property is changed dynamically 11706 // hence adding this check to clear existing state only for safari browsers 11707 this._updateFilesInDom($fileDomElt, remainingFiles); 11708 } catch(err){ 11709 console.error("Deleting files is not supported in your browser"); 11710 } 11711 }, 11712 11713 /** 11714 * This event listener gets called on click of close button in file upload 11715 * 11716 * @param event 11717 */ 11718 handleClick: function(event){ 11719 11720 var $elem = $(event.target), 11721 text = $elem.prev().text(), 11722 index = this._getIndexOfText(text, $elem), 11723 url = $elem.prev().data("key"), 11724 objectUrl = $elem.prev().data("objectUrl"); 11725 if (index != -1) { 11726 this.values.splice(index, 1); 11727 var fileObjIdx = this._getFileObjIdx(index); 11728 var $fileDomElt = this.$fileDomElements[fileObjIdx[0]]; 11729 if (!$fileDomElt || $fileDomElt[0].files.length === 1) { 11730 this.$fileDomElements.splice(fileObjIdx[0], 1); 11731 } else { 11732 this._deleteFilesFromInputDom($fileDomElt, [fileObjIdx[1]]); 11733 } 11734 if (isBrowserIE9OrIE10) { 11735 this.cloneFileInputAndUpdateIdForIE9(); 11736 } 11737 if (url != null) { 11738 // remove the data so that others don't use this url 11739 $elem.prev().removeData("key"); 11740 } 11741 if(objectUrl) { 11742 // revoke the object URL to avoid memory leaks in browser 11743 // since file is anyways getting deleted, remove the object URL's too 11744 window.URL.revokeObjectURL(objectUrl); 11745 } 11746 } 11747 // Remove the dom from view 11748 //All bound events and jQuery data associated with the element are also removed 11749 $elem.parent().remove(); 11750 // trigger the change event to update the value 11751 this.$element.trigger("change.fileupload"); 11752 // Set the focus on file upload button after click of close 11753 this.$elementFileUploadBtn.focus(); 11754 11755 }, 11756 11757 11758 displaySVG: function (objectUrl) { 11759 const url = objectUrl; 11760 const img = window.document.createElement('img'); 11761 img.src = url; 11762 const newTab = window.open('', '_blank', 'scrollbars=no,menubar=no,height=600,width=800,resizable=yes,toolbar=no,status=no'); 11763 newTab.document.body.appendChild(img); 11764 }, 11765 11766 11767 _previewFileUsingObjectUrl : function (file) { 11768 if (file) { 11769 if (window.navigator && window.navigator.msSaveOrOpenBlob) { // for IE 11770 window.navigator.msSaveOrOpenBlob(file, file.name); 11771 } else { 11772 var url = window.URL.createObjectURL(file); 11773 if (file.type === 'image/svg+xml') { 11774 this.displaySVG(url); 11775 } else { 11776 window.open(url, '', 'scrollbars=no,menubar=no,height=600,width=800,resizable=yes,toolbar=no,status=no'); 11777 } 11778 return url; 11779 } 11780 } 11781 }, 11782 11783 // this function maintains a map for 11784 handleFilePreview: function(event){ 11785 if(!this.options.disablePreview) { 11786 var $elem = $(event.target), 11787 text = $elem.text(), 11788 index = this._getIndexOfText(text, $elem), 11789 fileDom = null, 11790 fileName = null, 11791 fileUrl = null, 11792 timeStamp = new Date().getTime(); 11793 11794 // for draft usecase, if text contains "/" in it, it means the file is already uploaded 11795 // text should contain the path, assuming that the fileUrl is stored in data element 11796 11797 if (index != -1) { 11798 // Store the url of file as data 11799 if(!_.isUndefined($elem.data("key"))) 11800 fileUrl = $elem.data("key"); 11801 11802 if(fileUrl) { 11803 //prepend context path if not already appended 11804 if (!(fileUrl.lastIndexOf(this.options._getUrl, 0) === 0)) { 11805 fileUrl = this.options._getUrl + fileUrl; 11806 } 11807 this.previewFile.apply(this, [null, {"fileUrl" : fileUrl}]); 11808 } else { 11809 var previewFileObjIdx = this._getFileObjIdx(index); 11810 var previewFile = this.$fileDomElements[previewFileObjIdx[0]][0].files[previewFileObjIdx[1]]; 11811 var objectUrl = this._previewFileUsingObjectUrl(previewFile); 11812 if (objectUrl) { 11813 $elem.data("objectUrl", objectUrl); 11814 } 11815 } 11816 } 11817 } 11818 }, 11819 11820 previewFile: function(event){ 11821 var url = null; 11822 if(_.isUndefined(arguments[1])) 11823 url = this.$element[this.options.uploaderPluginName]("getFileUrl"); 11824 else 11825 url = arguments[1].fileUrl; 11826 var lastIndex = url.lastIndexOf('/'); 11827 //to make sure url has a slash '/' 11828 if(lastIndex >= 0) { 11829 //encode the filename after last slash to ensure the handling of special characters 11830 url = url.substr(0, lastIndex) +'/'+ encodeURIComponent(url.substr(lastIndex + 1)); 11831 } 11832 // this would work for dataURl or normal URL 11833 // todo: add support to preview base 64 encoded image, to preview base64 encoded binary, we would probably need 11834 // todo: the content type in the widget too 11835 window.open(url, '', 'scrollbars=no,menubar=no,height=600,width=800,resizable=yes,toolbar=no,status=no'); 11836 11837 }, 11838 11839 resetIfNotMultiSelect: function(){ 11840 if(!this.options.multiSelect){ 11841 // Reset the value and file array 11842 this.values = []; 11843 //this.comments = []; 11844 } 11845 }, 11846 11847 showFileList: function(fileName, comment, fileUrl){ 11848 if(!this.options.multiSelect || fileName == null || _.isUndefined(fileName)) { 11849 // if not multiselect, remove all the children of file list 11850 this.$elementFileList.empty(); 11851 } 11852 11853 // Add the file item 11854 // On click of close, remove the element and update the model 11855 // handle on click of preview button 11856 if(fileName != null) {
11857 this.$fileItem = this.$elementFileList.append(this.fileItem(fileName, comment, fileUrl)); 11858 } 11859 }, 11860 11861 /** 11862 * Handles the click on comment field 11863 * 11864 * TODO: Implement show/hide behaviour instead of replaceWith 11865 * This may be cause problem during bubble up of event 11866 * 11867 * @param event 11868 */ 11869 handleCommentClick : function(event){ 11870 var $commentElem = null, 11871 $elem = $(event.target); 11872 if ($elem.text() === _defaults.placeHolderText) { 11873 $commentElem = this.getNewCommentElement() 11874 } else { 11875 $commentElem = this.getNewCommentElement($(event.target).text()); 11876 } 11877 $elem.replaceWith($commentElem); 11878 // register the event again 11879 if(isBrowserIE9OrIE10){ 11880 $commentElem.focus().focusout($.proxy(this.handleCommentBlur, this)); 11881 } else { 11882 $commentElem.focus().blur($.proxy(this.handleCommentBlur, this)); 11883 } 11884 }, 11885 11886 handleCommentBlur : function(event){ 11887 var $commentSummaryElem = null, 11888 $elem = $(event.target); 11889 if ($elem.text() === _defaults.placeHolderText) { 11890 $commentSummaryElem = this.getNewCommentElementSummary(); 11891 } else { 11892 $commentSummaryElem = this.getNewCommentElementSummary($(event.target).text()); 11893 } 11894 $elem.replaceWith($commentSummaryElem); 11895 $commentSummaryElem.focus($.proxy(this.handleCommentClick,this)).click($.proxy(this.handleCommentClick,this)); 11896 // Add a div with the html 11897 this.$element.trigger("change.fileupload"); 11898 }, 11899 11900 // checks if file name is valid or not to prevent security threats 11901 isValid : function(fname) { 11902 var rg1=/^[^\\/:\*\;\$\%\?"<>\|]+$/; // forbidden characters \ / : * ? " < > | ; % $ 11903 var rg2=/^\./; // cannot start with dot (.) 11904 var rg3=/^(nul|prn|con|lpt[0-9]|com[0-9])(\.|$)/i; // forbidden file names 11905 return rg1.test(fname) && !rg2.test(fname) && !rg3.test(fname); 11906 }, 11907 11908 handleChange: function (evnt) { 11909 if (!this._isFileUpdate) { 11910 var currFileName = '', 11911 inValidSizefileNames = '', 11912 inValidNamefileNames = '', 11913 inValidMimeTypefileNames = '', 11914 $elem = $(evnt.target), 11915 files = $elem[0].files; 11916 // Initially set the invalid flag to false 11917 // if not multiselect then remove the extra domELement clone 11918 if (!this.options.multiSelect && this.$fileDomElements.length > 1) { 11919 this.$fileDomElements.splice(0, 1) 11920 } 11921 11922 var isInvalidSize = false, 11923 isInvalidFileName = false, 11924 isInvalidMimeType = false;
11925 this.resetIfNotMultiSelect(); 11926 // Iterate through all the files 11927 if (isBrowserIE9OrIE10) { // IE9 doesn't support FileList, hence files variable is undefined 11928 currFileName = $elem.val().split("\\").pop(); 11929 //update the last element of array 11930 if (this.$fileDomElements.length > 0) { 11931 this.$fileDomElements[this.$fileDomElements.length - 1] = $elem; 11932 } 11933 this.cloneFileInputAndUpdateIdForIE9(); 11934 11935 // In case of IE9, only do this 11936 if (_.isUndefined(files)) { 11937 this.showFileList(currFileName); 11938 this.values.push(currFileName); 11939 // trigger the change event to update the value 11940 this.$element.trigger("change.fileupload"); 11941 } 11942 } 11943 if (!_.isUndefined(files)) { 11944 var invalidFilesIndexes = []; 11945 _.each(files, function (file, fileIndex) { 11946 var isCurrentInvalidFileSize = false, 11947 isCurrentInvalidFileName = false, 11948 isCurrentInvalidMimeType = false;
11949 currFileName = file.name.split("\\").pop(); 11950 // Now size is in MB 11951 var size = file.size / 1024 / 1024; 11952 // check if file size limit is within limits 11953 if ((size > parseFloat(this.options.fileSizeLimit))) { 11954 isInvalidSize = isCurrentInvalidFileSize = true; 11955 inValidSizefileNames = currFileName + "," + inValidSizefileNames; 11956 } else if (!this.isValid(currFileName)) { 11957 // check if file names are valid (ie) there are no control characters in file names 11958 isInvalidFileName = isCurrentInvalidFileName = true; 11959 inValidNamefileNames = currFileName + "," + inValidNamefileNames; 11960 } else if (file.type) { 11961 var isMatch = this.regexMimeTypeList.some(function (rx) { 11962 return rx.test(file.type); 11963 }); 11964 if (!isMatch) { 11965 isInvalidMimeType = isCurrentInvalidMimeType = true; 11966 inValidMimeTypefileNames = currFileName + "," + inValidMimeTypefileNames; 11967 } 11968 } 11969 11970 // if the file is not invalid, show it and push it to internal array 11971 if (!isCurrentInvalidFileSize && !isCurrentInvalidFileName && !isCurrentInvalidMimeType) { 11972 this.showFileList(currFileName); 11973 this.values.push(currFileName); 11974 } else { 11975 invalidFilesIndexes.push(fileIndex); 11976 } 11977 11978 11979 }, this); 11980 11981 if (invalidFilesIndexes.length > 0) { 11982 var currentFileDomIndex, 11983 $currentFileDomElement, 11984 filesCount; 11985 if (this.$fileDomElements.length > 0) { 11986 currentFileDomIndex = this.$fileDomElements.length - 1; 11987 $currentFileDomElement = this.$fileDomElements[currentFileDomIndex]; 11988 if ($currentFileDomElement && $currentFileDomElement.length > 0) { 11989 filesCount = $currentFileDomElement[0].files.length; 11990 //if all the files are invalid remove the input element as well otherwise only remove the invalid files. 11991 if (filesCount === invalidFilesIndexes.length) { 11992 this.$fileDomElements.splice(-1, 1); 11993 } else { 11994 this._deleteFilesFromInputDom($currentFileDomElement, invalidFilesIndexes); 11995 } 11996 } 11997 } 11998 11999 // in case of IE10, create one extra element 12000 if (isBrowserIE9OrIE10) { 12001 this.cloneFileInputAndUpdateIdForIE9(); 12002 } 12003 } 12004 12005 // trigger the change event to update the value 12006 this.$element.trigger("change.fileupload"); 12007 } 12008 12009 if (isInvalidSize) { 12010 this.showInvalidMessage(inValidSizefileNames.substring(0, inValidSizefileNames.lastIndexOf(',')), this.invalidFeature.SIZE); 12011 } else if (isInvalidFileName) { 12012 this.showInvalidMessage(inValidNamefileNames.substring(0, inValidNamefileNames.lastIndexOf(',')), this.invalidFeature.NAME); 12013 } else if (isInvalidMimeType) { 12014 this.showInvalidMessage(inValidMimeTypefileNames.substring(0, inValidMimeTypefileNames.lastIndexOf(',')), this.invalidFeature.MIMETYPE); 12015 } 12016 } 12017 }, 12018 12019 cloneFileInputAndUpdateIdForIE9 : function(){ 12020 var elem = _.last(this.$fileDomElements), 12021 elemExists = elem != null, 12022 elemHasValue = elemExists && elem.val().length > 0, 12023 elemId = null, 12024 selector = null; 12025 12026 // CQ-4237903 : create clone to handle the case when user clicks cancel in chrome and for multiselect 12027 // on clicking cancel in chrome file browser, chrome removes all the files from the input element 12028 // remove the extra clone in $fileDomElement on handleChange 12029 if(!elemExists || elemHasValue) { 12030 elem = this.$element.clone(); 12031 // copy the data attributes 12032 elem.data(this.$element.data()); 12033 if(isBrowserIE9OrIE10){ 12034 elemId = this.$element.attr("id") + (++fileLabelsCount); 12035 elem.attr("id", elemId); 12036 elem.css({ 12037 'position' : 'absolute', 12038 'top' : '-2000px', 12039 'left': '-2000px' 12040 }); 12041 elem.appendTo('body'); 12042 this.updateLabelForAttr(elemId); 12043 } 12044 elem.change($.proxy(this.handleChange, this)); 12045 this.$fileDomElements.push(elem); 12046 } 12047 // Case: if it is not multiselect and if the first file dom element is null 12048 // this case would hit when we restore a single select file attachment and attach a new file 12049 if(!this.options.multiSelect && this.$fileDomElements[0] === null){ 12050 //Splice null out of it, since we are attaching a new file 12051 this.$fileDomElements.splice(0, 1); 12052 } 12053 // if the browser is not IE9, then click it 12054 if(!isBrowserIE9OrIE10) { 12055 elem.click(); 12056 } 12057 return true; 12058 }, 12059 12060 /** 12061 * In case of IE9, get the last element of fileDom and update the id for label 12062 * 12063 * @param fileInputId 12064 */ 12065 updateLabelForAttr : function(fileInputId){ 12066 this.$label.attr("for" , fileInputId); 12067 }, 12068 12069 createLabelForFileInput : function (fileInputId){ 12070 if(isBrowserIE9OrIE10) { 12071 this.$label = $("<label></label>").addClass("guide-fu-attach-button button") 12072 .text(this.options.buttonText) 12073 .attr('for',fileInputId); 12074 this.$elementFileUploadBtn.replaceWith(this.$label); 12075 this.$label.parent().attr("tabindex", 0).attr("role", "button").attr("aria-label", this.options.screenReaderText || ""); 12076 } 12077 }, 12078 12079 12080 constructor: function () { 12081 // Initialize the self instance 12082 var _self = this, 12083 isFirst = true; 12084 //jquery instance of file upload button 12085 this.$elementFileUploadBtn = this.$parent.find(this.options.buttonClass); 12086 this.$elementFileUploadBtn.attr("aria-label", this.options.screenReaderText || ""); 12087 if(isBrowserIE9OrIE10){ 12088 this.elementId = this.$element.attr("id"); 12089 this.createLabelForFileInput(this.$element.attr("id")); 12090 } 12091 12092 // html for file list 12093 this.$elementFileList = $(this.fileItemList()); 12094 // Initialize the value and file(Refer FileList class mdn) 12095 this.values = []; 12096 this._initialFileValueFileNameMap = {}; 12097 // List of dom elements of input type file
12098 this.$fileDomElements = []; 12099 12100 var flag = false, 12101 $currElem = null; 12102 12103 $(document).mousedown(function(e) { 12104 $currElem = $(e.target); 12105 }); 12106 // Enter key should result in click of button 12107 this.$elementFileUploadBtn 12108 .focus(function(){ 12109 _self.$element.trigger("focus.fileupload"); 12110 }) 12111 .click($.proxy(this.cloneFileInputAndUpdateIdForIE9, this)) 12112 .blur(function(event){ 12113 // Check if the currElem does not belong to the fileItemList 12114 if(!flag && $currElem!= null && $currElem.closest(".guide-fu-fileItemList").length <=0){ 12115 _self.$element.trigger("focusout.fileupload"); 12116 } 12117 flag = false; 12118 }); 12119 //Initialize the filePreview Plugin 12120 this.$element[this.options.uploaderPluginName]({ 12121 iframeContainer: this.options.iframeContainer, 12122 _filePath: this.options._filePath, 12123 _uuidGenerator: this.options._uuidGenerator, 12124 _getUrl: this.options._getUrl 12125 12126 }); 12127 // Getting input file value 12128 // listening on fileuploaded event 12129 this.$element.change($.proxy(this.handleChange, this)) 12130 .on("adobeFileUploader.fileUploaded", $.proxy(this.previewFile, this)); 12131 } 12132 }; 12133 12134 $.fn.adobeFileAttachment = function (option, value) { 12135 var get = '', 12136 element = this.each(function () { 12137 // in case of input type file 12138 if ($(this).attr('type') === 'file') { 12139 var $this = $(this), 12140 data = $this.data('adobeFileAttachment'), 12141 options = $.extend({}, AdobeFileAttachment.prototype.defaults, typeof option === 'object' && option); 12142 12143 // Save the adobeFileAttachment data in jquery 12144 if (!data) { 12145 $this.data('adobeFileAttachment', (data = new AdobeFileAttachment(this, options))); 12146 data.constructor(); 12147 } 12148 12149 // code to get and set an option 12150 if (typeof option === 'string') { 12151 get = data[option](value); 12152 } 12153 } 12154 }); 12155 12156 if (typeof get !== 'undefined') { 12157 return get; 12158 } else { 12159 return element; 12160 } 12161 }; 12162 12163 // fileSizeLimit is in MB, default value is 2MB 12164 AdobeFileAttachment.prototype.defaults = { 12165 'buttonText': 'Attach', 12166 'multiSelect': false, 12167 'fileSizeLimit': 2, 12168 'uploaderPluginName': "adobeFileUploader", 12169 'mimeType' : ['audio/*', 'video/*', 'image/*', 'text/*', 'application/pdf'] 12170 }; 12171 12172})($, window, window._); 12173(function($, _) { 12174 var xfaUtil = xfalib.ut.XfaUtil.prototype; 12175 $.widget( "xfaWidget.fileUpload", $.xfaWidget.abstractWidget, { 12176 12177 _widgetName:"fileUpload", 12178 _superPrototype : $.xfaWidget.abstractWidget.prototype, 12179 getOptionsMap: function(){ 12180 var parentOptionsMap = this._superPrototype.getOptionsMap.apply(this,arguments), 12181 newMap = $.extend({},parentOptionsMap, $.extend({}, this.options, { 12182 "value" : function(value) { 12183 this.$userControl.adobeFileAttachment("value", value); 12184 }, 12185 "fileList": function(value){ 12186 this.$userControl.adobeFileAttachment("fileList", value); 12187 }, 12188 "comment" : function(value){ 12189 this.$userControl.adobeFileAttachment("comment", value); 12190 }, 12191 // "access" can be either open or readonly 12192 "access" : function(value){ 12193 this.$userControl.adobeFileAttachment("access", value); 12194 } 12195 12196 })); 12197 12198 return newMap; 12199 12200 }, 12201 // TODO: Will need to remove this functions 12202 // will be tracked by LC-391200 12203 12204 _initializeOptions: function () { 12205 _.each(this.optionsHandler, function (value, key) { 12206 // overriding the behaviour of _initializeOptions 12207 // only for _uuidGenerator 12208 // as we font want getUUID to be called at render time 12209 if (typeof value === "function" && key !== '_uuidGenerator' ) { 12210 value.apply(this, [this.options[key]]) 12211 } 12212 }, this) 12213 }, 12214 12215 _getFileList: function(){ 12216 return this.$userControl.adobeFileAttachment("fileList"); 12217 }, 12218 12219 _getComment: function(){ 12220 return this.$userControl.adobeFileAttachment("comment"); 12221 }, 12222 _getFileNamePathMap: function (pathList) { 12223 return this.$userControl.adobeFileAttachment("getSetFilePathAndReturnNamePathMap", pathList); 12224 }, 12225 getEventMap: function() { 12226 var parentEventMap = this._superPrototype.getEventMap.apply(this, arguments), 12227 newMap = $.extend({}, parentEventMap, 12228 { 12229 "change" : null, 12230 "focusout.fileupload" : xfaUtil.XFA_EXIT_EVENT, 12231 "focus.fileupload" : xfaUtil.XFA_ENTER_EVENT, 12232 "change.fileupload" : xfaUtil.XFA_CHANGE_EVENT 12233 }); 12234 return newMap; 12235 }, 12236 render: function() { 12237 var $el = this._superPrototype.render.apply(this,arguments); 12238 $el.adobeFileAttachment(this.getOptionsMap()); 12239 return $el; 12240 }, 12241 showDisplayValue: function() { 12242 //since value can't be set in file element input, leav
12242ing this fn empty 12243 }, 12244 showValue: function() { 12245 //since value can't be set in file element input, leaving this fn empty 12246 }, 12247 getCommitValue: function() { 12248 this.options.fileList = this._getFileList(); 12249 this.options.comment = this._getComment(); 12250 return this.$userControl.adobeFileAttachment("value"); 12251 } 12252 }); 12253})($, window._); 12254 12255/** 12256 * Adobe FilePreview Widget Plugin 12257 * 12258 * Options expected by file preview is the url 12259 * 12260 * Options Required Are: 12261 * 12262 * iframeName: Name of the Iframe 12263 * iframeContainer: Container of the iframe(eg Body) 12264 * fileUploadPath: Path where the file is to be uploaded 12265 * fileUploadServlet: Servlet where the file is to be uploaded 12266 * 12267 */ 12268(function ($, _) { 12269 12270 var AdobeFileUploader = function (element, options) { 12271 this.options = options; 12272 this.$element = $(element); 12273 }; 12274 12275 AdobeFileUploader.prototype = { 12276 12277 _fileIframeName: "guide-fu-iframe", 12278 12279 _filePath: "/tmp/fd/mf", 12280 12281 _iframeContainer: "body#formBody", 12282 12283 12284 fileIframe: function (name) { 12285 return $("<iframe></iframe>").attr({ 12286 style: "display:none", 12287 name: name 12288 }); 12289 }, 12290 12291 uploadFile: function (fileObject) { 12292 var multiple = false, 12293 fileName = null, 12294 actionUrl = null, 12295 fileUploadPath = fileObject.fileUploadPath, 12296 uuid; 12297 12298 if (!fileUploadPath) { 12299 uuid = fileObject._uuidGenerator(); 12300 } 12301 12302 // if uuid exists only then upload the file in the current instance 12303 if (_.isObject(fileObject) && (fileUploadPath || uuid)) { 12304 var fileDom = fileObject.fileDom, 12305 $form = $(this.options.iframeContainer).find(".filePreview"); 12306 fileName = fileObject.fileName; 12307 multiple = fileObject.multiple; 12308 if(!fileUploadPath) { 12309 fileUploadPath = this.options.fileUploadPath + "/" + uuid; 12310 } 12311 if (fileDom !== null) { 12312 //prepend contextpath 12313 actionUrl = fileObject._getUrl + fileUploadPath; 12314 if (!multiple) { 12315 if (!(fileUploadPath.lastIndexOf(fileObject._getUrl, 0) === 0)) { 12316 this.fileUrl = fileObject._getUrl + fileUploadPath + "/" + fileName; 12317 } else { 12318 this.fileUrl = fileUploadPath + "/" + fileName; 12319 } 12320 } else { 12321 this.fileUrl = actionUrl; 12322 } 12323 // done to solve issue LC-5835 12324 if($form.length === 0) { 12325 $form = $("<form method='post' enctype='multipart/form-data'/>") 12326 .addClass("filePreview") 12327 // create id so that it does not intercept with other forms in the page 12328 .attr({ 12329 id : "form" + new Date().valueOf(), 12330 action : actionUrl, 12331 target : this.options.iframeName 12332 }) 12333 .appendTo(this.options.iframeContainer); 12334 } else { 12335 /// first empty all children, using detach so that data is not clear 12336 $form.children().detach(); 12337 // now update the new attributes 12338 $form.attr({ 12339 action : actionUrl, 12340 target : this.options.iframeName 12341 }); 12342 } 12343 // this is done so that the other events attached at some other level in DOM Tree don't interfere 12344 $form.one("submit", function(evnt){ 12345 evnt.stopPropagation(); 12346 }); 12347 12348 var data = new FormData(); 12349 12350 if (multiple) { 12351 _.each(fileDom, function (fileDomElement, index) { 12352 // OOTB, this code is still used in dashboard 12353 if(fileDomElement !== null && !_.isString(fileDomElement)) { 12354 $(fileDomElement[0]).attr('name', fileName[index]).appendTo($form); 12355 // fileDomElement might contain multiple files so all the files needs to be added to formdata. 12356 var currentFileNames = fileName[index].split("\n"); 12357 for(var fileIndex = 0; fileIndex < currentFileNames.length; fileIndex++) { 12358 data.append(currentFileNames[fileIndex], fileDomElement[0].files[fileIndex]); 12359 } 12360 } 12361 }, this); 12362 } else { 12363 fileDom.attr('name', fileName).appendTo($form); 12364 data.append(fileName, fileDom[0].files[0]); 12365 } 12366 12367 /* UseCase: Suppose the fileName is in other language, on click of fileName, it tries to upload the file 12368 so that it could be preview, this change would ensure that the file is properly previewed supp
12368orting 12369 the given UTF-8 charset */ 12370 $("<input type='hidden' name='_charset_' value='UTF-8'/>").appendTo($form); 12371 data.append("_charset_", "UTF-8"); 12372 if (!multiple) { 12373 this.fileMap[this.fileUrl] = this.$element; 12374 } 12375 var self = this; 12376 $.ajax({ 12377 url: $form.attr("action"), 12378 data: data, 12379 cache: false, 12380 contentType: false, 12381 processData: false, 12382 method: 'POST', 12383 type: 'POST', 12384 success: function(data){ 12385 if (!multiple) { 12386 self.handleSingleFileUpload(data); 12387 } else { 12388 self.handleMultipleFileUpload(data); 12389 } 12390 }, 12391 error: function() { 12392 this.$element.trigger("adobeFileUploader.fileUploadFailed"); 12393 } 12394 }); 12395 } 12396 } 12397 return this.fileUrl; 12398 }, 12399 12400 handleMultipleFileUpload: function (data) { 12401 this.$element.trigger("adobeFileUploader.multipleFileUploaded"); 12402 }, 12403 12404 getFileUrl: function () { 12405 return this.fileUrl; 12406 }, 12407 12408 getUrlContentsFromUploadData: function (data) { 12409 var temp; 12410 if(data != null) { 12411 temp = $(data).find("#ChangeLog").text().split("br", 2)[1]; 12412 } else { 12413 var selector = this.options.iframeContainer + " iframe[name='" + this.options.iframeName + "']"; 12414 temp = $(selector).contents().find("#ChangeLog").text().split("br", 2)[1]; 12415 } 12416 12417 temp = temp.substring(temp.indexOf("created") + 9, temp.indexOf(";<")); 12418 temp = temp.substring(0, temp.length - 2); 12419 var index = temp.indexOf("/jcr:content"); 12420 if (index !== -1) 12421 temp = temp.substring(0, index); 12422 return temp; 12423 }, 12424 12425 handleSingleFileUpload: function (data) { 12426 var url = this.getUrlContentsFromUploadData(data); 12427 12428 //prepend context path 12429 url = this.options._getUrl + url; 12430 if (url in this.fileMap) { 12431 this.fileMap[url].trigger("adobeFileUploader.fileUploaded"); 12432 } 12433 }, 12434 12435 initialize: function () { 12436 // Put iframe inside the iframe container 12437 // On the load of iframe, display the contents of file 12438 // since there is only one iframe for all the file attachments, there may be race condition 12439 if (this.$iframe == null || this.$iframe.length === 0) { 12440 this.$iframe = this.fileIframe(this.options.iframeName).appendTo(this.options.iframeContainer); 12441 // since there is only iframe for the preview of all file attachments 12442 // this map is added in the closure scope 12443 // map contains the url(key) vs fileDomElement(value) 12444 // it helps avoids the race condition 12445 this.fileMap = {}; 12446 } 12447 } 12448 }; 12449 12450 $.fn.adobeFileUploader = function (option, value) { 12451 var get = '', 12452 element = this.each(function () { 12453 // in case of input type file 12454 if ($(this).attr('type') === 'file') { 12455 var $this = $(this), 12456 data = $this.data('adobeFileUploader'), 12457 options = $.extend({}, AdobeFileUploader.prototype.defaults(option, value), typeof option === 'object' && option); 12458 12459 // Save the adobeFileAttachment data in jquery 12460 if (!data) { 12461 $this.data('adobeFileUploader', (data = new AdobeFileUploader(this, options))); 12462 data.initialize(); 12463 } else { 12464 // update elements if not equal, since sometimes one can clone too 12465 if(data.$element.get(0) !== this) { 12466 data.$element = $(this); 12467 } 12468 } 12469 12470 // code to get and set an option 12471 if (typeof option === 'string') { 12472 get = data[option](value); 12473 } 12474 } 12475 }); 12476 12477 if (typeof get !== 'undefined') { 12478 return get; 12479 } else { 12480 return element; 12481 } 12482 }; 12483 12484 12485 AdobeFileUploader.prototype.defaults = function (options,value) { 12486 var propertyObject = {}; 12487 if(typeof options == 'object') { 12488 propertyObject._fileIframeName = options._fileIframeName; 12489 propertyObject._filePath = options._filePath; 12490 propertyObject.actionUrl = options.actionUrl; 12491 propertyObject._getUrl = options._getUrl; 12492 } 12493 if(typeof value == 'object') { 12494 propertyObject._fileIframeName = value._fileIframeName; 12495 propertyObject._filePath = value._filePath; 12496 propertyObject.actionUrl = value.actionUrl; 12497 propertyObject._getUrl = options._getUrl; 12498 } 12499 return { 12500 'fileUploadPath': propertyObject._filePath || AdobeFileUploader.prototype._filePath, 12501 'iframeName': AdobeFileUploader.prototype._fileIframeName + new Date().valueOf(), 12502 'fileUploadServlet': propertyObject._filePath || AdobeFileUploader.prototype._filePath,
vendor: 4,462 bytes, lines 12503-12656
12503 'iframeContainer': propertyObject._iframeContainer || AdobeFileUploader.prototype._iframeContainer, 12504 '_getUrl': propertyObject._getUrl || "" 12505 }; 12506 }; 12507 12508})($, window._); 12509 12510/*! 12511 * Bootstrap v3.4.1 (https://getbootstrap.com/) 12512 * Copyright 2011-2019 Twitter, Inc. 12513 * Licensed under the MIT license 12514 */ 12515 12516if (typeof jQuery === 'undefined') { 12517 throw new Error('Bootstrap\'s JavaScript requires jQuery') 12518} 12519 12520+function ($) { 12521 'use strict'; 12522 var version = $.fn.jquery.split(' ')[0].split('.') 12523 if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) { 12524 throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4') 12525 } 12526}(jQuery); 12527 12528/* ======================================================================== 12529 * Bootstrap: transition.js v3.4.1 12530 * https://getbootstrap.com/docs/3.4/javascript/#transitions 12531 * ======================================================================== 12532 * Copyright 2011-2019 Twitter, Inc. 12533 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 12534 * ======================================================================== */ 12535 12536 12537+function ($) { 12538 'use strict'; 12539 12540 // CSS TRANSITION SUPPORT (Shoutout: https://modernizr.com/) 12541 // ============================================================ 12542 12543 function transitionEnd() { 12544 var el = document.createElement('bootstrap') 12545 12546 var transEndEventNames = { 12547 WebkitTransition : 'webkitTransitionEnd', 12548 MozTransition : 'transitionend', 12549 OTransition : 'oTransitionEnd otransitionend', 12550 transition : 'transitionend' 12551 } 12552 12553 for (var name in transEndEventNames) { 12554 if (el.style[name] !== undefined) { 12555 return { end: transEndEventNames[name] } 12556 } 12557 } 12558 12559 return false // explicit for ie8 ( ._.) 12560 } 12561 12562 // https://blog.alexmaccaw.com/css-transitions 12563 $.fn.emulateTransitionEnd = function (duration) { 12564 var called = false 12565 var $el = this 12566 $(this).one('bsTransitionEnd', function () { called = true }) 12567 var callback = function () { if (!called) $($el).trigger($.support.transition.end) } 12568 setTimeout(callback, duration) 12569 return this 12570 } 12571 12572 $(function () { 12573 $.support.transition = transitionEnd() 12574 12575 if (!$.support.transition) return 12576 12577 $.event.special.bsTransitionEnd = { 12578 bindType: $.support.transition.end, 12579 delegateType: $.support.transition.end, 12580 handle: function (e) { 12581 if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments) 12582 } 12583 } 12584 }) 12585 12586}(jQuery); 12587 12588/* ======================================================================== 12589 * Bootstrap: alert.js v3.4.1 12590 * https://getbootstrap.com/docs/3.4/javascript/#alerts 12591 * ======================================================================== 12592 * Copyright 2011-2019 Twitter, Inc. 12593 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 12594 * ======================================================================== */ 12595 12596 12597+function ($) { 12598 'use strict'; 12599 12600 // ALERT CLASS DEFINITION 12601 // ====================== 12602 12603 var dismiss = '[data-dismiss="alert"]' 12604 var Alert = function (el) { 12605 $(el).on('click', dismiss, this.close) 12606 } 12607 12608 Alert.VERSION = '3.4.1' 12609 12610 Alert.TRANSITION_DURATION = 150 12611 12612 Alert.prototype.close = function (e) { 12613 var $this = $(this) 12614 var selector = $this.attr('data-target') 12615 12616 if (!selector) { 12617 selector = $this.attr('href') 12618 selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 12619 } 12620 12621 selector = selector === '#' ? [] : selector 12622 var $parent = $(document).find(selector) 12623 12624 if (e) e.preventDefault() 12625 12626 if (!$parent.length) { 12627 $parent = $this.closest('.alert') 12628 } 12629 12630 $parent.trigger(e = $.Event('close.bs.alert')) 12631 12632 if (e.isDefaultPrevented()) return 12633 12634 $parent.removeClass('in') 12635 12636 function removeElement() { 12637 // detach from parent, fire event then clean up data 12638 $parent.detach().trigger('closed.bs.alert').remove() 12639 } 12640 12641 $.support.transition && $parent.hasClass('fade') ? 12642 $parent 12643 .one('bsTransitionEnd', removeElement) 12644 .emulateTransitionEnd(Alert.TRANSITION_DURATION) : 12645 removeElement() 12646 } 12647 12648 12649 // ALERT PLUGIN DEFINITION 12650 // ======================= 12651 12652 function Plugin(option) { 12653 return this.each(function () { 12654 var $this = $(this) 12655 var data = $this.data('bs.alert') 12656
vendor: 59,455 bytes, lines 12657-14643
12657 if (!data) $this.data('bs.alert', (data = new Alert(this))) 12658 if (typeof option == 'string') data[option].call($this) 12659 }) 12660 } 12661 12662 var old = $.fn.alert 12663 12664 $.fn.alert = Plugin 12665 $.fn.alert.Constructor = Alert 12666 12667 12668 // ALERT NO CONFLICT 12669 // ================= 12670 12671 $.fn.alert.noConflict = function () { 12672 $.fn.alert = old 12673 return this 12674 } 12675 12676 12677 // ALERT DATA-API 12678 // ============== 12679 12680 $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close) 12681 12682}(jQuery); 12683 12684/* ======================================================================== 12685 * Bootstrap: button.js v3.4.1 12686 * https://getbootstrap.com/docs/3.4/javascript/#buttons 12687 * ======================================================================== 12688 * Copyright 2011-2019 Twitter, Inc. 12689 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 12690 * ======================================================================== */ 12691 12692 12693+function ($) { 12694 'use strict'; 12695 12696 // BUTTON PUBLIC CLASS DEFINITION 12697 // ============================== 12698 12699 var Button = function (element, options) { 12700 this.$element = $(element) 12701 this.options = $.extend({}, Button.DEFAULTS, options) 12702 this.isLoading = false 12703 } 12704 12705 Button.VERSION = '3.4.1' 12706 12707 Button.DEFAULTS = { 12708 loadingText: 'loading...' 12709 } 12710 12711 Button.prototype.setState = function (state) { 12712 var d = 'disabled' 12713 var $el = this.$element 12714 var val = $el.is('input') ? 'val' : 'html' 12715 var data = $el.data() 12716 12717 state += 'Text' 12718 12719 if (data.resetText == null) $el.data('resetText', $el[val]()) 12720 12721 // push to event loop to allow forms to submit 12722 setTimeout($.proxy(function () { 12723 $el[val](data[state] == null ? this.options[state] : data[state]) 12724 12725 if (state == 'loadingText') { 12726 this.isLoading = true 12727 $el.addClass(d).attr(d, d).prop(d, true) 12728 } else if (this.isLoading) { 12729 this.isLoading = false 12730 $el.removeClass(d).removeAttr(d).prop(d, false) 12731 } 12732 }, this), 0) 12733 } 12734 12735 Button.prototype.toggle = function () { 12736 var changed = true 12737 var $parent = this.$element.closest('[data-toggle="buttons"]') 12738 12739 if ($parent.length) { 12740 var $input = this.$element.find('input') 12741 if ($input.prop('type') == 'radio') { 12742 if ($input.prop('checked')) changed = false 12743 $parent.find('.active').removeClass('active') 12744 this.$element.addClass('active') 12745 } else if ($input.prop('type') == 'checkbox') { 12746 if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false 12747 this.$element.toggleClass('active') 12748 } 12749 $input.prop('checked', this.$element.hasClass('active')) 12750 if (changed) $input.trigger('change') 12751 } else { 12752 this.$element.attr('aria-pressed', !this.$element.hasClass('active')) 12753 this.$element.toggleClass('active') 12754 } 12755 } 12756 12757 12758 // BUTTON PLUGIN DEFINITION 12759 // ======================== 12760 12761 function Plugin(option) { 12762 return this.each(function () { 12763 var $this = $(this) 12764 var data = $this.data('bs.button') 12765 var options = typeof option == 'object' && option 12766 12767 if (!data) $this.data('bs.button', (data = new Button(this, options))) 12768 12769 if (option == 'toggle') data.toggle() 12770 else if (option) data.setState(option) 12771 }) 12772 } 12773 12774 var old = $.fn.button 12775 12776 $.fn.button = Plugin 12777 $.fn.button.Constructor = Button 12778 12779 12780 // BUTTON NO CONFLICT 12781 // ================== 12782 12783 $.fn.button.noConflict = function () { 12784 $.fn.button = old 12785 return this 12786 } 12787 12788 12789 // BUTTON DATA-API 12790 // =============== 12791 12792 $(document) 12793 .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) { 12794 var $btn = $(e.target).closest('.btn') 12795 Plugin.call($btn, 'toggle') 12796 if (!($(e.target).is('input[type="radio"], input[type="checkbox"]'))) { 12797 // Prevent double click on radios, and the double selections (so cancellation) on checkboxes 12798 e.preventDefault() 12799 // The target component still receive the focus 12800 if ($btn.is('input,button')) $btn.trigger('focus') 12801 else $btn.find('input:visible,button:visible').first().trigger('focus') 12802 } 12803 }) 12804 .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) { 12805 $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type)) 12806 }) 12807 12808}(jQuery); 12809 12810/* ======================================================================== 12811 * Bootstrap: carousel.js v3.4.1 12812 * https://getbootstrap.com/docs/3.4/javascript/#carousel 12813 * ======================================================================== 12814 * Copyright 2011-2019 Twitter, Inc. 12815 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 12816 * ======================================================================== */ 12817 12818 12819+function ($) { 12820 'use strict'; 12821 12822 // CAROUSEL CLASS DEFINITION 12823 // ========================= 12824 12825 var Carousel = function (element, options) { 12826 this.$element = $(element) 12827 this.$indicators = this.$element.find('.carousel-indicators') 12828 this.options = options 12829 this.paused = null 12830 this.sliding = null 12831 this.interval = null 12832 this.$active = null 12833 this.$items = null 12834 12835 this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this)) 12836 12837 this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element 12838 .on('mouseenter.bs.carousel', $.proxy(this.pause, this)) 12839 .on('mouseleave.bs.carousel', $.proxy(this.cycle, this)) 12840 } 12841 12842 Carousel.VERSION = '3.4.1' 12843 12844 Carousel.TRANSITION_DURATION = 600 12845 12846 Carousel.DEFAULTS = { 12847 interval: 5000, 12848 pause: 'hover', 12849 wrap: true, 12850 keyboard: true 12851 } 12852 12853 Carousel.prototype.keydown = function (e) { 12854 if (/input|textarea/i.test(e.target.tagName)) return 12855 switch (e.which) { 12856 case 37: this.prev(); break 12857 case 39: this.next(); break 12858 default: return 12859 } 12860 12861 e.preventDefault() 12862 } 12863 12864 Carousel.prototype.cycle = function (e) { 12865 e || (this.paused = false) 12866 12867 this.interval && clearInterval(this.interval) 12868 12869 this.options.interval 12870 && !this.paused 12871 && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) 12872 12873 return this 12874 } 12875 12876 Carousel.prototype.getItemIndex = function (item) { 12877 this.$items = item.parent().children('.item') 12878 return this.$items.index(item || this.$active) 12879 } 12880 12881 Carousel.prototype.getItemForDirection = function (direction, active) { 12882 var activeIndex = this.getItemIndex(active) 12883 var willWrap = (direction == 'prev' && activeIndex === 0) 12884 || (direction == 'next' && activeIndex == (this.$items.length - 1)) 12885 if (willWrap && !this.options.wrap) return active 12886 var delta = direction == 'prev' ? -1 : 1 12887 var itemIndex = (activeIndex + delta) % this.$items.length 12888 return this.$items.eq(itemIndex) 12889 } 12890 12891 Carousel.prototype.to = function (pos) { 12892 var that = this 12893 var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active')) 12894 12895 if (pos > (this.$items.length - 1) || pos < 0) return 12896 12897 if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid" 12898 if (activeIndex == pos) return this.pause().cycle() 12899 12900 return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos)) 12901 } 12902 12903 Carousel.prototype.pause = function (e) { 12904 e || (this.paused = true) 12905 12906 if (this.$element.find('.next, .prev').length && $.support.transition) { 12907 this.$element.trigger($.support.transition.end) 12908 this.cycle(true) 12909 } 12910 12911 this.interval = clearInterval(this.interval) 12912 12913 return this 12914 } 12915 12916 Carousel.prototype.next = function () { 12917 if (this.sliding) return 12918 return this.slide('next') 12919 } 12920 12921 Carousel.prototype.prev = function () { 12922 if (this.sliding) return 12923 return this.slide('prev') 12924 } 12925 12926 Carousel.prototype.slide = function (type, next) { 12927 var $active = this.$element.find('.item.active') 12928 var $next = next || this.getItemForDirection(type, $active) 12929 var isCycling = this.interval 12930 var direction = type == 'next' ? 'left' : 'right' 12931 var that = this 12932 12933 if ($next.hasClass('active')) return (this.sliding = false) 12934 12935 var relatedTarget = $next[0] 12936 var slideEvent = $.Event('slide.bs.carousel', { 12937 relatedTarget: relatedTarget, 12938 direction: direction 12939 }) 12940 this.$element.trigger(slideEvent) 12941 if (slideEvent.isDefaultPrevented()) return 12942 12943 this.sliding = true 12944 12945 isCycling && this.pause() 12946 12947 if (this.$indicators.length) { 12948 this.$indicators.find('.active').removeClass('active') 12949 var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)]) 12950 $nextIndicator && $nextIndicator.addClass('active') 12951 } 12952 12953 var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid" 12954 if ($.support.transition && this.$element.hasClass('slide')) { 12955 $next.addClass(type) 12956 if (typeof $next === 'object' && $next.length) { 12957 $next[0].offsetWidth // force reflow 12958 } 12959 $active.addClass(direction) 12960 $next.addClass(direction) 12961 $active 12962 .one('bsTransitionEnd', function () { 12963 $next.removeClass([type, direction].join(' ')).addClass('active') 12964 $active.removeClass(['active', direction].join(' ')) 12965 that.sliding = false 12966 setTimeout(function () { 12967 that.$element.trigger(slidEvent) 12968 }, 0) 12969 }) 12970 .emulateTransitionEnd(Carousel.TRANSITION_DURATION) 12971 } else { 12972 $active.removeClass('active') 12973 $next.addClass('active') 12974 this.sliding = false 12975 this.$element.trigger(slidEvent) 12976 } 12977 12978 isCycling && this.cycle() 12979 12980 return this 12981 } 12982 12983 12984 // CAROUSEL PLUGIN DEFINITION 12985 // ========================== 12986 12987 function Plugin(option) { 12988 return this.each(function () { 12989 var $this = $(this) 12990 var data = $this.data('bs.carousel') 12991 var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option) 12992 var action = typeof option == 'string' ? option : options.slide 12993 12994 if (!data) $this.data('bs.carousel', (data = new Carousel(this, options))) 12995 if (typeof option == 'number') data.to(option) 12996 else if (action) data[action]() 12997 else if (options.interval) data.pause().cycle() 12998 }) 12999 } 13000 13001 var old = $.fn.carousel 13002 13003 $.fn.carousel = Plugin 13004 $.fn.carousel.Constructor = Carousel 13005 13006 13007 // CAROUSEL NO CONFLICT 13008 // ==================== 13009 13010 $.fn.carousel.noConflict = function () { 13011 $.fn.carousel = old 13012 return this 13013 } 13014 13015 13016 // CAROUSEL DATA-API 13017 // ================= 13018 13019 var clickHandler = function (e) { 13020 var $this = $(this) 13021 var href = $this.attr('href') 13022 if (href) { 13023 href = href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7 13024 } 13025 13026 var target = $this.attr('data-target') || href 13027 var $target = $(document).find(target) 13028 13029 if (!$target.hasClass('carousel')) return 13030 13031 var options = $.extend({}, $target.data(), $this.data()) 13032 var slideIndex = $this.attr('data-slide-to') 13033 if (slideIndex) options.interval = false 13034 13035 Plugin.call($target, options) 13036 13037 if (slideIndex) { 13038 $target.data('bs.carousel').to(slideIndex) 13039 } 13040 13041 e.preventDefault() 13042 } 13043 13044 $(document) 13045 .on('click.bs.carousel.data-api', '[data-slide]', clickHandler) 13046 .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler) 13047 13048 $(window).on('load', function () { 13049 $('[data-ride="carousel"]').each(function () { 13050 var $carousel = $(this) 13051 Plugin.call($carousel, $carousel.data()) 13052 }) 13053 }) 13054 13055}(jQuery); 13056 13057/* ======================================================================== 13058 * Bootstrap: collapse.js v3.4.1 13059 * https://getbootstrap.com/docs/3.4/javascript/#collapse 13060 * ======================================================================== 13061 * Copyright 2011-2019 Twitter, Inc. 13062 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 13063 * ======================================================================== */ 13064 13065/* jshint latedef: false */ 13066 13067+function ($) { 13068 'use strict'; 13069 13070 // COLLAPSE PUBLIC CLASS DEFINITION 13071 // ================================ 13072 13073 var Collapse = function (element, options) { 13074 this.$element = $(element) 13075 this.options = $.extend({}, Collapse.DEFAULTS, options) 13076 this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' + 13077 '[data-toggle="collapse"][data-target="#' + element.id + '"]') 13078 this.transitioning = null 13079 13080 if (this.options.parent) { 13081 this.$parent = this.getParent() 13082 } else { 13083 this.addAriaAndCollapsedClass(this.$element, this.$trigger) 13084 } 13085 13086 if (this.options.toggle) this.toggle() 13087 } 13088 13089 Collapse.VERSION = '3.4.1' 13090 13091 Collapse.TRANSITION_DURATION = 350 13092 13093 Collapse.DEFAULTS = { 13094 toggle: true 13095 } 13096 13097 Collapse.prototype.dimension = function () { 13098 var hasWidth = this.$element.hasClass('width') 13099 return hasWidth ? 'width' : 'height' 13100 } 13101 13102 Collapse.prototype.show = function () { 13103 if (this.transitioning || this.$element.hasClass('in')) return 13104 13105 var activesData 13106 var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing') 13107 13108 if (actives && actives.length) { 13109 activesData = actives.data('bs.collapse') 13110 if (activesData && activesData.transitioning) return 13111 } 13112 13113 var startEvent = $.Event('show.bs.collapse') 13114 this.$element.trigger(startEvent) 13115 if (startEvent.isDefaultPrevented()) return 13116 13117 if (actives && actives.length) { 13118 Plugin.call(actives, 'hide') 13119 activesData || actives.data('bs.collapse', null) 13120 } 13121 13122 var dimension = this.dimension() 13123 13124 this.$element 13125 .removeClass('collapse') 13126 .addClass('collapsing')[dimension](0) 13127 .attr('aria-expanded', true) 13128 13129 this.$trigger 13130 .removeClass('collapsed') 13131 .attr('aria-expanded', true) 13132 13133 this.transitioning = 1 13134 13135 var complete = function () { 13136 this.$element 13137 .removeClass('collapsing') 13138 .addClass('collapse in')[dimension]('') 13139 this.transitioning = 0 13140 this.$element 13141 .trigger('shown.bs.collapse') 13142 } 13143 13144 if (!$.support.transition) return complete.call(this) 13145 13146 var scrollSize = $.camelCase(['scroll', dimension].join('-')) 13147 13148 this.$element 13149 .one('bsTransitionEnd', $.proxy(complete, this)) 13150 .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize]) 13151 } 13152 13153 Collapse.prototype.hide = function () { 13154 if (this.transitioning || !this.$element.hasClass('in')) return 13155 13156 var startEvent = $.Event('hide.bs.collapse') 13157 this.$element.trigger(startEvent) 13158 if (startEvent.isDefaultPrevented()) return 13159 13160 var dimension = this.dimension() 13161 13162 this.$element[dimension](this.$element[dimension]())[0].offsetHeight 13163 13164 this.$element 13165 .addClass('collapsing') 13166 .removeClass('collapse in') 13167 .attr('aria-expanded', false) 13168 13169 this.$trigger 13170 .addClass('collapsed') 13171 .attr('aria-expanded', false) 13172 13173 this.transitioning = 1 13174 13175 var complete = function () { 13176 this.transitioning = 0 13177 this.$element 13178 .removeClass('collapsing') 13179 .addClass('collapse') 13180 .trigger('hidden.bs.collapse') 13181 } 13182 13183 if (!$.support.transition) return complete.call(this) 13184 13185 this.$element 13186 [dimension](0) 13187 .one('bsTransitionEnd', $.proxy(complete, this)) 13188 .emulateTransitionEnd(Collapse.TRANSITION_DURATION) 13189 } 13190 13191 Collapse.prototype.toggle = function () { 13192 this[this.$element.hasClass('in') ? 'hide' : 'show']() 13193 } 13194 13195 Collapse.prototype.getParent = function () { 13196 return $(document).find(this.options.parent) 13197 .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]') 13198 .each($.proxy(function (i, element) { 13199 var $element = $(element) 13200 this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element) 13201 }, this)) 13202 .end() 13203 } 13204 13205 Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) { 13206 var isOpen = $element.hasClass('in') 13207 13208 $element.attr('aria-expanded', isOpen) 13209 $trigger 13210 .toggleClass('collapsed', !isOpen) 13211 .attr('aria-expanded', isOpen) 13212 } 13213 13214 function getTargetFromTrigger($trigger) { 13215 var href 13216 var target = $trigger.attr('data-target') 13217 || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7 13218 13219 return $(document).find(target) 13220 } 13221 13222 13223 // COLLAPSE PLUGIN DEFINITION 13224 // ========================== 13225 13226 function Plugin(option) { 13227 return this.each(function () { 13228 var $this = $(this) 13229 var data = $this.data('bs.collapse') 13230 var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) 13231 13232 if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false 13233 if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) 13234 if (typeof option == 'string') data[option]() 13235 }) 13236 } 13237 13238 var old = $.fn.collapse 13239 13240 $.fn.collapse = Plugin 13241 $.fn.collapse.Constructor = Collapse 13242 13243 13244 // COLLAPSE NO CONFLICT 13245 // ==================== 13246 13247 $.fn.collapse.noConflict = function () { 13248 $.fn.collapse = old 13249 return this 13250 } 13251 13252 13253 // COLLAPSE DATA-API 13254 // ================= 13255 13256 $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { 13257 var $this = $(this) 13258 13259 if (!$this.attr('data-target')) e.preventDefault() 13260 13261 var $target = getTargetFromTrigger($this) 13262 var data = $target.data('bs.collapse') 13263 var option = data ? 'toggle' : $this.data() 13264 13265 Plugin.call($target, option) 13266 }) 13267 13268}(jQuery); 13269 13270/* ======================================================================== 13271 * Bootstrap: dropdown.js v3.4.1 13272 * https://getbootstrap.com/docs/3.4/javascript/#dropdowns 13273 * ======================================================================== 13274 * Copyright 2011-2019 Twitter, Inc. 13275 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 13276 * ======================================================================== */ 13277 13278 13279+function ($) { 13280 'use strict'; 13281 13282 // DROPDOWN CLASS DEFINITION 13283 // ========================= 13284 13285 var backdrop = '.dropdown-backdrop' 13286 var toggle = '[data-toggle="dropdown"]' 13287 var Dropdown = function (element) { 13288 $(element).on('click.bs.dropdown', this.toggle) 13289 } 13290 13291 Dropdown.VERSION = '3.4.1' 13292 13293 function getParent($this) { 13294 var selector = $this.attr('data-target') 13295 13296 if (!selector) { 13297 selector = $this.attr('href') 13298 selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 13299 } 13300 13301 var $parent = selector !== '#' ? $(document).find(selector) : null 13302 13303 return $parent && $parent.length ? $parent : $this.parent() 13304 } 13305 13306 function clearMenus(e) { 13307 if (e && e.which === 3) return 13308 $(backdrop).remove() 13309 $(toggle).each(function () { 13310 var $this = $(this) 13311 var $parent = getParent($this) 13312 var relatedTarget = { relatedTarget: this } 13313 13314 if (!$parent.hasClass('open')) return 13315 13316 if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return 13317 13318 $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget)) 13319 13320 if (e.isDefaultPrevented()) return 13321 13322 $this.attr('aria-expanded', 'false') 13323 $parent.removeClass('open').trigger($.Event('hidden.bs.dropdown', relatedTarget)) 13324 }) 13325 } 13326 13327 Dropdown.prototype.toggle = function (e) { 13328 var $this = $(this) 13329 13330 if ($this.is('.disabled, :disabled')) return 13331 13332 var $parent = getParent($this) 13333 var isActive = $parent.hasClass('open') 13334 13335 clearMenus() 13336 13337 if (!isActive) { 13338 if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { 13339 // if mobile we use a backdrop because click events don't delegate 13340 $(document.createElement('div')) 13341 .addClass('dropdown-backdrop') 13342 .insertAfter($(this)) 13343 .on('click', clearMenus) 13344 } 13345 13346 var relatedTarget = { relatedTarget: this } 13347 $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget)) 13348 13349 if (e.isDefaultPrevented()) return 13350 13351 $this 13352 .trigger('focus') 13353 .attr('aria-expanded', 'true') 13354 13355 $parent 13356 .toggleClass('open') 13357 .trigger($.Event('shown.bs.dropdown', relatedTarget)) 13358 } 13359 13360 return false 13361 } 13362 13363 Dropdown.prototype.keydown = function (e) { 13364 if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return 13365 13366 var $this = $(this) 13367 13368 e.preventDefault() 13369 e.stopPropagation() 13370 13371 if ($this.is('.disabled, :disabled')) return 13372 13373 var $parent = getParent($this) 13374 var isActive = $parent.hasClass('open') 13375 13376 if (!isActive && e.which != 27 || isActive && e.which == 27) { 13377 if (e.which == 27) $parent.find(toggle).trigger('focus') 13378 return $this.trigger('click') 13379 } 13380 13381 var desc = ' li:not(.disabled):visible a' 13382 var $items = $parent.find('.dropdown-menu' + desc) 13383 13384 if (!$items.length) return 13385 13386 var index = $items.index(e.target) 13387 13388 if (e.which == 38 && index > 0) index-- // up 13389 if (e.which == 40 && index < $items.length - 1) index++ // down 13390 if (!~index) index = 0 13391 13392 $items.eq(index).trigger('focus') 13393 } 13394 13395 13396 // DROPDOWN PLUGIN DEFINITION 13397 // ========================== 13398 13399 function Plugin(option) { 13400 return this.each(function () { 13401 var $this = $(this) 13402 var data = $this.data('bs.dropdown') 13403 13404 if (!data) $this.data('bs.dropdown', (data = new Dropdown(this))) 13405 if (typeof option == 'string') data[option].call($this) 13406 }) 13407 } 13408 13409 var old = $.fn.dropdown 13410 13411 $.fn.dropdown = Plugin 13412 $.fn.dropdown.Constructor = Dropdown 13413 13414 13415 // DROPDOWN NO CONFLICT 13416 // ==================== 13417 13418 $.fn.dropdown.noConflict = function () { 13419 $.fn.dropdown = old 13420 return this 13421 } 13422 13423 13424 // APPLY TO STANDARD DROPDOWN ELEMENTS 13425 // =================================== 13426 13427 $(document) 13428 .on('click.bs.dropdown.data-api', clearMenus) 13429 .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) 13430 .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle) 13431 .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown) 13432 .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown) 13433 13434}(jQuery); 13435 13436/* ======================================================================== 13437 * Bootstrap: modal.js v3.4.1 13438 * https://getbootstrap.com/docs/3.4/javascript/#modals 13439 * ======================================================================== 13440 * Copyright 2011-2019 Twitter, Inc. 13441 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 13442 * ======================================================================== */ 13443 13444 13445+function ($) { 13446 'use strict'; 13447 13448 // MODAL CLASS DEFINITION 13449 // ====================== 13450 13451 var Modal = function (element, options) { 13452 this.options = options 13453 this.$body = $(document.body) 13454 this.$element = $(element) 13455 this.$dialog = this.$element.find('.modal-dialog') 13456 this.$backdrop = null 13457 this.isShown = null 13458 this.originalBodyPad = null 13459 this.scrollbarWidth = 0 13460 this.ignoreBackdropClick = false 13461 this.fixedContent = '.navbar-fixed-top, .navbar-fixed-bottom' 13462 13463 if (this.options.remote) { 13464 this.$element 13465 .find('.modal-content') 13466 .load(this.options.remote, $.proxy(function () { 13467 this.$element.trigger('loaded.bs.modal') 13468 }, this)) 13469 } 13470 } 13471 13472 Modal.VERSION = '3.4.1' 13473 13474 Modal.TRANSITION_DURATION = 300 13475 Modal.BACKDROP_TRANSITION_DURATION = 150 13476 13477 Modal.DEFAULTS = { 13478 backdrop: true, 13479 keyboard: true, 13480 show: true 13481 } 13482 13483 Modal.prototype.toggle = function (_relatedTarget) { 13484 return this.isShown ? this.hide() : this.show(_relatedTarget) 13485 } 13486 13487 Modal.prototype.show = function (_relatedTarget) { 13488 var that = this 13489 var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget }) 13490 13491 this.$element.trigger(e) 13492 13493 if (this.isShown || e.isDefaultPrevented()) return 13494 13495 this.isShown = true 13496 13497 this.checkScrollbar() 13498 this.setScrollbar() 13499 this.$body.addClass('modal-open') 13500 13501 this.escape() 13502 this.resize() 13503 13504 this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this)) 13505 13506 this.$dialog.on('mousedown.dismiss.bs.modal', function () { 13507 that.$element.one('mouseup.dismiss.bs.modal', function (e) { 13508 if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true 13509 }) 13510 }) 13511 13512 this.backdrop(function () { 13513 var transition = $.support.transition && that.$element.hasClass('fade') 13514 13515 if (!that.$element.parent().length) { 13516 that.$element.appendTo(that.$body) // don't move modals dom position 13517 } 13518 13519 that.$element 13520 .show() 13521 .scrollTop(0) 13522 13523 that.adjustDialog() 13524 13525 if (transition) { 13526 that.$element[0].offsetWidth // force reflow 13527 } 13528 13529 that.$element.addClass('in') 13530 13531 that.enforceFocus() 13532 13533 var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget }) 13534 13535 transition ? 13536 that.$dialog // wait for modal to slide in 13537 .one('bsTransitionEnd', function () { 13538 that.$element.trigger('focus').trigger(e) 13539 }) 13540 .emulateTransitionEnd(Modal.TRANSITION_DURATION) : 13541 that.$element.trigger('focus').trigger(e) 13542 }) 13543 } 13544 13545 Modal.prototype.hide = function (e) { 13546 if (e) e.preventDefault() 13547 13548 e = $.Event('hide.bs.modal') 13549 13550 this.$element.trigger(e) 13551 13552 if (!this.isShown || e.isDefaultPrevented()) return 13553 13554 this.isShown = false 13555 13556 this.escape() 13557 this.resize() 13558 13559 $(document).off('focusin.bs.modal') 13560 13561 this.$element 13562 .removeClass('in') 13563 .off('click.dismiss.bs.modal') 13564 .off('mouseup.dismiss.bs.modal') 13565 13566 this.$dialog.off('mousedown.dismiss.bs.modal') 13567 13568 $.support.transition && this.$element.hasClass('fade') ? 13569 this.$element 13570 .one('bsTransitionEnd', $.proxy(this.hideModal, this)) 13571 .emulateTransitionEnd(Modal.TRANSITION_DURATION) : 13572 this.hideModal() 13573 } 13574 13575 Modal.prototype.enforceFocus = function () { 13576 $(document) 13577 .off('focusin.bs.modal') // guard against infinite focus loop 13578 .on('focusin.bs.modal', $.proxy(function (e) { 13579 if (document !== e.target && 13580 this.$element[0] !== e.target && 13581 !this.$element.has(e.target).length) { 13582 this.$element.trigger('focus') 13583 } 13584 }, this)) 13585 } 13586 13587 Modal.prototype.escape = function () { 13588 if (this.isShown && this.options.keyboard) { 13589 this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) { 13590 e.which == 27 && this.hide() 13591 }, this)) 13592 } else if (!this.isShown) { 13593 this.$element.off('keydown.dismiss.bs.modal') 13594 } 13595 } 13596 13597 Modal.prototype.resize = function () { 13598 if (this.isShown) { 13599 $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this)) 13600 } else { 13601 $(window).off('resize.bs.modal') 13602 } 13603 } 13604 13605 Modal.prototype.hideModal = function () { 13606 var that = this 13607 this.$element.hide() 13608 this.backdrop(function () { 13609 that.$body.removeClass('modal-open') 13610 that.resetAdjustments() 13611 that.resetScrollbar() 13612 that.$element.trigger('hidden.bs.modal') 13613 }) 13614 } 13615 13616 Modal.prototype.removeBackdrop = function () { 13617 this.$backdrop && this.$backdrop.remove() 13618 this.$backdrop = null 13619 } 13620 13621 Modal.prototype.backdrop = function (callback) { 13622 var that = this 13623 var animate = this.$element.hasClass('fade') ? 'fade' : '' 13624 13625 if (this.isShown && this.options.backdrop) { 13626 var doAnimate = $.support.transition && animate 13627 13628 this.$backdrop = $(document.createElement('div')) 13629 .addClass('modal-backdrop ' + animate) 13630 .appendTo(this.$body) 13631 13632 this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) { 13633 if (this.ignoreBackdropClick) { 13634 this.ignoreBackdropClick = false 13635 return 13636 } 13637 if (e.target !== e.currentTarget) return 13638 this.options.backdrop == 'static' 13639 ? this.$element[0].focus() 13640 : this.hide() 13641 }, this)) 13642 13643 if (doAnimate) this.$backdrop[0].offsetWidth // force reflow 13644 13645 this.$backdrop.addClass('in') 13646 13647 if (!callback) return 13648 13649 doAnimate ? 13650 this.$backdrop 13651 .one('bsTransitionEnd', callback) 13652 .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : 13653 callback() 13654 13655 } else if (!this.isShown && this.$backdrop) { 13656 this.$backdrop.removeClass('in') 13657 13658 var callbackRemove = function () { 13659 that.removeBackdrop() 13660 callback && callback() 13661 } 13662 $.support.transition && this.$element.hasClass('fade') ? 13663 this.$backdrop 13664 .one('bsTransitionEnd', callbackRemove) 13665 .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : 13666 callbackRemove() 13667 13668 } else if (callback) { 13669 callback() 13670 } 13671 } 13672 13673 // these following methods are used to handle overflowing modals 13674 13675 Modal.prototype.handleUpdate = function () { 13676 this.adjustDialog() 13677 } 13678 13679 Modal.prototype.adjustDialog = function () { 13680 var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight 13681 13682 this.$element.css({ 13683 paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '', 13684 paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : '' 13685 }) 13686 } 13687 13688 Modal.prototype.resetAdjustments = function () { 13689 this.$element.css({ 13690 paddingLeft: '', 13691 paddingRight: '' 13692 }) 13693 } 13694 13695 Modal.prototype.checkScrollbar = function () { 13696 var fullWindowWidth = window.innerWidth 13697 if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8 13698 var documentElementRect = document.documentElement.getBoundingClientRect() 13699 fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left) 13700 } 13701 this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth 13702 this.scrollbarWidth = this.measureScrollbar() 13703 } 13704 13705 Modal.prototype.setScrollbar = function () { 13706 var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10) 13707 this.originalBodyPad = document.body.style.paddingRight || '' 13708 var scrollbarWidth = this.scrollbarWidth 13709 if (this.bodyIsOverflowing) { 13710 this.$body.css('padding-right', bodyPad + scrollbarWidth) 13711 $(this.fixedContent).each(function (index, element) { 13712 var actualPadding = element.style.paddingRight 13713 var calculatedPadding = $(element).css('padding-right') 13714 $(element) 13715 .data('padding-right', actualPadding) 13716 .css('padding-right', parseFloat(calculatedPadding) + scrollbarWidth + 'px') 13717 }) 13718 } 13719 } 13720 13721 Modal.prototype.resetScrollbar = function () { 13722 this.$body.css('padding-right', this.originalBodyPad) 13723 $(this.fixedContent).each(function (index, element) { 13724 var padding = $(element).data('padding-right') 13725 $(element).removeData('padding-right') 13726 element.style.paddingRight = padding ? padding : '' 13727 }) 13728 } 13729 13730 Modal.prototype.measureScrollbar = function () { // thx walsh 13731 var scrollDiv = document.createElement('div') 13732 scrollDiv.className = 'modal-scrollbar-measure' 13733 this.$body.append(scrollDiv) 13734 var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth 13735 this.$body[0].removeChild(scrollDiv) 13736 return scrollbarWidth 13737 } 13738 13739 13740 // MODAL PLUGIN DEFINITION 13741 // ======================= 13742 13743 function Plugin(option, _relatedTarget) { 13744 return this.each(function () { 13745 var $this = $(this) 13746 var data = $this.data('bs.modal') 13747 var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option) 13748 13749 if (!data) $this.data('bs.modal', (data = new Modal(this, options))) 13750 if (typeof option == 'string') data[option](_relatedTarget) 13751 else if (options.show) data.show(_relatedTarget) 13752 }) 13753 } 13754 13755 var old = $.fn.modal 13756 13757 $.fn.modal = Plugin 13758 $.fn.modal.Constructor = Modal 13759 13760 13761 // MODAL NO CONFLICT 13762 // ================= 13763 13764 $.fn.modal.noConflict = function () { 13765 $.fn.modal = old 13766 return this 13767 } 13768 13769 13770 // MODAL DATA-API 13771 // ============== 13772 13773 $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) { 13774 var $this = $(this) 13775 var href = $this.attr('href') 13776 var target = $this.attr('data-target') || 13777 (href && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7 13778 13779 var $target = $(document).find(target) 13780 var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data()) 13781 13782 if ($this.is('a')) e.preventDefault() 13783 13784 $target.one('show.bs.modal', function (showEvent) { 13785 if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown 13786 $target.one('hidden.bs.modal', function () { 13787 $this.is(':visible') && $this.trigger('focus') 13788 }) 13789 }) 13790 Plugin.call($target, option, this) 13791 }) 13792 13793}(jQuery); 13794 13795/* ======================================================================== 13796 * Bootstrap: tooltip.js v3.4.1 13797 * https://getbootstrap.com/docs/3.4/javascript/#tooltip 13798 * Inspired by the original jQuery.tipsy by Jason Frame 13799 * ======================================================================== 13800 * Copyright 2011-2019 Twitter, Inc. 13801 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 13802 * ======================================================================== */ 13803 13804+function ($) { 13805 'use strict'; 13806 13807 var DISALLOWED_ATTRIBUTES = ['sanitize', 'whiteList', 'sanitizeFn'] 13808 13809 var uriAttrs = [ 13810 'background', 13811 'cite', 13812 'href', 13813 'itemtype', 13814 'longdesc', 13815 'poster', 13816 'src', 13817 'xlink:href' 13818 ] 13819 13820 var ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i 13821 13822 var DefaultWhitelist = { 13823 // Global attributes allowed on any supplied element below. 13824 '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN], 13825 a: ['target', 'href', 'title', 'rel'], 13826 area: [], 13827 b: [], 13828 br: [], 13829 col: [], 13830 code: [], 13831 div: [], 13832 em: [], 13833 hr: [], 13834 h1: [], 13835 h2: [], 13836 h3: [], 13837 h4: [], 13838 h5: [], 13839 h6: [], 13840 i: [], 13841 img: ['src', 'alt', 'title', 'width', 'height'], 13842 li: [], 13843 ol: [], 13844 p: [], 13845 pre: [], 13846 s: [], 13847 small: [], 13848 span: [], 13849 sub: [], 13850 sup: [], 13851 strong: [], 13852 u: [], 13853 ul: [] 13854 } 13855 13856 /** 13857 * A pattern that recognizes a commonly useful subset of URLs that are safe. 13858 * 13859 * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts 13860 */ 13861 var SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi 13862 13863 /** 13864 * A pattern that matches safe data URLs. Only matches image, video and audio types. 13865 * 13866 * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts 13867 */ 13868 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 13869 13870 function allowedAttribute(attr, allowedAttributeList) { 13871 var attrName = attr.nodeName.toLowerCase() 13872 13873 if ($.inArray(attrName, allowedAttributeList) !== -1) { 13874 if ($.inArray(attrName, uriAttrs) !== -1) { 13875 return Boolean(attr.nodeValue.match(SAFE_URL_PATTERN) || attr.nodeValue.match(DATA_URL_PATTERN)) 13876 } 13877 13878 return true 13879 } 13880 13881 var regExp = $(allowedAttributeList).filter(function (index, value) { 13882 return value instanceof RegExp 13883 }) 13884 13885 // Check if a regular expression validates the attribute. 13886 for (var i = 0, l = regExp.length; i < l; i++) { 13887 if (attrName.match(regExp[i])) { 13888 return true 13889 } 13890 } 13891 13892 return false 13893 } 13894 13895 function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) { 13896 if (unsafeHtml.length === 0) { 13897 return unsafeHtml 13898 } 13899 13900 if (sanitizeFn && typeof sanitizeFn === 'function') { 13901 return sanitizeFn(unsafeHtml) 13902 } 13903 13904 // IE 8 and below don't support createHTMLDocument 13905 if (!document.implementation || !document.implementation.createHTMLDocument) { 13906 return unsafeHtml 13907 } 13908 13909 var createdDocument = document.implementation.createHTMLDocument('sanitization') 13910 createdDocument.body.innerHTML = unsafeHtml 13911 13912 var whitelistKeys = $.map(whiteList, function (el, i) { return i }) 13913 var elements = $(createdDocument.body).find('*') 13914 13915 for (var i = 0, len = elements.length; i < len; i++) { 13916 var el = elements[i] 13917 var elName = el.nodeName.toLowerCase() 13918 13919 if ($.inArray(elName, whitelistKeys) === -1) { 13920 el.parentNode.removeChild(el) 13921 13922 continue 13923 } 13924 13925 var attributeList = $.map(el.attributes, function (el) { return el }) 13926 var whitelistedAttributes = [].concat(whiteList['*'] || [], whiteList[elName] || []) 13927 13928 for (var j = 0, len2 = attributeList.length; j < len2; j++) { 13929 if (!allowedAttribute(attributeList[j], whitelistedAttributes)) { 13930 el.removeAttribute(attributeList[j].nodeName) 13931 } 13932 } 13933 } 13934 13935 return createdDocument.body.innerHTML 13936 } 13937 13938 // TOOLTIP PUBLIC CLASS DEFINITION 13939 // =============================== 13940 13941 var Tooltip = function (element, options) { 13942 this.type = null 13943 this.options = null 13944 this.enabled = null 13945 this.timeout = null 13946 this.hoverState = null 13947 this.$element = null 13948 this.inState = null 13949 13950 this.init('tooltip', element, options) 13951 } 13952 13953 Tooltip.VERSION = '3.4.1' 13954 13955 Tooltip.TRANSITION_DURATION = 150 13956 13957 Tooltip.DEFAULTS = { 13958 animation: true, 13959 placement: 'top', 13960 selector: false, 13961 template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>', 13962 trigger: 'hover focus', 13963 title: '', 13964 delay: 0, 13965 html: false, 13966 container: false, 13967 viewport: { 13968 selector: 'body', 13969 padding: 0 13970 }, 13971 sanitize : true, 13972 sanitizeFn : null, 13973 whiteList : DefaultWhitelist 13974 } 13975 13976 Tooltip.prototype.init = function (type, element, options) { 13977 this.enabled = true 13978 this.type = type 13979 this.$element = $(element) 13980 this.options = this.getOptions(options) 13981 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)) 13982 this.inState = { click: false, hover: false, focus: false } 13983 13984 if (this.$element[0] instanceof document.constructor && !this.options.selector) { 13985 throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!') 13986 } 13987 13988 var triggers = this.options.trigger.split(' ') 13989 13990 for (var i = triggers.length; i--;) { 13991 var trigger = triggers[i] 13992 13993 if (trigger == 'click') { 13994 this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) 13995 } else if (trigger != 'manual') { 13996 var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin' 13997 var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout' 13998 13999 this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) 14000 this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) 14001 } 14002 } 14003 14004 this.options.selector ? 14005 (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : 14006 this.fixTitle() 14007 } 14008 14009 Tooltip.prototype.getDefaults = function () { 14010 return Tooltip.DEFAULTS 14011 } 14012 14013 Tooltip.prototype.getOptions = function (options) { 14014 var dataAttributes = this.$element.data() 14015 14016 for (var dataAttr in dataAttributes) { 14017 if (dataAttributes.hasOwnProperty(dataAttr) && $.inArray(dataAttr, DISALLOWED_ATTRIBUTES) !== -1) { 14018 delete dataAttributes[dataAttr] 14019 } 14020 } 14021 14022 options = $.extend({}, this.getDefaults(), dataAttributes, options) 14023 14024 if (options.delay && typeof options.delay == 'number') { 14025 options.delay = { 14026 show: options.delay, 14027 hide: options.delay 14028 } 14029 } 14030 14031 if (options.sanitize) { 14032 options.template = sanitizeHtml(options.template, options.whiteList, options.sanitizeFn) 14033 } 14034 14035 return options 14036 } 14037 14038 Tooltip.prototype.getDelegateOptions = function () { 14039 var options = {} 14040 var defaults = this.getDefaults() 14041 14042 this._options && $.each(this._options, function (key, value) { 14043 if (defaults[key] != value) options[key] = value 14044 }) 14045 14046 return options 14047 } 14048 14049 Tooltip.prototype.enter = function (obj) { 14050 var self = obj instanceof this.constructor ? 14051 obj : $(obj.currentTarget).data('bs.' + this.type) 14052 14053 if (!self) { 14054 self = new this.constructor(obj.currentTarget, this.getDelegateOptions()) 14055 $(obj.currentTarget).data('bs.' + this.type, self) 14056 } 14057 14058 if (obj instanceof $.Event) { 14059 self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true 14060 } 14061 14062 if (self.tip().hasClass('in') || self.hoverState == 'in') { 14063 self.hoverState = 'in' 14064 return 14065 } 14066 14067 clearTimeout(self.timeout) 14068 14069 self.hoverState = 'in' 14070 14071 if (!self.options.delay || !self.options.delay.show) return self.show() 14072 14073 self.timeout = setTimeout(function () { 14074 if (self.hoverState == 'in') self.show() 14075 }, self.options.delay.show) 14076 } 14077 14078 Tooltip.prototype.isInStateTrue = function () { 14079 for (var key in this.inState) { 14080 if (this.inState[key]) return true 14081 } 14082 14083 return false 14084 } 14085 14086 Tooltip.prototype.leave = function (obj) { 14087 var self = obj instanceof this.constructor ? 14088 obj : $(obj.currentTarget).data('bs.' + this.type) 14089 14090 if (!self) { 14091 self = new this.constructor(obj.currentTarget, this.getDelegateOptions()) 14092 $(obj.currentTarget).data('bs.' + this.type, self) 14093 } 14094 14095 if (obj instanceof $.Event) { 14096 self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false 14097 } 14098 14099 if (self.isInStateTrue()) return 14100 14101 clearTimeout(self.timeout) 14102 14103 self.hoverState = 'out' 14104 14105 if (!self.options.delay || !self.options.delay.hide) return self.hide() 14106 14107 self.timeout = setTimeout(function () { 14108 if (self.hoverState == 'out') self.hide() 14109 }, self.options.delay.hide) 14110 } 14111 14112 Tooltip.prototype.show = function () { 14113 var e = $.Event('show.bs.' + this.type) 14114 14115 if (this.hasContent() && this.enabled) { 14116 this.$element.trigger(e) 14117 14118 var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0]) 14119 if (e.isDefaultPrevented() || !inDom) return 14120 var that = this 14121 14122 var $tip = this.tip() 14123 14124 var tipId = this.getUID(this.type) 14125 14126 this.setContent() 14127 $tip.attr('id', tipId) 14128 this.$element.attr('aria-describedby', tipId) 14129 14130 if (this.options.animation) $tip.addClass('fade') 14131 14132 var placement = typeof this.options.placement == 'function' ? 14133 this.options.placement.call(this, $tip[0], this.$element[0]) : 14134 this.options.placement 14135 14136 var autoToken = /\s?auto?\s?/i 14137 var autoPlace = autoToken.test(placement) 14138 if (autoPlace) placement = placement.replace(autoToken, '') || 'top' 14139 14140 $tip 14141 .detach() 14142 .css({ top: 0, left: 0, display: 'block' }) 14143 .addClass(placement) 14144 .data('bs.' + this.type, this) 14145 14146 this.options.container ? $tip.appendTo($(document).find(this.options.container)) : $tip.insertAfter(this.$element) 14147 this.$element.trigger('inserted.bs.' + this.type) 14148 14149 var pos = this.getPosition() 14150 var actualWidth = $tip[0].offsetWidth 14151 var actualHeight = $tip[0].offsetHeight 14152 14153 if (autoPlace) { 14154 var orgPlacement = placement 14155 var viewportDim = this.getPosition(this.$viewport) 14156 14157 placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' : 14158 placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' : 14159 placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' : 14160 placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' : 14161 placement 14162 14163 $tip 14164 .removeClass(orgPlacement) 14165 .addClass(placement) 14166 } 14167 14168 var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight) 14169 14170 this.applyPlacement(calculatedOffset, placement) 14171 14172 var complete = function () { 14173 var prevHoverState = that.hoverState 14174 that.$element.trigger('shown.bs.' + that.type) 14175 that.hoverState = null 14176 14177 if (prevHoverState == 'out') that.leave(that) 14178 } 14179 14180 $.support.transition && this.$tip.hasClass('fade') ? 14181 $tip 14182 .one('bsTransitionEnd', complete) 14183 .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : 14184 complete() 14185 } 14186 } 14187 14188 Tooltip.prototype.applyPlacement = function (offset, placement) { 14189 var $tip = this.tip() 14190 var width = $tip[0].offsetWidth 14191 var height = $tip[0].offsetHeight 14192 14193 // manually read margins because getBoundingClientRect includes difference 14194 var marginTop = parseInt($tip.css('margin-top'), 10) 14195 var marginLeft = parseInt($tip.css('margin-left'), 10) 14196 14197 // we must check for NaN for ie 8/9 14198 if (isNaN(marginTop)) marginTop = 0 14199 if (isNaN(marginLeft)) marginLeft = 0 14200 14201 offset.top += marginTop 14202 offset.left += marginLeft 14203 14204 // $.fn.offset doesn't round pixel values 14205 // so we use setOffset directly with our own function B-0 14206 $.offset.setOffset($tip[0], $.extend({ 14207 using: function (props) { 14208 $tip.css({ 14209 top: Math.round(props.top), 14210 left: Math.round(props.left) 14211 }) 14212 } 14213 }, offset), 0) 14214 14215 $tip.addClass('in') 14216 14217 // check to see if placing tip in new offset caused the tip to resize itself 14218 var actualWidth = $tip[0].offsetWidth 14219 var actualHeight = $tip[0].offsetHeight 14220 14221 if (placement == 'top' && actualHeight != height) { 14222 offset.top = offset.top + height - actualHeight 14223 } 14224 14225 var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight) 14226 14227 if (delta.left) offset.left += delta.left 14228 else offset.top += delta.top 14229 14230 var isVertical = /top|bottom/.test(placement) 14231 var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight 14232 var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight' 14233 14234 $tip.offset(offset) 14235 this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical) 14236 } 14237 14238 Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) { 14239 this.arrow() 14240 .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%') 14241 .css(isVertical ? 'top' : 'left', '') 14242 } 14243 14244 Tooltip.prototype.setContent = function () { 14245 var $tip = this.tip() 14246 var title = this.getTitle() 14247 14248 if (this.options.html) { 14249 if (this.options.sanitize) { 14250 title = sanitizeHtml(title, this.options.whiteList, this.options.sanitizeFn) 14251 } 14252 14253 $tip.find('.tooltip-inner').html(title) 14254 } else { 14255 $tip.find('.tooltip-inner').text(title) 14256 } 14257 14258 $tip.removeClass('fade in top bottom left right') 14259 } 14260 14261 Tooltip.prototype.hide = function (callback) { 14262 var that = this 14263 var $tip = $(this.$tip) 14264 var e = $.Event('hide.bs.' + this.type) 14265 14266 function complete() { 14267 if (that.hoverState != 'in') $tip.detach() 14268 if (that.$element) { // TODO: Check whether guarding this code with this `if` is really necessary. 14269 that.$element 14270 .removeAttr('aria-describedby') 14271 .trigger('hidden.bs.' + that.type) 14272 } 14273 callback && callback() 14274 } 14275 14276 this.$element.trigger(e) 14277 14278 if (e.isDefaultPrevented()) return 14279 14280 $tip.removeClass('in') 14281 14282 $.support.transition && $tip.hasClass('fade') ? 14283 $tip 14284 .one('bsTransitionEnd', complete) 14285 .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : 14286 complete() 14287 14288 this.hoverState = null 14289 14290 return this 14291 } 14292 14293 Tooltip.prototype.fixTitle = function () { 14294 var $e = this.$element 14295 if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') { 14296 $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') 14297 } 14298 } 14299 14300 Tooltip.prototype.hasContent = function () { 14301 return this.getTitle() 14302 } 14303 14304 Tooltip.prototype.getPosition = function ($element) { 14305 $element = $element || this.$element 14306 14307 var el = $element[0] 14308 var isBody = el.tagName == 'BODY' 14309 14310 var elRect = el.getBoundingClientRect() 14311 if (elRect.width == null) { 14312 // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093 14313 elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top }) 14314 } 14315 var isSvg = window.SVGElement && el instanceof window.SVGElement 14316 // Avoid using $.offset() on SVGs since it gives incorrect results in jQuery 3. 14317 // See https://github.com/twbs/bootstrap/issues/20280 14318 var elOffset = isBody ? { top: 0, left: 0 } : (isSvg ? null : $element.offset()) 14319 var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() } 14320 var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null 14321 14322 return $.extend({}, elRect, scroll, outerDims, elOffset) 14323 } 14324 14325 Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) { 14326 return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } : 14327 placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } : 14328 placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } : 14329 /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width } 14330 14331 } 14332 14333 Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) { 14334 var delta = { top: 0, left: 0 } 14335 if (!this.$viewport) return delta 14336 14337 var viewportPadding = this.options.viewport && this.options.viewport.padding || 0 14338 var viewportDimensions = this.getPosition(this.$viewport) 14339 14340 if (/right|left/.test(placement)) { 14341 var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll 14342 var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight 14343 if (topEdgeOffset < viewportDimensions.top) { // top overflow 14344 delta.top = viewportDimensions.top - topEdgeOffset 14345 } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow 14346 delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset 14347 } 14348 } else { 14349 var leftEdgeOffset = pos.left - viewportPadding 14350 var rightEdgeOffset = pos.left + viewportPadding + actualWidth 14351 if (leftEdgeOffset < viewportDimensions.left) { // left overflow 14352 delta.left = viewportDimensions.left - leftEdgeOffset 14353 } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow 14354 delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset 14355 } 14356 } 14357 14358 return delta 14359 } 14360 14361 Tooltip.prototype.getTitle = function () { 14362 var title 14363 var $e = this.$element 14364 var o = this.options 14365 14366 title = $e.attr('data-original-title') 14367 || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) 14368 14369 return title 14370 } 14371 14372 Tooltip.prototype.getUID = function (prefix) { 14373 do prefix += ~~(Math.random() * 1000000) 14374 while (document.getElementById(prefix)) 14375 return prefix 14376 } 14377 14378 Tooltip.prototype.tip = function () { 14379 if (!this.$tip) { 14380 this.$tip = $(this.options.template) 14381 if (this.$tip.length != 1) { 14382 throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!') 14383 } 14384 } 14385 return this.$tip 14386 } 14387 14388 Tooltip.prototype.arrow = function () { 14389 return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')) 14390 } 14391 14392 Tooltip.prototype.enable = function () { 14393 this.enabled = true 14394 } 14395 14396 Tooltip.prototype.disable = function () { 14397 this.enabled = false 14398 } 14399 14400 Tooltip.prototype.toggleEnabled = function () { 14401 this.enabled = !this.enabled 14402 } 14403 14404 Tooltip.prototype.toggle = function (e) { 14405 var self = this 14406 if (e) { 14407 self = $(e.currentTarget).data('bs.' + this.type) 14408 if (!self) { 14409 self = new this.constructor(e.currentTarget, this.getDelegateOptions()) 14410 $(e.currentTarget).data('bs.' + this.type, self) 14411 } 14412 } 14413 14414 if (e) { 14415 self.inState.click = !self.inState.click 14416 if (self.isInStateTrue()) self.enter(self) 14417 else self.leave(self) 14418 } else { 14419 self.tip().hasClass('in') ? self.leave(self) : self.enter(self) 14420 } 14421 } 14422 14423 Tooltip.prototype.destroy = function () { 14424 var that = this 14425 clearTimeout(this.timeout) 14426 this.hide(function () { 14427 that.$element.off('.' + that.type).removeData('bs.' + that.type) 14428 if (that.$tip) { 14429 that.$tip.detach() 14430 } 14431 that.$tip = null 14432 that.$arrow = null 14433 that.$viewport = null 14434 that.$element = null 14435 }) 14436 } 14437 14438 Tooltip.prototype.sanitizeHtml = function (unsafeHtml) { 14439 return sanitizeHtml(unsafeHtml, this.options.whiteList, this.options.sanitizeFn) 14440 } 14441 14442 // TOOLTIP PLUGIN DEFINITION 14443 // ========================= 14444 14445 function Plugin(option) { 14446 return this.each(function () { 14447 var $this = $(this) 14448 var data = $this.data('bs.tooltip') 14449 var options = typeof option == 'object' && option 14450 14451 if (!data && /destroy|hide/.test(option)) return 14452 if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) 14453 if (typeof option == 'string') data[option]() 14454 }) 14455 } 14456 14457 var old = $.fn.tooltip 14458 14459 $.fn.tooltip = Plugin 14460 $.fn.tooltip.Constructor = Tooltip 14461 14462 14463 // TOOLTIP NO CONFLICT 14464 // =================== 14465 14466 $.fn.tooltip.noConflict = function () { 14467 $.fn.tooltip = old 14468 return this 14469 } 14470 14471}(jQuery); 14472 14473/* ======================================================================== 14474 * Bootstrap: popover.js v3.4.1 14475 * https://getbootstrap.com/docs/3.4/javascript/#popovers 14476 * ======================================================================== 14477 * Copyright 2011-2019 Twitter, Inc. 14478 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 14479 * ======================================================================== */ 14480 14481 14482+function ($) { 14483 'use strict'; 14484 14485 // POPOVER PUBLIC CLASS DEFINITION 14486 // =============================== 14487 14488 var Popover = function (element, options) { 14489 this.init('popover', element, options) 14490 } 14491 14492 if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js') 14493 14494 Popover.VERSION = '3.4.1' 14495 14496 Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, { 14497 placement: 'right', 14498 trigger: 'click', 14499 content: '', 14500 template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>' 14501 }) 14502 14503 14504 // NOTE: POPOVER EXTENDS tooltip.js 14505 // ================================ 14506 14507 Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype) 14508 14509 Popover.prototype.constructor = Popover 14510 14511 Popover.prototype.getDefaults = function () { 14512 return Popover.DEFAULTS 14513 } 14514 14515 Popover.prototype.setContent = function () { 14516 var $tip = this.tip() 14517 var title = this.getTitle() 14518 var content = this.getContent() 14519 14520 if (this.options.html) { 14521 var typeContent = typeof content 14522 14523 if (this.options.sanitize) { 14524 title = this.sanitizeHtml(title) 14525 14526 if (typeContent === 'string') { 14527 content = this.sanitizeHtml(content) 14528 } 14529 } 14530 14531 $tip.find('.popover-title').html(title) 14532 $tip.find('.popover-content').children().detach().end()[ 14533 typeContent === 'string' ? 'html' : 'append' 14534 ](content) 14535 } else { 14536 $tip.find('.popover-title').text(title) 14537 $tip.find('.popover-content').children().detach().end().text(content) 14538 } 14539 14540 $tip.removeClass('fade top bottom left right in') 14541 14542 // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do 14543 // this manually by checking the contents. 14544 if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide() 14545 } 14546 14547 Popover.prototype.hasContent = function () { 14548 return this.getTitle() || this.getContent() 14549 } 14550 14551 Popover.prototype.getContent = function () { 14552 var $e = this.$element 14553 var o = this.options 14554 14555 return $e.attr('data-content') 14556 || (typeof o.content == 'function' ? 14557 o.content.call($e[0]) : 14558 o.content) 14559 } 14560 14561 Popover.prototype.arrow = function () { 14562 return (this.$arrow = this.$arrow || this.tip().find('.arrow')) 14563 } 14564 14565 14566 // POPOVER PLUGIN DEFINITION 14567 // ========================= 14568 14569 function Plugin(option) { 14570 return this.each(function () { 14571 var $this = $(this) 14572 var data = $this.data('bs.popover') 14573 var options = typeof option == 'object' && option 14574 14575 if (!data && /destroy|hide/.test(option)) return 14576 if (!data) $this.data('bs.popover', (data = new Popover(this, options))) 14577 if (typeof option == 'string') data[option]() 14578 }) 14579 } 14580 14581 var old = $.fn.popover 14582 14583 $.fn.popover = Plugin 14584 $.fn.popover.Constructor = Popover 14585 14586 14587 // POPOVER NO CONFLICT 14588 // =================== 14589 14590 $.fn.popover.noConflict = function () { 14591 $.fn.popover = old 14592 return this 14593 } 14594 14595}(jQuery); 14596 14597/* ======================================================================== 14598 * Bootstrap: scrollspy.js v3.4.1 14599 * https://getbootstrap.com/docs/3.4/javascript/#scrollspy 14600 * ======================================================================== 14601 * Copyright 2011-2019 Twitter, Inc. 14602 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 14603 * ======================================================================== */ 14604 14605 14606+function ($) { 14607 'use strict'; 14608 14609 // SCROLLSPY CLASS DEFINITION 14610 // ========================== 14611 14612 function ScrollSpy(element, options) { 14613 this.$body = $(document.body) 14614 this.$scrollElement = $(element).is(document.body) ? $(window) : $(element) 14615 this.options = $.extend({}, ScrollSpy.DEFAULTS, options) 14616 this.selector = (this.options.target || '') + ' .nav li > a' 14617 this.offsets = [] 14618 this.targets = [] 14619 this.activeTarget = null 14620 this.scrollHeight = 0 14621 14622 this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this)) 14623 this.refresh() 14624 this.process() 14625 } 14626 14627 ScrollSpy.VERSION = '3.4.1' 14628 14629 ScrollSpy.DEFAULTS = { 14630 offset: 10 14631 } 14632 14633 ScrollSpy.prototype.getScrollHeight = function () { 14634 return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight) 14635 } 14636 14637 ScrollSpy.prototype.refresh = function () { 14638 var that = this 14639 var offsetMethod = 'offset' 14640 var offsetBase = 0 14641 14642 this.offsets = [] 14643 this.targets = []
vendor: 10,384 bytes, lines 14644-15013
14644 this.scrollHeight = this.getScrollHeight() 14645 14646 if (!$.isWindow(this.$scrollElement[0])) { 14647 offsetMethod = 'position' 14648 offsetBase = this.$scrollElement.scrollTop() 14649 } 14650 14651 this.$body 14652 .find(this.selector) 14653 .map(function () { 14654 var $el = $(this) 14655 var href = $el.data('target') || $el.attr('href') 14656 var $href = /^#./.test(href) && $(href) 14657 14658 return ($href 14659 && $href.length 14660 && $href.is(':visible') 14661 && [[$href[offsetMethod]().top + offsetBase, href]]) || null 14662 }) 14663 .sort(function (a, b) { return a[0] - b[0] }) 14664 .each(function () { 14665 that.offsets.push(this[0]) 14666 that.targets.push(this[1]) 14667 }) 14668 } 14669 14670 ScrollSpy.prototype.process = function () { 14671 var scrollTop = this.$scrollElement.scrollTop() + this.options.offset 14672 var scrollHeight = this.getScrollHeight() 14673 var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height() 14674 var offsets = this.offsets 14675 var targets = this.targets 14676 var activeTarget = this.activeTarget 14677 var i 14678 14679 if (this.scrollHeight != scrollHeight) { 14680 this.refresh() 14681 } 14682 14683 if (scrollTop >= maxScroll) { 14684 return activeTarget != (i = targets[targets.length - 1]) && this.activate(i) 14685 } 14686 14687 if (activeTarget && scrollTop < offsets[0]) { 14688 this.activeTarget = null 14689 return this.clear() 14690 } 14691 14692 for (i = offsets.length; i--;) { 14693 activeTarget != targets[i] 14694 && scrollTop >= offsets[i] 14695 && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1]) 14696 && this.activate(targets[i]) 14697 } 14698 } 14699 14700 ScrollSpy.prototype.activate = function (target) { 14701 this.activeTarget = target 14702 14703 this.clear() 14704 14705 var selector = this.selector + 14706 '[data-target="' + target + '"],' + 14707 this.selector + '[href="' + target + '"]' 14708 14709 var active = $(selector) 14710 .parents('li') 14711 .addClass('active') 14712 14713 if (active.parent('.dropdown-menu').length) { 14714 active = active 14715 .closest('li.dropdown') 14716 .addClass('active') 14717 } 14718 14719 active.trigger('activate.bs.scrollspy') 14720 } 14721 14722 ScrollSpy.prototype.clear = function () { 14723 $(this.selector) 14724 .parentsUntil(this.options.target, '.active') 14725 .removeClass('active') 14726 } 14727 14728 14729 // SCROLLSPY PLUGIN DEFINITION 14730 // =========================== 14731 14732 function Plugin(option) { 14733 return this.each(function () { 14734 var $this = $(this) 14735 var data = $this.data('bs.scrollspy') 14736 var options = typeof option == 'object' && option 14737 14738 if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options))) 14739 if (typeof option == 'string') data[option]() 14740 }) 14741 } 14742 14743 var old = $.fn.scrollspy 14744 14745 $.fn.scrollspy = Plugin 14746 $.fn.scrollspy.Constructor = ScrollSpy 14747 14748 14749 // SCROLLSPY NO CONFLICT 14750 // ===================== 14751 14752 $.fn.scrollspy.noConflict = function () { 14753 $.fn.scrollspy = old 14754 return this 14755 } 14756 14757 14758 // SCROLLSPY DATA-API 14759 // ================== 14760 14761 $(window).on('load.bs.scrollspy.data-api', function () { 14762 $('[data-spy="scroll"]').each(function () { 14763 var $spy = $(this) 14764 Plugin.call($spy, $spy.data()) 14765 }) 14766 }) 14767 14768}(jQuery); 14769 14770/* ======================================================================== 14771 * Bootstrap: tab.js v3.4.1 14772 * https://getbootstrap.com/docs/3.4/javascript/#tabs 14773 * ======================================================================== 14774 * Copyright 2011-2019 Twitter, Inc. 14775 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 14776 * ======================================================================== */ 14777 14778 14779+function ($) { 14780 'use strict'; 14781 14782 // TAB CLASS DEFINITION 14783 // ==================== 14784 14785 var Tab = function (element) { 14786 // jscs:disable requireDollarBeforejQueryAssignment 14787 this.element = $(element) 14788 // jscs:enable requireDollarBeforejQueryAssignment 14789 } 14790 14791 Tab.VERSION = '3.4.1' 14792 14793 Tab.TRANSITION_DURATION = 150 14794 14795 Tab.prototype.show = function () { 14796 var $this = this.element 14797 var $ul = $this.closest('ul:not(.dropdown-menu)') 14798 var selector = $this.data('target') 14799 14800 if (!selector) { 14801 selector = $this.attr('href') 14802 selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 14803 } 14804 14805 if ($this.parent('li').hasClass('active')) return 14806 14807 var $previous = $ul.find('.active:last a') 14808 var hideEvent = $.Event('hide.bs.tab', { 14809 relatedTarget: $this[0] 14810 }) 14811 var showEvent = $.Event('show.bs.tab', { 14812 relatedTarget: $previous[0] 14813 }) 14814 14815 $previous.trigger(hideEvent) 14816 $this.trigger(showEvent) 14817 14818 if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return 14819 14820 var $target = $(document).find(selector) 14821 14822 this.activate($this.closest('li'), $ul) 14823 this.activate($target, $target.parent(), function () { 14824 $previous.trigger({ 14825 type: 'hidden.bs.tab', 14826 relatedTarget: $this[0] 14827 }) 14828 $this.trigger({ 14829 type: 'shown.bs.tab', 14830 relatedTarget: $previous[0] 14831 }) 14832 }) 14833 } 14834 14835 Tab.prototype.activate = function (element, container, callback) { 14836 var $active = container.find('> .active') 14837 var transition = callback 14838 && $.support.transition 14839 && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length) 14840 14841 function next() { 14842 $active 14843 .removeClass('active') 14844 .find('> .dropdown-menu > .active') 14845 .removeClass('active') 14846 .end() 14847 .find('[data-toggle="tab"]') 14848 .attr('aria-expanded', false) 14849 14850 element 14851 .addClass('active') 14852 .find('[data-toggle="tab"]') 14853 .attr('aria-expanded', true) 14854 14855 if (transition) { 14856 element[0].offsetWidth // reflow for transition 14857 element.addClass('in') 14858 } else { 14859 element.removeClass('fade') 14860 } 14861 14862 if (element.parent('.dropdown-menu').length) { 14863 element 14864 .closest('li.dropdown') 14865 .addClass('active') 14866 .end() 14867 .find('[data-toggle="tab"]') 14868 .attr('aria-expanded', true) 14869 } 14870 14871 callback && callback() 14872 } 14873 14874 $active.length && transition ? 14875 $active 14876 .one('bsTransitionEnd', next) 14877 .emulateTransitionEnd(Tab.TRANSITION_DURATION) : 14878 next() 14879 14880 $active.removeClass('in') 14881 } 14882 14883 14884 // TAB PLUGIN DEFINITION 14885 // ===================== 14886 14887 function Plugin(option) { 14888 return this.each(function () { 14889 var $this = $(this) 14890 var data = $this.data('bs.tab') 14891 14892 if (!data) $this.data('bs.tab', (data = new Tab(this))) 14893 if (typeof option == 'string') data[option]() 14894 }) 14895 } 14896 14897 var old = $.fn.tab 14898 14899 $.fn.tab = Plugin 14900 $.fn.tab.Constructor = Tab 14901 14902 14903 // TAB NO CONFLICT 14904 // =============== 14905 14906 $.fn.tab.noConflict = function () { 14907 $.fn.tab = old 14908 return this 14909 } 14910 14911 14912 // TAB DATA-API 14913 // ============ 14914 14915 var clickHandler = function (e) { 14916 e.preventDefault() 14917 Plugin.call($(this), 'show') 14918 } 14919 14920 $(document) 14921 .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler) 14922 .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler) 14923 14924}(jQuery); 14925 14926/* ======================================================================== 14927 * Bootstrap: affix.js v3.4.1 14928 * https://getbootstrap.com/docs/3.4/javascript/#affix 14929 * ======================================================================== 14930 * Copyright 2011-2019 Twitter, Inc. 14931 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 14932 * ======================================================================== */ 14933 14934 14935+function ($) { 14936 'use strict'; 14937 14938 // AFFIX CLASS DEFINITION 14939 // ====================== 14940 14941 var Affix = function (element, options) { 14942 this.options = $.extend({}, Affix.DEFAULTS, options) 14943 14944 var target = this.options.target === Affix.DEFAULTS.target ? $(this.options.target) : $(document).find(this.options.target) 14945 14946 this.$target = target 14947 .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this)) 14948 .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this)) 14949 14950 this.$element = $(element) 14951 this.affixed = null 14952 this.unpin = null 14953 this.pinnedOffset = null 14954 14955 this.checkPosition() 14956 } 14957 14958 Affix.VERSION = '3.4.1' 14959 14960 Affix.RESET = 'affix affix-top affix-bottom' 14961 14962 Affix.DEFAULTS = { 14963 offset: 0, 14964 target: window 14965 } 14966 14967 Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) { 14968 var scrollTop = this.$target.scrollTop() 14969 var position = this.$element.offset() 14970 var targetHeight = this.$target.height() 14971 14972 if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false 14973 14974 if (this.affixed == 'bottom') { 14975 if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom' 14976 return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom' 14977 } 14978 14979 var initializing = this.affixed == null 14980 var colliderTop = initializing ? scrollTop : position.top 14981 var colliderHeight = initializing ? targetHeight : height 14982 14983 if (offsetTop != null && scrollTop <= offsetTop) return 'top' 14984 if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom' 14985 14986 return false 14987 } 14988 14989 Affix.prototype.getPinnedOffset = function () { 14990 if (this.pinnedOffset) return this.pinnedOffset 14991 this.$element.removeClass(Affix.RESET).addClass('affix') 14992 var scrollTop = this.$target.scrollTop() 14993 var position = this.$element.offset() 14994 return (this.pinnedOffset = position.top - scrollTop) 14995 } 14996 14997 Affix.prototype.checkPositionWithEventLoop = function () { 14998 setTimeout($.proxy(this.checkPosition, this), 1) 14999 } 15000 15001 Affix.prototype.checkPosition = function () { 15002 if (!this.$element.is(':visible')) return 15003 15004 var height = this.$element.height() 15005 var offset = this.options.offset 15006 var offsetTop = offset.top 15007 var offsetBottom = offset.bottom 15008 var scrollHeight = Math.max($(document).height(), $(document.body).height()) 15009 15010 if (typeof offset != 'object') offsetBottom = offsetTop = offset 15011 if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element) 15012 if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element) 15013
15014 var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom) 15015 15016 if (this.affixed != affix) { 15017 if (this.unpin != null) this.$element.css('top', '') 15018 15019 var affixType = 'affix' + (affix ? '-' + affix : '') 15020 var e = $.Event(affixType + '.bs.affix') 15021 15022 this.$element.trigger(e) 15023 15024 if (e.isDefaultPrevented()) return 15025 15026 this.affixed = affix 15027 this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null 15028 15029 this.$element 15030 .removeClass(Affix.RESET) 15031 .addClass(affixType) 15032 .trigger(affixType.replace('affix', 'affixed') + '.bs.affix') 15033 } 15034 15035 if (affix == 'bottom') { 15036 this.$element.offset({ 15037 top: scrollHeight - height - offsetBottom 15038 }) 15039 } 15040 } 15041 15042 15043 // AFFIX PLUGIN DEFINITION 15044 // ======================= 15045 15046 function Plugin(option) { 15047 return this.each(function () { 15048 var $this = $(this) 15049 var data = $this.data('bs.affix') 15050 var options = typeof option == 'object' && option 15051 15052 if (!data) $this.data('bs.affix', (data = new Affix(this, options))) 15053 if (typeof option == 'string') data[option]() 15054 }) 15055 } 15056 15057 var old = $.fn.affix 15058 15059 $.fn.affix = Plugin 15060 $.fn.affix.Constructor = Affix 15061 15062 15063 // AFFIX NO CONFLICT 15064 // ================= 15065 15066 $.fn.affix.noConflict = function () { 15067 $.fn.affix = old 15068 return this 15069 } 15070 15071 15072 // AFFIX DATA-API 15073 // ============== 15074 15075 $(window).on('load', function () { 15076 $('[data-spy="affix"]').each(function () { 15077 var $spy = $(this) 15078 var data = $spy.data() 15079 15080 data.offset = data.offset || {} 15081 15082 if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom 15083 if (data.offsetTop != null) data.offset.top = data.offsetTop 15084 15085 Plugin.call($spy, data) 15086 }) 15087 }) 15088 15089}(jQuery); 15090 15091/* 15092 * jQuery Templating Plugin 15093 * Copyright 2010, John Resig 15094 * Dual licensed under the MIT or GPL Version 2 licenses. 15095 */ 15096(function( jQuery, undefined ){ 15097 var oldManip = jQuery.fn.domManip, tmplItmAtt = "_tmplitem", htmlExpr = /^[^<]*(<[\w\W]+>)[^>]*$|\{\{\! /, 15098 newTmplItems = {}, wrappedItems = {}, appendToTmplItems, topTmplItem = { key: 0, data: {} }, itemKey = 0, cloneIndex = 0, stack = []; 15099 15100 function newTmplItem( options, parentItem, fn, data ) { 15101 // Returns a template item data structure for a new rendered instance of a template (a 'template item'). 15102 // The content field is a hierarchical array of strings and nested items (to be 15103 // removed and replaced by nodes field of dom elements, once inserted in DOM). 15104 var newItem = { 15105 data: data || (parentItem ? parentItem.data : {}), 15106 _wrap: parentItem ? parentItem._wrap : null, 15107 tmpl: null, 15108 parent: parentItem || null, 15109 nodes: [], 15110 calls: tiCalls, 15111 nest: tiNest, 15112 wrap: tiWrap, 15113 html: tiHtml, 15114 update: tiUpdate 15115 }; 15116 if ( options ) { 15117 jQuery.extend( newItem, options, { nodes: [], parent: parentItem } ); 15118 } 15119 if ( fn ) { 15120 // Build the hierarchical content to be used during insertion into DOM 15121 newItem.tmpl = fn; 15122 newItem._ctnt = newItem._ctnt || newItem.tmpl( jQuery, newItem ); 15123 newItem.key = ++itemKey; 15124 // Keep track of new template item, until it is stored as jQuery Data on DOM element 15125 (stack.length ? wrappedItems : newTmplItems)[itemKey] = newItem; 15126 } 15127 return newItem; 15128 } 15129 15130 // Override appendTo etc., in order to provide support for targeting multiple elements. (This code would disappear if integrated in jquery core). 15131 jQuery.each({ 15132 appendTo: "append", 15133 prependTo: "prepend", 15134 insertBefore: "before", 15135 insertAfter: "after", 15136 replaceAll: "replaceWith" 15137 }, function( name, original ) { 15138 jQuery.fn[ name ] = function( selector ) { 15139 var ret = [], insert = jQuery( selector ), elems, i, l, tmplItems, 15140 parent = this.length === 1 && this[0].parentNode; 15141 15142 appendToTmplItems = newTmplItems || {}; 15143 if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) { 15144 insert[ original ]( this[0] ); 15145 ret = this; 15146 } else { 15147 for ( i = 0, l = insert.length; i < l; i++ ) { 15148 cloneIndex = i; 15149 elems = (i > 0 ? this.clone(true) : this).get(); 15150 jQuery.fn[ original ].apply( jQuery(insert[i]), elems ); 15151 ret = ret.concat( elems ); 15152 } 15153 cloneIndex = 0; 15154 ret = this.pushStack( ret, name, insert.selector ); 15155 } 15156 tmplItems = appendToTmplItems; 15157 appendToTmplItems = null; 15158 jQuery.tmpl.complete( tmplItems ); 15159 return ret; 15160 }; 15161 }); 15162 15163 jQuery.fn.extend({ 15164 // Use first wrapped element as template markup. 15165 // Return wrapped set of template items, obtained by rendering template against data. 15166 tmpl: function( data, options, parentItem ) { 15167 return jQuery.tmpl( this[0], data, options, parentItem ); 15168 }, 15169 15170 // Find which rendered template item the first wrapped DOM element belongs to 15171 tmplItem: function() { 15172 return jQuery.tmplItem( this[0] ); 15173 }, 15174 15175 // Consider the first wrapped element as a template declaration, and get the compiled template or store it as a named template. 15176 template: function( name ) { 15177 return jQuery.template( name, this[0] ); 15178 }, 15179 15180 domManip: function( args, table, callback, options ) { 15181 // This appears to be a bug in the appendTo, etc. implementation 15182 // it should be doing .call() instead of .apply(). See #6227 15183 if ( args[0] && args[0].nodeType ) { 15184 var dmArgs = jQuery.makeArray( arguments ), argsLength = args.length, i = 0, tmplItem; 15185 while ( i < argsLength && !(tmplItem = jQuery.data( args[i++], "tmplItem" ))) {} 15186 if ( argsLength > 1 ) { 15187 dmArgs[0] = [jQuery.makeArray( args )]; 15188 } 15189 if ( tmplItem && cloneIndex ) { 15190 dmArgs[2] = function( fragClone ) { 15191 // Handler called by oldManip when rendered template has been inserted into DOM. 15192 jQuery.tmpl.afterManip( this, fragClone, callback ); 15193 }; 15194 } 15195 oldManip.apply( this, dmArgs ); 15196 } else { 15197 oldManip.apply( this, arguments ); 15198 } 15199 cloneIndex = 0; 15200 if ( !appendToTmplItems ) { 15201 jQuery.tmpl.complete( newTmplItems ); 15202 } 15203 return this; 15204 } 15205 }); 15206 15207 jQuery.extend({ 15208 // Return wrapped set of template items, obtained by rendering template against data. 15209 tmpl: function( tmpl, data, options, parentItem ) { 15210 var ret, topLevel = !parentItem; 15211 if ( topLevel ) { 15212 // This is a top-level tmpl call (not from a nested template using {{tmpl}}) 15213 parentItem = topTmplItem; 15214 tmpl = jQuery.template[tmpl] || jQuery.template( null, tmpl ); 15215 wrappedItems = {}; // Any wrapped items will be rebuilt, since this is top level 15216 } else if ( !tmpl ) { 15217 // The template item is already associated with DOM - this is a refresh. 15218 // Re-evaluate rendered template for the parentItem 15219 tmpl = parentItem.tmpl; 15220 newTmplItems[parentItem.key] = parentItem; 15221 parentItem.nodes = []; 15222 if ( parentItem.wrapped ) { 15223 updateWrapped( parentItem, parentItem.wrapped ); 15224 } 15225 // Rebuild, without creating a new template item 15226 return jQuery( build( parentItem, null, parentItem.tmpl( jQuery, parentItem ) )); 15227 } 15228 if ( !tmpl ) { 15229 return []; // Could throw... 15230 } 15231 if ( typeof data === "function" ) { 15232 data = data.call( parentItem || {} ); 15233 } 15234 if ( options && options.wrapped ) { 15235 updateWrapped( options, options.wrapped ); 15236 } 15237 ret = jQuery.isArray( data ) ? 15238 jQuery.map( data, function( dataItem ) { 15239 return dataItem ? newTmplItem( options, parentItem, tmpl, dataItem ) : null; 15240 }) : 15241 [ newTmplItem( options, parentItem, tmpl, data ) ]; 15242 return topLevel ? jQuery( build( parentItem, null, ret ) ) : ret; 15243 }, 15244 15245 // Return rendered template item for an element. 15246 tmplItem: function( elem ) { 15247 var tmplItem; 15248 if ( elem instanceof jQuery ) { 15249 elem = elem[0]; 15250 } 15251 while ( elem && elem.nodeType === 1 && !(tmplItem = jQuery.data( elem, "tmplItem" )) && (elem = elem.parentNode) ) {} 15252 return tmplItem || topTmplItem; 15253 }, 15254 15255 // Set: 15256 // Use $.template( name, tmpl ) to cache a named template, 15257 // where tmpl is a template string, a script element or a jQuery instance wrapping a script element, etc. 15258 // Use $( "selector" ).template( name ) to provide access by name to a script block template declaration. 15259 15260 // Get: 15261 // Use $.template( name ) to access a cached template. 15262 // Also $( selectorToScriptBlock ).template(), or $.template( null, templateString ) 15263 // will return the compiled template, without adding a name reference. 15264 // If templateString includes at least one HTML tag, $.template( templateString )
vendor: 15,878 bytes, lines 15264-15594
15264is equivalent 15265 // to $.template( null, templateString ) 15266 template: function( name, tmpl ) { 15267 if (tmpl) { 15268 // Compile template and associate with name 15269 if ( typeof tmpl === "string" ) { 15270 // This is an HTML string being passed directly in. 15271 tmpl = buildTmplFn( tmpl ) 15272 } else if ( tmpl instanceof jQuery ) { 15273 tmpl = tmpl[0] || {}; 15274 } 15275 if ( tmpl.nodeType ) { 15276 // If this is a template block, use cached copy, or generate tmpl function and cache. 15277 tmpl = jQuery.data( tmpl, "tmpl" ) || jQuery.data( tmpl, "tmpl", buildTmplFn( tmpl.innerHTML )); 15278 } 15279 return typeof name === "string" ? (jQuery.template[name] = tmpl) : tmpl; 15280 } 15281 // Return named compiled template 15282 return name ? (typeof name !== "string" ? jQuery.template( null, name ): 15283 (jQuery.template[name] || 15284 // If not in map, treat as a selector. (If integrated with core, use quickExpr.exec) 15285 jQuery.template( null, htmlExpr.test( name ) ? name : jQuery( name )))) : null; 15286 }, 15287 15288 encode: function( text ) { 15289 // Do HTML encoding replacing < > & and ' and " by corresponding entities. 15290 return ("" + text).split("<").join("<").split(">").join(">").split('"').join(""").split("'").join("'"); 15291 } 15292 }); 15293 15294 jQuery.extend( jQuery.tmpl, { 15295 tag: { 15296 "tmpl": { 15297 _default: { $2: "null" }, 15298 open: "if($notnull_1){_=_.concat($item.nest($1,$2));}" 15299 // tmpl target parameter can be of type function, so use $1, not $1a (so not auto detection of functions) 15300 // This means that {{tmpl foo}} treats foo as a template (which IS a function). 15301 // Explicit parens can be used if foo is a function that returns a template: {{tmpl foo()}}. 15302 }, 15303 "wrap": { 15304 _default: { $2: "null" }, 15305 open: "$item.calls(_,$1,$2);_=[];", 15306 close: "call=$item.calls();_=call._.concat($item.wrap(call,_));" 15307 }, 15308 "each": { 15309 _default: { $2: "$index, $value" }, 15310 open: "if($notnull_1){$.each($1a,function($2){with(this){", 15311 close: "}});}" 15312 }, 15313 "if": { 15314 open: "if(($notnull_1) && $1a){", 15315 close: "}" 15316 }, 15317 "else": { 15318 _default: { $1: "true" }, 15319 open: "}else if(($notnull_1) && $1a){" 15320 }, 15321 "html": { 15322 // Unecoded expression evaluation. 15323 open: "if($notnull_1){_.push($1a);}" 15324 }, 15325 "=": { 15326 // Encoded expression evaluation. Abbreviated form is ${}. 15327 _default: { $1: "$data" }, 15328 open: "if($notnull_1){_.push($.encode($1a));}" 15329 }, 15330 "!": { 15331 // Comment tag. Skipped by parser 15332 open: "" 15333 } 15334 }, 15335 15336 // This stub can be overridden, e.g. in jquery.tmplPlus for providing rendered events 15337 complete: function( items ) { 15338 newTmplItems = {}; 15339 }, 15340 15341 // Call this from code which overrides domManip, or equivalent 15342 // Manage cloning/storing template items etc. 15343 afterManip: function afterManip( elem, fragClone, callback ) { 15344 // Provides cloned fragment ready for fixup prior to and after insertion into DOM 15345 var content = fragClone.nodeType === 11 ? 15346 jQuery.makeArray(fragClone.childNodes) : 15347 fragClone.nodeType === 1 ? [fragClone] : []; 15348 15349 // Return fragment to original caller (e.g. append) for DOM insertion 15350 callback.call( elem, fragClone ); 15351 15352 // Fragment has been inserted:- Add inserted nodes to tmplItem data structure. Replace inserted element annotations by jQuery.data. 15353 storeTmplItems( content ); 15354 cloneIndex++; 15355 } 15356 }); 15357 15358 //========================== Private helper functions, used by code above ========================== 15359 15360 function build( tmplItem, nested, content ) { 15361 // Convert hierarchical content into flat string array 15362 // and finally return array of fragments ready for DOM insertion 15363 var frag, ret = content ? jQuery.map( content, function( item ) { 15364 return (typeof item === "string") ? 15365 // Insert template item annotations, to be converted to jQuery.data( "tmplItem" ) when elems are inserted into DOM. 15366 (tmplItem.key ? item.replace( /(<\w+)(?=[\s>])(?![^>]*_tmplitem)([^>]*)/g, "$1 " + tmplItmAtt + "=\"" + tmplItem.key + "\" $2" ) : item) : 15367 // This is a child template item. Build nested template. 15368 build( item, tmplItem, item._ctnt ); 15369 }) : 15370 // 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()}}. 15371 tmplItem; 15372 if ( nested ) { 15373 return ret; 15374 } 15375 15376 // top-level template 15377 ret = ret.join(""); 15378 15379 // Support templates which have initial or final text nodes, or consist only of text 15380 // Also support HTML entities within the HTML markup. 15381 ret.replace( /^\s*([^<\s][^<]*)?(<[\w\W]+>)([^>]*[^>\s])?\s*$/, function( all, before, middle, after) { 15382 frag = jQuery( middle ).get(); 15383 15384 storeTmplItems( frag ); 15385 if ( before ) { 15386 frag = unencode( before ).concat(frag); 15387 } 15388 if ( after ) { 15389 frag = frag.concat(unencode( after )); 15390 } 15391 }); 15392 return frag ? frag : unencode( ret ); 15393 } 15394 15395 function unencode( text ) { 15396 // Use createElement, since createTextNode will not render HTML entities correctly 15397 var el = document.createElement( "div" ); 15398 el.innerHTML = text; 15399 return jQuery.makeArray(el.childNodes); 15400 } 15401 15402 // Generate a reusable function that will serve to render a template against data 15403 function buildTmplFn( markup ) { 15404 return new Function("jQuery","$item", 15405 "var $=jQuery,call,_=[],$data=$item.data;" + 15406 15407 // Introduce the data as local variables using with(){} 15408 "with($data){_.push('" + 15409 15410 // Convert the template into pure JavaScript 15411 jQuery.trim(markup) 15412 .replace( /([\\'])/g, "\\$1" ) 15413 .replace( /[\r\t\n]/g, " " ) 15414 .replace( /\$\{([^\}]*)\}/g, "{{= $1}}" ) 15415 .replace( /\{\{(\/?)(\w+|.)(?:\(((?:[^\}]|\}(?!\}))*?)?\))?(?:\s+(.*?)?)?(\(((?:[^\}]|\}(?!\}))*?)\))?\s*\}\}/g, 15416 function( all, slash, type, fnargs, target, parens, args ) { 15417 var tag = jQuery.tmpl.tag[ type ], def, expr, exprAutoFnDetect; 15418 if ( !tag ) { 15419 throw "Template command not found: " + type; 15420 } 15421 def = tag._default || []; 15422 if ( parens && !/\w$/.test(target)) { 15423 target += parens; 15424 parens = ""; 15425 } 15426 if ( target ) { 15427 target = unescape( target ); 15428 args = args ? ("," + unescape( args ) + ")") : (parens ? ")" : ""); 15429 // Support for target being things like a.toLowerCase(); 15430 // In that case don't call with template item as 'this' pointer. Just evaluate... 15431 expr = parens ? (target.indexOf(".") > -1 ? target + parens : ("(" + target + ").call($item" + args)) : target; 15432 exprAutoFnDetect = parens ? expr : "(typeof(" + target + ")==='function'?(" + target + ").call($item):(" + target + "))"; 15433 } else { 15434 exprAutoFnDetect = expr = def.$1 || "null"; 15435 } 15436 fnargs = unescape( fnargs ); 15437 return "');" + 15438 tag[ slash ? "close" : "open" ] 15439 .split( "$notnull_1" ).join( target ? "typeof(" + target + ")!=='undefined' && (" + target + ")!=null" : "true" ) 15440 .split( "$1a" ).join( exprAutoFnDetect ) 15441 .split( "$1" ).join( expr ) 15442 .split( "$2" ).join( fnargs ? 15443 fnargs.replace( /\s*([^\(]+)\s*(\((.*?)\))?/g, function( all, name, parens, params ) { 15444 params = params ? ("," + params + ")") : (parens ? ")" : ""); 15445 return params ? ("(" + name + ").call($item" + params) : all; 15446 }) 15447 : (def.$2||"") 15448 ) + 15449 "_.push('"; 15450 }) + 15451 "');}return _;" 15452 ); 15453 } 15454 function updateWrapped( options, wrapped ) { 15455 // Build the wrapped content. 15456 options._wrap = build( options, true, 15457 // Suport imperative scenario in which options.wrapped can be set to a selector or an HTML string. 15458 jQuery.isArray( wrapped ) ? wrapped : [htmlExpr.test( wrapped ) ? wrapped : jQuery( wrapped ).html()] 15459 ).join(""); 15460 } 15461 15462 function unescape( args ) { 15463 return args ? args.replace( /\\'/g, "'").replace(/\\\\/g, "\\" ) : null; 15464 } 15465 function outerHtml( elem ) { 15466 var div = document.createElement("div"); 15467 div.appendChild( elem.cloneNode(true) ); 15468 return div.innerHTML; 15469 } 15470 15471 // Store template items in jQuery.data(), ensuring a unique tmplItem data data structure for each rendered template instance. 15472 function storeTmplItems( content ) { 15473 var keySuffix = "_" + cloneIndex, elem, elems, newClonedItems = {}, i, l, m; 15474 for ( i = 0, l = content.length; i < l; i++ ) { 15475 if ( (elem = content[i]).nodeType !== 1 ) { 15476 continue; 15477 } 15478 elems = elem.getElementsByTagName("*"); 15479 for ( m = elems.length - 1; m >= 0; m-- ) { 15480 processItemKey( elems[m] ); 15481 } 15482 processItemKey( elem ); 15483 } 15484 function processItemKey( el ) { 15485 var pntKey, pntNode = el, pntItem, tmplItem, key; 15486 // Ensure that each rendered template inserted into the DOM has its own template item, 15487 if ( (key = el.getAttribute( tmplItmAtt ))) { 15488 while ( pntNode.parentNode && (pntNode = pntNode.parentNode).nodeType === 1 && !(pntKey = pntNode.getAttribute( tmplItmAtt ))) { } 15489 if ( pntKey !== key ) { 15490 // The next ancestor with a _tmplitem expando is on a different key than this one. 15491 // So this is a top-level element within this template item 15492 // Set pntNode to the key of the parentNode, or to 0 if pntNode.parentNode is null, or pntNode is a fragment. 15493 pntNode = pntNode.parentNode ? (pntNode.nodeType === 11 ? 0 : (pntNode.getAttribute( tmplItmAtt ) || 0)) : 0; 15494 if ( !(tmplItem = newTmplItems[key]) ) { 15495 // The item is for wrapped content, and was copied from the temporary parent wrappedItem. 15496 tmplItem = wrappedItems[key]; 15497 tmplItem = newTmplItem( tmplItem, newTmplItems[pntNode]||wrappedItems[pntNode], null, true ); 15498 tmplItem.key = ++itemKey; 15499 newTmplItems[itemKey] = tmplItem; 15500 } 15501 if ( cloneIndex ) { 15502 cloneTmplItem( key ); 15503 } 15504 } 15505 el.removeAttribute( tmplItmAtt ); 15506 } else if ( cloneIndex && (tmplItem = jQuery.data( el, "tmplItem" )) ) { 15507 // This was a rendered element, cloned during append or appendTo etc. 15508 // TmplItem stored in jQuery data has already been cloned in cloneCopyEvent. We must replace it with a fresh cloned tmplItem. 15509 cloneTmplItem( tmplItem.key ); 15510 newTmplItems[tmplItem.key] = tmplItem; 15511 pntNode = jQuery.data( el.parentNode, "tmplItem" ); 15512 pntNode = pntNode ? pntNode.key : 0; 15513 } 15514 if ( tmplItem ) { 15515 pntItem = tmplItem; 15516 // Find the template item of the parent element. 15517 // (Using !=, not !==, since pntItem.key is number, and pntNode may be a string) 15518 while ( pntItem && pntItem.key != pntNode ) { 15519 // Add this element as a top-level node for this rendered template item, as well as for any 15520 // ancestor items between this item and the item of its parent element 15521 pntItem.nodes.push( el ); 15522 pntItem = pntItem.parent; 15523 } 15524 // Delete content built during rendering - reduce API surface area and memory use, and avoid exposing of stale data after rendering... 15525 delete tmplItem._ctnt; 15526 delete tmplItem._wrap; 15527 // Store template item as jQuery data on the element 15528 jQuery.data( el, "tmplItem", tmplItem ); 15529 } 15530 function cloneTmplItem( key ) { 15531 key = key + keySuffix; 15532 tmplItem = newClonedItems[key] = 15533 (newClonedItems[key] || newTmplItem( tmplItem, newTmplItems[tmplItem.parent.key + keySuffix] || tmplItem.parent, null, true )); 15534 } 15535 } 15536 } 15537 15538 //---- Helper functions for template item ---- 15539 15540 function tiCalls( content, tmpl, data, options ) { 15541 if ( !content ) { 15542 return stack.pop(); 15543 } 15544 stack.push({ _: content, tmpl: tmpl, item:this, data: data, options: options }); 15545 } 15546 15547 function tiNest( tmpl, data, options ) { 15548 // nested template, using {{tmpl}} tag 15549 return jQuery.tmpl( jQuery.template( tmpl ), data, options, this ); 15550 } 15551 15552 function tiWrap( call, wrapped ) { 15553 // nested template, using {{wrap}} tag 15554 var options = call.options || {}; 15555 options.wrapped = wrapped; 15556 // Apply the template, which may incorporate wrapped content, 15557 return jQuery.tmpl( jQuery.template( call.tmpl ), call.data, options, call.item ); 15558 } 15559 15560 function tiHtml( filter, textOnly ) { 15561 var wrapped = this._wrap; 15562 return jQuery.map( 15563 jQuery( jQuery.isArray( wrapped ) ? wrapped.join("") : wrapped ).filter( filter || "*" ), 15564 function(e) { 15565 return textOnly ? 15566 e.innerText || e.textContent : 15567 e.outerHTML || outerHtml(e); 15568 }); 15569 } 15570 15571 function tiUpdate() { 15572 var coll = this.nodes; 15573 jQuery.tmpl( null, null, null, this).insertBefore( coll[0] ); 15574 jQuery( coll ).remove(); 15575 } 15576})( jQuery ); 15577/*! 15578 * jQuery Mobile 1.4.1 15579 * Git HEAD hash: 18c1e32bfc4e0e92756dedc105d799131607f5bb <> Date: Wed Feb 12 2014 22:15:20 UTC 15580 * http://jquerymobile.com 15581 * 15582 * Copyright 2010, 2014 jQuery Foundation, Inc. and other contributors 15583 * Released under the MIT license. 15584 * http://jquery.org/license 15585 * 15586 */ 15587/*! 15588 * code snippet for just swipe-right and swipe-left 15589 */ 15590(function( $, window, undefined ) { 15591 var $document = $(document), 15592 TouchUtil = xfalib.ut.TouchUtil, 15593 touchStartEvent = TouchUtil.POINTER_DOWN, 15594 touchStopEvent = TouchUtil.POINTER_UP,
15595 touchMoveEvent = TouchUtil.POINTER_MOVE; 15596 15597 function triggerCustomEvent( obj, eventType, event, bubble ) { 15598 var originalType = event.type; 15599 event.type = eventType; 15600 if ( bubble ) { 15601 $.event.trigger( event, undefined, obj ); 15602 } else { 15603 $.event.dispatch.call( obj, event ); 15604 } 15605 event.type = originalType; 15606 } 15607 15608 $.event.special.swipe = { 15609 15610 // More than this horizontal displacement, and we will suppress scrolling. 15611 scrollSupressionThreshold: 30, 15612 15613 // More time than this, and it isn't a swipe. 15614 durationThreshold: 1000, 15615 15616 // Swipe horizontal displacement must be more than this. 15617 horizontalDistanceThreshold: 30, 15618 15619 // Swipe vertical displacement must be less than this. 15620 verticalDistanceThreshold: 30, 15621 15622 getLocation: function ( event ) { 15623 var winPageX = window.pageXOffset, 15624 winPageY = window.pageYOffset, 15625 x = event.clientX || event.originalEvent.clientX, 15626 y = event.clientY || event.originalEvent.clientY; 15627 15628 if ( event.pageY === 0 && Math.floor( y ) > Math.floor( event.pageY ) || 15629 event.pageX === 0 && Math.floor( x ) > Math.floor( event.pageX ) ) { 15630 15631 // iOS4 clientX/clientY have the value that should have been 15632 // in pageX/pageY. While pageX/page/ have the value 0 15633 x = x - winPageX; 15634 y = y - winPageY; 15635 } else if ( y < ( event.pageY - winPageY) || x < ( event.pageX - winPageX ) ) { 15636 15637 // Some Android browsers have totally bogus values for clientX/Y 15638 // when scrolling/zooming a page. Detectable since clientX/clientY 15639 // should never be smaller than pageX/pageY minus page scroll 15640 x = event.pageX - winPageX; 15641 y = event.pageY - winPageY; 15642 } 15643 15644 return { 15645 x: x, 15646 y: y 15647 }; 15648 }, 15649 15650 start: function( event ) { 15651 var data = event.originalEvent.touches ? 15652 event.originalEvent.touches[ 0 ] : event, 15653 location = $.event.special.swipe.getLocation( data ); 15654 return { 15655 time: ( new Date() ).getTime(), 15656 coords: [ location.x, location.y ], 15657 origin: $( event.target ) 15658 }; 15659 }, 15660 15661 stop: function( event ) { 15662 var data = event.originalEvent.touches ? 15663 event.originalEvent.touches[ 0 ] : event, 15664 location = $.event.special.swipe.getLocation( data ); 15665 return { 15666 time: ( new Date() ).getTime(), 15667 coords: [ location.x, location.y ] 15668 }; 15669 }, 15670 15671 handleSwipe: function( start, stop, thisObject, origTarget ) { 15672 if ( stop.time - start.time < $.event.special.swipe.durationThreshold && 15673 Math.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.horizontalDistanceThreshold && 15674 Math.abs( start.coords[ 1 ] - stop.coords[ 1 ] ) < $.event.special.swipe.verticalDistanceThreshold ) { 15675 var direction = start.coords[0] > stop.coords[ 0 ] ? "swipeleft" : "swiperight"; 15676 15677 triggerCustomEvent( thisObject, direction,$.Event( direction, { target: origTarget, swipestart: start, swipestop: stop } ), true ); 15678 return true; 15679 } 15680 return false; 15681 15682 }, 15683 15684 // This serves as a flag to ensure that at most one swipe event event is 15685 // in work at any given time 15686 eventInProgress: false, 15687 15688 setup: function() { 15689 var events, 15690 thisObject = this, 15691 $this = $( thisObject ), 15692 context = {}; 15693 15694 // Retrieve the events data for this element and add the swipe context 15695 events = $.data( this, "mobile-events" ); 15696 if ( !events ) { 15697 events = { length: 0 }; 15698 $.data( this, "mobile-events", events ); 15699 } 15700 events.length++; 15701 events.swipe = context; 15702 15703 context.start = function( event ) { 15704 // If its not a touch event on IE, ignore 15705 if (event.originalEvent.pointerType !== undefined && !(event.originalEvent.pointerType === 2 || event.originalEvent.pointerType === "touch")) { 15706 return; 15707 } 15708 15709 // Bail if we're already working on a swipe event 15710 if ( $.event.special.swipe.eventInProgress ) { 15711 return; 15712 } 15713 $.event.special.swipe.eventInProgress = true; 15714 15715 var stop, 15716 start = $.event.special.swipe.start( event ), 15717 origTarget = event.target, 15718 emitted = false;
15719 15720 context.move = function( event ) { 15721 if ( !start ) { 15722 return; 15723 } 15724 15725 stop = $.event.special.swipe.stop( event ); 15726 if ( !emitted ) { 15727 emitted = $.event.special.swipe.handleSwipe( start, stop, thisObject, origTarget ); 15728 if ( emitted ) { 15729 15730 // Reset the context to make way for the next swipe event 15731 $.event.special.swipe.eventInProgress = false; 15732 } 15733 } 15734 // prevent scrolling 15735 if ( Math.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.scrollSupressionThreshold ) { 15736 event.preventDefault(); 15737 } 15738 }; 15739 15740 context.stop = function() { 15741 emitted = true; 15742 15743 // Reset the context to make way for the next swipe event 15744 $.event.special.swipe.eventInProgress = false; 15745 $document.off( touchMoveEvent, context.move ); 15746 context.move = null; 15747 }; 15748 15749 $document.on( touchMoveEvent, context.move ) 15750 .one( touchStopEvent, context.stop ); 15751 }; 15752 $this.on( touchStartEvent, context.start ); 15753 }, 15754 15755 teardown: function() { 15756 var events, context; 15757 15758 events = $.data( this, "mobile-events" ); 15759 if ( events ) { 15760 context = events.swipe; 15761 delete events.swipe; 15762 events.length--; 15763 if ( events.length === 0 ) { 15764 $.removeData( this, "mobile-events" ); 15765 } 15766 } 15767 15768 if ( context ) { 15769 if ( context.start ) { 15770 $( this ).off( touchStartEvent, context.start ); 15771 } 15772 if ( context.move ) { 15773 $document.off( touchMoveEvent, context.move ); 15774 } 15775 if ( context.stop ) { 15776 $document.off( touchStopEvent, context.stop ); 15777 } 15778 } 15779 } 15780 }; 15781 $.each({ 15782 swipeleft: "swipe", 15783 swiperight: "swipe" 15784 }, function( event, sourceEvent ) { 15785 // Ignoring mouse events, for all browsers except IE 10>, which has pointer events. 15786 if (TouchUtil.POINTER_DOWN !== "mousedown") { 15787 $.event.special[ event ] = { 15788 setup: function() { 15789 $( this ).on( sourceEvent, $.noop ); 15790 }, 15791 teardown: function() { 15792 $( this ).off( sourceEvent ); 15793 } 15794 }; 15795 } 15796 }); 15797 15798})( jQuery, this ); 15799 15800/************************************************************************* 15801 * 15802 * ADOBE CONFIDENTIAL 15803 * __________________ 15804 * 15805 * Copyright 2017 Adobe Systems Incorporated 15806 * All Rights Reserved. 15807 *
15808 * NOTICE: All information contained herein is, and remains 15809 * the property of Adobe Systems Incorporated and its suppliers, 15810 * if any. The intellectual and technical concepts contained 15811 * herein are proprietary to Adobe Systems Incorporated and its 15812 * suppliers and may be covered by U.S. and Foreign Patents, 15813 * patents in process, and are protected by trade secret or copyright law. 15814 * Dissemination of this information or reproduction of this material 15815 * is strictly forbidden unless prior written permission is obtained 15816 * from Adobe Systems Incorporated. 15817 **************************************************************************/ 15818 15819(function (window, $) { 15820 15821 var DefaultPanelProvider = { 15822 15823 /** 15824 * Makes an ajax call and returns an object containing the template json of the template ids 15825 * @returns {Object} 15826 * @param options {Object} This object contains the path, the list of templateIds, and success handler 15827 */ 15828 getMultipleTemplateJson : function (options) { 15829 var externalizedPath = options.path, 15830 listOfTemplateIds = options.listOfTemplateIds; 15831 if (listOfTemplateIds.length > 0) { 15832 $.ajax({ 15833 url : externalizedPath, 15834 type : "GET", 15835 data : { 15836 listOfTemplateIds : JSON.stringify(listOfTemplateIds), 15837 fetchMultipleJson : true 15838 }, 15839 async : false, 15840 success : function (response) { 15841 options.success.call(this, JSON.parse(response.multipleJson)); 15842 }, 15843 error : function (error) { 15844 window.guideBridge._guide().logger().log(error); 15845 } 15846 }); 15847 } 15848 }, 15849 15850 /** 15851 * Makes an ajax call and gets json and html of the lazy loaded panel 15852 * @param options {Object}
15852 This object contains the templateId, fetchJson parameter and fetchHtml parameter. 15853 * These can be set to true or false depending on whether the respective content 15854 * needs to be fetched or not. Options object also contains the success, error, and complete handler as well. 15855 * @returns {JSONObject} The JSON object has two entries, json and html. 15856 */ 15857 getHtmlJson : function (options) { 15858 $.ajax({ 15859 url : options.path, 15860 type : "GET", 15861 data : { 15862 templateId : options.templateId, 15863 fetchJSON : options.fetchJSON, 15864 fetchHTML : options.fetchHTML, 15865 wcmmode : "disabled" 15866 }, 15867 async : false, 15868 success : options.success, 15869 error : options.error, 15870 complete : options.complete 15871 }); 15872 } 15873 }; 15874 15875 window.addEventListener("bridgeInitializeStart", function (evnt) { 15876 var bridge = evnt.detail.guideBridge; 15877 if (bridge) { 15878 bridge.registerPanelProvider(DefaultPanelProvider); 15879 } 15880 }); 15881 15882}(window, $)); 15883 15884 15885// jscs:disable requireDotNotation 15886/************************************************************************* 15887 * 15888 * ADOBE CONFIDENTIAL 15889 * __________________ 15890 * 15891 * Copyright 2014 Adobe Systems Incorporated 15892 * All Rights Reserved. 15893 *
15894 * NOTICE: All information contained herein is, and remains 15895 * the property of Adobe Systems Incorporated and its suppliers, 15896 * if any. The intellectual and technical concepts contained 15897 * herein are proprietary to Adobe Systems Incorporated and its 15898 * suppliers and may be covered by U.S. and Foreign Patents, 15899 * patents in process, and are protected by trade secret or copyright law. 15900 * Dissemination of this information or reproduction of this material 15901 * is strictly forbidden unless prior written permission is obtained 15902 * from Adobe Systems Incorporated. 15903 **************************************************************************/ 15904 15905(function ($, _) { 15906 Function.prototype.bind = Function.prototype.bind || function (ctx) { 15907 var that = this; 15908 return function () { 15909 that.call(ctx, arguments); 15910 }; 15911 }; 15912 15913 var nValidationContext = 0, 15914 /** 15915 * flag to check if adaptive forms is online or not 15916 * @type {boolean} 15917 */ 15918 checkAFOffline = false, 15919 _focusedSubmitButtonModel = null, 15920 sValidationContext = ""; 15921 15922 /** 15923 * Class representing the result of {@link GuideBridge} API. This class provides API to access the result of the 15924 * GuideBridge API and retrieve any error messages the API has thrown. 15925 * @class GuideResultObject 15926 * @docStatus review 2016-05-03 15927 * @since 6.0 15928 */ 15929 var GuideResultObject = function () { 15930 var _message = []; 15931 var _errorCode = []; 15932 var _somExpression = []; 15933 /** 15934 * The value of this property is true if the API succeeded, otherwise false. The 15935 * {@link GuideResultObject#getNextMessage|getNextMessage} API can be used to retrieve the error messages in 15936 * case the value of this property is false. 15937 * @summary whether the API succeeded or failed. 15938 * 15939 * @type {boolean} 15940 * @member errors 15941 * @memberof GuideResultObject 15942 * @instance 15943 * @readonly 15944 * @since 6.0 15945 */ 15946 this.errors = false; 15947 /** 15948 * The type of the data is specific to the API and documentation of that API provides more details about the 15949 * data 15950 * @summary data returned by GuideBridge API 15951 * 15952 * @member {*} data 15953 * @memberof GuideResultObject 15954 * @instance 15955 * @readonly 15956 * @since 6.0 15957 */ 15958 this.data; 15959 15960 /** 15961 * API to add a message in the GuideResultObject 15962 * @private 15963 * @memberof GuideResultObject 15964 * @instance 15965 * @since 6.0 15966 */ 15967 this.addMessage = function (code, msg, som) { 15968 this.errors = true; 15969 _message.push(msg); 15970 _somExpression.push(som); 15971 _errorCode.push(code); 15972 }; 15973 15974 /** 15975 * Error Message returned by GuideBridge API 15976 * @typedef {object} GuideResultObject~ErrorMessage 15977 * @property {number} code Error Code 15978 * @property {?string} somExpression Som Expression of the GuideNode the error is related to. It can be null if 15979 * error is not related to a GuideNode. For example, server failure when submitting the form. 15980 * @property {string} message User friendly message for the error. 15981 * @see GuideNode#somExpression 15982 */ 15983 /** 15984 * When a GuideBridge API fails, it throws an error message. This is indicated by the 15985 * {@link GuideResultObject#errors|errors} property. To get the errors, one has to call this API. The API can throw 15986 * multiple errors and the user has to call this API until it returns null indicating no more errors. 15987 * @summary Returns the error message thrown by the GuideBridge API. 15988 * @function getNextMessage 15989 * @memberof GuideResultObject 15990 * @instance 15991 * @return {GuideResultObject~ErrorMessage} object containing the error message 15992 * @since 6.0 15993 */ 15994 this.getNextMessage = function () { 15995 if (_errorCode.length == 0) { 15996 return null; 15997 } 15998 return { 15999 code : _errorCode.pop(), 16000 somExpression : _somExpression.pop(), 16001 message : _message.pop() 16002 }; 16003 }; 16004 }; 16005 16006 var GUIDE_BRIDGE_VERSION = "1.0"; 16007 /* 16008 * Callback to accept result of asynchronous GuideBridge APIs. 16009 * @callback GuideBridge~AsyncAPIResultCallback 16010 * @param {GuideResultObject}
16010 guideResultObject object containing the result of the API 16011 */ 16012 /* 16013 * Signature of the input to be passed to GuideBridge asynchronous APIs 16014 * @typedef {object} GuideBridge~AsyncAPIInput 16015 * @property {GuideBridge~AsyncAPIResultCallback} [success] callback which receives the result of the API in case of 16016 * success. The argument this callback will recieve will have its {@link GuideResultObject#errors|errors} property 16017 * as false. 16018 * @property {GuideBridge~AsyncAPIResultCallback} [error] callback which receives the result of the API in case of 16019 * failure. The argument this callback will recieve will have its {@link GuideResultObject#errors|errors} property 16020 * as true. 16021 * @param {object} [context] _this_ object inside the _success_ and _error_ callback will point to this 16022 * object 16023 */ 16024 /** 16025 * GuideBridge provides an interface using which, wrapper html (page hosting/embedding adaptive forms) or external 16026 * window scripts like Parent window javascript (in case form is embedded in an iframe), can communicate with 16027 * current Adaptive Form and manipulate or query it's current state. 16028 * 16029 * Some of the use cases for using this API 16030 * * Submit Adaptive Form from a custom button present outside the Form. 16031 * * Get current Adaptive Form state and save it in local storage for restoring it later on. 16032 * * Plugging in custom widgets. 16033 * * Manipulate the Adaptive Form component properties, like value, visibility from outside the Form 16034 * * Listen to bridge events and send data to Analytics server for reporting 16035 * 16036 * ### Accessing the Instance of GuideBridge 16037 * To access the GuideBridge APIs, one needs to get hold of an instance of GuideBridge. The object is 16038 * available on the window after the GuideBridge script is loaded. One can directly access it by using 16039 * `window.guideBridge`. But 16040 * that requires the user script is written after the GuideBridge script is loaded. In certain cases, a user might 16041 * not be 16042 * aware of when their script gets loaded, in those cases the recommended approach is to listen to the 16043 * {@link GuideBridge.event:bridgeInitializeStart|bridgeInitializeStart} event which provides an instance of 16044 * GuideBridge object. 16045 *``` 16046 * window.addEventListener("bridgeInitializeStart", function(evnt) { 16047 * // get hold of the guideBridge object 16048 * var gb = evnt.detail.guideBridge; 16049 * }) 16050 * ``` 16051 * 16052 * **Or**, if you are sure that your script will execute after GuideBridge Script is loaded, then you can directly 16053 * use `window.guideBridge`. In cases like your script is present at the bottom of the page or you are executing on 16054 * jquery dom ready event. 16055 * ``` 16056 * $(function () { 16057 * // one can directly access guideBridge object here. 16058 * window.guideBridge.connect(function () { 16059 * //call guideBridge APIs 16060 * }) 16061 * }) 16062 * ``` 16063 * 16064 * <a name="wait-form-ready"></a> 16065 * ### Wait for Form to get ready 16066 * After getting the GuideBridge object one needs to wait for the Form to get initialized. This can be done by 16067 * providing a callback to the {@link GuideBridge#connect|connect} API 16068 * ``` 16069 * guideBridge.connect(function (){ 16070 * //this callback will be called after adaptive form is initialized 16071 * // do your custom processing 16072 * }) 16073 * ``` 16074 * 16075 * _**Note:** There is no link between Dom ready events and the connect API. If one wants to access the HTML DOM 16076 * from inside the connect callback, the recommended approach is to listen on the jQuery 16077 * [ready](https://api.jquery.com/ready/) event or the native 16078 * [DOMContentLoaded](https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded) event. Similarly if one 16079 * wants to access GuideBridge APIs one needs to wait for the connect callback to get fired._ 16080 * 16081 * <a name="guidebridge-api-usage"></a> 16082 * ### Using the GuideBridge API 16083 * APIs are provided for external applications to connect with Adaptive Form and FormDom. The APIs can be
16084 * loosely divided into two categories, **synchronous** and **asynchronous**. 16085 * 16086 * The synchronous getter API returns a {@link GuideResultObject} which represents the result of the API whereas 16087 * each setter API throws an exception in case of error(s) and it is the responsibility of the API to catch those 16088 * exceptions. The {@link GuideResultObject} either contains error or the return value of the API and provides easy 16089 * mechanism to access each of them. 16090 * 16091 * ``` 16092 * var result = guideBridge.hideGlobalToolbar() 16093 * if (result.errors) { 16094 * console.error("Unable to hide toolbar"); 16095 * var msg = guideResultObject.getNextMessage(); 16096 * while (msg != null) { 16097 * console.error(msg.message); 16098 * msg = guideResultObject.getNextMessage(); 16099 * } 16100 * } else { 16101 * console.log("toolbar hidden successfully"); 16102 * } 16103 * ``` 16104 * 16105 * Each asynchronous API provides callback mechanism to return the result of the API. Each API takes a Javascript 16106 * Object having success and error handlers. The success and error handlers receive {@link GuideResultObject} as input. 16107 * In the success callback, the arguments {@link GuideResultObject#data|data} property is set to the return value 16108 * of the API, while in the error callback the {@link GuideResultObject#errors|errors} property is set to _true_. 16109 * Some APIs might need extra input and that will be defined by the API 16110 * ``` 16111 * guideBridge.getData({ 16112 * success : function (guideResultObject) { 16113 * console.log("data received" + guideResultObject.data); 16114 * } 16115 * error : function (guideResultObject) { 16116 * console.error("API Failed"); 16117 * var msg = guideResultObject.getNextMessage(); 16118 * while (msg != null) { 16119 * console.error(msg.message); 16120 * msg = guideResultObject.getNextMessage(); 16121 * } 16122 * } 16123 * }); 16124 * ``` 16125 * _**Note:** Some APIs do not follow the above norm and it is mentioned in the documentation of that API_ 16126 * 16127 * <a name="guidebridge-events"></a> 16128 * ### GuideBridge Events 16129 * 16130 * GuideBridge API triggers a set of events to notify the current action a user has taken. Developers can listen on 16131 * that event using the {@link GuideBridge#on|on} API and perform some tasks. For example a developer can listen on 16132 * {@link GuideBridge.event:elementFocusChanged|elementFocusChanged} and capture for how long a user spends time 16133 * on that field. All the events triggered by GuideBridge are mentioned below. 16134 * 16135 * GuideBridge provides an event object which contains extra information about the event. For 16136 * example _elementFocusChanged_ event provides information about the previous field that was in focus and the 16137 * current field that came to focus. 16138 * 16139 * The {@link GuideBridge#on|on} API takes a {@link GuideBridge~GuideBridgeEventCallback|GuideBridgeEventCallback} 16140 * as input. The callback is passed two arguments, event and payload where the extra information is passed in the 16141 * payload argument. The documentation of each event lists the values of different properties of the payload 16142 * object. 16143 * 16144 * ``` 16145 * guideBridge.on(eventName, function (event, payload) { 16146 * // access payload properties 16147 * ... 16148 * }) 16149 * ``` 16150 * 16151 * @class GuideBridge 16152 * @docStatus review 2016-05-03 16153 * @since 6.0 16154 */ 16155 var GuideBridge = function () { 16156 this._$target = null; 16157 this._guide = null; 16158 this._guideView = null; 16159 this._version = GUIDE_BRIDGE_VERSION; 16160 this._guideInitHandler = {}; 16161 // _guideModelInitHandler is for internal use only 16162 this._guideModelInitHandler = {}; 16163 $(window).on("guideModelInitialized", this._guideModelInitialized.bind(this)); 16164 $(window).on("guideInitialized", this._guideInitialized.bind(this)); 16165 $(window).on("guideInitializationError", this._guideError); 16166 this.userConfig = {}; 16167 this.panelProvider = null; 16168 // set the host name whether it is client or server, by default it is client 16169 this.hostName = "client"; 16170 }; 16171 16172 var _formInstanceUUID;
16173 var GUIDE_TEMP_STORAGE_PATH = "/tmp/fd/af", 16174 FM_DAM_ROOT = "/content/dam/formsanddocuments/", 16175 FM_AF_ROOT = "/content/forms/af/", 16176 _isAutoSaveEnabled = false, 16177 LOCAL_METADATA_SELECTOR = "local"; 16178 var createUUIDStorage = function (uuid) { 16179 var successFlag = true; 16180 // this is done so that when one clicks 16181 // the disabled link anyhow 16182 // you will not be able to 16183 // send request 16184 // More over if hack this too then we 16185 // have a check to prevent formation of 16186 // UUID folder at server side too ;) 16187 if (guideBridge._disablePreview()) { 16188 return false; 16189 } 16190 $.ajax({ 16191 url : guideBridge._getGuidePathUrl(".fd.tempstorageprovider.jsp"), 16192 type : "POST", 16193 async : false, 16194 data : {"uuidPath" : GUIDE_TEMP_STORAGE_PATH + "/" + uuid}, 16195 error : function (message) { 16196 guideBridge._guide.logger().log(message); 16197 successFlag = false; 16198 $.proxy(guideBridge._handleSubmitError(message), guideBridge); 16199 } 16200 }); 16201 return successFlag; 16202 }; 16203 16204 var defaultErrorHandler = function (obj) { 16205 if (typeof(console) == "undefined") { 16206 return; 16207 } 16208 var d = obj.getNextMessage(); 16209 while (d) { 16210 this._guide.logger().log(d.message); 16211 d = obj.getNextMessage(); 16212 } 16213 }; 16214 16215 /** 16216 * 16217 * Default function to check Validations errors after getting the data from the 16218 * server with getDataXML call. 16219 * @private 16220 */ 16221 var defaultValidationChecker = function (validations, obj) { 16222 if (validations && validations.length > 0) { 16223 for (var i = 0; i < validations.length; i++) { 16224 obj.addMessage(0, validations[i], ""); 16225 } 16226 return false; 16227 } 16228 return true; 16229 }; 16230 16231 function getOrElse() { 16232 return xfalib.ut.XfaUtil.prototype.getOrElse.apply(null, arguments); 16233 } 16234 16235 $.extend(GuideBridge.prototype, { 16236 16237 /** 16238 * Dispatched when the instance of GuideBridge is available. The GuideBridge object 16239 * will be passed to the listener and further communication can be done using that object. 16240 * 16241 * _**Note :** bridgeInitializeStart event is dispatched at window_ 16242 * 16243 * @summary Notifies when the instance of GuideBridge is available. 16244 * 16245 * @event bridgeInitializeStart 16246 * @property {Object} detail an object containing guideBridge 16247 * @property {GuideBridge} detail.guideBridge GuideBridge Instance 16248 * @memberof GuideBridge 16249 * @since 6.0 16250 * @example 16251 * window.addEventListener("bridgeInitializeStart", function(evnt) { 16252 * // get hold of the guideBridge object 16253 * var gb = evnt.detail.guideBridge; 16254 * //wait for the completion of adaptive forms 16255 * gb.connect(function (){ 16256 * //this function will be called after adaptive form is initialized 16257 * }) 16258 * }) 16259 */ 16260 GUIDE_BRIDGE_INITIALIZE_START : "bridgeInitializeStart", 16261 16262 /** 16263 * @summary Dispatched when the initialization of Adaptive Form is complete. 16264 * 16265 * @name bridgeInitializeComplete 16266 * @event 16267 * @property {object} payload payload passed to the event listener 16268 * @property {object} payload.target instance of GuideBridge object 16269 * @memberof GuideBridge 16270 * @deprecated since 6.3 this event is deprecated. Please use {@link GuideBridge#connect|connect} API 16271 * @since 6.0 16272 * @example 16273 * guideBridge.on("bridgeInitializeComplete" , function(event, payload) { 16274 * var gb = payload.target; 16275 * assert(gb === guideBridge) 16276 * } 16277 */ 16278 GUIDE_BRIDGE_INITIALIZE_COMPLETE : "bridgeInitializeComplete", 16279 16280 /** 16281 * @summary Dispatched when visibility of any Adaptive Form component(Panel or Field) changes. 16282 * @name elementVisibleChanged 16283 * @event 16284 * @property {object} payload payload containing more information about the event 16285 * @property {Scriptable} payload.target Adaptive Form component whose {@link Scriptable#visible|visible} property has 16286 * changed. 16287 * @property {boolean} payload.oldText old value of the visible property 16288 * @property {boolean} payload.newText new value of the visible property 16289 * @memberof GuideBridge 16290 * @since 6.0 16291 * @example 16292 * guideBridge.on("elementVisibleChanged" , function(event, payload) { 16293 * var component = payload.target; // scripting model of the component whose visibility has changed 16294 * var newValue = payload.newText; 16295 * if (newValue) { 16296 * console.log(component.name + " is visible now"; 16297 * } else { 16298 * console.log(component.name + " is hidden now"; 16299 * } 16300 * } 16301 * 16302 */ 16303 GUIDE_ELEMENT_VISIBLE_CHANGED : "elementVisibleChanged", 16304 16305 /** 16306 * @summary Dispatched when any Adaptive Form component is enabled/disabled, i.e. 16307 * {@link Scriptable#enabled|enabled} property of a component changes. 16308 * @name elementEnableChanged 16309 * @event 16310 * @property {object} payload payload containing more information about the event 16311 * @property {Scriptable} payload.target component whose {@link Scriptable#enabled|enabled} property has changed 16312 * @property {boolean} payload.oldText old value of the enabled property 16313 * @property {boolean} payload.newText new value of the enabled property 16314 * @memberof GuideBridge 16315 * @since 6.0 16316 * @example 16317 * guideBridge.on("elementEnableChanged" , function(event, payload) { 16318 * var component = payload.target; // scripting model of the component whose enabled property has changed 16319 * var newValue = payload.newText; 16320 * if (newValue) { 16321 * console.log(component.name + " is enabled now"; 16322 * } else { 16323 * console.log(component.name + " is disabled now"; 16324 * } 16325 * } 16326 */ 16327 GUIDE_ELEMENT_ENABLE_CHANGED : "elementEnableChanged", 16328 16329 /** 16330 * @summary Dispatched when value of any Field changes. 16331 * @name elementValueChanged 16332 * @event 16333 * @property {object} payload payload containing more information about the event 16334 * @property {Field} payload.target Field whose {@link Field#value|value} has changed 16335 * @property {string|number} payload.oldText old value of the Field 16336 * @property {string|number} payload.newText new value of the Field 16337 * @memberof GuideBridge 16338 * @since 6.0 16339 * @example 16340 * guideBridge.on("elementValueChanged" , function(event, payload) { 16341 * var component = payload.target; // Field whose value has changed 16342 * console.log("Value of component " + component.name + " was " + payload.oldText); 16343 * console.log("Value of component " + component.name + " is " + payload.newText); 16344 * } 16345 */ 16346 GUIDE_ELEMENT_VALUE_CHANGED : "elementValueChanged", 16347 16348 /** 16349 * In layouts like Wizard or Tabbed layout, when a user navigates from one tab to another, this event is 16350 * triggered 16351 * @summary Event to notify that the user has navigated from one Panel to another. 16352 * 16353 * @name elementNavigationChanged 16354 * @event 16355 * @property {object} payload payload containing more information about the event 16356 * @property {Panel} payload.target Panel to which the user moved to 16357 * @property {string} payload.prevText SomExpression of the panel from which user moved 16358 * @property {string} payload.newText SomExpression of the panel to which user moved 16359 * @memberof GuideBridge 16360 * @see GuideNode#somExpression 16361 * @since 6.0 16362 * @example 16363 * guideBridge.on("elementNavigationChanged" , function(event, payload) { 16364 * var component = payload.target;
16365 * console.log("old panel's SOM Expression: " + payload.oldText); 16366 * console.log("new panel's SOM Expression: " + payload.newText); 16367 * } 16368 */ 16369 GUIDE_ELEMENT_NAVIGATION_CHANGED : "elementNavigationChanged", 16370 16371 /** 16372 * @summary Dispatched whenever a Field/Panel gets Focus 16373 * @name elementFocusChanged 16374 * @event 16375 * @property {object} payload payload containing more information about the event 16376 * @property {Panel|Field} payload.target new focused component 16377 * @property {string} oldText SOM Expression of component that was previously in focus or null 16378 * @property {string} newText SOM Expression of the component that is currently in focus or null 16379 * @memberof GuideBridge 16380 * @see GuideNode#somExpression 16381 * @see {@link GuideBridge#setFocus|setFocus API} 16382 * @since 6.0 16383 * @example 16384 * guideBridge.on("elementFocusChanged" , function(event, payload) { 16385 * var component = payload.target; 16386 * console.log("old elements's SOM Expression: " + payload.oldText); 16387 * console.log("new elements's SOM Expression: " + payload.newText); 16388 * } 16389 */ 16390 GUIDE_ELEMENT_FOCUS_CHANGED : "elementFocusChanged", 16391 16392 /** 16393 * @summary Dispatched when a user looks at the help description of any Adaptive Form component(Panel or field) 16394 * @name elementHelpShown 16395 * @event 16396 * @property {object} payload payload containing more information about the event 16397 * @property {Panel|Field} payload.target component whose help is being shown 16398 * @property {string} payload._property what kind of help is being shown. The value can be 16399 * * shortDescription (if Short Description becomes visible) 16400 * * longDescription (if Long Description becomes visible) 16401 * @property {string} payload.prevText empty string 16402 * @property {object} payload.newText object containing the help content 16403 * @property {string} payload.newText.help help content of the component 16404 * @memberof GuideBridge 16405 * @since 6.0 16406 * @see {@link https://helpx.adobe.com/aem-forms/6-1/authoring-in-field-help.html|Help Description in Adaptive Form} 16407 * @example 16408 * guideBridge.on("elementHelpShown" , function(event, payload) { 16409 * var component = payload.target; 16410 * console.log("component whose help is shown " + payload.target.name); 16411 * console.log("Help shown: " + payload._property); 16412 * console.log("Help Content: " + payload.newText.help); 16413 * } 16414 */ 16415 GUIDE_ELEMENT_HELP_SHOWN : "elementHelpShown", 16416 16417 /** 16418 * @summary Dispatched when validity of a Field changes. 16419 * @name elementValidationStatusChanged 16420 * @event 16421 * @property {object} payload payload containing more information about the event 16422 * @property {Field} payload.target Field which either became valid/invalid 16423 * @property {boolean} payload.prevText old validation status 16424 * @property {boolean} payload.newText new validation status 16425 * @memberof GuideBridge 16426 * @see Field#validate 16427 * @see Field#validationState 16428 * @since 6.0 16429 * @example 16430 * guideBridge.on("elementValidationStatusChanged" , function(event, payload) { 16431 * var component = payload.target; 16432 * if (payload.prevText) { 16433 * console.log("component became invalid" ); 16434 * } else { 16435 * console.log("component became valid" ); 16436 * } 16437 * } 16438 */ 16439 GUIDE_ELEMENT_VALIDATION_STATUS_CHANGED : "elementValidationStatusChanged", 16440 16441 /** 16442 * Developers must not modify the Form Fields inside the listener. This is mostly use to update the UI outside 16443 * the Form or capture some data for analytics. If you want to modify form field value on the click of a button 16444 * please use the [Click Expression](https://helpx.adobe.com/aem-forms/6-1/adaptive-form-expressions.html#main-pars_header_6) 16445 * provided in the Forms Authoring. 16446 * 16447 * @summary Dispatched when a Button component is clicked. 16448 * 16449 * @name elementButtonClicked 16450 * @event 16451 * @property {object} payload payload containing more information about the event 16452 * @property {Button} payload.target Button which was clicked 16453 * @memberof GuideBridge 16454 * @since 6.0 16455 * @see {@link https://helpx.adobe.com/aem-forms/6-1/adaptive-form-expressions.html#main-pars_header_6|Click Expression in Buttons} 16456 * @example 16457 * guideBridge.on("elementButtonClicked" , function(event, payload) { 16458 * var component = payload.target; // Button which wass clicked 16459 * console.log("Button which was clicked " + component.name); 16460 * } 16461 */ 16462 GUIDE_ELEMENT_BUTTON_CLICKED : "elementButtonClicked", 16463 16464 /** 16465 * Whenever the full form validations are run via the {@link GuideBridge#validate|val
16465idate} API, this event is triggered. 16466 * @summary Dispatched when the validation of all the Adaptive Form fields are completed. 16467 * 16468 * @name validationComplete 16469 * @event 16470 * @property {object} payload payload containing more information about the event 16471 * @property {GuideContainerNode} payload.target root Node of the Adaptive Form 16472 * @property {boolean} payload.prevText result of running the validation. true if validations are successful, 16473 * false otherwise 16474 * @property {Field~ValidationError[]} payload.newText List of objects containing error messages. 16475 * @memberof GuideBridge 16476 * @since 6.0 16477 * @example 16478 * guideBridge.on("validationComplete" , function(event, payload) { 16479 * if (payload.prevText) { 16480 * console.log("validation success"); 16481 * } else { 16482 * console.log("validation failure"); 16483 * if (payload.newText.length) { 16484 * payload.newText.forEach(function (error) { 16485 * console.log("validation failed for " + error.som + " with message " + error.errorText); 16486 * }) 16487 * } 16488 * } 16489 * } 16490 */ 16491 GUIDE_VALIDATION_COMPLETE : "validationComplete", 16492 16493 /** 16494 * Adaptive Form can be configured to be saved automatically at regular intervals. This can be controlled 16495 * dynamically based on the values filled in the Form. Authors can write custom scripts which can enable/disable 16496 * auto save functionality dynamically 16497 * @summary Dispatched when auto save gets enabled in the Form 16498 * @name guideAutoSaveStart 16499 * @event 16500 * @property {object} payload payload containing more information about the event 16501 * @property {GuideContainerNode} payload.target root Node of the Adaptive Form 16502 * @memberof GuideBridge 16503 * @since 6.1 16504 * @see {@link https://helpx.adobe.com/aem-forms/6-1/auto-save-an-adaptive-form.html|Auto Save an Adaptive Form} 16505 * @example 16506 * guideBridge.on("guideAutoSaveStart" , function(event, payload) { 16507 * console.log("Forms is now being saved as draft automatically"); 16508 * } 16509 */ 16510 GUIDE_AUTO_SAVE_START : "guideAutoSaveStart", 16511 16512 /** 16513 * @summary Dispatched when save of adaptive form data has started 16514 * @name saveStarted 16515 * @event 16516 * @memberof GuideBridge 16517 * @since 6.1 16518 * @example 16519 * guideBridge.on("saveStarted" , function(event) { 16520 * console.log("Save of Adaptive Form data is about to start"); 16521 * } 16522 */ 16523 GUIDE_SAVE_START : "saveStarted", 16524 16525 /** 16526 * @summary Dispatched when save of adaptive form data is completed 16527 * @name saveCompleted 16528 * @event 16529 * @memberof GuideBridge 16530 * @since 6.1 16531 * @example 16532 * guideBridge.on("saveCompleted" , function(event) { 16533 * console.log("Save of Adaptive Form data is completed"); 16534 * } 16535 */ 16536 GUIDE_SAVE_COMPLETED : "saveCompleted", 16537 16538 /** 16539 * Users can add some pre submit code in the listener to this event. 16540 * @summary Dispatched when the user clicks on the submit button 16541 * @name submitStart 16542 * @event 16543 * @memberof GuideBridge 16544 * @since 6.0 16545 * @example 16546 * guideBridge.on("submitStart" , function(event) { 16547 * // do some pre submit processing 16548 * } 16549 */ 16550 GUIDE_SUBMIT_START : "submitStart", 16551 GUIDE_PATH : "guidePath", 16552 GUIDE_NAME : "guideName", 16553 GUIDE_DESC : "guideDesc", 16554 GUIDE_TYPE : "guideType", 16555 16556 /** 16557 * @summary Dispatched when an Adaptive Form fragment is lazily loaded successfully 16558 * @name elementLazyLoaded 16559 * @property {object} payload payload containing more information about the event 16560 * @property {Panel} payload.target Adaptive Form Fragment which is lazily loaded 16561 * @event 16562 * @memberof GuideBridge 16563 * @since 6.1 FP1 16564 * @see {@link https://helpx.adobe.com/aem-forms/6-1/lazy-loading-adaptive-forms.html|Lazy Loading Adaptive Form} 16565 * @example 16566 * guideBridge.on("elementLazyLoaded" , function(event, payload) { 16567 * var component = payload.target; 16568 * console.log("Panel " + component.name + " loaded"); 16569 * } 16570 */ 16571 GUIDE_ELEMENT_LAZY_LOADED : "elementLazyLoaded", 16572 16573 /** 16574 * All GuideBridge APIs (except {@link GuideBridge#connect|connect}) require Adaptive Form to be initialized. 16575 * Checking the return value of this API is not necessary if guideBridge API is called only after the 16576 * <a href="#wait-form-ready">Form is initialized</a> 16577 * @summary Whether the Adaptive Form has been initialized or not 16578 * 16579 * @method 16580 * @memberof GuideBridge 16581 * @returns {boolean} true if the Adaptive Form is ready for interaction, false otherwise 16582 * @since 6.0 16583 * @instance 16584 */ 16585 isConnected : function () { 16586 if (this._guide) { 16587 return true; 16588 } 16589 return false;
16590 }, 16591 16592 /** 16593 * Specify a callback function which is called/notified when Adaptive Form gets initialized. After Adaptive 16594 * Form is initialized GuideBridge is ready for interaction and one can call any API. 16595 * 16596 * The callback can also be registered after the Form gets initialized. In that case, the callback will be 16597 * called immediately. 16598 * 16599 * @summary Register a callback to be executed when the Adaptive Form gets initialized 16600 * @param handler {function} function that would be called when guideBridge is ready for interaction. The 16601 * signature of the callback should be 16602 * ``` 16603 * function() { 16604 * // app specific code here 16605 * } 16606 * ``` 16607 * @param {object} [context] _this_ object in the callback function will point to context 16608 * @since 6.0 16609 * @instance 16610 * @method 16611 * @memberof GuideBridge 16612 * @example 16613 * guideBridge.connect(function() { 16614 * console.log("Hurrah! Guide Bridge Activated"); 16615 * }) 16616 */ 16617 connect : function (handler, context) { 16618 context = context || guideBridge; 16619 if (this.isConnected()) { 16620 // handle exceptions gracefully since it executes in our thread 16621 try { 16622 handler.call(context); 16623 } catch (exception) { 16624 // guide model should be initialized in bridge in connect, still adding a null check 16625 if (this._guide) { 16626 this._guide.logger().log(exception); 16627 } 16628 } 16629 } else { 16630 this._guideInitHandler.handler = this._guideInitHandler.handler || []; 16631 this._guideInitHandler.handler.push(handler); 16632 this._guideInitHandler.context = this._guideInitHandler.context || []; 16633 this._guideInitHandler.context.push(context); 16634 } 16635 }, 16636 16637 /** 16638 * @private 16639 * @since 6.5 16640 */ 16641 _modelConnect : function (handler, context) { 16642 context = context || guideBridge; 16643 if (this.isConnected()) { 16644 // handle exceptions gracefully since it executes in our thread 16645 try { 16646 handler.call(context); 16647 } catch (exception) { 16648 // guide model should be initialized in bridge in connect, still adding a null check 16649 if (this._guide) { 16650 this._guide.logger().log(exception); 16651 } 16652 } 16653 } else { 16654 this._guideModelInitHandler.handler = this._guideModelInitHandler.handler || []; 16655 this._guideModelInitHandler.handler.push(handler); 16656 this._guideModelInitHandler.context = this._guideModelInitHandler.context || []; 16657 this._guideModelInitHandler.context.push(context); 16658 } 16659 16660 }, 16661 16662 _guideModelInitialized : function (e) { 16663 this._guide = e.guide; 16664 if (this._guideModelInitHandler.handler) { 16665 for (var i = 0; i < this._guideModelInitHandler.handler.length; i++) { 16666 try { 16667 this._guideModelInitHandler.handler[i].call(this._guideModelInitHandler.context[i]); 16668 } catch (exception) { 16669 // guide model should be initialized in bridge in connect, still adding a null check 16670 if (this._guide) { 16671 this._guide.logger().log(exception); 16672 } 16673 } 16674 } 16675 } 16676 }, 16677 16678 /* 16679 * 16680 * Handler for guideInitialized event which is fired by Adaptive Form library after Adaptive Form Dom is initialized 16681 * 16682 * @private 16683 */ 16684 _guideInitialized : function (e) { 16685 if (this._guideInitHandler.handler) { 16686 for (var i = 0; i < this._guideInitHandler.handler.length; i++) { 16687 try { 16688 this._guideInitHandler.handler[i].call(this._guideInitHandler.context[i]); 16689 } catch (exception) { 16690 // guide model should be initialized in bridge in connect, still adding a null check 16691 if (this._guide) { 16692 this._guide.logger().log(exception); 16693 } 16694 } 16695 } 16696 } 16697 window.guideBridge.trigger("bridgeInitializeComplete", 16698 guidelib.event.GuideModelEvent.createEvent( 16699 "bridgeInitializeComplete", 16700 guideBridge 16701 ) 16702 ); 16703 }, 16704 _setGuideView : function (guideView) { 16705 this._guideView = guideView; 16706 }, 16707 _guideError : function (e) { 16708 this._guide.logger().debug("AF", e); 16709 }, 16710 _checkGuide : function (obj) { 16711 if (!this._guide) { 16712 obj.addMessage(1, "Guide Dom not Initialized", ""); 16713 return false;
16714 } 16715 return true; 16716 }, 16717 /** 16718 * @summary returns the version of GuideBridge library 16719 * @returns {string} the version of the GuideBridge library 16720 * @method getBridgeVersion 16721 * @memberof GuideBridge 16722 * @instance 16723 * @since 6.0 16724 */ 16725 getBridgeVersion : function () { 16726 return this._version; 16727 }, 16728 16729 /** 16730 * Callback to execute when bridgeInitializeStart is triggered. 16731 * @callback GuideBridge~postExternalCallback 16732 * @param {string} name constant string `bridgeInitializeStart` 16733 * @param {object} data object containing the GuideBridge instance 16734 * @param {GuideBridge} data.guideBridge instance of GuideBridge 16735 * @since 6.0 16736 * @deprecated since 6.3 this callback is deprecated. One must do the handling in 16737 * {@link GuideBridge.events:bridgeInitializeStart} event 16738 * @memberof GuideBridge 16739 * @see GuideBridge#registerConfig 16740 * @see GuideBridge~postExternalMessageConfig 16741 */ 16742 /** 16743 * @typedef {object} GuideBridge~postExternalMessageConfig 16744 * @property {GuideBridge~postExternalCallback} postExternalHandler callback to be executed when GuideBridge 16745 * instance is available 16746 * @since 6.0 16747 * @deprecated since 6.3 this configuration is deprecated. One must do the handling in 16748 * {@link GuideBridge.events:bridgeInitializeStart} event 16749 * @memberof GuideBridge 16750 * @see GuideBridge#registerConfig 16751 */ 16752 /** 16753 * @typedef {object} GuideBridge~submitConfig 16754 * @property {HTMLFormElement} form During submission Adaptive Form creates a new HTMLFormElement and puts all the 16755 * value in that Form. One can provide an existing HTMLFormElement that will be reused for submitting the Form. The 16756 * action and method property of the Form element will be ignored. 16757 * @property {boolean} useAjax submit the form via a XMLHttpRequest rather than using a HTMLFormElement 16758 * instance is available 16759 * @property {function} submitSuccessHandler success Handler to be called post submission. This option is ignored 16760 * if _useAjax_ is set to false 16761 * @since 6.0 16762 * @memberof GuideBridge 16763 * @see GuideBridge#registerConfig 16764 */ 16765 /** 16766 * @typedef {object} GuideBridge~renderConfig 16767 * @property {boolean} enableFocusOnFirstField option to enable focus on first field. Default value is true. 16768 * @since 6.5 16769 * @memberof GuideBridge 16770 * @see GuideBridge#registerConfig 16771 */ 16772 /** 16773 * Adaptive Form uses some default named configurations to provide its default behaviour. This configurations 16774 * can be modified by providing a new configuration. 16775 * 16776 * The API accepts the name of the configuration and updated configuration. Based on value of the new 16777 * configuration the behaviour of the Form gets changed. 16778 * Currently supported configurations are: 16779 * #### postExternalMessageConfig 16780 * 16781 * <div class="deprecated"><span class="deprecated-heading">Deprecated :</span><span> since 6.2 this 16782 * configuration is deprecated. Use the {@link GuideBridge.events:bridgeInitializeStart} event to do the same 16783 * handling</span> 16784 * </div> 16785 * In case Adaptive Form is embedded inside an iframe, this configuration allows developers to provide 16786 * GuideBridge Instance to parent or child windows.
16787 * 16788 * By default, GuideBridge instance is only available to the current window and to the parent window if it 16789 * doesn't violate the cross-origin policy. Now there may be a case when this doesn't solves the problem, then 16790 * one can take advantage of this configuration to extend this functionality. 16791 * 16792 * For the signature of the configuration see 16793 * {@link GuideBridge~postExternalMessageConfig|postExternalMessageConfig} 16794 * ##### Example 16795 * To provide the GuideBridge instance to a child window 16796 * ``` 16797 * window.on("bridgeInitializeStart", function (evnt) { 16798 * var gb = evnt.detail.guideBridge; 16799 * gb.registerConfig("postExternalMessageConfig", { 16800 * "postExternalHandler" : function(data) { 16801 * // assume we have a child window with an id 'childWindowId' 16802 * var childWindow = document.getElementById("#childWindowId").contentWindow; 16803 * var tmpEvent = document.createEvent("CustomEvent"); 16804 * tmpEvent.initCustomEvent(data.name, true, true, data.data); 16805 * childWindow.dispatchEvent(tmpEvent); 16806 * } 16807 * }); 16808 * }); 16809 * ``` 16810 * #### widgetConfig 16811 * The configuration is used to modify the appearance of a specific Field. Adaptive Form allows developers to 16812 * [create custom widgets](http://helpx.adobe.com/aem-forms/6-1/custom-appearance-widget-adaptive-form.html) and 16813 * use them in their Forms. 16814 * 16815 * The signature of the config is 16816 * ``` 16817 * { "<component-identifier> : "<widget-name>"} 16818 * ``` 16819 * where `<component-identifier>` can be either the name or classname of Adaptive Form Field, 16820 * while widget name is the name of the jQuery Widget. 16821 * 16822 * #### submitConfig 16823 * To modify the default submit behaviour one can provide this configuration. The signature of the config is 16824 * defined {@link GuideBridge~submitConfig|below} 16825 * ``` 16826 * guideBridge.registerConfig("submitConfig", {"useAjax" : true}); 16827 * ``` 16828 * 16829 * #### renderConfig 16830 * To modify the default render behaviour one can provide this configuration. The signature of the config is 16831 * defined {@link GuideBridge~renderConfig|below} 16832 * ``` 16833 * guideBridge.registerConfig("renderConfig", {"enableFocusOnFirstField" : false}); 16834 * ``` 16835 * @summary Registers user/portal specific configurations to GuideBridge 16836 * @returns {GuideResultObject} {@link GuideResultObject} with {@link GuideResultObject#data|data} having the 16837 * old configuration against the same _key_ 16838 * 16839 * @param key {string} configuration name. one of the following 16840 * * postExternalMessageConfig 16841 * * widgetConfig 16842 * * submitConfig 16843 * * renderConfig 16844 * @param {widgetConfig|GuideBridge~submitConfig|GuideBridge~renderConfig|GuideBridge~postExternalMessageConfig} [config] configuration object for the configuration 16845 * @method 16846 * @memberof GuideBridge 16847 * @since 6.0 16848 * @instance 16849 */ 16850 registerConfig : function (key, config) { 16851 var obj = new GuideResultObject(); 16852 obj.data = this.userConfig[key]; 16853 this.userConfig[key] = config; 16854 obj.completed = true; 16855 return obj; 16856 }, 16857 16858 /** 16859 * Their exists a customPropertyMap which can be set from the server. For prefilling files 16860 * fileAttachmentMap key should be present in the map. 16861 * @name customContextProperty 16862 * @param value {object} object to be replaced with the current customPropertyMap. 16863 * @memberof GuideBridge 16864 * @method 16865 * since 6.0 16866 */ 16867 16868 /** 16869 * Their exists a customPropertyMap which can be set from the server. For prefilling files 16870 * fileAttachmentMap key should be present in the map. 16871 * @name customContextProperty 16872 * @param property {string} object to be replaced with the current customPropertyMap. 16873 * @method 16874 * @memberof GuideBridge 16875 * since 6.0 16876 */ 16877 16878 /** 16879 * Their exists a customPropertyMap which can be set from the server. For prefilling files 16880 * fileAttachmentMap key should be present in the map. 16881 * @param property {string} property to update in the custom property map 16882 * @param value {*} value of the property 16883 * @return {*} old value of the property 16884 * since 6.0 16885 */ 16886 customContextProperty : function (property, value) { 16887 var customPropertyMap = getOrElse(guidelib, "__runtime__.guideContext.customPropertyMap", {}); 16888 // use both the customContextProperty map since customers also access that 16889 var newCustomPropertyMap = _.extend({}, customPropertyMap, getOrElse(this._guide, "runtime.guideContext.customPropertyMap", {})); 16890 if (_.isUndefined(value)) { 16891 if (_.isObject(property)) { 16892 guideBridge._modelConnect((function (newCustomPropertyMap, property) { 16893 return function () { 16894 var localMap = _.extend({}, guideBridge._guide.runtime.guideContext.customPropertyMap, newCustomPropertyMap); 16895 _.extend(localMap, property); 16896 guideBridge._guide.runtime.guideContext.customPropertyMap = localMap; 16897 }; 16898 })(newCustomPropertyMap, property)); 16899 } else { 16900 return newCustomPropertyMap[property]; 16901 } 16902 } else { 16903 var oldValue = newCustomPropertyMap[property]; 16904 guideBridge._modelConnect((function (property, value, newCustomPropertyMap) { 16905 return function () { 16906 var localMap = _.extend({}, guideBridge._guide.runtime.guideContext.customPropertyMap, newCustomPropertyMap); 16907 localMap[property] = value; 16908 guideBridge._guide.runtime.guideContext.customPropertyMap = localMap; 16909 }; 16910 })(property, value, newCustomPropertyMap)); 16911 return oldValue; 16912 } 16913 }, 16914 16915 getNavigablePanel : function (somExpression) { 16916 return this._guideView.getSomOnNavigableAncestor(somExpression); 16917 }, 16918 16919 /** 16920 * Sets the value of a property for a set of {@link GuideNode} to a different value. Property must be a valid 16921 * writable property for that Node 16922 * 16923 * Each entry in _somList_ should have a corresponding entry in the _valueList_. Mismatch in the length of these
16924 * two arguments will make the function do nothing 16925 * @summary Modify a property for a set of Nodes 16926 * @method setProperty 16927 * @param {string[]} somList an array having someExpression for the nodes. Invalid SomExpressions and 16928 * the corresponding value in the _valueList_ are ignored. 16929 * @param {string} propertyName name of the property which has to be modified 16930 * @param {Array.<*>} valueList an array containing value of the _propertyName_ for each element in _somList_ 16931 * 16932 * @memberof GuideBridge 16933 * @instance 16934 * @since 6.0 16935 * @see GuideNode#somExpression 16936 * @example <caption>Modifying the value of a set of fields</caption> 16937 * guideBridge.setProperty(["SOM_OF_FIELD_1", "SOM_OF_FIELD_2"...... "SOM_OF_FIELD_N"] 16938 * "value" 16939 * [VALUE_1, VALUE_2 .... VALUE_N]); 16940 * @example <caption>Hiding a single field</caption> 16941 * guideBridge.setProperty(["SOM_OF_FIELD_1"] 16942 * "visibility" 16943 * [false]); 16944 */ 16945 setProperty : function (somList, propertyName, valueList) { 16946 if (!propertyName) { 16947 return; 16948 } 16949 if (!_.isArray(somList) || !_.isArray(valueList)) { 16950 return; 16951 } 16952 if (somList.length !== valueList.length) { 16953 return; 16954 } 16955 var gb = this; 16956 _.each(somList, function (som, index) { 16957 var node = gb.resolveNode(som); 16958 if (node) { 16959 node[propertyName] = valueList[index]; 16960 } else { 16961 gb._guide.logger().log("som not valid:" + som); 16962 } 16963 }); 16964 if (!this._guide._currentContext) { 16965 this._guide.runPendingExpressions(); 16966 } 16967 }, 16968 16969 /** 16970 * Used to retrieve the Form data as XML. The API gets the data xml synchronously/asynchronously based on the 16971 * _async_ option and invokes the success/error handlers passed in the arguments upon completion. 16972 * 16973 * In the success callback the {@link GuideResultObject#data|data} parameter contains the xml string. 16974 * 16975 * The success and error handlers receive {@link GuideResultObject} as input. 16976 * @summary Return Form data as XML. 16977 * 16978 * @param {object} options input to the getDataXML API 16979 * @param {function} [options.success] callback which receives the result of the API 16980 * in case of success. 16981 * @param {function} [options.error] callback which receives the result of the API in 16982 * case of failure. 16983 * {@link GuideResultObject#errors|errors} property as true. 16984 * @param {object} [options.context] _this_ object inside the _success_ and _error_ callback will point to this 16985 * object 16986 * @param {boolean} [options.async=true] whether to make the server call asynchronously or not. If false, the 16987 * browser will wait for the server to return the XML and then execute the success or error callbacks object 16988 * @see <a href="#guidebridge-api-usage" >GuideBridge API Usage</a> 16989 * @method 16990 * @memberof GuideBridge 16991 * @since 6.0 16992 * @instance 16993 * @example 16994 * guideBridge.getDataXML({ 16995 * success : function (guideResultObject) { 16996 * console.log("xml data received" + guideResultObject.data); 16997 * } 16998 * error : function (guideResultObject) { 16999 * console.error("API Failed"); 17000 * var msg = guideResultObject.getNextMessage(); 17001 * while (msg != null) { 17002 * console.error(msg.message); 17003 * msg = guideResultObject.getNextMessage(); 17004 * } 17005 * } 17006 * }); 17007 * 17008 * @deprecated since 6.3 this API is deprecated. Use getData API instead. 17009 * @param options 17010 */ 17011 getDataXML : function (options) { 17012 guideBridge.getData(options); 17013 }, 17014 17015 /** 17016 * Used to retrieve the Form data as XML or JSON depending on the Schema Type. Only for JSON Schema based Forms 17017 * and Form Data Model based forms, the data will be in JSON format while for others, the data will be in XML format. 17018 * The API gets the data synchronously/asynchronously based on the 17019 * _async_ option and invokes the success/error handlers passed in the arguments upon completion. 17020 * 17021 * In the success callback the {@link GuideResultObject#data|data} parameter contains the data string. 17022 * 17023 * The success and error handlers receive {@link GuideResultObject} as input. 17024 * @summary Return Form data as XML or JSON depending on the Schema Type. 17025 * 17026 * @param {object} options input to the getData API 17027 * @param {function} [options.success] callback which receives the result of the API 17028 * in case of success. 17029 * @param {function} [options.error] callback which receives the result of the API in 17030 * case of failure. 17031 * {@link GuideResultObject#errors|errors} property as true. 17032 * @param {object} [options.context] _this_ object inside the _success_ and _error_ callback will point to this 17033 * object 17034 * @param {boolean} [options.async=true] whether to make the server call asynchronously or not. If false, the 17035 * browser will wait for the server to return the data (XML or JSON) and then execute the success or error callbacks object 17036 * @see <a href="#guidebridge-api-usage" >GuideBridge API Usage</a> 17037 * @method 17038 * @memberof GuideBridge 17039 * @since 6.3 17040 * @instance 17041 * @example 17042 * guideBridge.getData({ 17043 * success : function (guideResultObject) { 17044 * console.log("data received" + guideResultObject.data); 17045 * } 17046 * error : function (guideResultObject) { 17047 * console.error("API Failed"); 17048 * var msg = guideResultObject.getNextMessage(); 17049 * while (msg != null) { 17050 * console.error(msg.message); 17051 * msg = guideResultObject.getNextMessage(); 17052 * } 17053 * } 17054 * }); 17055 * @deprecated use {@link GuideBridge#getFormDataString} instead 17056 */ 17057 getData : function (options) { 17058 options = options || {}; 17059 17060 /* Earlier this API would support boundData for getting data tro be merged in PDF. Now that flag has been renamed to dorData 17061 * Earlier, boundData flag now maps to boundData for backward compatibility. 17062 * */ 17063 options.dorData = options.dorData || options.boundData; 17064 17065 var resultObject = new GuideResultObject(); 17066 if (!options.guideState && !this._checkGuide(resultObject)) { 17067 options.error.call(options.context, resultObject); 17068 return; 17069 } 17070 17071 this._submitInternal({ 17072 success : function (data) { 17073 var resultJson = data || {}; 17074 resultObject.completed = true; 17075 if (options.dorData) { 17076 resultObject.data = resultJson["dorDataXml"]; 17077 } else { 17078 resultObject.data = resultJson["data"]; 17079 } 17080 if (_.isFunction(options.success)) { 17081 options.success.call(options.context, resultObject); 17082 } 17083 }, 17084 error : function (xhr, txtStatus, errorThrown) { 17085 var msg = "Error in getData API"; 17086 resultObject.completed = false;
17087 resultObject.addMessage(2, msg, ""); 17088 if (_.isFunction(options.error)) { 17089 options.error.call(options.context, resultObject); 17090 } 17091 }, 17092 guideState : options.guideState, 17093 async : options.async, 17094 fileUploadPath : options.fileUploadPath, 17095 excludeFormState : options.excludeFormState || false, 17096 dorData : options.dorData || false 17097 }); 17098 }, 17099 17100 17101 /** 17102 * returns form data object {@link FormData} 17103 * @returns {*} 17104 * @private 17105 */ 17106 _getFormDataObj : function() { 17107 guideBridge._updateAFSubmissionInfo(); 17108 guideBridge._guide.internal.liveDataUtils.updateLiveData(null, true); // fetching client side data 17109 guideBridge._guide.internal.liveDataUtils.insertSubmissionInfo(guideBridge._guide.runtime.guideContext.afSubmissionInfo); 17110 var data = guideBridge._guide.internal.liveDataUtils.getLiveDataStr(); 17111 var contentType = "application/xml"; 17112 if (guideBridge._guide.internal.liveDataUtils instanceof guidelib.model.LiveJsonUtils) { 17113 contentType = "application/json"; 17114 } 17115 return new guidelib.model.FormData({ 17116 "data": data, 17117 "contentType" : contentType, 17118 "attachments": guideBridge.getFileAttachmentWrapper() 17119 }); 17120 }, 17121 17122 /** 17123 * invoked inside server-side-validation to return excludeFromDor data. 17124 * @param {Object} guide input to _getExcludeFromDorData API 17125 * @returns {Array} containing excludeFromDoR info 17126 * */ 17127 _getExcludeFromDorData : function (guide) { 17128 var newGuide = guide ? guide : guideBridge._guide; 17129 var excludeFromDorData = null; 17130 window.guideBridge._updateAFSubmissionInfo(newGuide); 17131 var afSubmissionInfo = newGuide.runtime.guideContext.afSubmissionInfo; 17132 if(afSubmissionInfo.excludeFromDoR) { 17133 excludeFromDorData = afSubmissionInfo.excludeFromDoR; 17134 } 17135 return excludeFromDorData; 17136 }, 17137 17138 17139 /** 17140 * returns FormData object {@link FormData} containing form data xml or json and attachments 17141 * @param {object} options input to the getData API 17142 * @param {function} [options.success] callback which receives the result of the API 17143 * in case of success. 17144 * @method 17145 * @memberof GuideBridge 17146 * @since 6.5 17147 * @instance 17148 */ 17149 getFormDataObject : function (options) { 17150 var formDataObj = guideBridge._getFormDataObj(); 17151 var resultObject = new GuideResultObject(); 17152 resultObject.data = formDataObj; 17153 if (options && typeof options.success === 'function') { 17154 options.success(resultObject); 17155 } 17156 }, 17157 17158 /** 17159 * returns string representation of form data xml or json 17160 * @param {object} options input to the getData API 17161 * @param {function} [options.success] callback which receives the result of the API 17162 * in case of success. 17163 * @method 17164 * @memberof GuideBridge 17165 * @since 6.5 17166 * @instance 17167 */ 17168 getFormDataString : function (options) { 17169 var formDataObj = guideBridge._getFormDataObj(); 17170 var resultObject = new GuideResultObject(); 17171 resultObject.data = formDataObj.data; 17172 if (options && typeof options.success === 'function') { 17173 options.success(resultObject); 17174 } 17175 }, 17176 17177 /** 17178 * @summary Hides all the submit buttons present in the Adaptive Form 17179 * 17180 * @returns {GuideResultObject} the data property of GuideResultObject would be undefined. The API will fail if 17181 * the Form is not initialized which would be indicated by the {@link GuideResultObject#errors|errors} property. 17182 * @memberof GuideBridge 17183 * @instance 17184 * @since 6.0 17185 */ 17186 hideSubmitButtons : function () { 17187 return this._hideElements("guideButton", "submit"); 17188 }, 17189 17190 /** 17191 * This API is designed to evaluate the expression entered by the author. 17192 * This API is given only to enable Auto Save meta information use case. 17193 * @returns value obtained after executing the expression. 17194 * @method 17195 * @private 17196 * @memberof GuideBridge 17197 * @deprecated since 6.3 this API is deprecated 17198 */ 17199 _evaluateExpression : function (expression) { 17200 if (this._guide) { 17201 var compiledExpression = this._guide._compileExpression(expression, null); 17202 return compiledExpression.apply(this._guide); 17203 } 17204 }, 17205 17206 /** 17207 * Adaptive Form can be configured to save draft automatically. This property indicates whether Adaptive Form is 17208 * configured to save draft automatically or not. 17209 * 17210 * Enabling auto save doesn't mean that AF will create the draft when the Form is loaded. Based on the result of 17211 * **Auto save start expression** the draft will be created. Once the expression returns true, drafts will be 17212 * saved at regular interval or at specific events as configured. 17213 * 17214 * @summary Whether autoSave is enabled for this Adaptive Form or not 17215 * @returns {boolean} true if auto save is enabled otherwise false. 17216 * @method 17217 * @memberof GuideBridge 17218 * @instance 17219 * @since 6.1 FP1 17220 * @see {@link https://helpx.adobe.com/aem-forms/6-1/auto-save-an-adaptive-form.html|Saving an adaptive Form} 17221 */ 17222 getAutoSaveEnabledStatus : function () { 17223 var _isAutoSaveEnable = false;
17224 // check if form is loaded or not, if loaded then check for auto save 17225 if (this.isConnected()) { 17226 _isAutoSaveEnable = this._guide.enableAutoSave; 17227 } 17228 return _isAutoSaveEnable; 17229 }, 17230 17231 /** 17232 * This API indicates that auto save is enabled and draft is being saved at the configured location. 17233 * @summary Whether Adaptive Form data is being saved as draft or not. 17234 * @returns {Boolean} whether autoSave has started. 17235 * @method 17236 * @memberof GuideBridge 17237 * @instance 17238 * @since 6.1 FP1 17239 * @see {@link https://helpx.adobe.com/aem-forms/6-1/auto-save-an-adaptive-form.html|Saving an adaptive Form} 17240 **/ 17241 hasAutoSaveStarted : function () { 17242 return this._guide && this._guide.enableAutoSave && this._guide.autoSaveStart; 17243 }, 17244 17245 /** 17246 * @summary the autoSaveinfo that is stored at the guideContainer. 17247 * @returns {object} object contains the additional meta information stored along with form data 17248 * @method 17249 * @memberof GuideBridge 17250 * @instance 17251 * @since 6.1 FP1 17252 * @deprecated since 6.3 17253 */ 17254 getAutoSaveInfo : function () { 17255 return this._guide.autoSaveInfo; 17256 }, 17257 17258 /** 17259 * The API is used to provide extra information to be saved in Final data XML. It can also be used to retrieve 17260 * that information. 17261 * 17262 * If _value_ is null then the value of the _property_ is returned 17263 * @summary store or retrieve submission related information 17264 * @param {string} property name of the property against which to save the value or retrieve the value of 17265 * property 17266 * @param {string} [value] value to save. 17267 * @returns {*} old value of the property 17268 * @method 17269 * @since 6.1 FP1 17270 * @memberof GuideBridge 17271 * @instance 17272 * @deprecated since 6.3 17273 */ 17274 afSubmissionInfo : function (property, value) { 17275 var afSubmissionInfo = guideBridge._guide.runtime.guideContext.afSubmissionInfo || {}; 17276 if (_.isUndefined(value)) { 17277 return afSubmissionInfo[property]; 17278 } else { 17279 var oldValue = afSubmissionInfo[property]; 17280 afSubmissionInfo[property] = value; 17281 guideBridge._guide.runtime.guideContext.afSubmissionInfo = afSubmissionInfo; 17282 return oldValue; 17283 } 17284 }, 17285 17286 /** 17287 * @summary returns the globalMetaInfo object after all the computation. This object will be set in guideContext for submission 17288 * @returns {object} In a format {"key 1": computation result of registered expression, "key 2":...} 17289 * @method 17290 * @since 6.1 FP1 17291 * @memberof GuideBridge 17292 * @instance 17293 * @example 17294 * { 17295 * "key 1": computation result of registered expression, 17296 * ... 17297 * } 17298 * @deprecated since 6.3 17299 */ 17300 getComputedSubmissionMetadata : function () { 17301 var computedMetadata = {}, 17302 currentMetadata = null, 17303 compiledExpression = null, 17304 metadata = this.getSubmissionMetadataInfo(); 17305 if (metadata) { 17306 if (_.isObject(metadata)) { 17307 for (var key in metadata) { 17308 try { 17309 currentMetadata = JSON.parse(metadata[key]); 17310 compiledExpression = this._guide._compileExpression(currentMetadata["value"]); 17311 computedMetadata[currentMetadata["key"]] = compiledExpression.apply(this._guide); 17312 } catch (exception) { 17313 if (this._guide) { 17314 this._guide.logger().log(exception); 17315 } 17316 } 17317 } 17318 } else if (_.isString(metadata)) { 17319 try { 17320 currentMetadata = JSON.parse(metadata); 17321 compiledExpression = this._guide._compileExpression(currentMetadata["value"]); 17322 computedMetadata[currentMetadata["key"]] = compiledExpression.apply(this._guide); 17323 } catch (exception) { 17324 if (this._guide) { 17325 this._guide.logger().log(exception); 17326 } 17327 } 17328 } 17329 } 17330 return computedMetadata; 17331 }, 17332 17333 /** 17334 * @summary this API returns the globalMetaInfo stored in global context (in globalMetaInfo tab). 17335 * @returns {object} 17336 * @method 17337 * @memberof GuideBridge 17338 * @instance 17339 * @deprecated since 6.3 17340 */ 17341 getGlobalMetaInfo : function () { 17342 return this._guide.globalMetaInfo; 17343 }, 17344 17345 /** 17346 * @summary this API returns the metadata configured for submission. Value depends on the selection of metadata 17347 * type, local or global. 17348 * @returns {Object} 17349 * @method 17350 * @since 6.1 FP1 17351 * @memberof GuideBridge 17352 * @instance 17353 * @deprecated since 6.3 17354 */ 17355 getSubmissionMetadataInfo : function () { 17356 if (this._guide.submissionMetaInfo && this._guide.submissionMetaInfo.metadataselector === LOCAL_METADATA_SELECTOR) { 17357 // In order to maintain backward compatibility, this piece of code will always be here. 17358 // For the cases where metadata selection is being configured for submit actions 17359 return getOrElse(this._guide, "submissionMetaInfo.metadata", null); 17360 } else { 17361 //From 6.2 onwards, we are asking author to provide metadata only at one place, which is global to whole form 17362 // In case, metadataselector's value is "global" or not configured at all, this block will get executed 17363 return getOrElse(this._guide, "globalMetaInfo.metadata", null); 17364 } 17365 }, 17366 17367 /** 17368 * The API enables auto save in Adaptive Form 17369 * @summary enable auto save in Adaptive Form. 17370 * @param value {boolean} true to enable auto save otherwise false. 17371 * @method 17372 * @memberof GuideBridge 17373 * @instance 17374 * @since 6.1 FP1 17375 * @see {@link GuideBridge#getAutoSaveEnabledStatus|getAutoSaveEnabledStatus} 17376 * @see {@link https://helpx.adobe.com/aem-forms/6-1/auto-save-an-adaptive-form.html|Auto Save an Adaptive Form} 17377 */ 17378 setEnabledAutoSave : function (value) { 17379 this._guide.enableAutoSave = value; 17380 }, 17381 17382 /** 17383 * @summary Hides all the file attachment listing buttons present in the Adaptive Form 17384 * 17385 * @returns {GuideResultObject} the data property of GuideResultObject would be undefined. The API will fail if
17386 * the Form is not initialized which would be indicated by the {@link GuideResultObject#errors} property. 17387 * @memberof GuideBridge 17388 * @instance 17389 * @since 6.0 17390 */ 17391 hideFileAttachmentListingButtons : function () { 17392 return this._hideElements("guideListFileAttachmentButton"); 17393 }, 17394 17395 /** 17396 * @todo: Function can change as per usecase, it can behave as a wrapper 17397 * where it can use the configuration provided through registerConfig and invoke any callback if required 17398 * 17399 * @returns {boolean} boolean indicating whether Adaptive Form is offline 17400 * @private 17401 */ 17402 isOffline : function () { 17403 return checkAFOffline; 17404 }, 17405 17406 /** 17407 * function to set the status of Adaptive Form (online or offline) 17408 * @type {boolean} 17409 * @private 17410 */ 17411 setIsOffline : function (value) { 17412 checkAFOffline = value; 17413 }, 17414 17415 /** 17416 * @summary Hide all the File Attachment component present in the Adaptive Form 17417 * 17418 * @returns {GuideResultObject} the data property of GuideResultObject would be undefined. The API will fail if 17419 * the Form is not initialized which would be indicated by the {@link GuideResultObject#errors} property. 17420 * @memberof GuideBridge 17421 * @instance 17422 * @since 6.0 17423 */ 17424 hideFileAttachments : function () { 17425 return this._hideElements("guideFileUpload"); 17426 }, 17427 17428 /** 17429 * @summary Hides the global toolbar of the Adaptive Form. 17430 * @returns {GuideResultObject} the data property of GuideResultObject would be undefined. The API will fail if 17431 * the Form is not initialized which would be indicated by the {@link GuideResultObject#errors} property. 17432 * @memberof GuideBridge 17433 * @instance 17434 * @since 6.0 17435 */ 17436 hideGlobalToolbar : function () { 17437 var resultObject = new GuideResultObject(), 17438 $toolbar; 17439 17440 // If guide dom not initialized, return 17441 if (!this._checkGuide(resultObject)) { 17442 return resultObject; 17443 } 17444 17445 if (guideBridge._guide.toolbar) { 17446 $toolbar = this._getGuideDomElement(guideBridge._guide.toolbar.somExpression); 17447 if ($toolbar && $toolbar.length > 0) { 17448 $toolbar.hide(); 17449 } 17450 } 17451 17452 resultObject.completed = true; 17453 return resultObject; 17454 }, 17455 17456 /* 17457 * 17458 * This API is designed to return all the toolbar buttons present in the Adaptive Form(except submit, save, reset and file attachment listing) 17459 * 17460 * @returns {GuideResultObject} data contains an array of all the tool bar buttons available(except submit, save, reset and file attachment listing) 17461 * Each element of data property is an object holding model and html property. 17462 * The html string does not contain any script tags, this is to avoid crosss site scripting attacks 17463 */ 17464 /* 17465 getToolbarButtons : function(){ 17466 var resultObject = new GuideResultObject(), 17467 resultData = [], 17468 $elem = null; 17469 // If guide dom not initialized, return 17470 if (!this._checkGuide(resultObject)) { 17471 return resultObject; 17472 } 17473 resultObject.completed = true; 17474 this.visit(function(node){ 17475 // Check if this node is a guide button and if it resides inside a guideToolBar 17476 if(node.className === "guideButton" && node.parent.className === "guideToolbar"){ 17477 if(node.type !== "submit" && node.type !== "save" && node.type !== "fileattachmentlisting" && node.type !== "next" && node.type !=="prev") { 17478 $elem = this._getGuideDomElement(node.somExpression); 17479 // Remove the script tag from the $html, we don't support execution of Adaptive Form Scripts in parent or other domain 17480 // This is to avoid cross site scripting attacks 17481 $elem.find("script").remove(); 17482 resultData.push({ 17483 "model" : node, 17484 "html" : $elem.html() 17485 }); 17486 } 17487 } 17488 }); 17489 resultObject.data = resultData; 17490 return resultObject; 17491 }, */ 17492 17493 /** 17494 * @summary Hides all the save buttons present in the Adaptive Form 17495 * 17496 * @returns {GuideResultObject} the data property of GuideResultObject would be undefined. The API will fail if
17497 * the Form is not initialized which would be indicated by the {@link GuideResultObject#errors} property. 17498 * @memberof GuideBridge 17499 * @instance 17500 * @since 6.0 17501 */ 17502 hideSaveButtons : function () { 17503 return this._hideElements("guideButton", "save"); 17504 }, 17505 17506 /** 17507 * @summary Hides all the reset buttons present in the Adaptive Form 17508 * 17509 * @returns {GuideResultObject} the data property of GuideResultObject would be undefined. The API will fail if 17510 * the Form is not initialized which would be indicated by the {@link GuideResultObject#errors} property. 17511 * @memberof GuideBridge 17512 * @instance 17513 * @since 6.3 17514 */ 17515 hideResetButtons : function () { 17516 return this._hideElements("guideButton", "reset"); 17517 }, 17518 17519 /** 17520 * The API can be used to retrieve the value of a specific property for a list of AF components. If the property 17521 * doesn't exists for a component then the corresponding value in the resulting array will be null. 17522 * 17523 * The {@link GuideResultObject#data|data} element of the return object will be an array containing the values 17524 * of the _property_ for each component in the list of components 17525 * 17526 * The API fails if the Form is not initiailzed 17527 * 17528 * **_Note:_** If a somExpression provided doesn't points to a valid {@link GuideNode} null is returned for 17529 * that element and an error message is added in the returned object 17530 * @summary returns the value of a specific property for a set of Adaptive Form Components 17531 * 17532 * @param {object} options input object containing the propertyName and the list of components 17533 * @param {string} options.propertyName name of the property whose value has to be returned 17534 * @param {string[]} options.somExpression list of somExpression of the components for which the value is to be 17535 * returned. 17536 * 17537 * @returns {GuideResultObject} The {@link GuideResultObject#data|data} member of the object contains the property 17538 * values 17539 * @method 17540 * @memberof GuideBridge 17541 * @since 6.0 17542 * @instance 17543 * @deprecated since 6.3 17544 * @see GuideNode#somExpression 17545 * @example 17546 * var result = guideBridge.getElementProperty({ 17547 * propertyName: "value", 17548 * somExpression: ["somExpression1", "somExpression2"] 17549 * }); 17550 * if (result.errors) { 17551 * console.log("some som expressions were invalid"); 17552 * var err = result.getNextMessage(); 17553 * while(err != null) { 17554 * //err.somExpression will point to the invalid somExpression in the Field. 17555 * console.log(err.message); 17556 * } 17557 * } 17558 * for(var i = 0; i< result.data.length; i++) { 17559 * console.log(result.data[i]); 17560 * } 17561 */ 17562 getElementProperty : function (options) { 17563 var somExpressions = options.somExpressions; 17564 var propertyName = options.propertyName; 17565 var resultObject = new GuideResultObject(); 17566 if (!this._checkGuide(resultObject)) { 17567 return resultObject; 17568 } 17569 resultObject.data = []; 17570 for (var i = 0; i < somExpressions.length; i++) { 17571 var element = this.resolveNode(somExpressions[i]); 17572 if (element == null) { 17573 resultObject.addMessage(0, "No element " + somExpressions[i] + " exists", somExpressions[i]); 17574 resultObject.data.push(null); 17575 } else { 17576 resultObject.completed = true; 17577 resultObject.data.push(element[propertyName]); 17578 } 17579 } 17580 return resultObject; 17581 }, 17582 17583 _getGuideDomElement : function (somExpression, option) { 17584 if (this._guideView) { 17585 return this._guideView._getGuideDomElement(somExpression, option); 17586 } else { 17587 return null; 17588 } 17589 }, 17590 17591 getTempPath : function () { 17592 return "/tmp/fd/af/" + this._getUUID(); 17593 }, 17594 17595 /** 17596 * File Attachment object 17597 * @typedef {object} GuideBridge~FileAttachementObject 17598 * @property {string} name name of the uploaded File 17599 * @property {string} path path of the uploaded File 17600 * @memberof GuideBridge 17601 * @since 6.0 17602 */ 17603 /** 17604 * Success callback that is called from {@link GuideBridge#getFileAttachmentsInfo} with the list of File 17605 * Attachments 17606 * @callback GuideBridge~FileAttachmentInfoHandler 17607 * @param {GuideBridge~FileAttachementObject[]} fileAttachementList list of file attachement objects uploaded 17608 * in the Form 17609 */ 17610 /** 17611 * The API provides a list containing File Names and File URLS for the Files Attached by the user using the 17612 * File Attachment component. The API is a asynchronous API and takes success handler which is called with 17613 * the list of File Names and URLs. 17614 * 17615 * @param {object} options Object containing the callback which will be invoked with the result of this API 17616 * @param {function} options.success success callback which will be invoked. The signature of the callback should 17617 * match the signature of {@link GuideBridge~FileAttachmentInfoHandler|FileAttachmentInfoHandler} 17618 * @param {object} [options.context] _this_ parameter in the success handler will point to this object 17619 * 17620 * @example <caption>Example usage of the getFileAttachmentsInfo API</caption> 17621 * guideBridge.getFileAttachmentsInfo({ 17622 * success:function(list) { 17623 * for(var i = 0; i< list.length; i++) { 17624 * console.log(list[i].name + " "+ list[i].path); 17625 * } 17626 * } 17627 * }); 17628 * @method 17629 * @memberof GuideBridge 17630 * @since 6.0 17631 * @instance 17632 */ 17633 getFileAttachmentsInfo : function (options) { 17634 var fileAttachmentsList = this._getFileAttachmentsList(), 17635 list; 17636 17637 function collectFileUrls(event) { 17638 list = []; 17639 //TODO: need to modularize collectFileUrs() 17640 // here this is the context of the function who calls it 17641 _.each(this.attachments, function (att) { 17642 list.push({name : att.split("/")[1], path : this.fileUrl + "/" + att}); 17643 }, this); 17644 if (this.options.success) { 17645 this.options.success.call(this.options.context, list); 17646 } 17647 } 17648 var optionArgument = {"options" : options, 17649 "fileAttachmentsList" : fileAttachmentsList, 17650 "fileUploadPath" : this.getTempPath(), 17651 "callback" : collectFileUrls 17652 }; 17653 this._getGuideAttachments(optionArgument); 17654 }, 17655 17656 /** 17657 * Syntax - argObject : {"options" : options to be passed to the callback, 17658 * "fileAttachmentsList" : fileAttachmentsList, 17659 * "fileUploadPath" :fileUploadPath 17660 * "callback" :callback, "errorCallback" :errorCallback} 17661 * @param {object}
17661 argObject Input object containing the callbacks that will be invoked 17662 * to provide the result of the API 17663 * @private 17664 * @memberof GuideBridge 17665 * @since 6.0 17666 */ 17667 _getGuideAttachments : function (argObject) { 17668 var fileDoms = [], 17669 fileNames = [], 17670 fileUrl = null, 17671 didSubmit = false, 17672 contextRoot = this._getContextRoot(), 17673 options = argObject.options, 17674 fileAttachmentsList = argObject.fileAttachmentsList, 17675 fileUploadPath = argObject.fileUploadPath, 17676 callback = argObject.callback, 17677 errorCallback = argObject.errorCallback, 17678 fileNameDomMap; 17679 17680 // In the case of draft, url comes with context root. Need to remove it so that correct 17681 // value gets stored in model 17682 if (contextRoot) { 17683 if (fileUploadPath.indexOf(contextRoot) === 0) { 17684 fileUploadPath = fileUploadPath.substring(contextRoot.length); 17685 } 17686 } 17687 // File attachment list is an array containing the list of file attachments 17688 // We need to fetch the fileNameDomMap even when there's no fileAttachmentsList as there can be 17689 // lazy loaded file attachment models as well. 17690 fileNameDomMap = this._juiceOutNameAndFileDomMap(fileAttachmentsList); 17691 fileDoms = fileNameDomMap.fileDom; 17692 fileNames = fileNameDomMap.fileName; 17693 if (fileDoms.length > 0) { 17694 // since there can be a dom element which is null, in case of draft reload, get the first 17695 // non null file dom 17696 var firstNonNullFileDom = _.indexOf(fileDoms, _.find(fileDoms, function (item) { 17697 return item !== null && !_.isString(item); 17698 })); 17699 // fileUploadPath doesn't contain the context path and hence we need to to pass the baseURL 17700 // FileUploader takes a _getUrl option which is baseUrl/contextPath 17701 if (firstNonNullFileDom !== -1 && fileUploadPath) { 17702 var uploaderPluginName = guideBridge.userConfig.uploaderPluginName || "adobeFileUploader"; 17703 fileUrl = fileDoms[firstNonNullFileDom][uploaderPluginName]("uploadFile", { 17704 'fileName' : fileNames, 17705 'fileDom' : fileDoms, 17706 'fileUploadPath' : fileUploadPath, 17707 'multiple' : true, 17708 _getUrl : guideBridge._getUrl("") 17709 }); 17710 17711 // The file url returned by file upload widget can contain context root. 17712 // Remove it so that correct value gets stored in model. 17713 if (contextRoot) { 17714 if (fileUrl.indexOf(contextRoot) === 0) { 17715 fileUrl = fileUrl.substring(contextRoot.length); 17716 } 17717 } 17718 17719 fileDoms[firstNonNullFileDom].one("adobeFileUploader.multipleFileUploaded", 17720 $.proxy(callback, { 17721 "attachments" : fileNames, 17722 "fileUrl" : fileUrl, 17723 "fileAttachmentsList" : fileAttachmentsList, 17724 "options" : options 17725 }) 17726 ); 17727 if (errorCallback) { 17728 fileDoms[firstNonNullFileDom].one("adobeFileUploader.fileUploadFailed", 17729 $.proxy(errorCallback, { 17730 "attachments" : fileNames, 17731 "fileUrl" : fileUrl, 17732 "fileAttachmentsList" : fileAttachmentsList, 17733 "options" : options 17734 }) 17735 ); 17736 } 17737 didSubmit = true; 17738 } 17739 // if fileUrl is not yet set, default it to fileUploadPath 17740 if (fileUrl === null && fileUploadPath) { 17741 fileUrl = fileUploadPath; 17742 } 17743 } 17744 if (!didSubmit) { 17745 // if there are no files attached, still call the callback to submit the json contents 17746 // if there is only one file attachment component with no files, in this case else is
17746important 17747 callback.apply({ 17748 "attachments" : fileNames, 17749 "fileUrl" : fileUrl, 17750 "fileAttachmentsList" : fileAttachmentsList, 17751 "options" : options 17752 }); 17753 } 17754 }, 17755 /** 17756 * Iterates over all the components in the Adaptive Form and invokes its {@link GuideNode#visit|visit} method 17757 * passing the _callback_ to the API. 17758 * 17759 * @summary Traverse all the components in the Adaptive Form and invoke callback function for each of the 17760 * component 17761 * @param {function} callback Function to be called for every Adaptive Form Component present 17762 * in the Form. The signature of the callback matches the signature of 17763 * {@link GuideNode~VisitorCallback|VisitorCallback} 17764 * @param {object} [context=window] _this_ object in the callback will point to this object 17765 * 17766 * @example <caption>Creating a list of all components having name <i>testName</i></caption> 17767 * var myList = [] 17768 * guideBridge.visit(function(cmp) { 17769 * if(cmp.name === "testName") { 17770 * myList.push[cmp]; 17771 * } 17772 * }}; 17773 * @method 17774 * @memberof GuideBridge 17775 * @since 6.0 17776 * @instance 17777 */ 17778 visit : function (callback, context) { 17779 this._guide.visit(callback, context || window); 17780 }, 17781 17782 /** 17783 * 17784 * Hides the elements of the specified class name. 17785 * In case of guideButton, it checks for type too, if no type is specified in "guideButton", then that button 17786 * cannot be made hidden 17787 * 17788 * @param className String representing the classname of the node 17789 * @param type [optional] type will be used only if the classname is "guideButton" 17790 * @private 17791 */ 17792 _hideElements : function (className, type) { 17793 var resultObject = new GuideResultObject(); 17794 // If guide dom not initialized, return 17795 if (!this._checkGuide(resultObject)) { 17796 return resultObject; 17797 } 17798 resultObject.completed = true; 17799 this.visit(function (node) { 17800 // if the class name is guide button only the use the type 17801 if (node.className === "guideButton") { 17802 if (node.type === type) { 17803 node.visible = false; 17804 } 17805 } else { 17806 // else just compare the classname and hide it 17807 if (node.className === className) { 17808 node.visible = false; 17809 } 17810 } 17811 }); 17812 return resultObject; 17813 }, 17814 17815 /** 17816 * In Adaptive Form there is a summary component to show the summary of submission. This API hides the parent 17817 * panel of the summary component. If the component is not present inside the Form, this operation doesn't do 17818 * anything 17819 * @summary Hides the panel that contains the summary component. 17820 * 17821 * @returns {GuideResultObject} the data property of GuideResultObject would be undefined. The API will fail if 17822 * the Form is not initialized which would be indicated by the {@link GuideResultObject#errors} property. 17823 * @memberof GuideBridge 17824 * @instance 17825 * @since 6.0 17826 */ 17827 hideSummaryPanel : function () { 17828 var resultObject = new GuideResultObject(); 17829 // If guide dom not initialized, return 17830 if (!this._checkGuide(resultObject)) { 17831 return resultObject; 17832 } 17833 resultObject.completed = true; 17834 this.visit(function (node) { 17835 if (node.className === "guideNode" && node.jsonModel['sling:resourceType'] === "fd/afaddon/components/summary") { 17836 node.panel.visible = false; 17837 } 17838 }); 17839 return resultObject; 17840 }, 17841 17842 _getFileAttachmentsList : function () { 17843 var fileAttachmentsList = []; 17844 this.visit(function (node) { 17845 if (node.className === "guideFileUpload") { 17846 fileAttachmentsList.push(node); 17847 } 17848 }); 17849 return fileAttachmentsList; 17850 }, 17851 17852 /** 17853 * @summary the captchaData which will be submitted to server for validation purposes. 17854 * @param captchaModel 17855 * @returns {object}
17855 object contains the captchaData which includes captcha service provider name, its SOM exp and 17856 * data coming from OOTB/third-party captcha widget. 17857 * @method 17858 * @memberof GuideBridge 17859 * @instance 17860 * @since 6.3 17861 */ 17862 _getCaptchaData : function (captchaModel) { 17863 if (captchaModel) { 17864 return { 17865 serviceType : captchaModel.captchaService, 17866 somExpression : captchaModel.somExpression, 17867 validationMessage : captchaModel.validateExpMessage, 17868 mandatoryMessage : captchaModel.mandatoryMessage, 17869 data : captchaModel.value 17870 }; 17871 } 17872 return {}; 17873 }, 17874 17875 /** 17876 * This function returns the additional action Field information that is required during submit. 17877 * 17878 * @returns {object} object having the action Field information. 17879 * @memberof GuideBridge 17880 */ 17881 _getAdditionalSubmitInfo : function () { 17882 var additionalSubmitInfo = {}, 17883 actionFieldDiv = $("#actionField"); 17884 var thankYouPage = this._getThankYouPageFromConfig(); 17885 if (typeof thankYouPage === "string") { 17886 document.getElementById(":redirect").value = thankYouPage; 17887 } 17888 var actionFields = actionFieldDiv.find('input') 17889 .each(function () { 17890 additionalSubmitInfo[$(this).attr("name")] = $(this).val(); 17891 if ($(this).attr("name") == "_guideValueMap" && $(this).val() == "yes") { 17892 var guideKeyValue = {}; 17893 window.guideBridge._guide._collectValues(guideKeyValue); 17894 additionalSubmitInfo['_guideValuesMap'] = JSON.stringify(guideKeyValue); 17895 } 17896 }); 17897 return additionalSubmitInfo; 17898 }, 17899 17900 /** 17901 * Gets the guideDom based on whether reducedJSON option is true or not. 17902 * If reducedJSON is true, only the white-listed properties are included. 17903 * 17904 * @returns {object} guideDom 17905 * @memberof GuideBridge 17906 */ 17907 17908 _getGuideDom : function (options) { 17909 var guideDom; 17910 if (options.reducedJSON) { 17911 guideDom = guideBridge._guide._getReducedJSON(); 17912 } else { 17913 guideDom = guideBridge._guide.jsonModel; 17914 } 17915 return guideDom; 17916 }, 17917 17918 /** 17919 * Creates the guideState and the liveXml. 17920 * 17921 * @param options {object} options should contain a GuideResultObject [{obj:"<GuideResultObject type>"}] 17922 * @memberof GuideBridge 17923 * Steps performed by the function - 17924 * 1) creates the xfaState 17925 * 2) creates the guideState that consists of guideDom, guideContext and additionalSubmitInfo 17926 * 3) creates guideLiveData 17927 * 4) adds xfaState and guideLiveData to the guideState 17928 * 17929 * @private 17930 */ 17931 _createGuideStateAndLiveXml : function (options) { 17932 var obj = new GuideResultObject(); 17933 // add the guideResultObject to options so that it can be passed to the success handler 17934 options.obj = obj; 17935 17936 if (!this._checkGuide(obj)) { 17937 return; 17938 } 17939 17940 var saveXfaXml = function (xfaResultObj) { 17941 if (!xfaResultObj.errors && xfaResultObj.completed) { 17942 xfaState.currentContext = {'data' : xfaResultObj.data}; 17943 } 17944 }; 17945 17946 obj.data = {}; 17947 var xfaState = null; 17948 if (this._isXfaGuide() && this._isValidXFAGuide()) { 17949 var xfaResultObject = null; 17950 if (options.reducedJSON) { 17951 //If reduceJson is asked, then xfaState should also be reduced by passing the diff and bSubmit flag to true 17952 xfaResultObject = window.formBridge.getFormState(true, true); 17953 } else { 17954 xfaResultObject = window.formBridge.getFormState(); 17955 } 17956 if (xfaResultObject.errors) { 17957 guideBridge._guide.logger().log("Error in getting Xfa State:" + JSON.stringify(xfaResultObject.getNextMessage())); 17958 alert(guidelib.util.GuideUtil.getLocalizedMessage("AF", guidelib.i18n.LogMessages["AEM-AF-901-001"])); 17959 } 17960 xfaState = xfaResultObject.data; 17961 } 17962 17963 var guideDom = guideBridge._getGuideDom(options); 17964 17965 //adding additionalSubmitInfo in the guideState. 17966 //additionalSubmitInfo contains the information about action fields. 17967 var additionalSubmitInfo = guideBridge._getAdditionalSubmitInfo(); 17968 //set the updated file attachment map in the customPropertyMap 17969 guideBridge.customContextProperty("fileAttachmentMap", JSON.stringify(this.getFileAttachmentMap())); 17970 var guideState = { 17971 guideDom : guideDom, 17972 //save renderContext in guide state to enable deferred submit even if guide is not open 17973 guideContext : guideBridge._guide.runtime.guideContext, 17974 additionalSubmitInfo : additionalSubmitInfo 17975 }; 17976 17977 if (guideBridge._guide.allLazyChildren.length > 0) { 17978 guideBridge._guide.internal.liveDataUtils.updateLiveData(); 17979 var listOfDirtyPanels = guideBridge._guide.internal.GuideDirtyMarkerAndVisitor.flatten
17979DirtyPanelMapToCSV(); 17980 if (listOfDirtyPanels.length > 0) { 17981 this.afSubmissionInfo("afDraft", listOfDirtyPanels); 17982 } 17983 // save live xml & xfa state as xml for restoration of lazy model on 'restore' 17984 guideState.guideLiveData = guideBridge._guide.internal.liveDataUtils.getLiveDataStr(); 17985 if (this._isXfaGuide() && this._isValidXFAGuide()) { 17986 formBridge.getDataXML({"success" : saveXfaXml}); // currently xfa restore relies on formBridge.getDataXML being sync 17987 } 17988 } 17989 obj.data.guideState = guideState; 17990 if (xfaState) { 17991 obj.data.guideState.xfaState = xfaState; 17992 } 17993 17994 }, 17995 17996 _updateAFSubmissionInfo : function (guide) { 17997 if (guideBridge.isGuideLoaded(true) && !guide) { 17998 var previousFocusSom = this._guideView._previousFocusItemSom; 17999 var previousItemModel = guideBridge.resolveNode(this._guideView._previousFocusItemSom); 18000 if (getOrElse(previousItemModel, "parent.className", undefined) === "guideToolbar") { 18001 previousFocusSom = previousItemModel.parent.parent.somExpression; 18002 } 18003 this.afSubmissionInfo("lastFocusItem", this._guideView.getSomOnNavigableAncestor(previousFocusSom)); 18004 } 18005 this.afSubmissionInfo("computedMetaInfo", guideBridge.getComputedSubmissionMetadata()); 18006 var newGuide = guide ? guide : guideBridge._guide; 18007 this.afSubmissionInfo("excludeFromDoR", newGuide._getExcludeFromDorMap()); 18008 // send state override on in cases when we have dor 18009 var stateOverrides = {}; 18010 if (newGuide.dorType && "none" !== newGuide.dorType) { 18011 stateOverrides = newGuide._getStateOverrideMap(); 18012 } 18013 this.afSubmissionInfo("stateOverrides", stateOverrides); 18014 // Add signers to af submission info 18015 this.afSubmissionInfo("signers", newGuide._getSigners()); 18016 18017 }, 18018 18019 18020 /** 18021 * Adaptive Form stores its state in the form of JSON. The Files attached in the component are uploaded 18022 * onto the server and their paths are returned in the JSON state except in certain conditions mentioned below. 18023 * The API is an asynchronous call which calls the success and error handlers with the data. 18024 * 18025 * In the below mentioned scenarios the file will not be uploaded 18026 * * User doesn't have **write permissions** on the _fileUploadPath_ provided 18027 * * The _fileUploadPath_ property doesn't point to a node of type _**sling:Folder**_ 18028 * 18029 * @summary Retrieve the current state of Adaptive Form as json string 18030 * @param {object} options Input object containing the callbacks that will be invoked 18031 * to provide the result of the API 18032 * @param {function} [options.success] callback which receives the result of the API 18033 * in case of success. 18034 * {@link GuideResultObject#errors|errors} property as false. 18035 * @param {function} [options.error] callback which receives the result of the API in 18036 * case of failure. 18037 * {@link GuideResultObject#errors|errors} property as true. 18038 * @param {object} [options.context] _this_ object inside the _success_ and _error_ callback will point to this 18039 * object 18040 * @param {string} [options.fileUploadPath] controls whether the files in the File Attachment component have to be 18041 * uploaded or not. If _fileUploadPath_ is non null, only then file gets uploaded and the model's value is 18042 * updated with the file url 18043 * 18044 * @method 18045 * @memberof GuideBridge 18046 * @since 6.0 18047 * @instance 18048 */ 18049 getGuideState : function (options) { 18050 18051 var fileAttachmentsList = []; 18052 18053 // walk through the model to get the list of file attachment components 18054 // do this only and only if login!= anonymous 18055 if (!guideBridge._disablePreview()) { 18056 fileAttachmentsList = this._getFileAttachmentsList(); 18057 } 18058 18059 guideBridge._updateAFSubmissionInfo(); 18060 18061 if (!guidelib.runtime.progressive && guideBridge.isGuideLoaded(true)) { 18062 this.customContextProperty("lastFocusItem", this._guideView.getSomOnNavigableAncestor(this._guideView._previousFocusItemSom)); 18063 } 18064 18065 // Walk through the list of file Attachment components 18066 // and update the value of every item 18067 // Get the list of file Attachments 18068 if (options.fileUploadPath && !guideBridge._disablePreview()) { 18069 var optionArgument = {"options" : options, 18070 "fileAttachmentsList" : fileAttachmentsList, 18071 "fileUploadPath" : options.fileUploadPath, 18072 "callback" : window.guideBridge._collectFileUrls, 18073 "errorCallback" : window.guideBridge._fileUploadFailed}; 18074 18075 this._getGuideAttachments(optionArgument); 18076 } else { 18077 this._createGuideStateAndLiveXml(options); 18078 if (options.success) { 18079 options.success.call(options.context, options.obj); 18080 } 18081 } 18082 18083 }, 18084 18085 /** 18086 * Validates the Adaptive Form or it's specific panel and return the validation status. The API also moves 18087 * focus to first invalid element 18088 * @summary validate the entire Form or a component in Adaptive Form 18089 * @param {Field~ValidationError[]} errorList Input must be an empty array. The array will be filled with list 18090 * of Adaptive Form Components that failed validation. 18091 * @param {string}
18091 [somExpression] SOM Expression of the Guide Node for which validation should be triggered. 18092 * If not provided, it would validate the entire Adaptive Form 18093 * @param {boolean} [setFocus=true] If true, set focus to the first invalid element. 18094 * @returns {boolean} true if the component/form was valid, false otherwise 18095 * @method 18096 * @memberof GuideBridge 18097 * @since 6.0 18098 * @instance 18099 * @see Field#validate 18100 * @see Panel#validate 18101 */ 18102 validate : function (errorList, somExpression, setFocus, guide) { 18103 // guide parameter is not to be documented and it is meant for internal use only 18104 var guideNode = null, 18105 isFocusEnabled = _.isUndefined(setFocus) ? true : setFocus, 18106 ec = guidelib.util.ErrorConstants, 18107 validationContext, 18108 afContainer = guide ? guide : this._guide; // done, to keep this thread safe 18109 // get Json of all the dirty , non visited (templateJson missing from cache) 18110 if (afContainer.allLazyChildren.length > 0) { 18111 afContainer.guideLazyUtil.putDirtyToTemplateCacheIfMissing(afContainer); 18112 } 18113 if (somExpression) { 18114 guideNode = this.resolveNode(somExpression); 18115 // how to know if the panel is navigable from the model. We do not bring the nonNavigable property ? 18116 if (guideNode instanceof guidelib.model.GuidePanel) { 18117 validationContext = ec.CONTEXT_NAVIGATION; 18118 } 18119 } else { 18120 guideNode = afContainer; 18121 validationContext = ec.CONTEXT_SUBMISSION; 18122 } 18123 this.setValidationContext(validationContext); 18124 var status = false; 18125 if (!errorList) { 18126 errorList = []; 18127 } 18128 status = guideNode.validate(errorList); 18129 18130 try { 18131 // there can be errors in the user script, hence handling the exception gracefully, and resetting the global error state properly 18132 this._guide._triggerOnBridge("validationComplete", this._guide, status, "", errorList); 18133 if (!status && isFocusEnabled) { 18134 var errorSom = errorList[0]["som"]; 18135 18136 guideBridge._guide.on(guidelib.event.GuideModelEvent.LAZY_LOADED, function () { 18137 var errorField = guideBridge.resolveNode(errorSom); 18138 if (errorField) { 18139 errorField.validate(); 18140 } 18141 }, {}); 18142 18143 this.setFocus(errorSom); 18144 18145 guideBridge._guide.off(guidelib.event.GuideModelEvent.LAZY_LOADED); 18146 } 18147 18148 } catch (exception) { 18149 this._guide.logger().log(exception); 18150 } finally { 18151 // since the errors have been published reset the state back to normal 18152 //guidelib.runtime.errorManager.setGlobalError(false); 18153 this.unsetValidationContext(validationContext); 18154 return status; 18155 } 18156 18157 }, 18158 18159 // todo: submit behaviour should make sure that if the value of file upload 18160 /** 18161 * Adaptive Form can be restore in three ways 18162 * * by passing the JSON data obtained from {@link GuideBridge#getGuideState}. This can be done by setting 18163 * _**data**_ property . 18164 * * by passing a URL pointing to a resource that returns JSON/XML data that should be used. This can be done by setting 18165 * _**dataRef**_ property. The data can be obtained by calling the 18166 * {@link GuideBridge#getData|getData} API. 18167 * * by passing a URL pointing to a resource that returns JSON data obtained from {@link GuideBridge#getGuideState}. 18168 * This can be done by setting _**guideStatePathRef**_ property . 18169 * 18170 * When restoring from dataRef, only values and other properties, that are dependant on value, are restored. For 18171 * example, If a Field was hidden based on the click of a Button then 18172 * when restoring from data XML/JSON the Field will not remain hidden. 18173 * 18174 * **NOTE:** The _data_, _dataRef_ and _guideStatePathRef_ must not be null simultaneously and only one property 18175 * must be specified. Specifying more than one can lead to undesired results. 18176 * @summary restore/prepopulate the state of Adaptive Form from an earlier saved state 18177 * @param {object}
18177 options object containing the callbacks to be invoked on 18178 * success/failure and data from where to restore the object. 18179 * @param {function} [options.success] callback which receives the result of the API 18180 * in case of success 18181 * {@link GuideResultObject#errors|errors} property as false. 18182 * @param {function} [options.error] callback which receives the result of the API in 18183 * case of failure. 18184 * {@link GuideResultObject#errors|errors} property as true. 18185 * @param {object} [options.context] _this_ object inside the _success_ and _error_ callback will point to this 18186 * object. 18187 * @param {object} [options.data] It must be the value of the {@link GuideResultObject#data|data} property passed to 18188 * the _success_ handler of {@link GuideBridge#getGuideState|getGuideState} API. 18189 * @param {string} [options.dataRef] URL pointing to the data XML/JSON. 18190 * @param {string} [options.guideStatePathRef] URL pointing to the JSON state of Adaptive Form. 18191 * 18192 * @method 18193 * @memberof GuideBridge 18194 * @since 6.0 18195 * @instance 18196 * @example <caption>Restoring from JSON data</caption> 18197 * var jsonData; 18198 * guideBridge.getGuideState({ 18199 * success : function (guideResultObj) { 18200 * jsonData = guideResultObj.data; 18201 * }, 18202 * error : function (guideResultObj) { 18203 * // log error 18204 * } 18205 * }); 18206 * 18207 * // after some time or on click of a button or reloading the page 18208 * guideBridge.restoreGuideState({ 18209 * guideState : jsonData.guideState, 18210 * error : function (guideResultObject) { 18211 * // log the errors 18212 * } 18213 * }) 18214 * 18215 * @example <caption>Restoring from data XML/JSON</caption> 18216 * guideBridge.getData({ 18217 * success : function (guideResultObj) { 18218 * var data = guideResultObj.data; 18219 * //post the data to a server that saves it at say http://abc.com/my/data.xml 18220 * //or http://abc.com/my/data.json 18221 * }, 18222 * error : function (guideResultObj) { 18223 * // log the errors 18224 * } 18225 * }); 18226 * 18227 * // after some time or on click of a button or reloading the page 18228 * guideBridge.restoreGuideState({ 18229 * dataRef : "http://abc.com/my/data.xml", 18230 * error : function (guideResultObject) { 18231 * // log the errors 18232 * } 18233 * }) 18234 * 18235 * @example <caption>Restoring from URL to a JSON</caption> 18236 * guideBridge.getGuideState({ 18237 * success : function (guideResultObj) { 18238 * var json = guideResultObj.data; 18239 * //post the JSON to a server that saves it at say http://abc.com/my/data.json 18240 * }, 18241 * error : function (guideResultObj) { 18242 * // log the errors 18243 * } 18244 * }); 18245 * 18246 * // after some time or on click of a button or reloading the page 18247 * guideBridge.restoreGuideState({ 18248 * guideStatePathRef : "http://abc.com/my/data.json", 18249 * error : function (guideResultObject) { 18250 * // log the errors 18251 * } 18252 * }) 18253 **/ 18254 restoreGuideState : function (options) { 18255 var parameters, 18256 path; 18257 if (options && options.dataRef) { 18258 parameters = {"dataRef" : options.dataRef}; 18259 } else if (options && options.guideStatePathRef) { 18260 parameters = {"guideStatePathRef" : options.guideStatePathRef}; 18261 } 18262 // if parameters have DataRef or guideStatePathRef, a recursive call is made to restoreGuideState. 18263 if (parameters) { 18264 path = window.guideBridge.getGuidePath(); 18265 path = path + ".guidejson"; 18266 $.ajax({ 18267 url : path, 18268 type : "GET", 18269 async : false, 18270 cache : false, 18271 data : parameters, 18272 success : function (response) { 18273 //case where section information exist in guideState 18274 if (response.guideState && response.guideState.guideContext 18275 && response.guideState.guideContext.customPropertyMap 18276 && response.guideState.guideContext.customPropertyMap.sections 18277 && response.guideState.guideContext.customPropertyMap.sections.length > 0) { 18278 // todo: add safe check for string vs array 18279 window.guideBridge.customContextProperty.sections = response.guideState.guideContext.customPropertyMap.sections; 18280 } 18281 //passing the options again, but with DataRef or guideStatePathRef removed from it. 18282 window.guideBridge.restoreGuideState(_.extend( 18283 {}, 18284 options, 18285 { 18286 guideState : response.guideState, 18287 dataRef : undefined, 18288 guideStatePathRef : undefined 18289 } 18290 )); 18291 if (guidelib.runtime.progressive) { 18292 // Initialize the progressive 18293 // We are not directly playing json on the model, since may be the json of entire progressive is not brought upfront 18294 // Only in case of static service, we bring the entire json, hence creating model if not present 18295 guidelib.runtime.progressive._initializeSectionModelAndPlayJson(window.guideBridge.customContextProperty.sections); 18296 18297 // Now render the last section 18298 guidelib.runtime.progressive.renderLastSection(); 18299 } 18300 }, 18301 error : function (response) { 18302 window.guideBridge._guide.logger().log("Error: " + response); 18303 } 18304 }); 18305 return; 18306 } 18307 18308 /* 18309 * We have to merge the runtime guideContext with the guideContext passed in the guideState 18310 * so that no custom properties that were set in the guideState.guideContext are ignored. 18311 */ 18312 guidelib.__runtime__.guideContext = guidelib.__runtime__.guideContext || {}; 18313 if (guideBridge.isGuideLoaded()) { 18314 guideBridge._guide.runtime.guideContext = guideBridge._guide.runtime.guideContext || {}; 18315 } 18316 var gc = getOrElse(options, "guideState.guideContext", undefined); 18317 if (!_.isUndefined(options.guideState.guideContext)) { 18318 /* Runtime custom property map is set by external application and hence, shallow copy will set the value 18319 * as set externally. If no value was set, the guideState custom property map keys stay. 18320 */ 18321 _.extend(gc.customPropertyMap, guidelib.__runtime__.guideContext.customPropertyMap); 18322 if (guideBridge.isGuideLoaded()) { 18323 _.extend(gc.customPropertyMap, guideBridge._guide.runtime.guideContext.customPropertyMap); 18324 } 18325 } 18326 // not setting at guidelib runtime, but honoring if anyone has set customPropertyMap 18327 // through guidelib.runtime.guideContext directly 18328 if (guideBridge.isGuideLoaded()) { 18329 _.extend(guideBridge._guide.runtime.guideContext, gc); 18330 } 18331 18332 if (!this._guide) { 18333 this.storage = {}; 18334 this.storage.guideState = options.guideState; 18335 //NOCHECKMARX - This is error callback to be provided by the user of this API. 18336 this.storage.error = options.error; 18337 this.storage.success = options.success; 18338 this.storage.context = options.context; 18339 } else { 18340 this._playGuideJson(options); 18341 // Trigger the event 18342 // If guide has restore state, call sync guide node to html 18343 // Case 1: If this is called before view gets initialized, there would be no listener present, hence nothing would happen 18344 // Case 2: If it is called after view gets initialized(using restore guide state in mobile workspace), then the model would sync to view 18345 // using this event 18346 // If view is initialized, which means a listener would to MODEL_REFRESH would be set, hence just trigger the event for execution 18347 if (this._guideView) { 18348 this._guide._triggerEvent(guidelib.event.GuideModelEvent.MODEL_REFRESH, "jsonModel", null, null); 18349 } 18350 } 18351 18352 }, 18353 18354 /** 18355 * Adaptive Form can set data in three ways: 18356 * * by passing the JSON data obtained from {@link GuideBridge#getGuideState}. This can be done by setting 18357 * _**data**_ property . 18358 * * by passing a URL pointing to a resource that returns data JSON/XML that should be used. This can be done by setting 18359 * _**dataRef**_ property. The data can be obtained by calling the 18360 * {@link GuideBridge#getData|getData} API. 18361 * * by passing a URL pointing to a resource that returns JSON data obtained from {@link GuideBridge#getGuideState}. 18362 * This can be done by setting _**guideStatePathRef**_ property . 18363 * 18364 * When setting data from dataRef, only values and other properties, that are dependant on value, are set. For 18365 * example, If a Field was hidden based on the click of a Button in the data passed then 18366 * when setting data from XML/JSON the Field will not remain hidden. 18367 * 18368 * **NOTE:** The _data_, _dataRef_ and _guideStatePathRef_ must not be null simultaneously and only one property 18369 * must be specified. Specifying more than one can lead to undesired results. 18370 * @summary Populate the Adaptive Form from the data. 18371 * @param {object}
18371 options object containing the callbacks to be invoked on 18372 * success/failure and data from where to restore the object. 18373 * @param {function} [options.success] callback which receives the result of the API 18374 * in case of success 18375 * {@link GuideResultObject#errors|errors} property as false. 18376 * @param {function} [options.error] callback which receives the result of the API in 18377 * case of failure. 18378 * {@link GuideResultObject#errors|errors} property as true. 18379 * @param {object} [options.context] _this_ object inside the _success_ and _error_ callback will point to this 18380 * object. 18381 * @param {object} [options.data] It must be the value of the {@link GuideResultObject#data|data} property passed to 18382 * the _success_ handler of {@link GuideBridge#getGuideState|getGuideState} API. 18383 * @param {string} [options.dataRef] URL pointing to the data JSON/XML. 18384 * @param {string} [options.guideStatePathRef] URL pointing to the JSON state of Adaptive Form. 18385 * 18386 * @method 18387 * @memberof GuideBridge 18388 * @since 6.3 18389 * @instance 18390 * @example <caption>Setting data from JSON data</caption> 18391 * var jsonData; 18392 * guideBridge.getGuideState({ 18393 * success : function (guideResultObj) { 18394 * jsonData = guideResultObj.data; 18395 * }, 18396 * error : function (guideResultObj) { 18397 * // log the errors 18398 * } 18399 * }); 18400 * 18401 * guideBridge.setData({ 18402 * guideState : jsonData, 18403 * error : function (guideResultObject) { 18404 * // log the errors 18405 * } 18406 * }) 18407 * 18408 * @example <caption>Setting data from XML/JSON</caption> 18409 * guideBridge.getData({ 18410 * success : function (guideResultObj) { 18411 * var data = guideResultObj.data; 18412 * //post the XML/JSON to a server that saves it at say http://abc.com/my/data.xml 18413 * //or http://abc.com/my/data.json 18414 * }, 18415 * error : function (guideResultObj) { 18416 * // log the errors 18417 * } 18418 * }); 18419 * 18420 * guideBridge.setData({ 18421 * dataRef : "http://abc.com/my/data.xml", 18422 * error : function (guideResultObject) { 18423 * // log the errors 18424 * } 18425 * }) 18426 * 18427 * @example <caption>Setting data from URL to a JSON</caption> 18428 * guideBridge.getGuideState({ 18429 * success : function (guideResultObj) { 18430 * var json = guideResultObj.data; 18431 * //post the JSON to a server that saves it at say http://abc.com/my/data.json 18432 * }, 18433 * error : function (guideResultObj) { 18434 * // log the errors 18435 * } 18436 * }); 18437 * 18438 * guideBridge.setData({ 18439 * guideStatePathRef : "http://abc.com/my/data.json", 18440 * error : function (guideResultObject) { 18441 * // log the errors 18442 * } 18443 * }) 18444 **/ 18445 setData : function (options) { 18446 guideBridge.restoreGuideState(options); 18447 }, 18448 18449 /* 18450 * @private 18451 */ 18452 _getStorage : function () { 18453 var storage = null; 18454 if (this.storage) { 18455 // Get the storage 18456 storage = this.storage; 18457 this.storage = null; 18458 } 18459 return storage; 18460 }, 18461 18462 getGuideContext : function () { 18463 var obj = new GuideResultObject(); 18464 obj.data = jQuery.extend(true, {}, (this._guide ? this._guide.runtime.guideContext : null)); 18465 return obj; 18466 }, 18467 18468 _getContextRoot : function () { 18469 return this.userConfig["contextPath"]; 18470 }, 18471 18472 _getEnableFocusOnFirstField : function () { 18473 var renderConfig = this.userConfig.renderConfig || {}, 18474 enableFocusOnFirstField = renderConfig.enableFocusOnFirstField === undefined ? true : renderConfig.enableFocusOnFirstField, 18475 // convert "true"/"false" strings to boolean too 18476 enableFocusOnFirstFieldAsBoolean = enableFocusOnFirstField === 'true' || (enableFocusOnFirstField === 'false' ? false : enableFocusOnFirstField); 18477 // default value is true 18478 return enableFocusOnFirstFieldAsBoolean; 18479 }, 18480 18481 _updateAjaxUrl : function (baseUrl) { 18482 if (this.hostName === "server") { 18483 $.ajaxPrefilter(function (options, originalOptions, jqXHR) { 18484 // 'Rebase' the URL if required. 18485 var thisUrl = options.url; 18486 if ((thisUrl.lastIndexOf('http://', 0) !== 0) && (thisUrl.lastIndexOf('https://', 0) !== 0)) { 18487 // thisUrl is relative. 18488 // thisUrl may or may not begin with slash
18489 // encoding taken care by the ajax call 18490 if (thisUrl.indexOf("/") === 0) { 18491 // if begins with slash 18492 thisUrl = baseUrl + thisUrl; 18493 } else { 18494 thisUrl = baseUrl + "/" + thisUrl; 18495 } 18496 options.url = thisUrl; 18497 } 18498 }); 18499 18500 // Native XHR Wrapper 18501 var originalOpen = XMLHttpRequest.prototype.open; 18502 XMLHttpRequest.prototype.open = function(method, url) { 18503 if ((url.lastIndexOf('http://', 0) !== 0) && (url.lastIndexOf('https://', 0) !== 0)) { 18504 // url is relative 18505 if (url.indexOf("/") === 0) { 18506 url = baseUrl + url; 18507 } else { 18508 url = baseUrl + "/" + url; 18509 } 18510 } 18511 originalOpen.apply(this, arguments); 18512 }; 18513 } 18514 }, 18515 18516 _getUrl : function (url) { 18517 var baseUrl = this.userConfig["baseUrl"], 18518 contextPath = this.userConfig["contextPath"]; 18519 if (baseUrl) { 18520 return baseUrl + url; 18521 } else if (contextPath && contextPath !== "/" && url.indexOf(contextPath) !== 0 && (url.length === 0 || url.indexOf("/") === 0)) { 18522 //if url does not have contextPath and starts with /, pre-pend contextPath 18523 // Also url.length check because I need to pass "" to getUrl and get context path 18524 return contextPath + url; 18525 } 18526 return url; 18527 }, 18528 18529 _getGuidePathUrl : function (urlSuffix, guidePath) { 18530 // guidePath here refers to the path got from json state of guide 18531 // we use this path, if there is no guidePath set in guidelib.runtime.guideContext, cases where guide is not initialized but 18532 // guideBridge is present 18533 var path = guidePath || this.getGuidePath(), 18534 url = path + (urlSuffix || ""); 18535 return this._getUrl(url); 18536 }, 18537 18538 /** 18539 * @summary Returns the path which refers to the location of 18540 * the content resource of adaptive form container 18541 * @returns {String} Path to the content resource of the adaptive form container 18542 * @method 18543 * @memberof GuideBridge 18544 * @since 6.5 18545 * @instance 18546 */ 18547 getGuidePath : function () { 18548 var guideContext = this.getGuideContext().data; 18549 if (guideContext && guideContext.hasOwnProperty("guidePath")) { 18550 return guideContext["guidePath"]; 18551 } 18552 return null; 18553 }, 18554 18555 /** 18556 * @summary Given a somExpression, return the {@link GuideNode} having the same somExpression. 18557 * @param {string} somExpression somExpression of the Adaptive Form component 18558 * @returns {GuideNode} GuideNode matching the som expression or null if not found 18559 * @method 18560 * @memberof GuideBridge 18561 * @since 6.0 18562 * @instance 18563 * @see GuideNode#somExpression 18564 */ 18565 resolveNode : function (somExpression) { 18566 return this._guide.resolveNode(somExpression); 18567 }, 18568 /* 18569 * Internal API. Should be used carefully. 18570 */ 18571 _resolveId : function (id) { 18572 var node = this._guide._modelTemplateCacheStore.getModel(id); 18573 return node; 18574 }, 18575 18576 /** 18577 * Helper method for accesibility announcements 18578 * Is part of the fix for FORMS-7071 (CQ-4276669) 18579 */ 18580 _ariaLiveAnnouncement : function (text) { 18581 var ariaLiveElement = $("#ariaLiveElement"); 18582 setTimeout(function() { 18583 $(ariaLiveElement).text(text); 18584 return (setTimeout(function() { 18585 $(ariaLiveElement).text(""); 18586 }, 2000)) 18587 }, 500); 18588 }, 18589 18590 /** 18591 * Invokes {@link Field#resetData}
18591 API for all the Fields inside the Form to reset their values to default 18592 * @summary Reset the values of all the Fields to their default values. 18593 * 18594 * @method 18595 * @memberof GuideBridge 18596 * @instance 18597 * @since 6.0 18598 */ 18599 reset : function () { 18600 if (window.xfalib && window.xfalib.runtime && window.xfalib.runtime.xfa) { 18601 var xfa = window.xfalib.runtime.xfa; 18602 xfa.host.resetData(); 18603 } 18604 this._guide.resetData(); 18605 18606 if (this._guide.internal.liveDataUtils.isLiveDataInitialized()) { 18607 this._guide.internal.liveDataUtils.updateLiveData(); 18608 } 18609 18610 var guideDirtyMarkerAndVisitor = this._guide.internal.GuideDirtyMarkerAndVisitor; 18611 guideDirtyMarkerAndVisitor.visitMap = guidelib.model.util.CommonUtils.createMap(this._guide.allLazyChildren, 0); 18612 18613 this._ariaLiveAnnouncement(guidelib.i18n.strings["formHasBeenReset"]); 18614 }, 18615 18616 _getPreviousFocus : function () { 18617 return this._guideView._previousFocusItemSom; 18618 }, 18619 18620 /** 18621 * Returns the somExpression of the current {@link Panel} or current {@link Field} in Focus. The API can also 18622 * be used to get the somExpression of the Navigable Panel that contains the current Element in Focus. 18623 * 18624 * @summary return the somExpression of the {@link Panel} or {@link Field} that is currently in focus 18625 * @param {object} options configuration to be passed to the API to get the desired result 18626 * @param {?string} [options.focusOption] Currently the following value of this option are supported 18627 * * `navigablePanel`: if one wants to get the somExpression of the Navigable Panel 18628 * @returns {string} somExpression of Adaptive Form component representing the field or panel. 18629 * @method 18630 * @memberof GuideBridge 18631 * @instance 18632 * @since 6.0 18633 * @see {GuideNode#somExpression} 18634 * @example 18635 * guideBridge.getFocus({"focusOption": "navigablePanel"}) 18636 */ 18637 getFocus : function (options) { 18638 var focusOption; 18639 if (_.isUndefined(options)) { 18640 return this._guideView.currentFocusItemSom; 18641 } 18642 if ((focusOption = getOrElse(options, "focusOption", null)) === "navigablePanel") { 18643 return this._guideView._lastFocussedPanelForNonActionFields; 18644 } 18645 this._guide.logger().log("Invalid Focus option.", focusOption); 18646 }, 18647 18648 /** 18649 * The API is equivalent to calling 18650 * `guideBridge.setFocus(options.somExpression, options.focusOption, options.runCompletionScript)` 18651 * @summary An alternate signature to the {@link GuideBridge#setFocus|setFocus} API 18652 * @method setFocus 18653 * @memberof GuideBridge 18654 * @instance 18655 * @since 6.1 FP1 18656 * @param {object} options options passed to the API 18657 * @param {string} options.somExpression somExpression to set the focus to 18658 * @param {string} options.focusOption item inside the Panel to focus to 18659 * @param {string} options.runCompletionScript whether to run the completion script or not. 18660 * @return {boolean} true if the focus was set successfully otherwise false. 18661 */ 18662 18663 /** 18664 * In Adaptive Form one can focus a Field/Panel. Setting focus on a Panel means setting focus to its first 18665 * child. This can be controlled using the _focusOption_ provided in this API. 18666 * 18667 * The API provides two mechanism to focus a Field/Panel. 18668 * * **Direct** : By providing the somExpression of the Field/Panel. If the somExpression of Panel is provided, 18669 * then based on the focusOption one of its child (or their child) is set to Focus 18670 * * **Indirect** : By providing an item's relative position inside a Panel, first or last item inside of a 18671 * Panel, sibling of current focussed Item of a Panel, etc. If the item is a Panel then the First Item of 18672 * that Panel (if that is again a Panel, this process continues until a Field is found) is activated. 18673 * 18674 * The first way is trivial, by providing the _somExpression_ of a {@link Field} to the API, the focus will be 18675 * set to the Field. 18676 * 18677 * If that Field is inside a Panel that is not currently open because of tabbed/wizard navigation, then that tab 18678 * would be opened and focus would be set to the Field/Panel. 18679 * 18680 * The API can also execute the 18681 * [completion expression](https://helpx.adobe.com/aem-forms/6-1/adaptive-form-expressions.html#main-pars_header_8) 18682 * of the current Panel and only if the expression returns true set focus to the required element. 18683 * 18684 * **Note:** 18685 * * If _focusOption_ is either of nextItemDeep or prevItemDeep then _somExpression_ parameter must not be 18686 * passed. Otherwise the API will throw an exception 18687 * * If _somExpression_ points to a {@link Field} and _focusOption_ is not _nextItemDeep_ or _prevItemDeep_ then 18688 * _focusOption_ is ignored. 18689 * 18690 * @summary Sets focus to a {@link Field} or {@link Panel} 18691 * @param {?string} somExpression SOM Expression of the Adaptive Form Field or Panel which has to be activated. 18692 * @param {string} [focusOption=firstItem] The option provides the mechanism to focus onto an sibling of the 18693 * current active item. 18694 * * **_firstItem_** - Focuses to the first focusable item of the Panel whose _SOM Expression_ is provided 18695 * * **_lastItem_** - Focuses to the last focusable item of the Panel whose _SOM Expression_ is provided 18696 * 18697 * If either the _firstItem_ or _lastItem_ is a Panel, then the _firstItem_ of that Panel (until a Field is 18698 * found) is set to Focus. 18699 * 18700 * * **_nextItem_** - Next sibling component of the current active Item of the Panel whose _somExpression_ is 18701 * provided. It is equivalent to the result of `panel.navigationContext.nextItem` API. 18702 * * **prevItem** - Previous sibling component of the current active Item of the Panel show _somExpression_ is 18703 * provided. It is equivalent to the result of `panel.navigationContext.prevItem` API. 18704 * 18705 * * **_nextItemDeep_** - Focus is set to the next Navigable Panel of root Panel in DFS Order 18706 * * **_prevItemDeep_** - Focus is set to the next Navigable Panel of root Panel in DFS Order 18707 * @param {boolean} [runCompletionScript=false] indicating whether to execute the completion expression or not. 18708 * @returns {boolean} true if the focus was set to requested field successfully otherwise false 18709 * @method 18710 * @memberof GuideBridge 18711 * @since 6.0 18712 * @instance 18713 * @example 18714 * setFocus(somExpression); // Focus is set to the specified somExpression. 18715 * setFocus(this.panel.somExpression,'nextItem',true); // Focus is set to next item in the Panel. 18716 * setFocus(null,'nextItemDeep',true); // Focus is set to next navigable Panel in rootPanel 18717 */ 18718 setFocus : function (somExpression, focusOption, runCompletionScript) { 18719 var options, 18720 focusDone, 18721 originalSkipFieldFocus; 18722 if (_.isObject(somExpression)) { 18723 options = somExpression; 18724 } else { 18725 options = { 18726 somExpression : somExpression, 18727 focusOption : focusOption, 18728 runCompletionScript : runCompletionScript 18729 }; 18730 } 18731 try { 18732 originalSkipFieldFocus = this._guideView.skipFieldFocus; 18733 /** 18734 * Setting of this._guideView.skipFieldFocus was added for issue LC-3911361 18735 * Here we set a skipFieldFocus property for gudeContainerView, which prevents 18736 * actual 'input' / widget focus. This was done to prevent opening of keyboard or dropdown spinner 18737 * or date picker.. in case of swipe and use of deep navigators in mobile view of Adaptive Form. 18738 * 18739 * when user validates Adaptive Form, skipFieldFocus is set to options.skipFieldFocus based on somExpression 18740 * which has default value of'undefined' else the skipFieldFocus set to the negated value of global variable 18741 * enableFocusOnFirstField to enable/disable focus on first field of Adaptive Form. 18742 */ 18743 var fallbackSkipFieldFocus = !this._guide.enableFocusOnFirstField; 18744 if (!fallbackSkipFieldFocus) { 18745 fallbackSkipFieldFocus = !guideBridge._getEnableFocusOnFirstField(); 18746 } 18747 this._guideView.skipFieldFocus = options.somExpression ? options.skipFieldFocus : fallbackSkipFieldFocus; 18748 focusDone = this._guideView.setFocus(options); 18749 } finally { 18750 this._guideView.skipFieldFocus = originalSkipFieldFocus; //moving back to original state 18751 } 18752 //TODO: need a more common place to do that. 18753 if (!this._guide._currentContext) { 18754 this._guide.runPendingExpressions(); 18755 } 18756 return focusDone; 18757 }, 18758 18759 /** 18760 * Loads the lazy fragment specified by somExpression 18761 * @param {string} somExpression somexpression of the lazy loaded fragment 18762 * @param {object} options options to control the behaviour of loadLazyFragment API. 18763 * @param {function} [options.error] callback which receives the result of the API in 18764 * case of failure. 18765 * @method 18766 * @memberof GuideBridge 18767 * @since 6.4 18768 * @instance 18769 * @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 18770 * would load both</caption> 18771 * guideBridge.loadLazyFragment("x[0].y[0].z[0]"); 18772 * 18773 */ 18774 loadLazyFragment : function (somExpression, options) { 18775 if (!_.isUndefined(somExpression)) { 18776 var relativeSom = guidelib.util.GuideUtil.relativeSom(this._guide.rootPanel.somExpression, somExpression); 18777 if (relativeSom) { 18778 var somTokens = relativeSom.split("."); 18779 var currItem = this._guide.rootPanel; 18780 _.each(somTokens, function (qName) { 18781 if (currItem != null) { 18782 var arr = currItem._findChildren(qName, false); 18783 if (arr.length > 0) { 18784 var node = arr[0]; 18785 if (node && node._lazyReference && !node._itemsLoaded) { 18786 this._guide.internal.liveDataUtils.updateLiveData(); 18787 node._loadLazyFragment(options); 18788 } 18789 currItem = node; 18790 } else { 18791 currItem = null; 18792 } 18793 } 18794 }, this); 18795 } 18796 } 18797 }, 18798 18799 /* 18800 * Get the download link of signed document set by signing service. 18801 * @return: url from where the signed document can be accessed, empty in case its not set by signing service. 18802 */ 18803 getSignedDocDownloadLink : function () { 18804 var url = ""; 18805 if (!_.isUndefined(FD) 18806 && !_.isUndefined(FD.AFaddon) 18807 && !_.isUndefined(FD.AFaddon.Signing) 18808 && !_.isUndefined(FD.AFaddon.Signing.signedDocDownloadLink)) { 18809 url = FD.AFaddon.Signing.signedDocDownloadLink; 18810 } 18811 return url; 18812 }, 18813 18814 /* 18815 If true is passed to the function then it checks for model and view both, 18816 if false or no parameter is passed, then it checks the model only. 18817 */ 18818 isGuideLoaded : function (complete) { 18819 if (complete) { 18820 return !_.isEmpty(window.guideBridge._guide && window.guideBridge._guideView); 18821 } 18822 return !_.isEmpty(window.guideBridge._guide); 18823 }, 18824 18825 _doInternalSubmit : function (options) { 18826 if (options.excludeFormState) { 18827 var submissionInfo = options.guideState.data.guideState.guideContext.afSubmissionInfo; 18828 if (submissionInfo && submissionInfo.hasOwnProperty('lastFocusItem')) { 18829 submissionInfo.lastFocusItem = undefined; 18830 } 18831 } 18832 // Make a clone of options so that original options are not modified. 18833 // Remove additionalSubmitInfo from the guideState so that no extra information 18834 // is sent to the server. 18835 var clonedGuideState = JSON.parse(JSON.stringify(options.guideState)); 18836 if (!_.isEmpty(clonedGuideState.data.guideState.additionalSubmitInfo)) { 18837 clonedGuideState.data.guideState.additionalSubmitInfo = {}; 18838 } 18839 var guideState = clonedGuideState, 18840 strContent = this.getMultipartData({ 18841 guideState : JSON.stringify(guideState.data), 18842 dorData : options.dorData || false, 18843 _charset_ : "UTF-8" 18844 }), 18845 // check if guide state is present, if yes get guide path from guide state 18846 // Specifically written for mobile workspace to getDataXML from current json state 18847 guidePath = ((guideState && guideState.data) ? guideState.data.guideState.guideContext.guidePath : null); 18848 18849 $.ajax({ 18850 url : this._getGuidePathUrl(".af.internalsubmit.jsp", guidePath), 18851 type : "POST", 18852 async : options.async || false, 18853 contentType : "multipart/form-data; charset=UTF-8; boundary=" + strContent[0], 18854 data : strContent[1], 18855 success : options.success, 18856 error : options.error 18857 }); 18858 }, 18859 18860 _submitInternal : function (options) { 18861 var self = this; 18862 options = options || {}; 18863 if (!options.guideState) { 18864 this.getGuideState({ 18865 "diff" : "diff", 18866 "fileUploadPath" : options.fileUploadPath, 18867 "success" : function (guideState) { 18868 self._doInternalSubmit({ 18869 guideState : guideState, 18870 success : options.success, 18871 error : options.error, 18872 async : options.async, 18873 excludeFormState : options.excludeFormState, 18874 dorData : options.dorData 18875 }); 18876 }, 18877 "error" : options.error, 18878 reducedJSON : true 18879 }); 18880 } else { 18881 this._doInternalSubmit({ 18882 guideState : options.guideState, 18883 success : options.success, 18884 error : options.error, 18885 async : options.async, 18886 excludeFormState : options.excludeFormState, 18887 dorData : options.dorData 18888 }); 18889 } 18890 }, 18891 18892 getMultipartData : function (data) { 18893 //Start multipart formatting 18894 var initBoundary = this.randomString(); 18895 var strBoundary = "--" + initBoundary; 18896 var strMultipartBody = ""; 18897 var strCRLF = "\r\n"; 18898 18899 //Create multipart for each element of the form 18900 for (var key in data) { 18901 if (data.hasOwnProperty(key)) { 18902 var value = _.isObject(data[key]) ? JSON.stringify(data[key]) : data[key]; 18903 strMultipartBody += 18904 strBoundary + 18905 strCRLF + 18906 "Content-Disposition: form-data; name=\"" + key + "\"" + 18907 strCRLF + 18908 strCRLF + 18909
18909 value + 18910 strCRLF; 18911 } 18912 } 18913 //End the body by delimiting it 18914 strMultipartBody += strBoundary + "--" + strCRLF; 18915 //Return boundary without -- and the multipart content 18916 return [initBoundary, strMultipartBody]; 18917 }, 18918 18919 randomString : function () { 18920 var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz"; 18921 var string_length = 8; 18922 var randomstring = ''; 18923 for (var i = 0; i < string_length; i++) { 18924 var rnum = Math.floor(Math.random() * chars.length); 18925 randomstring += chars.substring(rnum, rnum + 1); 18926 } 18927 return randomstring; 18928 }, 18929 18930 /* 18931 * Get the file Attachment map that contains a mapping of som expression vs path when files have been uploaded 18932 * and som expression vs name when the files have not yet been uploaded . 18933 * @return: map of som expression and paths. 18934 * @private 18935 */ 18936 getFileAttachmentMap : function () { 18937 var fileAttachmentMap = {}, 18938 fileAttachmentsList = window.guideBridge._getFileAttachmentsList(); 18939 for (var i = 0; i < fileAttachmentsList.length; i++) { 18940 var node = fileAttachmentsList[i]; 18941 if (!_.isEmpty(node.fileAttachment.value)) { 18942 fileAttachmentMap[node.somExpression] = node.fileAttachment.value; 18943 } 18944 } 18945 18946 var lazyAttachmentMap = this._guide.internal.liveDataUtils._getLazyAttachmentMap(); 18947 _.each(lazyAttachmentMap, function (mapObject, key) { 18948 fileAttachmentMap[key] = mapObject.value; 18949 }); 18950 return fileAttachmentMap; 18951 }, 18952 18953 /* 18954 * sets the value of the file attachment component based on the map that is passed. 18955 * @private 18956 */ 18957 putFileAttachmentMap : function (fileAttachmentMap) { 18958 _.each(fileAttachmentMap, function (value, som) { 18959 var node = guideBridge.resolveNode(som); 18960 node.fileAttachment.value = value; 18961 }); 18962 }, 18963 18964 _appendFileAttachmentsToFormData : function(dataForm, fileNameDomMap, fileAttachmentsList) { 18965 var fileNamesIndex, 18966 fileDoms = fileNameDomMap.fileDom, 18967 fileNames = fileNameDomMap.fileName, 18968 faPromise = {}, 18969 rejectedFileNames = [], 18970 isIOS = guidelib.util.GuideUtil._isIOS(), 18971 createUnorderedList = function(list, bulletChar) { 18972 var result = ""; 18973 for (var i = 0; i<list.length; ++i) { 18974 result += bulletChar + " " + list[i] + "\n"; 18975 } 18976 return "\n" + result; 18977 }, 18978 throwException = function(fileNames) { 18979 if (fileNames && fileNames.length > 0) { 18980 throw guidelib.util.GuideUtil.getLocalizedMessage("AF", guidelib.i18n.LogMessages["AEM-AF-901-024"], [createUnorderedList(fileNames, "•")]); 18981 } 18982 }; 18983 for (fileNamesIndex = 0; fileNamesIndex < fileNames.length; fileNamesIndex++) { 18984 // multiple files inside one filedom element & draft save case is handled. 18985 var currentFileNames = fileNames[fileNamesIndex].split("\n"); 18986 for (var fileIndex = 0; fileIndex < currentFileNames.length; fileIndex++) { 18987 if (currentFileNames[fileIndex] && _.isString(fileDoms[fileNamesIndex])) { 18988 //handle draft save scenario when fileDoms[fileNamesIndex] is string(URL) & currentFileNames[fileIndex] is a url 18989 dataForm.append("_guideFileAttachment." + guideBridge._getRelativeFilePath(currentFileNames[fileIndex]), fileDoms[fileNamesIndex]); 18990 } 18991 } 18992 } 18993 dataForm.append("_guideAttachments", fileNames.toString()); 18994 if (isIOS) { 18995 var allFAPromises = []; 18996 _.each(fileAttachmentsList, function (fileAttachmentModel, index) { 18997 var fileAttachmentWrapperPromises = fileAttachmentModel._fileAttachmentWrapperIOS; 18998 if (fileAttachmentWrapperPromises) { 18999 allFAPromises.push.apply(allFAPromises, fileAttachmentWrapperPromises); 19000 } 19001 });
19002 faPromise = Promise.allSettled(allFAPromises).then(function(results){ 19003 for (var pIndex = 0; pIndex < results.length; pIndex++) { 19004 // if status rejected, fail submission 19005 if (results[pIndex].status === "rejected") { 19006 rejectedFileNames.push(results[pIndex].reason); 19007 } else { 19008 var resultValue = results[pIndex].value; 19009 var completeNameOfFile = resultValue.formElementName + "/" + resultValue.name; 19010 dataForm.append(completeNameOfFile, resultValue.dataURLtoBlob(), resultValue.name); 19011 } 19012 } 19013 // to fail this promise, throw an exception here 19014 throwException(rejectedFileNames); 19015 return dataForm; 19016 }); 19017 } else { 19018 var allFileAccessPromise = []; 19019 for (fileNamesIndex = 0; fileNamesIndex < fileNames.length; fileNamesIndex++) { 19020 // multiple files inside one filedom element & draft save case is handled. 19021 var currentFileNames = fileNames[fileNamesIndex].split("\n"); 19022 for (var fileIndex = 0; fileIndex < currentFileNames.length; fileIndex++) { 19023 // in case of IOS, file binary is from file object, we use the in-memory data 19024 if (fileDoms[fileNamesIndex] && !_.isString(fileDoms[fileNamesIndex]) && fileDoms[fileNamesIndex].length > 0) { 19025 // promise is not supported in IE11 19026 // for IE11, we don't read file bytes 19027 if (window.Promise) { 19028 var fileAccessPromise = guidelib.util.GuideUtil._checkIfFileIsAccessible(currentFileNames[fileIndex], fileDoms[fileNamesIndex][0].files[fileIndex]); 19029 allFileAccessPromise.push(fileAccessPromise); 19030 } else { 19031 // append each file of input file element to formdata 19032 dataForm.append(currentFileNames[fileIndex], fileDoms[fileNamesIndex][0].files[fileIndex]); 19033 } 19034 19035 } 19036 } 19037 } 19038 // promise is not supported in IE11 19039 if (window.Promise) { 19040 faPromise = Promise.allSettled(allFileAccessPromise).then(function (results) { 19041 for (var pIndex = 0; pIndex < results.length; pIndex++) { 19042 // if status rejected, fail submission 19043 if (results[pIndex].status === "rejected") { 19044 rejectedFileNames.push(results[pIndex].reason); 19045 } else { 19046 var resultValue = results[pIndex].value; 19047 dataForm.append(resultValue.fileName, resultValue.file); 19048 } 19049 } 19050 throwException(rejectedFileNames); 19051 return dataForm; 19052 }); 19053 } else { 19054 faPromise = $.Deferred().resolve(dataForm); 19055 } 19056 } 19057 return faPromise; 19058 }, 19059 19060 doAjaxSubmitWithFileAttachment : function (actionUrl, submitData, options, fileAttachmentsList) { 19061 var _options = options || {}, 19062 self = this, 19063 dataForm = new FormData(), 19064 fileNameDomMap = this._juiceOutNameAndFileDomMap(fileAttachmentsList), 19065 faPromise = this._appendFileAttachmentsToFormData(dataForm, fileNameDomMap, fileAttachmentsList); 19066 19067 var _submitForm = function () { 19068 $.ajax({ 19069 url : actionUrl, 19070 type : "POST", 19071 processData : false, 19072 cache : false, 19073 contentType : false, 19074 dataType : 'json', 19075 data : dataForm, 19076 success : function (data) { 19077 self.doAjaxSubmitSuccess(data, _options); 19078 }, 19079 error : function (data) { 19080 self.doAjaxSubmitError(data, _options); 19081 } 19082 }); 19083 };
19084 faPromise.then(function (dataForm) { 19085 $.each(submitData, function (key, val) { 19086 if (typeof val == "object") { 19087 val = JSON.stringify(val); 19088 } 19089 dataForm.append(key, val); 19090 }); 19091 _submitForm(); 19092 }) 19093 .catch(function (e) { 19094 // handle errors here 19095 console.error("Error while reading file bytes in IOS"); 19096 self.doAjaxSubmitError(data, _options); 19097 }); 19098 }, 19099 19100 19101 doAjaxSubmit : function (actionUrl, submitData, options) { 19102 var _options = options || {}, 19103 self = this, 19104 asyncSubmit = _options.async !== false, 19105 strContent = this.getMultipartData(submitData); 19106 $.ajax({ 19107 url : actionUrl, 19108 type : "POST", 19109 traditional : true, 19110 async : asyncSubmit, 19111 contentType : "multipart/form-data; charset=UTF-8; boundary=" + strContent[0], 19112 data : strContent[1], 19113 success : function (data) { 19114 self.doAjaxSubmitSuccess(data, _options); 19115 }, 19116 error : function (data) { 19117 self.doAjaxSubmitError(data, _options); 19118 } 19119 }); 19120 }, 19121 19122 KEY_AF_SUCCESS_PAYLOAD : "afSuccessPayload", 19123 19124 doAjaxSubmitSuccess : function (data, options) { 19125 var guideResultObject = new GuideResultObject(); 19126 guideResultObject.data = data; 19127 guideResultObject.completed = true; 19128 // remove the submitting message too after success of ajax submit 19129 guideBridge._showGuideLoading(false); 19130 if (_.isFunction(options.success)) { 19131 options.success.call(options.context, guideResultObject); 19132 } else { 19133 if (data.hasOwnProperty("signingURL")) { 19134 // Adobe sign : FormFiller enabled case. 19135 window.location.href = data.signingURL; 19136 } else { 19137 var payload = {}; 19138 if (data.hasOwnProperty(guideBridge.KEY_AF_SUCCESS_PAYLOAD)) { 19139 try { 19140 payload = JSON.parse(data[guideBridge.KEY_AF_SUCCESS_PAYLOAD]); 19141 payload.data = this._guide.internal.afdata; 19142 var schemaType = this._guide.runtime.guideContext.schemaType; 19143 if (!schemaType) { 19144 //TODO define a constant for schema Type. 19145 schemaType = "xmlschema"; 19146 } 19147 payload.contentType = schemaType; 19148 } catch (e) { 19149 guideBridge._guide.logger().log("Error while parsing AF Success Payload: " + e); 19150 } 19151 } 19152 guideBridge._guide.executeExpression("submitSuccess", payload); // Executing Rule Editor code for submit success. 19153 } 19154 } 19155 }, 19156 19157 doAjaxSubmitError : function (data, options) { 19158 var guideResultObject = new GuideResultObject(); 19159 guideResultObject.data = data; 19160 guideResultObject.completed = false; 19161 guideResultObject.addMessage(2, "Error in Async Submit", ""); 19162 guideBridge._showGuideLoading(false); 19163 if (_.isFunction(options.error)) { 19164 options.error.call(options.context, guideResultObject); 19165 } else { 19166 var errorPayload = {}; 19167 try { 19168 errorPayload = JSON.parse(data.responseText); 19169 } catch (e) { 19170 guideBridge._guide.logger().log("Error while parsing errorPayload." + e); 19171 } 19172 guideBridge._guide.executeExpression("submitError", errorPayload); //Executing Rule Editor code for submitError 19173 } 19174 }, 19175 19176 handleUpload : function () { 19177 self = this.self; 19178 this.submitData['_guideAttachments'] = this.attachments.toString(); 19179 _.each(this.attachments, function (att) { 19180 this.submitData["_guideFileAttachment." + att] = this.submitData['fileUrl'] + "/" + att; 19181 }, this); 19182 delete this.submitData['fileUrl']; 19183 self.doAjaxSubmit(this.actionUrl, this.submitData, this.options); 19184 }, 19185 19186 _handleSubmitError : function (data, message) { 19187 // case: show message if it exists, for example, there could be client side errors during submit 19188 if (message) { 19189 alert(message); 19190 } else { 19191 var status = Number(data.status); 19192 switch (status) { 19193 case 502: 19194 alert(guidelib.util.GuideUtil.getLocalizedMessage("AF", guidelib.i18n.LogMessages["AEM-AF-901-003"])); 19195 break; 19196 default: 19197 alert(guidelib.util.GuideUtil.getLocalizedMessage("AF", guidelib.i18n.LogMessages["AEM-AF-901-004"])); 19198 break; 19199 } 19200 } 19201 guideBridge._showGuideLoading(false); 19202 }, 19203 19204 updateSubmitData : function (fileAttachmentsList, submitData, fileList) { 19205 var fileCount = 0, 19206 attachments = [], 19207 name; 19208 if (fileList.length === 0 && fileAttachmentsList.length > 0 && !guideBridge._disablePreview()) { 19209 _.each(fileAttachmentsList, function (fileUploadComponentId, index) { 19210 var currentCount = 0; 19211 var componentInModel = window.guideBridge._resolveId(fileUploadComponentId); 19212 var fileNameList = componentInModel["fileAttachment"].value; 19213 if (fileNameList) { 19214 var fileNames = fileNameList.split("\n"); 19215 _.each(fileNames, function (fileUrl, index) { 19216 name = componentInModel.name + "/" + fileUrl.substring(fileUrl.lastIndexOf("/") + 1); 19217 if (name) {
19218 attachments[fileCount++] = name; 19219 submitData["_guideFileAttachment." + name] = fileUrl; 19220 } 19221 }, this); 19222 } 19223 }, this); 19224 submitData['_guideAttachments'] = attachments; 19225 } else if (fileList.length > 0) { 19226 _.each(fileList, function (file, index) { 19227 name = guideBridge._getRelativeFilePath(file); 19228 attachments[fileCount++] = name; 19229 submitData["_guideFileAttachment." + name] = file; 19230 }, this); 19231 submitData['_guideAttachments'] = attachments; 19232 } 19233 }, 19234 19235 _collectFileUrls : function (event) { 19236 var list = [], 19237 fileUploadError = false; 19238 19239 // Populate list to have path of all the uploaded files. The file Attachment component whose model was 19240 // loaded would have their fileNames first followed by the list of file names of unloaded file upload components. 19241 _.each(this.attachments, function (attachment) { 19242 _.each(attachment.split("\n"), function (att) { 19243 // check if att is a url and hence push it directly to list 19244 if (_.isString(att) && att.match(/\//g).length > 1) { 19245 list.push(att); 19246 } else { 19247 list.push(this.fileUrl + "/" + att); 19248 } 19249 }, this); 19250 }, this); 19251 19252 var options = { 19253 fileUrlList : list, 19254 fileUploadModelsList : this.fileAttachmentsList, 19255 lazyAttachmentMap : guideBridge._guide.internal.liveDataUtils._getLazyAttachmentMap() 19256 }; 19257 guidelib.util.GuideUtil._updateFileModelsAndLazyMap(options); 19258 19259 var submitOptions = this.options.ajaxSubmitObject; 19260 if (submitOptions && submitOptions.ajaxSubmitDataHandler) { 19261 submitOptions.ajaxSubmitDataHandler.call(this.options.context, submitOptions.fileAttachmentsList, submitOptions.submitData, list); 19262 window.guideBridge.doAjaxSubmit(submitOptions.actionUrl, submitOptions.submitData, this.options); 19263 } else if (this.options.success) { 19264 //create the guideState now as the model has been updated with the latest values. 19265 //do this only during getGuideState and not on ajax submit 19266 guideBridge._createGuideStateAndLiveXml(this.options); 19267 this.options.success.call(this.options.context, this.options.obj); 19268 } 19269 19270 }, 19271 19272 _fileUploadFailed : function (event) { 19273 $.proxy(guideBridge._handleSubmitError({ 19274 "status" : "500" 19275 }), guideBridge); 19276 }, 19277 19278 // This function extracts the form name from the guideContainerPath. 19279 _getFormName : function (guidePath) { 19280 var formName = ""; 19281 if (guidePath) { 19282 var index = guidePath.indexOf("/jcr:content/guideContainer"); 19283 guidePath = guidePath.substring(0, index); 19284 formName = guidePath.substring(guidePath.lastIndexOf("/") + 1); 19285 } 19286 return formName; 19287 }, 19288 19289 // This function creates a UUID that is used for ajax submit 19290 _getUUIDForAjaxSubmit : function () { 19291 var uuidSuffix = Math.floor((Math.random() * 10000) + 1), 19292 uuidCurrentTime = new Date().getTime(), 19293 successFlag = true; 19294 var guidePath = window.guideBridge.getGuidePath(); 19295 this._formInstanceUUID = window.guideBridge._getFormName(guidePath) + uuidCurrentTime + uuidSuffix; 19296 successFlag = createUUIDStorage(this._formInstanceUUID); 19297 if (successFlag) { 19298 return this._formInstanceUUID; 19299 } else { 19300 return null; 19301 } 19302 }, 19303 19304 /** 19305 * returns the form element to be used for submission in case of non-ajax 19306 * submit. 19307 * The function looks in the submitConfig for a form and if not present, 19308 * creates a new form 19309 * @returns {object} jQuery object for form element 19310 * @private 19311 */ 19312 _getFormForSubmission : function () { 19313 var submitConfig = this.userConfig.submitConfig || {}, 19314 form = submitConfig.form || $("<form method='post' enctype='multipart/form-data'></form>").appendTo($("body")); 19315 return $(form); 19316 }, 19317 19318 _getThankYouPageFromConfig : function () { 19319 var submitConfig = this.userConfig.submitConfig || {}; 19320 return submitConfig.thankyouPage; 19321 }, 19322 19323 /** 19324 * This function prepare the guideValueMap and returns it. 19325 * @returns A map consisting of name and value for all the unbound components 19326 * @private 19327 */ 19328 _prepareGuideValueMap : function () { 19329 var guideValueMap = {}, visitedMap = {}; 19330 this.visit(function (node) { 19331 if (!node.bindRef && !visitedMap[node.somExpression]) { 19332 if (node instanceof guidelib.model.Field && node.value) { 19333 visitedMap[node.somExpression] = true; 19334 guideValueMap[node.getAttribute("name")] = node.value; 19335 } else if (node instanceof guidelib.model.GuideCompositeField) { 19336 var obj = guideValueMap[node.getAttribute("name")] = {}; 19337 _.each(node.items, function (childNode, index) { 19338 visitedMap[childNode.somExpression] = true; 19339 if (childNode.value) { 19340 obj[childNode.getAttribute("name")] = childNode.value; 19341 } 19342 }, this); 19343 } 19344 } 19345 }); 19346 return guideValueMap; 19347 }, 19348 19349 _showGuideLoading : function (flag, msg) { 19350 if(!flag){ 19351 if(_focusedSubmitButtonModel){ 19352 _focusedSubmitButtonModel.enabled = true; 19353 _focusedSubmitButtonModel = null; 19354 } 19355 } 19356 var util = guidelib.util.GuideUtil; 19357 if (util) { 19358 util.showGuideLoading(flag); 19359 if (msg !== undefined) { 19360 util.showMessages(msg); 19361 } else { 19362 util.removeAllMessages(); 19363 } 19364 } 19365 }, 19366 19367 _submitAfterValidation : function (options, submitSuccess, submitError) { 19368 var self = this; 19369 if (guidelib.util.GuideUtil) { 19370 var msg = guidelib.i18n.strings.submittingForm; 19371 if (options && options.submissionSelector === 'agreement') { 19372 msg = guidelib.i18n.strings.generatingSignAgreement; 19373 } 19374 guidelib.util.GuideUtil.showMessages(msg); 19375 } 19376 // Trigger submitStart before calling internal submit. 19377 if (guideBridge.isGuideLoaded() && self._guide._triggerOnBridge) { 19378 self._guide._triggerOnBridge("submitStart", "", "", "", ""); 19379 } 19380 var excludeFormState = true; 19381 if (options && options.hasOwnProperty("excludeFormState")) { 19382 excludeFormState = options.excludeFormState; 19383 } 19384 try { 19385 var guideState = getOrElse(options, "guideState", null); 19386 if (guideState || guideBridge.isGuideLoaded()) { 19387 var twoStepSubmission = getOrElse(options, "twoStepSubmission", true); 19388 if (guideState || self._guide.xdpRef || twoStepSubmission) { 19389 self._submitInternal({ 19390 guideState : guideState, 19391 success : function () { 19392 try { 19393 submitSuccess.apply(self, arguments); 19394 } catch (e) { 19395 self._handleInternalSubmitError(submitError, self, arguments); 19396 } 19397 }, 19398 error : function () { 19399 self._handleInternalSubmitError(submitError, self, arguments); 19400 }, 19401 async : true, 19402 excludeFormState : excludeFormState 19403 }); 19404 } else { 19405 self.getFormDataString({ 19406 success : function () { 19407 try { 19408 submitSuccess.apply(self, arguments); 19409 } catch (e) { 19410 self._handleInternalSubmitError(submitError, self, arguments); 19411 } 19412 } 19413 }); 19414 } 19415 } else { 19416 console.error("Form Submission failed as the form doesn't exist on the page") 19417 } 19418 } catch (e) { 19419 self._showGuideLoading(false); 19420 if (console && console.error) { 19421 console.error(e); 19422 } 19423 } 19424 }, 19425 19426 _handleCaptchaTimeout : function () { 19427 window.alert(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.LogMessages["AEM-AF-901-025"])); 19428 window.guideBridge.setEnabledAutoSave(_isAutoSaveEnabled); 19429 guideBridge._showGuideLoading(false); 19430 return; 19431 }, 19432 19433 /** 19434 * Validate and submits the data of the Adaptive Form to the pre-configured submit action. 19435 * 19436 * The success handler provided in the argument is executed only if the Adaptive Form is configured to use AJAX 19437 * for submission using {@link GuideBridge#registerConfig|registerConfig} API 19438 * @summary submits the Adaptive Form 19439 * @param {object} options options to control the behaviour of submit API. 19440 * @param {string} [options.submissionSelector] url selector governs the submission behaviour at server 19441 * Default value is "submit", other options are "agreement", "signSubmit" 19442 * @param {function} [options.success] callback which receives the result of the API 19443 * in case of success. 19444 * {@link GuideResultObject#errors|errors} property as false. 19445 * @param {function} [options.error] callback which receives the result of the API in 19446 * case of failure. 19447 * {@link GuideResultObject#errors|errors} property as true. 19448 * @param {object} [options.context] _this_ object inside the _success_ and _error_ callback will point to this 19449 * object 19450 * @param {boolean} [options.validate=true] whether to validate the form before submission or not 19451 * @method 19452 * @memberof GuideBridge 19453 * @since 6.0 19454 * @instance 19455 * @example <caption>Submitting the form without validation</caption> 19456 * guideBridge.submit({ 19457 * validate: false, 19458 * error : function (guideResultObject) {//log message} 19459 * }); 19460 * @example <caption>Submitting the form and showing a success message</caption> 19461 * guideBridge.registerConfig("submitConfig" : {"useAjax" : true}); 19462 * guideBridge.submit({ 19463 * validate: false, 19464 * error : function (guideResultObject) {//log message} 19465 * success : function (guideResultObject) {alert("data submitted successfully") 19466 * }); 19467 */ 19468 19469 submit : function (options) { 19470 // Disabling the submit button 19471 if (this._guideView) { 19472 var focusedElementSOM = guideBridge.getFocus(); 19473 if (focusedElementSOM) { 19474 _focusedSubmitButtonModel = guideBridge.resolveNode(focusedElementSOM); 19475 _focusedSubmitButtonModel.enabled = false;
19476 } 19477 } 19478 _isAutoSaveEnabled = window.guideBridge.getAutoSaveEnabledStatus(); 19479 //Disable auto save till submission is not completed 19480 if (_isAutoSaveEnabled) { 19481 window.guideBridge.setEnabledAutoSave(false); 19482 } 19483 var self = this; 19484 var guideContextFromOptions, 19485 runtimeGuideContext = getOrElse(this._guide, "runtime.guideContext", {}); 19486 if (getOrElse(options, "guideState", "")) { 19487 guideContextFromOptions = options.guideState.data.guideState.guideContext; 19488 } 19489 var localGuideContext = guideContextFromOptions || runtimeGuideContext; 19490 // to submit guideContainerForm which will be stopped so that autocomplete values can be remembered 19491 $(".guideContainerFormSubmitButton").click(); 19492 19493 window.guideBridge._populateBindRefToSomMap(); 19494 19495 function submitError(data) { 19496 self._ariaLiveAnnouncement(guidelib.i18n.strings["formSubmitFail"]); 19497 if (options && options.error) { 19498 options.error.call(options.context || this, data); 19499 } else { 19500 $.proxy(guideBridge._handleSubmitError(data), guideBridge); 19501 } 19502 } 19503 19504 function submitSuccess(result) { 19505 var isAjaxSubmit = false; 19506 19507 if (options) { 19508 isAjaxSubmit = options.success ? true : false; 19509 } 19510 options = options || {}; 19511 options.success = options.success || (self.userConfig.submitConfig || {}).submitSuccessHandler; 19512 isAjaxSubmit = isAjaxSubmit || (self.userConfig.submitConfig || {useAjax : false}).useAjax || guideBridge._guide.enableAsyncSubmission; 19513 var submitData = {}; 19514 19515 if (this.isGuideLoaded()) { 19516 var guideCaptchaList = []; 19517 this.visit(function (node) { 19518 if (node.className === "guideCaptcha") { 19519 guideCaptchaList.push(node); 19520 } 19521 }); 19522 var captchaModel = guideCaptchaList[0]; 19523 if (captchaModel) { 19524 var captchaData = window.guideBridge._getCaptchaData(captchaModel); 19525 submitData['captchaData'] = captchaData; 19526 } 19527 } 19528 19529 // check if guide state is present, if yes get guide path from guide state 19530 var guidePath = getOrElse(options, "guideState.data.guideState.guideContext.guidePath", ""), 19531 guideContainerPath = guidePath || window.guideBridge.getGuidePath(), 19532 aemFormComponentPath = this.userConfig.submitConfig ? this.userConfig.submitConfig.aemFormComponentPath : "", 19533 submissionSelector = options.submissionSelector || "submit", 19534 actionUrl = window.guideBridge._getGuidePathUrl(".af." + submissionSelector + ".jsp", guideContainerPath); 19535 19536 submitData['guideContainerPath'] = guideContainerPath; 19537 submitData['aemFormComponentPath'] = aemFormComponentPath; 19538 submitData['_asyncSubmit'] = isAjaxSubmit; 19539 submitData['_charset_'] = "UTF-8"; 19540 var customPropMap = localGuideContext.customPropertyMap || {}; 19541 // need to remove lastFocusItem from being sent as a different property 19542 // as it being sent in xml and with afSubmissionInfo as well. 19543 var whiteListedProperties = ["lastFocusItem"]; 19544 for (var prop in customPropMap) { 19545 if (customPropMap.hasOwnProperty(prop) && whiteListedProperties.indexOf(prop) < 0) { 19546 submitData[prop] = customPropMap[prop]; 19547 } 19548 } 19549 // todo: Have to remove the excludeFromDor map from the submission info, is this required ? 19550 if (this.isGuideLoaded()) {
19551 submitData['afSubmissionInfo'] = this._guide.runtime.guideContext.afSubmissionInfo || {}; 19552 } 19553 var resultJson = result, 19554 guideJson, 19555 data, 19556 fileAttachmentsList, 19557 attachments = [], 19558 fileCount = 0; 19559 if (resultJson.hasOwnProperty("guideValue")) { 19560 guideJson = resultJson.guideValue; 19561 } else if (!_.isUndefined(options.guideValueMap)) { 19562 guideJson = options.guideValueMap; 19563 } else { 19564 // todo: why is this required in client ? 19565 guideJson = window.guideBridge._prepareGuideValueMap(); 19566 } 19567 if (resultJson.hasOwnProperty("data")) { 19568 data = resultJson["data"]; 19569 } 19570 19571 if (resultJson.hasOwnProperty("fileAttachmentsList")) { 19572 fileAttachmentsList = resultJson["fileAttachmentsList"]; 19573 } 19574 19575 for (var key in guideJson) { 19576 if (guideJson.hasOwnProperty(key)) { 19577 submitData[key] = guideJson[key]; 19578 } 19579 } 19580 19581 if (data) { 19582 submitData['jcr:data'] = data; 19583 submitData['jcr:data@TypeHint'] = "Binary"; 19584 if (self.isGuideLoaded()) { 19585 self._guide.internal.afdata = data; 19586 } 19587 } 19588 if (!_.isUndefined(options.fileAttachmentMap)) { 19589 submitData.fileAttachmentMap = options.fileAttachmentMap; 19590 } else { 19591 //send the fileAttachmentMap through submit data to restore submission attachments for read only viewing 19592 submitData.fileAttachmentMap = JSON.stringify(guideBridge._getFileAttachmentMapForSubmit()); 19593 } 19594 // read the additional information from the guideState if it is passed in options 19595 // otherwise get the additional information from the DOM 19596 var additionalSubmitInfo = {}; 19597 if (options.guideState && options.guideState.data.guideState.additionalSubmitInfo) { 19598 additionalSubmitInfo = options.guideState.data.guideState.additionalSubmitInfo; 19599 } else { 19600 additionalSubmitInfo = guideBridge._getAdditionalSubmitInfo(); 19601 } 19602 // append additionalSubmitInfo to the submitData 19603 $.extend(true, submitData, additionalSubmitInfo); 19604 19605 if (isAjaxSubmit && isAjaxSubmit === true) { 19606 // 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. 19607 // we just update the submitData with the attachment information 19608 if (options.fileAttachmentMap) { 19609 var attachmentMap = JSON.parse(options.fileAttachmentMap); 19610 var keys = _.keys(attachmentMap); 19611 for (var i = 0; i < keys.length; i++) { 19612 if (attachmentMap[keys[i]]) { 19613 var fileNames = attachmentMap[keys[i]].split("\n"); 19614 for (var j = 0; j < fileNames.length; j++) { 19615 var name = guideBridge._getRelativeFilePath(fileNames[j]); 19616 attachments[fileCount++] = name; 19617 submitData["_guideFileAttachment." + name] = fileNames[j]; 19618 } 19619 } 19620 } 19621 submitData['_guideAttachments'] = attachments; 19622 self.doAjaxSubmit(actionUrl, submitData, options); 19623 } else { 19624 var attachedFilesList = []; 19625 var currentCount = 0; 19626 // need to check if the guide is loaded, as it is not available for mobile workspace app use case 19627 if (guideBridge.isGuideLoaded()) { 19628 attachedFilesList = window.guideBridge._getFileAttachmentsList(); 19629 } 19630 _.each(attachedFilesList, function (object) { 19631 var fileNameList = object["fileAttachment"].value; 19632 if (fileNameList) { 19633 currentCount++; 19634 } 19635 }); 19636 // If a file has been attached and isAjaxSubmit is true, then a UUID is generated and 19637 // the files are uploaded at temp storage path. 19638 // The submit data is updated with the attached files and then 19639 // doAjaxSubmit is called. 19640 if (currentCount > 0) { 19641 self.doAjaxSubmitWithFileAttachment(actionUrl, submitData, options, attachedFilesList); 19642 } else { 19643 self.doAjaxSubmit(actionUrl, submitData, options); 19644 } 19645 } 19646 } else { 19647 var $form = self._getFormForSubmission(); 19648 $form.attr('action', actionUrl); 19649 $form.attr('data-name', 'afSubmissionForm'); 19650 for (var fields in submitData) { 19651 if (submitData.hasOwnProperty(fields)) { 19652 var value = submitData[fields]; 19653 $("<input>").attr("type", "hidden") 19654 .attr("name", fields) 19655 .val(_.isObject(value) ? JSON.stringify(value) : value) 19656 .appendTo($form); 19657 } 19658 } 19659 /* 19660 * This means we did not do any preprocessing 19661 * for file attachments so fileAttachment list won't be present 19662 * so posting DOM for the files. 19663 * */ 19664 var attachmentNameDomMap = guideBridge._getFileNameFileDomMap(), 19665 fileNameList = [], 19666 _guideAttachments = ""; 19667 // A string containing the names of all the files that are attached is stored in the variable _guideAttachments. 19668 // For all the files that have been uploaded already and don't have a dom element are 19669 // added to $form with prefix "_guideFileAttachment." 19670 if (attachmentNameDomMap && attachmentNameDomMap.fileDom) { 19671 fileNameList = attachmentNameDomMap.fileName; 19672 _.each(attachmentNameDomMap.fileDom, function (file, index) { 19673 if (!_.isString(file)) { 19674 file.attr("name", fileNameList[index].split["\n"]) 19675 .attr("class", "hidden") 19676 .appendTo($form); 19677 _guideAttachments += fileNameList[index] + ","; 19678 } else { 19679 if (fileNameList[index]) { 19680 var name = guideBridge._getRelativeFilePath(fileNameList[index]); 19681 $("<input>").attr("type", "hidden") 19682 .attr("name", "_guideFileAttachment." + name) 19683 .attr("value", file) 19684 .appendTo($form); 19685 _guideAttachments += name + ","; 19686 } 19687 } 19688 }); 19689 } 19690 $("<input>").attr("type", "hidden") 19691 .attr("name", "_guideAttachments") 19692 .attr("value", _guideAttachments) 19693 .appendTo($form); 19694 19695 $form.submit(); 19696 } 19697 } 19698 19699 self._showGuideLoading(true, guidelib.i18n.strings.val
19699idatingForm); 19700 // since validate is synchronous call, putting this in timeout 19701 // so that html changes can be display 19702 setTimeout(function () { 19703 // update the snapshot just before validating 19704 // so that we get true state of play before loading panels 19705 if (guideBridge.isGuideLoaded() && guideBridge._guide.allLazyChildren && guideBridge._guide.allLazyChildren.length > 0) { 19706 self._guide.internal.liveDataUtils.updateLiveData(); 19707 } 19708 var isValid = false; 19709 try { 19710 isValid = self._performConditionalValidation(options); 19711 } catch (e) { 19712 isValid = false; 19713 } finally { 19714 self._showGuideLoading(true); 19715 } 19716 if (isValid) { 19717 /* Handle Invisible Recaptcha on form submission */ 19718 var recaptchaInvisibleElement = FD.isToggleEnabled(guidelib.util.FeatureToggleConstants.FT_TURNSTILE_HCAPTCHA) ? 19719 $("#captchaInvisible") : $("#recaptchaInvisible"); 19720 if (recaptchaInvisibleElement != undefined && recaptchaInvisibleElement.attr("af-recaptcha-execute") == "") { 19721 recaptchaInvisibleElement.trigger({ 19722 type: "recaptchaExecution", 19723 submitParameters: { 19724 options: options, 19725 success: submitSuccess, 19726 error: submitError 19727 }, 19728 triggerPostSubmission: true 19729 }); 19730 return; 19731 } 19732 guideBridge._submitAfterValidation(options, submitSuccess, submitError); 19733 } else { 19734 window.guideBridge.setEnabledAutoSave(_isAutoSaveEnabled); 19735 self._showGuideLoading(false); 19736 return; 19737 } 19738 }, 1); 19739 }, 19740 /** 19741 * @private 19742 */ 19743 _handleInternalSubmitError : function (submitError, selfVar, args) { 19744 try { 19745 submitError.apply(selfVar, args); 19746 } catch (e) { 19747 //ignoring the error 19748 } finally { 19749 guideBridge._showGuideLoading(false); 19750 19751 } 19752 }, 19753 /** 19754 * @private 19755 */ 19756 _getFileAttachmentMapForSubmit : function () { 19757 var fileAttachmentMap = {}, 19758 fileAttachmentsList = window.guideBridge._getFileAttachmentsList(); 19759 for (var i = 0; i < fileAttachmentsList.length; i++) { 19760 var node = fileAttachmentsList[i]; 19761 if (!_.isUndefined(node.value) && node.value.length > 0) { 19762 var attachmentList = node.value.split("\n"); 19763 for (var j = 0; j < attachmentList.length; j++) { 19764 attachmentList[j] = node.name + "/" + attachmentList[j]; 19765 } 19766 fileAttachmentMap[node.somExpression] = attachmentList.join('\n'); 19767 } 19768 } 19769 19770 var lazyAttachmentMap = this._guide.internal.liveDataUtils._getLazyAttachmentMap(); 19771 _.each(lazyAttachmentMap, function (mapObject, key) { 19772 var attachmentList = mapObject.value.split("\n"); 19773 for (var j = 0; j < attachmentList.length; j++) { 19774 attachmentList[j] = guidelib.util.GuideUtil.guideSomToComponentName(key) + "/" + attachmentList[j]; 19775 } 19776 fileAttachmentMap[key] = attachmentList.join('\n'); 19777 }); 19778 return fileAttachmentMap; 19779 }, 19780 19781 ERROR_CAUSED_BY : { 19782 CAPTCHA_VALIDATION : "CAPTCHA_VALIDATION", 19783 SERVER_SIDE_VALIDATION : "SERVER_SIDE_VALIDATION", 19784 FORM_SUBMISSION : "FORM_SUBMISSION", 19785 AGREEMENT_CREATION : "AGREEMENT_CREATION", 19786 AGREEMENT_CREATION : "AGREEMENT_CREATION", 19787 SERVICE_INVOCATION_FAILURE: "SERVICE_INVOCATION_FAILURE" 19788 }, 19789 19790 /** 19791 * This API displays validation error messages at the field level corresponding to the input errorJson object 19792 * @summary Displays validation error messages at field level 19793 * @memberof GuideBridge 19794 * @instance 19795 * @param {object}
19795 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) 19796 * @see {@link https://helpx.adobe.com/experience-manager/6-5/forms/using/custom-validation-message-adaptive-forms.html%7CCustom validation message in adaptive form} 19797 */ 19798 handleServerValidationError : function (errorJson) { 19799 var self = this; 19800 if (errorJson) { 19801 var errors = errorJson.errors; 19802 if (errors && errors.length > 0) { 19803 var firstFocusableSom; 19804 _.each(errors, function (object, i) { 19805 var errMsg; 19806 if (object.errorMessages) { 19807 errMsg = object.errorMessages.join("\n"); 19808 } else { 19809 errMsg = object.errorMessage; 19810 } 19811 var som = (object.somExpression) ? object.somExpression : self._guide._bindRefMap[object.bindRef]; 19812 var node = self.resolveNode(som); 19813 19814 if (node) { 19815 if (!firstFocusableSom) { 19816 firstFocusableSom = som; 19817 } 19818 node.markAsInvalid(errMsg); 19819 } 19820 }); 19821 // set focus to first invalid node 19822 if (firstFocusableSom) { 19823 self.setFocus(firstFocusableSom); 19824 } 19825 } 19826 } 19827 }, 19828 19829 /* Handle the server side validation failure in case of submission fails. 19830 * This function handles Captcha validation as well as server side validation. 19831 * @private 19832 */ 19833 _handleServerValidationError : function (errorJson) { 19834 var self = this; 19835 window.guideBridge.setEnabledAutoSave(_isAutoSaveEnabled); 19836 if (errorJson) { 19837 if (errorJson.errorCausedBy && errorJson.errorCausedBy === this.ERROR_CAUSED_BY.CAPTCHA_VALIDATION) { 19838 var errors = errorJson.errors, 19839 firstFocusableSom = errors[0].somExpression; 19840 _.each(errors, function (object, i) { 19841 var somExpression = object.somExpression, 19842 errorMessage = object.errorMessage, 19843 guideCaptcha; 19844 /*Setting focus to load captcha's view. 19845 This is required when panel's children get loaded later. 19846 Setting focus ensures that view is loaded properly so that model can throw 19847 'guide.errorChanged' event and view can listen the same. 19848 */ 19849 self.setFocus(somExpression); 19850 guideCaptcha = self.resolveNode(somExpression); 19851 if (guideCaptcha) { 19852 guideCaptcha.showCaptchaError(errorMessage); 19853 } 19854 }); 19855 //Setting focus to the first captcha element. 19856 self.setFocus(firstFocusableSom); 19857 } else if (errorJson.errorCausedBy && errorJson.errorCausedBy === this.ERROR_CAUSED_BY.FORM_SUBMISSION 19858 || errorJson.errorCausedBy === this.ERROR_CAUSED_BY.AGREEMENT_CREATION) { 19859 if (errorJson.errors && errorJson.errors.length > 0) { 19860 window.guideBridge.handleServerValidationError(errorJson); 19861 } else { 19862 var statusCode = errorJson.originCode ? Number(errorJson.originCode) : 500, 19863 errorMessage = statusCode === 400 ? (errorJson.errorMessage ? errorJson.errorMessage : "") : ""; 19864 // show the message returned by server only if if the HTTP status code is 400 19865 // this is done so that users could act upon the error and re-submit the form 19866 $.proxy(guideBridge._handleSubmitError({ 19867 "status" : statusCode 19868 }, errorMessage), guideBridge); 19869 } 19870 } else { 19871 //Everything else is "SERVER_SIDE_VALIDATION". Calling this as it was being called. 19872 window.guideBridge.handleServerValidationError(errorJson); 19873 } 19874 } 19875 }, 19876 19877 /* 19878 * Populates bindRefToSomMap. 19879 * This function is called during submission and during unloading of a lazy fragment 19880 * @param {node} is equal to the lazy loaded fragment model if this is called during lazy fragment unloading 19881 * @private 19882 */ 19883 _populateBindRefToSomMap : function (node) { 19884 19885 /* 19886 * While populating bindRefToSomMap we basically check if any panel is repeatable panel. 19887 * If a panel is repeatable, in that node and its desce
19887ndant nodes we replace the bindRef 19888 * by corresponding json-pointer in the map. 19889 * parameter {jsonp} refers to the json-pointer of the parent node. It is valid if 19890 * some ancestor of current node in the hierarchy was a repeatable panel 19891 */ 19892 var bindRefToSomMapper = function (node, map, jsonp) { 19893 var path, bindref; 19894 if (node.bindRef) { 19895 if (node.repeatable) { // current node is a repeatable panel 19896 if (jsonp) { // some ancestor panel in the hierarchy was a repeatable panel 19897 path = jsonp + "/" + node.bindRef.split("/").slice(-1)[0] + "/" + node.index; 19898 bindref = path; 19899 } else { // current node is the first repeatable panel in the hierarchy 19900 path = node.bindRef + "/" + node.index; 19901 bindref = path; 19902 } 19903 } else { 19904 if (jsonp) { // some panel in the upper level was a repeatable panel 19905 path = jsonp + "/" + node.bindRef.split("/").slice(-1)[0]; 19906 bindref = path; 19907 } else { // no repeatable panel till now 19908 bindref = node.bindRef; 19909 } 19910 } 19911 map[bindref] = node.somExpression; 19912 } 19913 19914 if (node._children) { 19915 node._children.forEach(function (element) { 19916 bindRefToSomMapper(element, map, path); 19917 }); 19918 } 19919 }; 19920 var jsonp; 19921 19922 // since we support lazy-loading for a fragment upto only two level deep, the immediate parent panel 19923 // of a lazy-loaded fragment can atmost be a repeatable panel. so we only check the repeatability for the parent 19924 if (node && node.parent && node.parent.repeatable && node.parent.bindRef) { 19925 jsonp = node.parent.bindRef + "/" + node.parent.index; 19926 } 19927 19928 if (!node) { 19929 node = window.guideBridge._guide; 19930 } 19931 19932 if (window.guideBridge.isGuideLoaded()) { 19933 if (!window.guideBridge._guide._bindRefMap) { 19934 window.guideBridge._guide._bindRefMap = {}; 19935 } 19936 bindRefToSomMapper(node, window.guideBridge._guide._bindRefMap, jsonp); 19937 } 19938 }, 19939 19940 SELECTOR_FORM_CONTAINER : "#guideContainerForm", 19941 19942 THANK_YOU_OPTION : { 19943 PAGE : "page", 19944 MESSAGE : "message" 19945 }, 19946 /* 19947 * default Submit Success Handler. 19948 * This function handles the Thank You Page/Message 19949 */ 19950 _defaultSubmitSuccessHandler : function (successPayload) { 19951 if (successPayload) { 19952 if (successPayload.thankYouOption === this.THANK_YOU_OPTION.MESSAGE) { 19953 var tyMessage = $("<div class='tyMessage'>" + successPayload.thankYouContent + "</div>"); 19954 $(this.SELECTOR_FORM_CONTAINER).replaceWith(tyMessage); 19955 tyMessage.attr({'tabindex': '-1', 19956 'role': 'alertdialog'}); 19957 tyMessage.focus(); 19958 } else if (successPayload.thankYouOption === this.THANK_YOU_OPTION.PAGE) { 19959 window.location.href = encodeURI(successPayload.thankYouContent); 19960 } 19961 } 19962 }, 19963 19964 // This function gets the relative path of the file. 19965 // Suppose the component Name is attachment and the file name is a.jpg, 19966 // then it will return "attachment/a.jpg" as the path 19967 _getRelativeFilePath : function (fileName) { 19968 var relPath = fileName; 19969 if (fileName.indexOf("/") !== -1) { 19970 var splitPath = fileName.split("/"); 19971 if (splitPath.length > 2) { 19972 relPath = splitPath[splitPath.length - 2] + "/" + splitPath[splitPath.length - 1]; 19973 } 19974 } 19975 return relPath; 19976 }, 19977 19978 // We do not need to validate if options.validate = false. 19979 // This function makes sure that validations are not performed when validate flag is false. 19980 // Validation is performed in all the other cases. 19981 _performConditionalValidation : function (options) { 19982 if (getOrElse(options, "validate", true)) { 19983 return guideBridge.validate(null, null, true, false); 19984 } 19985 return true; 19986 }, 19987 19988 /** 19989 * This API returns the HTML content of another Adaptive Form and optionally load the Form inside an HTML 19990 * element 19991 * 19992 * The {@link GuideResultObject#data|data}
19992 property of the result passed to success handler will contain the HTML of 19993 * the Form 19994 * @summary load an Adaptive Form given its path 19995 * @param {object} options object to pass to the API 19996 * @param {function} [options.success] callback which receives the result of the API 19997 * in case of success. 19998 * {@link GuideResultObject#errors|errors} property as false. 19999 * @param {function} [options.error] callback which receives the result of the API in 20000 * case of failure. 20001 * {@link GuideResultObject#errors|errors} property as true. 20002 * @param {object} [options.context] _this_ object inside the _success_ and _error_ callback will point to this 20003 * object 20004 * @param {string} options.path Path of the Adaptive Form whose HTML is required. If sever is running at a 20005 * context path, this parameter must have the context path 20006 * @param {string} [options.dataRef] URL of the resource that returns the XML. The protocol of the URL must 20007 * match the supported URL protocols 20008 * @param {string} [options.containerSelector] jquery Selector of the HTML element where to insert the HTML 20009 * of the form. 20010 * @method 20011 * @memberof GuideBridge 20012 * @since 6.1 FP1 20013 * @instance 20014 * @example 20015 * guideBridge.loadAdaptiveForm({ 20016 * success : function (guideResultObj) {console.log("html is " + guideResultObj.data)}, 20017 * error : function (guideResultObj) { //log errors}, 20018 * dataRef : "http://url/of/the/dataRef", 20019 * path : "/contextpath/content/dam/formsanddocuments/form1" 20020 * }) 20021 * @see {@link https://api.jquery.com/category/selectors/|jQuery selectors} 20022 * @see <a href="#guidebridge-api-usage" >GuideBridge API Usage</a> 20023 */ 20024 loadAdaptiveForm : function (options) { 20025 if (options && options.path) { 20026 // Let's covert the adaptive form asset path or af path 20027 // @todo: add notion of channel type in the options to load adaptive form 20028 var path = options.path.replace(FM_DAM_ROOT, FM_AF_ROOT); 20029 path += "/jcr:content/guideContainer.html"; 20030 $.ajax({ 20031 url : path, 20032 type : "GET", 20033 data : { 20034 // lets set the wcmmode to disabled 20035 wcmmode : "disabled", 20036 // Set the data reference 20037 "dataRef" : options.dataRef 20038 }, 20039 async : false, 20040 success : function (data) { 20041 // Get the container selector and do a replaceWith HTML 20042 // not using jquery since jquery create a separate array objects for script, link etc 20043 if (options.containerSelector) { 20044 //NOCHECKMARX - data is coming from serverside preventing Reflective XSS All Clients. 20045 $(options.containerSelector).html(data); 20046 } 20047 var guideResultObject = new GuideResultObject(); 20048 // data would here be html 20049 guideResultObject.data = data; 20050 guideResultObject.completed = true; 20051 if (options.success && _.isFunction(options.success)) { 20052 options.success.call(options.context, guideResultObject); 20053 } 20054 }, 20055 error : function (data) { 20056 var guideResultObject = new GuideResultObject();
20057 // data is an object containing xhr request, status and error 20058 guideResultObject.data = data; 20059 guideResultObject.completed = false; 20060 guideResultObject.addMessage(2, "Error in getting HTML of Adaptive Form: " + options.path, ""); 20061 if (options.error && _.isFunction(options.error)) { 20062 options.error.call(options.context, guideResultObject); 20063 } 20064 } 20065 }); 20066 } else { 20067 if (typeof(console) !== "undefined") { 20068 console.log("Path of Adaptive Form not specified to loadAdaptiveForm API"); 20069 } 20070 } 20071 }, 20072 20073 /** 20074 * Unloads the Form loaded using the {@link GuideBridge#loadAdaptiveForm|loadAdaptiveForm} API 20075 * @summary Unloads an adaptive Form from the browser, removing all the existing event listeners, data, html. 20076 * @param containerSelector jQuery Selector of the container, which contains the HTML of the Adaptive Form 20077 * @method 20078 * @memberof GuideBridge 20079 * @since 6.1 FP1 20080 * @instance 20081 * @see {@link https://api.jquery.com/category/selectors/|jQuery selectors} 20082 */ 20083 unloadAdaptiveForm : function (containerSelector) { 20084 // Let's clear all intervals 20085 // Never make intervals, which are not cleared 20086 if (window.guidelib && window.guidelib.intervals) { 20087 // check for null safe 20088 window.clearInterval(window.guidelib.intervals.intId); 20089 } 20090 // Remove all the child present in the container 20091 $(containerSelector).children().remove(); 20092 // Clean the date picker html 20093 // todo: clean other HTML which we add outside Adaptive Form 20094 $('body').find(".datePickerTarget").remove(); 20095 20096 // todo: what are the even listeners to clean ? 20097 $(window).off("guideModelInitialized"); 20098 $(window).off("guideInitialized"); 20099 $(window).off("guideInitializationError"); 20100 // todo: What if there is an existing load, scroll or resize listener already present in page ? 20101 $(window).off("load scroll resize"); 20102 $(window).off("keydown.guides"); 20103 20104 $('.guideContainerWrapperNode').off("swiperight"); 20105 $('.guideContainerWrapperNode').off("swipeleft"); 20106 20107 // Remove all delegated event listeners 20108 $(document).off('click.guidetab.data-api'); 20109 $(document).off('click.guideAddRemove.data-api'); 20110 20111 // Remove date picker event listeners 20112 $(window).off("touchstart.datetimepicker mousedown.datetimepicker"); 20113 20114 if (window.guidelib) { 20115 // Start cleaning data 20116 window.guidelib.runtime = { 20117 guide : null, 20118 af : null, // not sure if making it null would impact, since this namespace hold's public functions 20119 guideContext : null, 20120 _private : {}, 20121 errorManager : null 20122 }; 20123 20124 window.guidelib.internal = { 20125 liveModel : null, 20126 liveDataUtils : null, 20127 GuideDirtyMarkerAndVisitor : null 20128 }; 20129 } 20130 20131 if (window.guideBridge) { 20132 // Unload all guideBridge references 20133 window.guideBridge._guide = null; 20134 window.guideBridge._guideView = null; 20135 window.guideBridge._$target = null; 20136 window.guideBridge._guideDoc = null; 20137 } 20138 if (window.xfalib) { 20139 // We always load ut for logger 20140 window.xfalib.ut = null; 20141 } 20142 // If form bridge exist's call form bridge to destroy form 20143 if (window.formBridge) { 20144 window.formBridge.destroyForm(); 20145 } 20146 // Clear any jquery cache, this should avoid memory leak 20147 if (window.jQuery) { 20148 // note: repeatable template marker div was held by jquery fragment 20149 // Before converting the HTML string to a DOM subtree, there is a lot of process involved 20150 // To make the process faster there is a "fragment cache" that saves the processed string as DOM nodes 20151 // Let's clean the fragment cache 20152 window.jQuery.fragments = {}; 20153 } 20154 20155 if (window.guidelib && window.guidelib.model) { 20156 // Clean accessible objects 20157 window.guidelib.model.GuideNode.guideUtil = null; 20158 } 20159 20160 // Lets clean all guidelib object's at first level 20161 // Let's hope there are no closure objects created or any reference of objects inside guidelib 20162 _.each(window.guidelib, function (obj, key) { 20163 // "util", "event", "model", "view", "runtime", "author", "log", "i18n", "guideReplaced" get's cleaned here 20164 window.guidelib[key] = undefined; 20165 }); 20166 20167 if ($) { 20168 // Lets clean all jquery plugin's created 20169 //window.$.Widget = undefined; 20170 //window.$.widget = undefined; 20171 $.xfaWidget = undefined; 20172 // May be required if we want to unload the entire page. 20173 // window.$.fn = undefined; 20174 $.prototype.abstractWidget = undefined; 20175 $.prototype.adobeDateTimePicker = undefined; 20176 $.prototype.adobeFileAttachment = undefined; 20177 $.prototype.adobeFileUploader = undefined; 20178 $.prototype.dateTimeEdit = undefined; 20179 $.prototype.dropDownList = undefined; 20180 $.prototype.defaultWidget = undefined; 20181 $.prototype.fileUpload = undefined; 20182 $.prototype.imageField = undefined; 20183 $.prototype.listBox = undefined; 20184 $.prototype.nwkListBox = undefined; 20185 $.prototype.numericInput = undefined; 20186 $.prototype.signatureField = undefined; 20187 $.prototype.ScribbleImageField = undefined; 20188 $.prototype.textField = undefined; 20189 $.prototype.xfaButton = undefined; 20190 $.prototype.XfaCheckBox = undefined; 20191 } 20192 }, 20193 20194 /** 20195 * Disables all the fields and global toolbar 20196 * @private 20197 */ 20198 _disableForm : function () { 20199 var rootPanel = guideBridge.resolveNode("guide[0].guide1[0].guideRootPanel[0]"), 20200 globalToolbar = guideBridge.resolveNode("guide[0].guide1[0].toolbar[0]"); 20201 20202 // The following API disables the loaded fields 20203 rootPanel.disableAllFields(); 20204 // The following API disables the form toolbar 20205 if (globalToolbar) { 20206 globalToolbar.disableAllFields(); 20207 } 20208 }, 20209 20210 /** 20211 * @summary Disables the adaptive form, i.e. it disables all the fields and buttons, including toolbar's button 20212 * @method 20213 * @memberof GuideBridge 20214 * @since 6.3 20215 */ 20216 disableForm : function () { 20217 guideBridge._disableForm(); 20218 //Listening on guideBridge for "elementLazyLoaded" event to disable lazily loaded fields 20219 guideBridge.on("elementLazyLoaded", guideBridge._disableForm); 20220 }, 20221 20222 _playGuideJson : function (options) { 20223 this._guide.setGuideState(guidelib.model.GuideSchema.prototype.GuideStateConstants.GUIDE_STATE_MERGE_PROGRESS); 20224 /* 20225 * no need to check here since merged json will not have xfaState if
20226 * xdp is invalid 20227 */ 20228 if (this._isXfaGuide() && options.guideState.xfaState && options.guideState.xfaState.xfaDom) { 20229 var that = this; 20230 window.formBridge.restoreFormState({ 20231 formState : options.guideState.xfaState, 20232 context : this, 20233 //NOCHECKMARX - This is error callback to be provided by the user of this API. 20234 error : options.error || defaultErrorHandler, 20235 success : function () { 20236 that._playNonXfaJson(options); 20237 } 20238 }); 20239 } else { 20240 this._playNonXfaJson(options); 20241 } 20242 }, 20243 20244 _playNonXfaJson : function (options) { 20245 // try to get xml-s from restore state 1st as they will be more relevant than the prefill state 20246 var xmlStr = getOrElse(options, "guideState.guideLiveData", null) 20247 || getOrElse(options, "guideState.guidePrefillXml", null), 20248 xfaXmlStr = getOrElse(options, "guideState.xfaState.currentContext.data", null) 20249 || JSON.parse(getOrElse(options, "guideState.xfaState.xfaRenderContext", "{}")).data, 20250 jsonStr = getOrElse(options, "guideState.guidePrefillJson", null); 20251 if (xmlStr || xfaXmlStr) { 20252 this._guide.internal.liveDataUtils.initLiveData(xmlStr, xfaXmlStr, 20253 _.isString(this._guide.xdpRef), _.isString(this._guide.xsdRef), 20254 this._guide.getAttribute("xsdRootElement")); 20255 this._guide.internal.liveModel.prefillCrossFragFields(this._guide); 20256 this._guide.internal.liveDataUtils.dropXfaXml(); 20257 } else if (jsonStr) { 20258 this._guide.internal.liveDataUtils.initLiveData(jsonStr, this._guide.runtime.guideContext); 20259 } else { 20260 this._guide.internal.liveDataUtils.initLiveData(null, null, 20261 _.isString(this._guide.xdpRef), _.isString(this._guide.xsdRef), 20262 this._guide.getAttribute("xsdRootElement")); 20263 } 20264 20265 // If the restore state is not stored in local storage,then use it from the json passed from the server 20266 if (options.guideState.guideDom) { 20267 this._guide.playJson(options.guideState.guideDom, options.attachments); 20268 } 20269 if (options.guideState.unboundDataMap && options.guideState.unboundDataMap.data) { 20270 this.visit(function (node) { 20271 // Fileupload value should not be set again, as it replaces the url with the file name 20272 if (!(node instanceof guidelib.model.GuideFileUpload) && (node instanceof guidelib.model.Field || node instanceof guidelib.model.GuideCompositeField) 20273 && !node.getAttribute("bindRef") && options.guideState.unboundDataMap.data[node.name]) { 20274 var nodeValue = options.guideState.unboundDataMap.data[node.name]; 20275 //If the xml had empty tag, an empty object will come in the map, so set to null. 20276 if (_.isObject(nodeValue) && _.isEmpty(nodeValue)) { 20277 node._setGuideValue(null); 20278 } else { 20279 node._setGuideValue(nodeValue); 20280 } 20281 20282 if (node.className === "guideRadioButton") { 20283 node.prevOnItem = node.getSelectedIndex(node.jsonModel._value); 20284 } 20285 } 20286 }); 20287 } 20288 this._guide.setGuideState(guidelib.model.GuideSchema.prototype.GuideStateConstants.GUIDE_STATE_MERGE_COMPLETE); 20289 this._guide.prepare(); 20290 20291 if (options.success) { 20292 options.success.call(this); 20293 } 20294 }, 20295 20296 _postExternalMessage : function (message) { 20297 if (this.userConfig["postExternalMessageConfig"] && _.isFunction(this.userConfig["postExternalMessageConfig"]["postExternalHandler"])) { 20298 var externalHandler = this.userConfig["postExternalMessageConfig"]["postExternalHandler"]; 20299 externalHandler(message); 20300 } 20301 }, 20302 20303 _isXfaGuide : function () { 20304 if (this._guide.xdpRef) { 20305 return true; 20306 } else { 20307 return false;
20308 } 20309 }, 20310 _readRuntimeLocale : function (runtimeLocale) { 20311 return this.customContextProperty("runtimeLocale", runtimeLocale); 20312 20313 }, 20314 20315 /* 20316 * checks whether xdp present in Adaptive Form is valid or not 20317 * This is verified by checking the xdpRef property in guideContext 20318 */ 20319 _isValidXFAGuide : function () { 20320 return !_.isUndefined(this._guide.runtime.guideContext.xdpRef); 20321 }, 20322 20323 _isEditDesignMode : function () { 20324 if (window.CQ && window.CQ.WCM && (window.CQ.WCM.isEditMode() || window.CQ.WCM.isDesignMode())) { 20325 return true; 20326 } else { 20327 return false; 20328 } 20329 }, 20330 20331 /** 20332 * 20333 * This function does following: 20334 * a) On first call, it creates the uuid storage and returns the UUID 20335 * b) On subsequent calls, it just returns the uuid 20336 * c) if uuid is not created then it returns null 20337 * 20338 * @private 20339 */ 20340 _getUUID : function () { 20341 if (this._formInstanceUUID) { 20342 return this._formInstanceUUID; 20343 } 20344 //Generate the UUID for the form instance on client side 20345 var successFlag = true; 20346 this._formInstanceUUID = guideBridge._produceUUID(); 20347 successFlag = createUUIDStorage(this._formInstanceUUID); 20348 if (!successFlag) { 20349 var message = "Could not create UUID storage"; 20350 guideBridge._guide.logger().log(message); 20351 } 20352 return this._formInstanceUUID; 20353 }, 20354 20355 /** 20356 * This will produce new UUID 20357 * @returns {string} 20358 * @private 20359 */ 20360 _produceUUID : function () { 20361 var uuid = $('div.guideContainerWrapperNode').data("tmproot"), 20362 uuidSuffix = Math.floor((Math.random() * 10000) + 1), 20363 uuidCurrentTime = new Date().getTime(); 20364 return uuid + "_" + uuidCurrentTime + uuidSuffix; 20365 }, 20366 20367 /** 20368 * Signature of the callback for the GuideBridgeEvent Listener. It must be passed as handler in the 20369 * {@link GuideBridge#on|on} API. 20370 * @callback GuideBridge~GuideBridgeEventCallback 20371 * @param {jQuery.Event} event jQuery Event Object with target property being the instance of GuideBridge 20372 * @param {Object} payload Payload containing extra information in the API 20373 * @see {@link http://api.jquery.com/category/events/event-object/|jQuery.Event} 20374 * @since 6.0 20375 */ 20376 /** 20377 * The API can be used to add an event listener for events triggered by GuideBridge object 20378 * 20379 * @summary add a listener on a GuideBridge Event. 20380 * @param eventName {string} name of the event for which listener has to be added. It must be one of the 20381 * following events 20382 * * bridgeInitializeComplete 20383 * * elementEnableChanged 20384 * * elementFocusChanged 20385 * * elementHelpShown 20386 * * elementLazyLoaded 20387 * * elementNavigationChanged 20388 * * elementValidationStatusChanged 20389 * * elementValueChanged 20390 * * elementVisibleChanged: 20391 * * guideAutoSaveStart 20392 * * submitStart 20393 * * validationComplete 20394 * @param {function} handler callback to be invoked whenever the event is triggered. The signature of the 20395 * callback is {@link GuideBridge~GuideBridgeEventCallback|GuideBridgeEventCallback} 20396 * @param {object} [context] The _this_ object in the _handler_ will point to _context_ 20397 * 20398 * @method on 20399 * @memberof GuideBridge 20400 * @instance 20401 * @since 6.0 20402 */ 20403 on : function (eventName, handler, context) { 20404 this._$target.on(eventName, handler, context); 20405 }, 20406 20407 /** 20408 * Unregister the event registered using the {@link GuideBridge#on|on} function 20409 * 20410 * @param eventName {string} name of the event to un-register. 20411 * @param [selector] {string} selector which should match the one originally passed to guideBridge's on() while registering handlers 20412 * @param [handler] {function} handler which needs to un-registered. If not provided all the event listeners 20413 * will be unregistered 20414 * 20415 * @method off 20416 * @memberof GuideBridge 20417 * @instance 20418 * @since 6.0 20419 */ 20420 20421 off : function (eventName, selector, handler) { 20422 this._$target.off(eventName, selector, handler); 20423 }, 20424 20425 /** 20426 * Internal API 20427 * @param extraParamerts 20428 * @param eventName 20429 * @private 20430 */ 20431 trigger : function (eventName, extraParamerts) { 20432 this._$target.trigger(eventName, extraParamerts); 20433 }, 20434 20435 /** 20436 * This will return information 20437 * weather the the file attachment preview 20438 * needs to be enabled or not 20439 * @private 20440 * */ 20441 _disablePreview : function () { 20442 if (this._guide && this._guide.runtime && this._guide.runtime.guideContext) { 20443 return this._guide.runtime.guideContext.disablePreview; 20444 } 20445 }, 20446 /** 20447 * If the name of the file attachments have to be made unique then the 20448 * vaule of this function would be true else false 20449 * @returns {*} 20450 * @private 20451 */ 20452 _makeFileNameUnique : function () { 20453 if (this._guide && this._guide.runtime && this._guide.runtime.guideContext) { 20454 return this._guide.runtime.guideContext.makeFileNameUnique; 20455 } 20456 }, 20457 /*this function is used to mince out 20458 * file attachmenemts name and dom in case of 20459 * anonymous user 20460 * */ 20461 _getFileNameFileDomMap : function () { 20462 var fileAttachmentsList = this._getFileAttachmentsList(); 20463 return this._juiceOutNameAndFileDomMap(fileAttachmentsList); 20464 }, 20465 20466 /** 20467 * Returns a list of file attachment wrapper object represeting all file binaries 20468 * @returns reference of {@link guidelib.model.FileAttachmentWrapper} 20469 * @method 20470 * @memberof GuideBridge 20471 * @since FaaCS 20472 * @instance 20473 */ 20474 getFileAttachmentWrapper : function() { 20475 var fileNameDomBindRefMap = this._getFileNameFileDomMap(), 20476 attachments = [], 20477 fileDoms = fileNameDomBindRefMap.fileDom, 20478 fileNames = fileNameDomBindRefMap.fileName, 20479 bindRefs = fileNameDomBindRefMap.fileBindRef, 20480 contentTypes = fileNameDomBindRefMap.fileContentType, 20481 _getFileName = function (fileName, componentName) { 20482 // if file name contains component name 20483 if (fileName.indexOf(componentName) !== -1) { 20484 return fileName.replace(componentName + "/", ""); 20485 } else if (fileName.indexOf("/") !== -1) { 20486 // if file name is a URL 20487 return fileName.substring(fileName.lastIndexOf('/') + 1); 20488 } 20489 }; 20490 20491 var fileNamesIndex; 20492 for (fileNamesIndex = 0; fileNamesIndex < fileNames.length; fileNamesIndex++) { 20493 // multiple files inside one filedom element & draft save case is handled. 20494 var currentFileNames = fileNames[fileNamesIndex].split("\n"); 20495 for (var fileIndex = 0; fileIndex < currentFileNames.length; fileIndex++) { 20496 if (fileDoms[fileNamesIndex] && !_.isString(fileDoms[fileNamesIndex]) && fileDoms[fileNamesIndex].length > 0) { 20497 // append each file of input file element 20498 attachments.push(new guidelib.model.FileAttachmentWrapper({ 20499 name : _getFileName(currentFileNames[fileIndex], bindRefs[fileNamesIndex]), 20500 data : fileDoms[fileNamesIndex][0].files[fileIndex], 20501 contentType : fileDoms[fileNamesIndex][0].files[fileIndex].type, 20502 bindRef : bindRefs[fileNamesIndex] 20503 })); 20504 } else if (currentFileNames[fileIndex]) { 20505 //handle draft save scenario when fileDoms[fileNamesIndex] is null & currentFileNames[fileIndex] is a url 20506 attachments.push(new guidelib.model.FileAttachmentWrapper({ 20507 name : _getFileName(guideBridge._getRelativeFilePath(currentFileNames[fileIndex]), bindRefs[fileNamesIndex]), 20508 data : fileDoms[fileNamesIndex], 20509 contentType : contentTypes[fileNamesIndex], 20510 bindRef : bindRefs[fileNamesIndex] 20511 })); 20512 20513 } 20514 } 20515 } 20516 return attachments; 20517 }, 20518 20519 /** 20520 * Returns the file attachment name and dom (input type=file) element
20521 * The returned object contains a list of file Doms and a list of corresponding file Names. 20522 * If the file is already uploaded, then the file DOM is null and file Name contains the URL. 20523 * @param fileAttachmentsList object list of file attachment models 20524 * @returns {{fileName: Array, fileDom: Array}} 20525 * @private 20526 */ 20527 _juiceOutNameAndFileDomMap : function (fileAttachmentsList) { 20528 var fileDoms = [], 20529 fullFileNames = [], 20530 fullContentTypes = [], 20531 fileBindRefs = [], 20532 fileContentTypes = [], 20533 fileCount = 0, 20534 loadedFileDoms = [], 20535 loadedBindRefs = [], 20536 loadedContentTypes = [], 20537 loadedFileNames = []; 20538 20539 _.each(fileAttachmentsList, function (fileAttachmentModel, index) { 20540 var fileName = fileAttachmentModel._getFileAttachmentNames(), 20541 fileAttachmentModelValue = fileAttachmentModel.value, 20542 effectiveBindRef = fileAttachmentModel._getEffectiveBindRef(), 20543 fileNameList = fileName; // even in case of makeFileNameUnique context set, fileName has the correct unique value 20544 if (fileNameList) { 20545 var fileNames = fileNameList.split("\n"); 20546 var fileList = $.extend(true, [], fileAttachmentModel.fileList); 20547 var fileNamesIndex = 0; 20548 20549 _.each(fileList, function (inputFileDOM, currIndex) { 20550 var fileNamesOfFileDom = null; 20551 20552 // case: if there is a file dom 20553 if (!_.isString(inputFileDOM)) { 20554 _.each(inputFileDOM[0].files, function (file) { 20555 var fileName = fileNames[fileNamesIndex++]; 20556 if (fileName) { 20557 if (fileNamesOfFileDom) { 20558 fileNamesOfFileDom += "\n" + fileAttachmentModel.name + "/" + fileName; 20559 } else { 20560 fileNamesOfFileDom = fileAttachmentModel.name + "/" + fileName; 20561 } 20562 } 20563 }); 20564 if (fileNamesOfFileDom != null) { 20565 // Check if the value exist in the file, this is done because in IE9 and IE10 the list 20566 // will have an extra empty dom 20567 if ($(inputFileDOM).val().length > 0) { 20568 $(inputFileDOM).attr('name', fileNamesOfFileDom); 20569 loadedFileNames[fileCount] = fileNamesOfFileDom; 20570 loadedBindRefs[fileCount] = effectiveBindRef; 20571 // since the api is internal, we are not setting this 20572 loadedContentTypes[fileCount] = null; // we don't set "\n" separated content type here 20573 loadedFileDoms[fileCount++] = $(inputFileDOM); 20574 } 20575 } 20576 } else { 20577 // these values are nothing but field present as part of guidelib.model.FileAttachmentWrapper 20578 // @note: to minimize the refactoring, not reusing the same model 20579 // since there is no file dom in case of draft reload, make it null 20580 loadedFileNames[fileCount] = fileAttachmentModel.name + "/" + fileNames[currIndex]; 20581 loadedBindRefs[fileCount] = effectiveBindRef; // we add effective bindRef here 20582 loadedContentTypes[fileCount] = fileAttachmentModel._getContentType(fileList[currIndex]); // we add effective bindRef here 20583 loadedFileDoms[fileCount++] = fileList[currIndex]; // we add the file URL in fileDom 20584 fileNamesIndex++; 20585 } 20586 }, this); 20587 20588 } 20589 }, this); 20590 20591 // create the dom and name map for lazy file upload components as well 20592 var lazyFileMap = this._guide.internal.liveDataUtils._getLazyAttachmentMap(), 20593 lazyFileDom = [], 20594 lazyFileBindRef = [], 20595 lazyFileContentType = [], 20596 lazyFileName = []; 20597 _.each(lazyFileMap, function (mapObject, key) { 20598 var fileList = mapObject.fileList; 20599 var fileUploadValue = mapObject.value.split("\n"); 20600 var fileUploadBindRef = mapObject.bindRef; 20601 var fileNames = mapObject.fileNames.split("\n"); 20602 var fileNamesIndex = 0; 20603 _.each(fileList, function (value) { 20604 if (!_.isString(value)) { 20605 var fileNamesOfFileDom = null; 20606 _.each(value[0].files, function (file) { 20607 var fileName = fileUploadValue[fileNamesIndex++]; 20608 if (fileName) { 20609 var fullName = guidelib.util.GuideUtil.guideSomToComponentName(key) + "/" + fileName; 20610 if (fileNamesOfFileDom) { 20611 fileNamesOfFileDom += "\n" + fullName; 20612 } else { 20613 fileNamesOfFileDom = fullName; 20614 } 20615 } 20616 }); 20617 20618 lazyFileDom.push(value); 20619 lazyFileName.push(fileNamesOfFileDom); 20620 } else { 20621 var fullName = guidelib.util.GuideUtil.guideSomToComponentName(key) + "/" + fileNames[fileNamesIndex]; 20622 lazyFileDom.push(value); 20623 lazyFileName.push(fullName); 20624 fileNamesIndex++; 20625 } 20626 lazyFileBindRef.push(fileUploadBindRef); 20627 lazyFileContentType.push(null); // todo: check if this use-case would ever hit 20628 }); 20629 }); 20630 20631 // concatenate the arrays for loaded and unloaded file doms and names 20632 fileDoms = loadedFileDoms.concat(lazyFileDom); 20633 fullFileNames = loadedFileNames.concat(lazyFileName); 20634 fileBindRefs = loadedBindRefs.concat(lazyFileBindRef); 20635 fileContentTypes = loadedContentTypes.concat(lazyFileContentType); 20636 20637 return { 20638 "fileName" : fullFileNames, 20639 "fileDom" : fileDoms, 20640 "fileBindRef" : fileBindRefs,
20641 "fileContentType" : fileContentTypes 20642 }; 20643 }, 20644 20645 setValidationContext : function (context) { 20646 var ec = guidelib.util.ErrorConstants; 20647 if (typeof ec[context] === "number") { 20648 var nContext = ec[context]; 20649 if (nValidationContext < nContext) { 20650 nValidationContext = nContext; 20651 sValidationContext = context; 20652 } 20653 } 20654 }, 20655 20656 unsetValidationContext : function (context) { 20657 if (context === sValidationContext) { 20658 nValidationContext = 0; 20659 sValidationContext = ""; 20660 } 20661 }, 20662 20663 getValidationContext : function () { 20664 return sValidationContext; 20665 }, 20666 20667 /** 20668 * @summary Enable/Disable the swipe gesture for navigation on touch devices. 20669 * @param swiptLeft boolean flag to enable(true)/disable(false) the swipe left gesture to perform next item navigation 20670 * @param swipeRight boolean flag to enable(true)/disable(false) the swipe right gesture to perform previous item navigation 20671 * @method 20672 * @memberof GuideBridge 20673 * @instance 20674 * @since 6.3 20675 */ 20676 enableSwipeGesture : function (swiptLeft, swipeRight) { 20677 $guideWrapperNode = $('.guideContainerWrapperNode'); 20678 $guideWrapperNode.off('swipeleft', window.guideBridge._performItemDeepNavigationNext); 20679 $guideWrapperNode.off('swiperight', window.guideBridge._performItemDeepNavigationPrevious); 20680 if (swiptLeft) { 20681 $guideWrapperNode.on('swipeleft', window.guideBridge._performItemDeepNavigationNext); 20682 } 20683 if (swipeRight) { 20684 $guideWrapperNode.on('swiperight', window.guideBridge._performItemDeepNavigationPrevious); 20685 } 20686 }, 20687 20688 /** 20689 * Enable the next item navigation (deep) using swipe left gesture 20690 * @private 20691 */ 20692 _performItemDeepNavigationNext : function () { 20693 window.guideBridge.setFocus({ 20694 somExpression : null, 20695 focusOption : 'nextItemDeep', 20696 runCompletionScript : true, 20697 skipFieldFocus : true 20698 }); 20699 }, 20700 20701 /** 20702 * Enable the previous item navigation (deep) using swipe right gesture 20703 * @private 20704 */ 20705 _performItemDeepNavigationPrevious : function () { 20706 window.guideBridge.setFocus({ 20707 somExpression : null, 20708 focusOption : 'prevItemDeep', 20709 runCompletionScript : true, 20710 skipFieldFocus : true 20711 }); 20712 }, 20713 20714 /** 20715 * Update the model popup that appears at click of file attachment listing button 20716 * This function is currently run of the clickExp of fileAttachmentListingButton 20717 * @param node 20718 * @private 20719 */ 20720 _updateFileListing : function (node) { 20721 var somExpression = node.somExpression, 20722 viewOfListingButton = guideBridge._guideView.getView(somExpression); 20723 viewOfListingButton._clearFileListing(); 20724 guideBridge.visit($.proxy(viewOfListingButton._updateFileListing, viewOfListingButton)); 20725 20726 }, 20727 20728 registerPanelProvider : function (panelProvider) { 20729 var resultObj = new GuideResultObject(); 20730 if (this.panelProvider == null) { 20731 resultObj.data = panelProvider; 20732 this.panelProvider = panelProvider; 20733 return resultObj; 20734 } 20735 resultObj.addMessage(2, "registrationError: PanelProvider already registered", ""); 20736 return resultObj; 20737 } 20738 }); 20739 20740 window.guideBridge = new GuideBridge(); 20741 window.guideBridge._$target = $(window.guideBridge); 20742 20743 window.guideBridge.on("af.invisibleMandatoryRecaptchaInitialization", function (event, data) { 20744 var model = data.jsonModel.target.jsonModel; 20745 var formContainerSelector = guidelib.util.GuideUtil.GUIDE_CONTAINER_FORM_CLASS; 20746 if(FD.isToggleEnabled(guidelib.util.FeatureToggleConstants.FT_TURNSTILE_HCAPTCHA)) { 20747 $(formContainerSelector).append('<div id="captchaInvisible"></div>'); 20748 var captchaInvisibleElement = $("#captchaInvisible"), captchaElement = $("[data-captchaservice]"); 20749 20750 captchaInvisibleElement.attr({ 20751 "modelId" : model.id || model.templateId, 20752 "af-recaptcha-execute" : "", 20753 "data-locale" : captchaElement.attr("data-locale") 20754 }); 20755 20756 if (model.captchaService === 'turnstile') { 20757 captchaInvisibleElement.on("recaptchaExecution", guidelib.util.CaptchaUtil.captchaExecution); 20758 var turnstileParameters = { 20759 'sitekey' : model.siteKey, 20760 'theme' : model.theme || 'light', 20761 'size' : model.size, 20762 'language' : captchaElement.attr('data-locale'), 20763 'execution' : 'execute' 20764 }; 20765 guidelib.util.CaptchaUtil.renderCaptcha(captchaInvisibleElement, model, 20766 model.clientJsUrl, 'cf-turnstile-response', turnstileParameters); 20767 } else if (model.captchaService === 'hcaptcha') { 20768 captchaInvisibleElement.on("recaptchaExecution", guidelib.util.CaptchaUtil.captchaExecution); 20769 var hcaptchaParameters = { 20770 'sitekey' : model.siteKey, 20771 'theme' : model.theme || 'light', 20772 'size' : model.size, 20773 }; 20774 guidelib.util.CaptchaUtil.renderCaptcha(captchaInvisibleElement, model, 20775 model.clientJsUrl, 'h-captcha-response', hcaptchaParameters); 20776 } else { 20777 captchaInvisibleElement.attr({ 20778 "data-externaldomain" : captchaElement.attr("data-externaldomain") 20779 }); 20780 captchaInvisibleElement.on("recaptchaExecution", guidelib.util.RecaptchaUtil.recaptchaExecution); 20781 guidelib.util.RecaptchaUtil.renderRecaptcha(captchaInvisibleElement, model); 20782 } 20783 } else { 20784 $(formContainerSelector).append('<div id="recaptchaInvisible"></div>'); 20785 var recaptchaInvisibleElement = $("#recaptchaInvisible"), captchaElement = $("[data-captchaservice]"); 20786 20787 recaptchaInvisibleElement.attr({ 20788 "modelId" : model.id || model.templateId, 20789 "af-recaptcha-execute" : "", 20790 "data-externaldomain" : captchaElement.attr("data-externaldomain"), 20791 "data-locale" : captchaElement.attr("data-locale") 20792 }); 20793 recaptchaInvisibleElement.on("recaptchaExecution", guidelib.util.RecaptchaUtil.recaptchaExecution); 20794 guidelib.util.RecaptchaUtil.renderRecaptcha(recaptchaInvisibleElement, model); 20795 } 20796 }); 20797 20798 try { 20799 var evnt = document.createEvent("CustomEvent"); 20800 evnt.initCustomEvent("bridgeInitializeStart", true, true, {"guideBridge" : window.guideBridge}); 20801 window.dispatchEvent(evnt); 20802 } catch (exception) { 20803 // written for env rhino to execute(for server side validation) 20804 // todo: once env rhino implements CustomEvent and initCustomEvent remove this 20805 // this._guide.logger().log(exception); 20806 } 20807 20808 if (!window.guideBridge.userConfig["postExternalMessageConfig"]) { 20809 if (window !== window.parent) { 20810 try { 20811 window.parent.document.getElementById(window.name); 20812 //We are here means no cross domain issue. So if user has not defined custom postExternalMessageConfig and 20813 // then we'll create one which would just send event on parent. 20814 window.guideBridge.registerConfig("postExternalMessageConfig", { 20815 "postExternalHandler" : function (message) { 20816 try { 20817 var tmpEvent = document.createEvent("CustomEvent"); 20818 tmpEvent.initCustomEvent(message.name, true, true, message.data); 20819 window.parent.dispatchEvent(tmpEvent); 20820 } catch (exception) { 20821 // written for env rhino to execute 20822 //this._guide.logger().log(exception); 20823 } 20824 } 20825 }); 20826 } catch (e) { 20827 //ignore the error 20828 } 20829 } 20830 } 20831 20832 window.guideBridge._postExternalMessage({ 20833 name : "bridgeInitializeStart", 20834 data : { 20835 "guideBridge" : window.guideBridge 20836 } 20837 }); 20838})($, _); 20839/** 20840 * @package guidelib.model.DataNode 20841 * @version 0.0.1 20842 */ 20843 20844(function ($, _, guideBridge, guidelib, formBridge, xfalib) { 20845 20846 var LiveDataUtils = guidelib.model.LiveDataUtils = xfalib.ut.Class.extend({ 20847 20848 constants : { 20849 SKELETON_XML : '<afData><afUnboundData><data/></afUnboundData><afBoundData><data xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/"/></afBoundData></afData>', 20850 SKELETON_JSON : '{"afData":{"afUnboundData":{"data":{}},"afBoundData":{"data":{}}}}', 20851 UNBOUND_SKELETON : '<unBound></unBound>', 20852 UNBOUND_JSON_SKELETON : '{"afUnboundData":{}}', 20853 INDEXED_XPATH_PAT : new RegExp(/\/[^\/]+\[\d+\]/), 20854 INDEXED_XPATH_PAT_JSON : new RegExp(/\/[^\/]+\/\d+/), 20855 XFA_DATA_NODE_ATTR_NAME : "xfa:dataNode", 20856 XFA_DATA_NODE_ATTR_VALUE : "dataGroup", 20857 UNKNOWN_XSD_ROOT_ELEMENT : "?", 20858 AF_ROOT_TAG : "afData", 20859 BOUND_TAG : "afBoundData", 20860 UNBOUND_TAG : "afUnboundData", 20861 XFA_TAG : "xfa", 20862 DATA_TAG : "data", 20863 BOUND_DATA_XPATH : "afBoundData/data", 20864 UNBOUND_DATA_XPATH : "afUnboundData/data", 20865 AF_DRAFT_TAG : "afSubmissionInfo/afDraft" 20866 }, 20867 20868 initialize : function () { 20869 LiveDataUtils._super.initialize.call(this); 20870 this._boundDataRoot = null; 20871 this._unboundDataRoot = null; 20872 this._xfaDataRoot = null; 20873 this._fetchingClientSideData = false; // this state indicates that we are fetching client side data, its not use-case to fetch lazy data 20874 this.lazyAttachmentMap = {}; 20875 this.attachments = []; 20876 }, 20877 20878 /** 20879 * This function updates the lazy attachment Map from 20880 * the map passed 20881 * @param fileAttachmentMap 20882 * @private 20883 */ 20884 _updateLazyAttachmentMap : function(fileAttachmentMap) { 20885 _.each(fileAttachmentMap, function (value, key) { 20886 this.lazyAttachmentMap[key] = {}; 20887 this.lazyAttachmentMap[key].fileList = value.split("\n"); 20888 this.lazyAttachmentMap[key].value = value; 20889 }, this); 20890 }, 20891 20892 /** 20893 * This function updates the lazy attachment Map from the model. 20894 * It gets the value and fileList from the model and updates the map. 20895 * If the fileUpload component is not in a lazy panel then it removes 20896 * its entry form the map(if the entry is already there). 20897 * @param model 20898 * @private 20899 */ 20900 _updateLazyAttachmentMapFromModel : function (model) { 20901 // add the component in the map only when its in a lazy panel 20902 // add the entry in map only when its not not empty 20903 if (model.parent._selfOrAncestorIsLazyReference && model.value && model.fileList && !this._fetchingClientSideData) { 20904 this.lazyAttachmentMap[model.somExpression] = { 20905 value : model.value, 20906 fileList : model.fileList, 20907 bindRef : model._getEffectiveBindRef(), 20908 fileNames : model._getFileAttachmentNames() 20909 }; 20910 } else { 20911 if (this.lazyAttachmentMap[model.somExpression]) { 20912 delete this.lazyAttachmentMap[model.somExpression]; 20913 } 20914 } 20915 }, 20916 20917 /** 20918 * This function returns the value in the lazy attachment map for the model. 20919 * It removes the entry from the map as well. This is required so that the map gets 20920 * updated with the new values when the panel unloads. 20921 * @param model 20922 * @returns {*} 20923 * @private 20924 */ 20925 _getAttachmentDataForModel : function (model) { 20926 var effectiveBindRef = model._getEffectiveBindRef(); 20927 if (model.somExpression && !_.isEmpty(this.lazyAttachmentMap)) { 20928 var data = this.lazyAttachmentMap[model.somExpression]; 20929 delete this.lazyAttachmentMap[model.somExpression]; 20930 return data; 20931 } 20932 if (effectiveBindRef && !_.isEmpty(this.attachments)) { 20933 var data = model._getCurrentFileAttachmentWrapper(this.attachments); 20934 return data; 20935 } 20936 }, 20937 20938 _getLazyAttachmentMap : function () { 20939 return this.lazyAttachmentMap; 20940 }, 20941 20942 dropXfaXml : function () { 20943 this._xfaDataRoot = null; 20944 }, 20945 20946 // only called from test framework 20947 destroy : function () { 20948 this._liveDataDoc = null; 20949 this._boundDataRoot = null; 20950 this._unboundDataRoot = null; 20951 this._xfaDataRoot = null; 20952 }, 20953 20954 initLiveData : function (prefillDataStr, xfaPrefillDataStr, isXdp, isXsd, xsdRootElement, attachments) { 20955 this.attachments = attachments; 20956 }, 20957 20958 isLiveDataInitialized : function () { 20959 }, 20960 20961 getLiveDataStr : function () { 20962 }, 20963 20964 getLiveDataDoc : function () { 20965 return this._liveDataDoc; 20966 }, 20967 20968 _isNonNaked : function () { 20969 }, 20970 20971 _getNameAndIndex : function (xpathPart) { 20972 }, 20973 20974 isIndexedPath : function (xpath) { 20975 }, 20976 20977 _createElements : function (contextNode, xpathParts) { 20978 }, 20979 20980 _createRepeatedElements : function (contextNode, xpathParts) { 20981 }, 20982 20983 _createChildElement : function (parentElement, elemName) { 20984 }, 20985 20986 _createAttributeNode : function (parentElement, attrName) { 20987 }, 20988 20989 getContextNode : function (schemaPath, dataSection, createMissingNodes, lastNodeValue) { 20990 }, 20991 20992 addIndexToPath : function (path, index) { 20993 }, 20994 20995 _getElement : function (node, xpath, options) {}, 20996 20997 hasChildNodes : function (node) { 20998 }, 20999 21000 /** 21001 * Removes a child node from its parent 21002 * @param parentNode {Node} Parent Node from which to remove the child node 21003 * @param targetNode {String} Node name of the child to remove 21004 * @param index Index of the child node to remove 21005 */ 21006 removeChild : function (parentNode, targetNodeName, index) { 21007 }, 21008 21009 insertNode : function (parentNode, childNodeName, index) { 21010 }, 21011 21012 _getDataContext : function (model, bound_indexedXpathSoFar, unBound_indexedXpathSoFar) { 21013 var bindRef = model.bindRef, 21014 liveDataUtils = this, 21015 xmlSec, 21016 indexedXpath; 21017 21018 if (model._isXfaNode()) { 21019 xmlSec = liveDataUtils.constants.XFA_TAG; 21020 indexedXpath = xfalib.ut.XMLUtils.dataSom2xpath(model.dataSom); 21021 } else if (_.isEmpty(bindRef)) { 21022 xmlSec = liveDataUtils.constants.UNBOUND_TAG; 21023 indexedXpath = unBound_indexedXpathSoFar + '/' + model.getAttribute("name").replace(/\s+/g, ''); 21024 // use attr 'name' here, as schema might have an elem called 'name' 21025 } else { 21026 xmlSec = liveDataUtils.constants.BOUND_TAG; 21027 21028 var xpathMatch = liveDataUtils.getMatchingXpathHierarchy(bou
21028nd_indexedXpathSoFar, bindRef); 21029 if (xpathMatch.isCrossHierarchy) { 21030 indexedXpath = bindRef; 21031 } else { 21032 indexedXpath = bound_indexedXpathSoFar; 21033 if (!_.isEmpty(xpathMatch.suffixParts)) { 21034 indexedXpath += '/' + xpathMatch.suffixParts.join('/'); 21035 } 21036 } 21037 } 21038 21039 return { 21040 'xmlSec' : xmlSec, 21041 'indexedXpath' : indexedXpath 21042 }; 21043 }, 21044 21045 /** 21046 * return true if both xpath parts have same element name and indices 21047 * absence of index in the templateName is ignored 21048 * @param indexedName 21049 * @param templateName 21050 * @returns {boolean} 21051 * @private 21052 * @memberof LiveDataUtils 21053 */ 21054 _cmpXpathParts : function (indexedName, templateName) { 21055 }, 21056 21057 /** 21058 * get a partition of the matching xpath part hierarchy 21059 * the matching parts have same element names and agreeable indices 21060 * @param parentXpath 21061 * @param currentXpath 21062 * @returns {{prefixParts: Array, suffixParts: (*|Array.<T>|list), isCrossHierarchy: boolean}} 21063 * @memberof LiveDataUtils 21064 */ 21065 getMatchingXpathHierarchy : function (parentXpath, currentXpath) { 21066 var isCrossHierarchy = false, 21067 prefixParts = [], 21068 suffixParts = this._sanitizedXpathParts(currentXpath); 21069 21070 _.find(this._sanitizedXpathParts(parentXpath), function (parentPart) { 21071 if (this._cmpXpathParts(parentPart, suffixParts[0])) { 21072 prefixParts.push(parentPart); 21073 suffixParts.shift(); 21074 } else { 21075 isCrossHierarchy = true; 21076 return true; 21077 } 21078 }, this); 21079 21080 return { 21081 'prefixParts' : prefixParts, 21082 'suffixParts' : suffixParts, 21083 'isCrossHierarchy' : isCrossHierarchy 21084 }; 21085 }, 21086 21087 _getXpathContext : function (targetPanel) { 21088 var boundXpath = '', 21089 unBoundXpath = '', 21090 ancestors = [], 21091 panel = targetPanel.parent; 21092 21093 while (panel instanceof guidelib.model.GuidePanel) { 21094 if (panel._preserveLazyValue()) { 21095 ancestors.unshift(panel); 21096 } 21097 panel = panel.parent; 21098 } 21099 21100 _.each(ancestors, function (ancestor) { 21101 var xmlContext = ancestor._syncModelAndData(boundXpath, unBoundXpath); 21102 boundXpath = xmlContext.bound; 21103 unBoundXpath = xmlContext.unBound; 21104 }); 21105 21106 return { 21107 'bound' : boundXpath, 21108 'unBound' : unBoundXpath 21109 }; 21110 }, 21111 21112 _applyOnLiveData : function (action, targetPanel) { 21113 if (_.isString(targetPanel)) { 21114 targetPanel = guideBridge.resolveNode(targetPanel); 21115 } 21116 21117 if (targetPanel instanceof guidelib.model.GuidePanel) { 21118 var indexedXpathsFromRoot = targetPanel._guide().internal.liveDataUtils._getXpathContext(targetPanel); 21119 targetPanel[action](indexedXpathsFromRoot.bound, indexedXpathsFromRoot.unBound); 21120 } else { 21121 guideBridge._guide.rootPanel[action]('', ''); 21122 } 21123 }, 21124 21125 /** 21126 * will capture the currently loaded model hierarchy in a xml doc to be referred to later by lazily loaded panels 21127 * @private 21128 * @memberof LiveDataUtils 21129 */ 21130 updateLiveData : function (targetPanel, fetchingClientSideData) { 21131 this._fetchingClientSideData = !_.isUndefined(fetchingClientSideData); 21132 this._applyOnLiveData('_updateLiveData', targetPanel); 21133 this._fetchingClientSideData = false; 21134 }, 21135 21136 /** 21137 * will replay the model hierarchy from the live xml, for the supplied panel 21138 * @param targetPanel 21139 * @private 21140 * @memberof LiveDataUtils 21141 */ 21142 playLiveData : function (targetPanel) { 21143 this._applyOnLiveData('_playLiveData', targetPanel); 21144 }, 21145 21146 getListOfDirtyPanels : function (dataString) { 21147 return []; 21148 }, 21149 21150 addDataNodeInfo : function (contextNode) { 21151 }, 21152 21153 /** 21154 * Set the value of the node referred by xpath in the bounded/unbounded 21155 * section as specified by section. This optionally creates the data nodes 21156 * if they are not present 21157 * @param xpath 21158 * @param section 21159 * @param createMissingNodes 21160 * @param value 21161 */ 21162 setDataValue : function (xpath, section, createMissingNodes, value) { 21163 }, 21164 21165 /** 21166 * Set the rich text(html) value of the node referred by xpath in the bounded/unbounded 21167 * section as specified by section. This optionally creates the data nodes 21168 * if they are not present 21169 * @param xpath 21170 * @param xmlSection 21171 * @param createMissingNodes 21172 * @param value 21173 */ 21174 setRichTextValue : function (xpath, xmlSection, createMissingNodes, value) { 21175 this.setDataValue(xpath, xmlSection, createMissingNodes, value); 21176 }, 21177 21178 /** 21179 * Returns the value of the node referred by xpath in the bounded/unbounded 21180 * section as specified by section. It returns undefined if the node doesn't 21181 * exist 21182 * @param xpath 21183 * @param section 21184 */ 21185 getDataValue : function (xpath, section) { 21186 }, 21187 21188 _convertModelIndexToDataIndex : function (index) { 21189 }, 21190 21191 getParentRef : function (path) { 21192 }, 21193 21194 /** 21195 * returns the parent data node for the context specified by dataNodeContext 21196 * @param dataNodeContext {object} containing xpath and section 21197 * @param createIfMissing 21198 * @returns {*} 21199 * @param parentNodeValue 21200 */ 21201 getParentDataNode : function (dataNodeContext, createIfMissing, parentNodeValue) {
21202 var parentRef = this.getParentRef(dataNodeContext.indexedXpath), 21203 parentNode; 21204 if (_.isEmpty(parentRef)) { 21205 parentNode = this.getContextNode("", dataNodeContext.xmlSec, false); 21206 } else { 21207 parentNode = this.getContextNode(parentRef, dataNodeContext.xmlSec, createIfMissing, parentNodeValue); 21208 } 21209 return parentNode; 21210 }, 21211 21212 /** 21213 * Insert submission Info in the data 21214 * @param submissionInfo {object} object containing the properties to be added as submission info in data 21215 */ 21216 insertSubmissionInfo : function (submissionInfo) { 21217 21218 } 21219 21220 }); 21221 21222}($, _, window.guideBridge, window.guidelib, window.formBridge, window.xfalib)); 21223 21224/** 21225 * @package guidelib.model.DataNode 21226 * @version 0.0.1 21227 */ 21228 21229(function ($, _, guideBridge, guidelib, formBridge, xfalib) { 21230 var getOrElse = xfalib.ut.XfaUtil.prototype.getOrElse; 21231 21232 var LiveJsonUtils = guidelib.model.LiveJsonUtils = guidelib.model.LiveDataUtils.extend({ 21233 21234 initialize : function () { 21235 LiveJsonUtils._super.initialize.call(this); 21236 this._liveDataDoc = null; 21237 }, 21238 21239 initLiveData : function (prefillDataStr, guideContext) { 21240 LiveJsonUtils._super.initLiveData.apply(this, arguments); 21241 prefillDataStr = prefillDataStr || getOrElse(guideContext, "guidePrefillJson", null); 21242 21243 if (_.isString(prefillDataStr) && prefillDataStr.length > 0) { 21244 var prefillDataDoc = JSON.parse(prefillDataStr); 21245 21246 if (this._isNonNaked(prefillDataDoc)) { 21247 // non naked json, assuming full hierarchy afdata/afbounddata/data 21248 this._liveDataDoc = prefillDataDoc; 21249 this._boundDataRoot = this._getElement(this._liveDataDoc.afData, this.constants.BOUND_DATA_XPATH); 21250 this._unboundDataRoot = this._getElement(this._liveDataDoc.afData, this.constants.UNBOUND_DATA_XPATH); 21251 21252 } else { 21253 // naked json start from prefill data root 21254 this._boundDataRoot = prefillDataDoc; 21255 this._unboundDataRoot = JSON.parse(this.constants.UNBOUND_JSON_SKELETON)[this.constants.UNBOUND_TAG]; // need this for unbound data fill across lazy 21256 this._liveDataDoc = prefillDataDoc; 21257 } 21258 } else { 21259 // init default skeleton for no prefill cases 21260 this._liveDataDoc = JSON.parse(this.constants.SKELETON_JSON); 21261 this._boundDataRoot = this._getElement(this._liveDataDoc.afData, this.constants.BOUND_DATA_XPATH); 21262 this._unboundDataRoot = this._getElement(this._liveDataDoc.afData, this.constants.UNBOUND_DATA_XPATH); 21263 } 21264 if (this._boundDataRoot == null && this._isNonNaked(prefillDataDoc)) { 21265 this._liveDataDoc.afData.afBoundData = this._liveDataDoc.afData.afBoundData || {}; 21266 this._liveDataDoc.afData.afBoundData.data = this._liveDataDoc.afData.afBoundData.data || {}; 21267 this._boundDataRoot = this._liveDataDoc.afData.afBoundData.data; 21268 } 21269 }, 21270 21271 /* 21272 * This API gets the element w.r.t to the node. 21273 * Eg - path is a/b/c, then it converts the path to a.b.c and then searches for c. 21274 */ 21275 _getElement : function (node, path, options) { 21276 if (!(node instanceof Object)) { 21277 return null; 21278 } 21279 21280 if (_.isEmpty(path) || !_.isString(path)) { 21281 return node; 21282 } 21283 options = options || {}; 21284 var index = options.index; 21285 var convertedPath = path.split('/').join('.'); 21286 if (!(_.isUndefined(index) || _.isNull(index))) { 21287 convertedPath = convertedPath + "." + index; 21288 } 21289 return getOrElse(node, convertedPath, null); 21290 }, 21291 21292 /** 21293 * This function checks if the data contains naked or non naked json 21294 * @returns {boolean} returns true if there exists a afData node inside data 21295 * @private 21296 * @memberof LiveJsonUtils 21297 * @param prefillData 21298 */ 21299 _isNonNaked : function (prefillData) { 21300 prefillData = prefillData || this.getLiveDataDoc(); 21301 if (prefillData) { 21302 return prefillData.hasOwnProperty("afData"); 21303 } else { 21304 return false;
21305 } 21306 }, 21307 21308 isLiveDataInitialized : function () { 21309 return (this.getLiveDataDoc() instanceof Object); 21310 }, 21311 21312 getLiveDataStr : function () { 21313 if (this.isLiveDataInitialized()) { 21314 return JSON.stringify(this.getLiveDataDoc()); 21315 } else { 21316 return ''; 21317 } 21318 }, 21319 21320 /* 21321 * This API will remove the spaces,"\" from the path. 21322 * It will return an array after splitting the path. 21323 * Eg - for a/0/b/c, it will return ["a/0","b","c"] 21324 */ 21325 _sanitizedXpathParts : function (path) { 21326 var pathParts = (path || '').replace(/^\//, '').replace(/\s+/g, ''); 21327 pathParts = this._splitForIndex(pathParts); 21328 21329 return _.filter(pathParts, function (xpathPart) { 21330 return this._getNameAndIndex(xpathPart) !== null; 21331 }, this); 21332 }, 21333 21334 _splitForIndex : function (path) { 21335 var pathArray = []; 21336 var pathParts = path.split('/'); 21337 for (var i = 0; i < pathParts.length; i++) { 21338 var str = pathParts[i]; 21339 if ((i + 1) < pathParts.length && !isNaN(pathParts[i + 1]) && !_.isEmpty(pathParts[i + 1])) {
21340 str = str + "/" + pathParts[i + 1]; 21341 i = i + 1; 21342 } 21343 pathArray.push(str); 21344 } 21345 return pathArray; 21346 }, 21347 21348 /** 21349 * Returns the index associated with the pathPart. 21350 * Eg - if pathPart is 'a/1', then it returns {name : a, index : 1} 21351 * @param pathPart 21352 * @returns {*} 21353 * @private 21354 */ 21355 _getNameAndIndex : function (pathPart) { 21356 if (pathPart) { 21357 var elName = pathPart.match(/^([^\s\/]+)(?:\/(\d+))?$/); // match the whole string 21358 if (elName !== null) { 21359 return { 21360 name : elName[1], 21361 index : elName[2] ? parseInt(elName[2]) : -1 21362 // -1 index for depicting non repeatable element 21363 }; 21364 } 21365 } 21366 return null; 21367 }, 21368 21369 _cmpXpathParts : function (indexedName, templateName) { 21370 if (indexedName && templateName) { 21371 var match1 = this._getNameAndIndex(indexedName), 21372 match2 = this._getNameAndIndex(templateName); 21373 return !_.isEmpty(match1 && match2) 21374 && match1.name === match2.name 21375 && (match2.index === -1 || match1.index === match2.index); 21376 } 21377 return false; 21378 }, 21379 21380 /** 21381 * This function gets or creates the node if its not there. The node can be any valid JSON Value 21382 * null, string, object, array, number, boolean. 21383 * @param schemaPath 21384 * @param dataSection 21385 * @param createMissingNodes 21386 * @param lastNodeValue 21387 * @returns {*} 21388 */ 21389 getContextNode : function (schemaPath, dataSection, createMissingNodes, lastNodeValue) { 21390 var contextNode, 21391 baseContextNode, 21392 basePath = "", 21393 pathParts = this._sanitizedXpathParts(schemaPath); 21394 if (dataSection == this.constants.BOUND_TAG) { 21395 baseContextNode = this._boundDataRoot; 21396 if (this._isNonNaked(this._liveDataDoc)) { 21397 basePath = "afData/" + this.constants.BOUND_DATA_XPATH + "/"; 21398 } 21399 } else if (dataSection === this.constants.UNBOUND_TAG) { 21400 baseContextNode = this._unboundDataRoot; 21401 if (this._isNonNaked(this._liveDataDoc)) { 21402 basePath = "afData/" + this.constants.UNBOUND_DATA_XPATH + "/"; 21403 } 21404 } 21405 if (!_.isEmpty(pathParts)) { 21406 var path = (basePath + pathParts.join('/')); 21407 21408 // return baseContextNode for naked json. path can be "" only for naked json. 21409 if (path == "" && !this._isNonNaked(this._liveDataDoc)) { 21410 return baseContextNode; 21411 } 21412 21413 contextNode = this._getElement(this._liveDataDoc, path); 21414 if (!contextNode && createMissingNodes) { 21415 contextNode = this._createElements(baseContextNode, pathParts, lastNodeValue); 21416 } 21417 } else { 21418 contextNode = baseContextNode; 21419 } 21420 return contextNode; 21421 }, 21422 21423 /** 21424 * This function creates the node at the path. 21425 * 21426 * @param contextNode 21427 * @param pathParts 21428 * @returns {*} 21429 * @private 21430 * @param lastNodeValue 21431 */ 21432 _createElements : function (contextNode, pathParts, lastNodeValue) { 21433 if (!(contextNode instanceof Object)) { 21434 return null; 21435 } 21436 21437 if (_.isEmpty(pathParts)) { 21438 return contextNode; 21439 } 21440 21441 // recurse and create one level of tags at a time 21442 contextNode = this._createRepeatedElements(contextNode, pathParts, lastNodeValue); 21443 return contextNode; 21444 }, 21445 21446 // it will always return the parent node after checking the last token 21447 _createRepeatedElements : function (contextNode, pathParts, lastNodeValue) { 21448 var childContextNode = contextNode, 21449 xpathPart = this._getNameAndIndex(pathParts[0]), 21450 elemName = xpathPart.name, 21451 index = xpathPart.index || 0, 21452 i, 21453 isLastToken = (pathParts.length == 1), 21454 elementNode = contextNode[elemName]; 21455 // -1 signifies non repeating element 21456 if (index === -1) { 21457 if (elementNode == null) { 21458 childContextNode = this._createChildElement(contextNode, elemName, isLastToken, lastNodeValue); 21459 } else { 21460 childContextNode = elementNode; 21461 } 21462 // if its the last token, then stop recursion here and return the created node 21463 if (isLastToken) { 21464 return childContextNode; 21465 } 21466 } else { 21467 if (elementNode != null) { 21468 var numOfChildren = elementNode.length; 21469 if (numOfChildren < index + 1) { 21470 // create immediate 'extra' children 21471 for (i = numOfChildren; i < index + 1; ++i) { 21472 childContextNode = {}; 21473 contextNode[elemName].push(childContextNode); 21474 } 21475 } else { 21476 childContextNode = elementNode[index]; 21477 } 21478 } else { 21479 contextNode[elemName] = []; 21480 for (i = 0; i < index + 1; ++i) { 21481 childContextNode = {}; 21482 contextNode[elemName].push(childContextNode); 21483 } 21484 } 21485 } 21486 // recursively create descendants 21487 return this._createElements(childContextNode, pathParts.slice(1), lastNodeValue); 21488 }, 21489 21490 _createChildElement : function (parentElement, elemName, isLastToken, nodeValue) { 21491 if (parentElement instanceof Object) { 21492 if (isLastToken) { 21493 parentElement[elemName] = nodeValue; 21494 } else { 21495 parentElement[elemName] = {}; 21496 } 21497 return parentElement[elemName]; 21498 } 21499 }, 21500 21501 isIndexedPath : function (xpath) { 21502 return (xpath || "").match(this.constants.INDEXED_XPATH_PAT_JSON) !== null; 21503 }, 21504 21505 /** 21506 * This function sets the value of the field in the live data document. 21507 * @param xpath 21508 * @param xmlSection 21509 * @private 21510 * @param createMissingNodes 21511 * @param value 21512 */ 21513 setDataValue : function (xpath, xmlSection, createMissingNodes, value) { 21514 var lastSlash = xpath.lastIndexOf("/"), 21515 parentPath = xpath.substring(0, lastSlash), 21516 name = xpath.substring(lastSlash + 1), 21517 parent = this.getContextNode(parentPath, xmlSection, createMissingNodes, {}); 21518 if (parent instanceof Object) { 21519 if (createMissingNodes || parent.hasOwnProperty(name)) { 21520 parent[name] = value; 21521 } 21522 } 21523 }, 21524 21525 /** 21526 * This function sets the value in the model from the live data document. 21527 * @param node 21528 * @param field 21529 * @private 21530 */ 21531 getDataValue : function (xpath, xmlSection) { 21532 var lastSlash = xpath.lastIndexOf("/"), 21533 parentPath = xpath.substring(0, lastSlash), 21534 name = xpath.substring(lastSlash + 1), 21535 parent = this.getContextNode(parentPath, xmlSection, false); 21536 if (parent instanceof Object) { 21537 return parent[name] === undefined ? null : parent[name]; 21538 } 21539 return null; 21540 }, 21541 21542 getRichTextValue : function (xpath, xmlSection) { 21543 return this.getDataValue(xpath, xmlSection); 21544 }, 21545 21546 addIndexToPath : function (path, index) { 21547 if (path.match(/\/\d+$/) === null) { // only add repeat index if it doesn't already end in one 21548 path += '/' + (index); 21549 } else { 21550 this.logger().debug("AF", "Tried to add index to already indexed JSON path :" + path); 21551 } 21552 return path; 21553 }, 21554 21555 hasChildNodes : function (node) { 21556 return !_.isEmpty(node); 21557 }, 21558 21559 removeChild : function (parentNode, targetNodeName, index) { 21560 parentNode[targetNodeName].splice(index, 1); 21561 }, 21562 21563 insertNode : function (parentNode, childNodeName, index) { 21564 if (parentNode[childNodeName] == null) { 21565 parentNode[childNodeName] = []; 21566 } 21567 for (var i = 0; i < index; i++) { 21568 if (parentNode[childNodeName][i] == null) { 21569 parentNode[childNodeName][i] = {}; 21570 } 21571 } 21572 parentNode[childNodeName].splice(index, 0, {}); 21573 return parentNode[childNodeName][index]; 21574 }, 21575 21576 getDataInstances : function (dataContext, dataNodeName) { 21577 return this.getContextNode(dataContext.indexedXpath, dataContext.xmlSec); 21578 }, 21579 21580 _convertModelIndexToDataIndex : function (index) { 21581 if (index < 0) { 21582 return 0; 21583 } 21584 return index; 21585 }, 21586 21587 getParentRef : function (path) { 21588 return path.replace(/\/[^\/]+(?:\/\d+)?$/, ""); 21589 }, 21590 21591 insertSubmissionInfo : function (submissionInfo, rootNode) { 21592 if (this._isNonNaked()) { 21593 var node = rootNode, 21594 self = this, 21595 finalValue, insert, keyNode; 21596 if (node == null) { 21597 node = this._liveDataDoc.afData.afSubmissionInfo; 21598 } 21599 if (node == null && this._liveDataDoc.afData.afSubmissionInfo == null) { 21600 node = {}; 21601 this._liveDataDoc.afData.afSubmissionInfo = node; 21602 } 21603 _.each(submissionInfo, function (value, key) { 21604 if (value instanceof Array) { 21605 // we only support string items in json array 21606 finalValue = []; 21607 insert = true; 21608 _.each(value, function (arrItem, index) { 21609 if (typeof arrItem === "string") { 21610 finalValue.push(arrItem); 21611 } else { 21612 //ignore this. we currently do not support anything other than string 21613 } 21614 }); 21615 if (insert) { 21616 node[key] = finalValue.join(','); 21617 } 21618 } else if (typeof (value) === "object" && value != null) { 21619 keyNode = node[key]; 21620 if (keyNode == null) { 21621 keyNode = {}; 21622 node[key] = keyNode; 21623 } 21624 self.insertSubmissionInfo(value, keyNode); 21625 } else { 21626 node[key] = value; 21627 } 21628 }); 21629 } 21630 } 21631 21632 }); 21633 21634}($, _, window.guideBridge, window.guidelib, window.formBridge, window.xfalib)); 21635 21636/** 21637 * @package guidelib.model.DataNode 21638 * @version 0.0.1 21639 */ 21640 21641(function ($, _, guideBridge, guidelib, formBridge, xfalib) { 21642 var isXdp, isXsd, isNone; 21643 21644 var LiveXmlUtils = guidelib.model.LiveXmlUtils = guidelib.model.LiveDataUtils.extend({ 21645 21646 initialize : function () { 21647 LiveXmlUtils._super.initialize.call(this); 21648 21649 if (_.isUndefined(document.evaluate)) { 21650 wgxpath.install(); 21651 } 21652 this._liveDataDoc = null; 21653 }, 21654 21655 initLiveData : function (prefillXmlStr, xfaPrefillXmlStr, isXdp, isXsd, xsdRootElement) { 21656 LiveXmlUtils._super.initLiveData.apply(this, arguments); 21657 isXdp = isXdp || false; 21658 isXsd = isXsd || false; 21659 isNone = !(isXdp || isXsd); 21660 this.xsdRootElement = xsdRootElement; 21661 // init default skeleton for no pefill cases 21662 this._liveDataDoc = $.parseXML(this.constants.SKELETON_XML); 21663 this._boundDataRoot = this._getElement(this._liveDataDoc.documentElement, this.constants.BOUND_DATA_XPATH); 21664 this._unboundDataRoot = this._getElement(this._liveDataDoc.documentElement, this.constants.UNBOUND_DATA_XPATH); 21665 21666 if (_.isString(prefillXmlStr) && prefillXmlStr.length > 0) { 21667 var prefillXmlDoc = $.parseXML(prefillXmlStr); 21668 21669 // find data root 21670 if (this._isNonNaked(prefillXmlDoc)) { 21671 // non naked xml, assuming full hierarchy afdata/afbounddata/data 21672 21673 var prefillBoundDataRoot, 21674 prefillUnBoundDataRoot, 21675 newDataNode; 21676 21677 if (!isXdp) { //capture bound data from prefill, for both none(may contain bound form/frag) and xsd 21678 prefillBoundDataRoot = this._getElement(prefillXmlDoc.documentElement, this.constants.BOUND_DATA_XPATH); 21679 if (null == prefillBoundDataRoot) { 21680 prefillBoundDataRoot = this._getElement(prefillXmlDoc.documentElement, this.constants.BOUND_TAG + 21681 "/" + guideBridge._guide.jsonModel.xsdRootElement); 21682 } 21683 if (prefillBoundDataRoot) { 21684 newDataNode = this._liveDataDoc.importNode(prefillBoundDataRoot, true); 21685 this._boundDataRoot.parentNode.replaceChild(newDataNode, this._boundDataRoot); 21686 this._boundDataRoot = newDataNode; 21687 } 21688 } 21689 21690 prefillUnBoundDataRoot = this._getElement(prefillXmlDoc.documentElement, this.constants.UNBOUND_DATA_XPATH); 21691 if (prefillUnBoundDataRoot) { 21692 newDataNode = this._liveDataDoc.importNode(prefillUnBoundDataRoot, true); 21693 this._unboundDataRoot.parentNode.replaceChild(newDataNode, this._unboundDataRoot); 21694 this._unboundDataRoot = newDataNode; 21695 } 21696 21697 } else { 21698 // naked xml start from prefill data root 21699 21700 if (isNone) { 21701 this._unboundDataRoot = prefillXmlDoc.documentElement; 21702 this._boundDataRoot = null; 21703 } else { 21704 if (isXsd) { 21705 this._boundDataRoot = prefillXmlDoc.documentElement; 21706 } 21707 21708 var unBoundXmlDoc = $.parseXML(this.constants.UNBOUND_SKELETON); 21709 this._unboundDataRoot = unBoundXmlDoc.documentElement; // need this for unbound data fill across lazy 21710 } 21711 this._liveDataDoc = prefillXmlDoc; 21712 } 21713 } 21714 21715 if (isXdp) { // don't need the bound data sec, model is always loaded & server will fill during submission 21716 if (_.isString(xfaPrefillXmlStr) && xfaPrefillXmlStr.length > 0) { 21717 this._xfaDataRoot = xfalib.ut.XMLUtils.getXFARootFormElementFromXML($.parseXML(xfaPrefillXmlStr)); 21718 } 21719 this._boundDataRoot.parentNode.parentNode.removeChild(this._boundDataRoot.parentNode); 21720 this._boundDataRoot = null; 21721 } 21722 }, 21723 21724 isLiveDataInitialized : function () { 21725 return (this.getLiveDataDoc() instanceof Node); 21726 }, 21727 21728 getLiveDataStr : function () { 21729 if (this.isLiveDataInitialized()) { 21730 return (new XMLSerializer()).serializeToString(this.getLiveDataDoc()); 21731 } else { 21732 return ''; 21733 } 21734 }, 21735 21736 _ignoreXpathRoot : function (xpathRoot) { 21737 return this.xsdRootElement === this.cons
21737tants.UNKNOWN_XSD_ROOT_ELEMENT 21738 || this.xsdRootElement === xpathRoot; 21739 }, 21740 21741 /** 21742 * will return the apt node, in the AF xml, based on the xml context passed in. 21743 * Will create nodes if it doesn't exist and createMissingNodes is passed as true 21744 * @param schemaPath 21745 * @param dataSection 21746 * @param createMissingNodes 21747 * @returns {*} 21748 * @memberof LiveXmlUtils 21749 */ 21750 getContextNode : function (schemaPath, dataSection, createMissingNodes) { 21751 var contextNode, 21752 baseContextNode, 21753 xpathParts = this._sanitizedXpathParts(schemaPath); 21754 if (dataSection === this.constants.BOUND_TAG) { 21755 baseContextNode = this._boundDataRoot; 21756 } else if (dataSection === this.constants.UNBOUND_TAG) { 21757 baseContextNode = this._unboundDataRoot; 21758 } else if (dataSection === this.constants.XFA_TAG) { 21759 baseContextNode = this._xfaDataRoot; 21760 } 21761 if (!_.isEmpty(xpathParts)) { 21762 if (dataSection === this.constants.BOUND_TAG) { 21763 if (this._ignoreXpathRoot(xpathParts[0])) { 21764 xpathParts = xpathParts.slice(1); // discard xsd schema root 21765 if (xpathParts.length === 0) { 21766 return baseContextNode; 21767 } 21768 } 21769 } 21770 21771 contextNode = this._getElement(baseContextNode, xpathParts.join('/')); 21772 21773 if (!contextNode && createMissingNodes) { 21774 contextNode = this._createElements(baseContextNode, xpathParts); 21775 } 21776 } else if (_.isEmpty(schemaPath)) { 21777 contextNode = baseContextNode; 21778 } 21779 return contextNode; 21780 }, 21781 21782 addIndexToPath : function (path, index) { 21783 if (path.match(/\[\d+\]$/) === null) { // only add repeat index if it doesn't already end in one 21784 path += '[' + (index + 1) + ']'; // indices in xpath 1 based} 21785 } else { 21786 this.logger().debug("AF", "Tried to add index to already indexed xpath :" + path); 21787 } 21788 return path; 21789 }, 21790 21791 getDataInstances : function (dataContext, dataNodeName) { 21792 var node = this.getContextNode(dataContext.indexedXpath, dataContext.xmlSec); 21793 if (node != null) { 21794 return _.filter(node.parentNode.childNodes, function (child) { 21795 return (child instanceof Element) && child.nodeName === dataNodeName; 21796 }, this); 21797 } 21798 return null; 21799 }, 21800 21801 _findLastDataNode : function (parentContextNode, dataNodeName) { 21802 var xmlUtils = xfalib.ut.XMLUtils, 21803 iterator = xmlUtils.evaluateXPath(dataNodeName, parentContextNode, null, null, null), 21804 result = xmlUtils.iteratorToArray(iterator); 21805 if (result.length > 0) { 21806 return result[result.length - 1]; 21807 } 21808 return null; 21809 }, 21810 21811 hasChildNodes : function (node) { 21812 return node.hasChildNodes(); 21813 }, 21814 21815 removeChild : function (parentNode, targetNodeName, index) { 21816 var childNode = this._getElement(parentNode, targetNodeName + "[" + (index + 1) + "]", null); 21817 if (childNode) { 21818 parentNode.removeChild(childNode); 21819 } 21820 }, 21821 21822 insertNode : function (parentNode, childNodeName, index) { 21823 var childNode = this._getElement(parentNode, childNodeName + "[" + (index + 1) + "]", null), 21824 node = parentNode.ownerDocument.createElement(childNodeName); 21825 if (childNode) { 21826 parentNode.insertBefore(node, childNode); 21827 } else { 21828 var lastNode = this._findLastDataNode(parentNode, childNodeName); 21829 if (lastNode && lastNode.nextSibling) { 21830 parentNode.insertBefore(node, lastNode.nextSibling); 21831 } else if (lastNode && !lastNode.nextSibling) { 21832 // for the case when the last node is there but there is no next sibling. 21833 // we don't need to create all the nodes for this scenario. 21834 parentNode.appendChild(node); 21835 } else { 21836 // we need to create all the nodes till the count reaches the index. 21837 for (var i = 0; i <= index; i++) { 21838 var newNode = parentNode.ownerDocument.createElement(childNodeName); 21839 parentNode.appendChild(newNode); 21840 } 21841 } 21842 } 21843 return node; 21844 }, 21845 21846 /** 21847 * Form an xpath part returns the index as well as the tagName. 21848 * Index returned is 0 if not present 21849 * @param xpathName 21850 * @returns {*} 21851 * @private 21852 * @memberof LiveXmlUtils 21853 */ 21854 _getNameAndIndex : function (xpathPart) { 21855 if (xpathPart) { 21856 var elName = xpathPart.match(/^([^[\s\/]+)(?:\[(\d+)\])?$/); // match the whole string 21857 if (elName !== null) { 21858 return { 21859 name : elName[1], 21860 index : elName[2] ? parseInt(elName[2]) : 0 21861 }; 21862 } 21863 } 21864 return null; 21865 }, 21866 21867 _cmpXpathParts : function (indexedName, templateName) { 21868 if (indexedName && templateName) { 21869 var match1 = this._getNameAndIndex(indexedName), 21870 match2 = this._getNameAndIndex(templateName); 21871 return !_.isEmpty(match1 && match2) 21872 && match1.name === match2.name 21873 && (match2.index === 0 || match1.index === match2.index); 21874 } 21875 return false;
21876 }, 21877 21878 /** 21879 * Will split an xpath string into an array containing one xml element/node per part 21880 * This expects only the simple xpath syntax allowed in bindRefs of xsd bound fields 21881 * of the form /a/b/c/@d 21882 * @param xpath 21883 * @returns {*|Array.<T>|list} 21884 * @private 21885 * @memberof LiveXmlUtils 21886 */ 21887 _sanitizedXpathParts : function (xpath) { 21888 var xpathParts = (xpath || '').replace(/^\//, '').replace(/\s+/g, '').split('/'); 21889 21890 if (_.last(xpathParts) === "text()") { // ignore "/text()" appended to bindRef for SimpleType schema element 21891 xpathParts.splice(-1, 1); // drop last element 21892 } 21893 21894 return _.filter(xpathParts, function (xpathPart) { 21895 return this._getNameAndIndex(xpathPart) !== null; 21896 }, this); 21897 }, 21898 21899 /** 21900 * returns true if the xpath uses indices 21901 * @param xpath 21902 * @returns {boolean} 21903 * @memberof LiveXmlUtils 21904 */ 21905 isIndexedPath : function (xpath) { 21906 return (xpath || "").match(this.constants.INDEXED_XPATH_PAT) !== null; 21907 }, 21908 21909 _createElements : function (contextNode, xpathParts) { 21910 if (!(contextNode instanceof Node)) { 21911 return null; 21912 } 21913 21914 if (_.isEmpty(xpathParts)) { 21915 return contextNode; 21916 } 21917 21918 if (xpathParts[0][0] === '@') { // xpath parts having '@' as 1st char must be and attr 21919 var attrName = xpathParts[0].slice(1); 21920 // in bindrefs attributes are the last xpath part, so no need to recurse 21921 contextNode = this._createAttributeNode(contextNode, attrName); 21922 } else { 21923 // recurse and create one level of tags at a time 21924 contextNode = this._createRepeatedElements(contextNode, xpathParts); 21925 } 21926 21927 return contextNode; 21928 }, 21929 21930 /** 21931 * This will update the xml with the required tags, 21932 * and return the context node matching the xpath query. 21933 * Further if xml has lesser number of tags than the index in each part, 21934 * it'll fill those gaps with empty tags. 21935 * @param contextNode node beneath which tags are to be created 21936 * @param xpathParts 21937 * @returns {*} 21938 * @private 21939 * @memberof LiveXmlUtils 21940 */ 21941 _createRepeatedElements : function (contextNode, xpathParts) { 21942 var childContextNode = contextNode, 21943 xpathPart = this._getNameAndIndex(xpathParts[0]), 21944 elemName = xpathPart.name, 21945 index = xpathPart.index || 1, 21946 i, 21947 children = _.filter(contextNode.childNodes, function (child) { 21948 return (child instanceof Element) && child.nodeName === elemName; 21949 }); 21950 21951 if (children.length < index) { 21952 // create immediate 'extra' children 21953 for (i = children.length; i < index; ++i) { 21954 childContextNode = this._createChildElement(contextNode, elemName); 21955 } 21956 } else { 21957 childContextNode = children[index - 1]; // indices are 1 based in xml 21958 } 21959 // recursively create descendants 21960 return this._createElements(childContextNode, xpathParts.slice(1)); 21961 }, 21962 21963 _createChildElement : function (parentElement, elemName) { 21964 if (parentElement instanceof Element) { 21965 var childElem = parentElement.ownerDocument.createElement(elemName); 21966 parentElement.appendChild(childElem); 21967 return childElem; 21968 } 21969 }, 21970 21971 _createAttributeNode : function (parentElement, attrName) { 21972 if (parentElement instanceof Element) { 21973 var attrNode = parentElement.ownerDocument.createAttribute(attrName); 21974 parentElement.setAttributeNode(attrNode); 21975 return attrNode; 21976 } 21977 }, 21978 21979 /** 21980 * finds xml node/element based on current context node and xpath 21981 * @param node 21982 * @param xpath 21983 * @param options 21984 * @returns {*} 21985 * @private 21986 * @memberof LiveXmlUtils 21987 */ 21988 _getElement : function (node, xpath, options) { 21989 if (!(node instanceof Node)) { 21990 return null; 21991 } 21992 21993 if (_.isEmpty(xpath) || !_.isString(xpath)) { 21994 return node; 21995 } 21996 options = options || {}; 21997 var nsResolver = options.nsResolver; 21998 var index = options.index; 21999 // in IE singleNodeValue maybe null for attribute queries, 22000 // so find parent element of attribute, and then explicitly check for attribute node's presence 22001 22002 var xpathParts = xpath.split('/@'), 22003 checkAttr = false, 22004 attributeName; 22005 22006 if (xpathParts.length > 2) { // more than 1 attr unsupported 22007 xfalib.ut.XfaUtil.prototype.getLogger().error("BindRefs must be Xpaths ending in atmost one attribute"); // TODO localize 22008 return null; 22009 } else if (xpathParts.length === 2) { 22010 xpath = xpathParts[0]; // find parent el and seek attribute there 22011 attributeName = xpathParts[1]; // attr can only be in the last part 22012 checkAttr = true; 22013 } 22014 if (!(_.isUndefined(index) || _.isNull(index))) { 22015 xpath = xpath + "[" + index + "]"; 22016 } 22017 if (!window.XPathResult) { 22018 document.evaluate = undefined; 22019 wgxpath.install(window, true); 22020 } 22021 var result = xfalib.ut.XMLUtils.evaluateXPath(xpath, node, nsResolver, XPathResult.FIRST_ORDERED_NODE_TYPE, null), 22022 el; 22023 22024 if (result && result.resultType === XPathResult.FIRST_ORDERED_NODE_TYPE) { 22025 el = result.singleNodeValue; 22026 if (el instanceof Node) { 22027 if (!checkAttr) { 22028 return el; 22029 } else if (el.hasAttribute(attributeName)) { 22030 el = el.getAttributeNode(attributeName); 22031 if (el instanceof Node) { 22032 return el; 22033 } 22034 } 22035 } 22036 } 22037 }, 22038 22039 /** 22040 * This function checks if the document was naked or non naked xml 22041 * @param doc 22042 * @returns {boolean} returns true if there exists a afData node inside data false otherwise 22043 * @private 22044 * @memberof LiveXmlUtils 22045 */ 22046 _isNonNaked : function (doc) { 22047 doc = doc || this.getLiveDataDoc(); 22048 if (doc) { 22049 return doc.documentElement.tagName === this.constants.AF_ROOT_TAG; 22050 } else { 22051 return false;
22052 } 22053 }, 22054 22055 /** 22056 * Returns list of panels touched by the end user before saving the draft 22057 * @param dataString 22058 */ 22059 getListOfDirtyPanels : function (dataString) { 22060 if (dataString == null || dataString === "") { 22061 return []; 22062 } 22063 var livePrefillXmlDoc = $.parseXML(dataString), 22064 draftDoc = this._getElement(livePrefillXmlDoc.documentElement, this.constants.AF_DRAFT_TAG); 22065 if (_.isUndefined(draftDoc) || draftDoc.childNodes.length === 0) { 22066 return []; 22067 } 22068 var draftStr = draftDoc.firstChild.textContent.replace(/\"/g, ""), 22069 retVal = []; 22070 // not using filter here explicitly, due to ES4 syntax 22071 if (draftStr) { 22072 retVal = draftStr.split(","); 22073 } 22074 return retVal; 22075 }, 22076 22077 /** 22078 * This function sets the rich text value of the field in the live data. 22079 * @param xpath 22080 * @param xmlSection 22081 * @param createMissingNodes 22082 * @param value 22083 * @private 22084 */ 22085 setRichTextValue : function (xpath, xmlSection, createMissingNodes, value) { 22086 var node = this.getContextNode(xpath, xmlSection, createMissingNodes); 22087 if (node instanceof Node) { 22088 var richTextNode = $.parseXML(value); 22089 // clear the text content before appending child 22090 node.textContent = ""; 22091 node.appendChild(richTextNode.documentElement); 22092 } 22093 }, 22094 22095 setDataValue : function (xpath, xmlSection, createMissingNodes, value) { 22096 var node = this.getContextNode(xpath, xmlSection, createMissingNodes); 22097 if (node instanceof Node) { 22098 node.textContent = value; 22099 } 22100 }, 22101 22102 getDataValue : function (xpath, xmlSection) { 22103 var node = this.getContextNode(xpath, xmlSection, false); 22104 if (node instanceof Node) { 22105 return node.textContent || null; 22106 } 22107 return undefined; 22108 }, 22109 22110 getRichTextValue : function (xpath, xmlSection) { 22111 var node = this.getContextNode(xpath, xmlSection, false); 22112 if (node instanceof Node) { 22113 return node.innerHTML.trim(); 22114 } 22115 return undefined; 22116 }, 22117 22118 _convertModelIndexToDataIndex : function (index) { 22119 if (index < 0) { 22120 return 1; 22121 } 22122 return index + 1; 22123 }, 22124 22125 getParentRef : function (path) { 22126 return path.substring(0, path.lastIndexOf("/")); 22127 }, 22128 22129 insertSubmissionInfo : function (submissionInfo, rootNode) { 22130 if (this._isNonNaked()) { 22131 var xmlutils = xfalib.ut.XMLUtils, 22132 node = rootNode === undefined 22133 ? xmlutils.findOrCreateElement("afSubmissionInfo", this._liveDataDoc.documentElement) 22134 : rootNode, 22135 self = this; 22136 _.each(submissionInfo, function (value, key) { 22137 var keyNode; 22138 if (value instanceof Array) { 22139 // we only support string items in json array 22140 var finalValue = [], insert = true; 22141 _.each(value, function (arrItem, index) { 22142 if (typeof arrItem === "string") { 22143 finalValue.push(arrItem); 22144 } else if (arrItem instanceof Object && arrItem != null) { 22145 insert = false; 22146 var el = node.ownerDocument.createElement(key); 22147 node.appendChild(el); 22148 self.insertSubmissionInfo(arrItem, el); 22149 } 22150 }); 22151 if (insert) { 22152 keyNode = xmlutils.findOrCreateElement(key, node); 22153 keyNode.textContent = finalValue.join(','); 22154 node.appendChild(keyNode); 22155 } 22156 } else if (typeof (value) === "object" && value != null) { 22157 keyNode = xmlutils.findOrCreateElement(key, node); 22158 self.insertSubmissionInfo(value, keyNode); 22159 node.appendChild(keyNode); 22160 } else { 22161 keyNode = xmlutils.findOrCreateElement(key, node); 22162 keyNode.textContent = value; 22163 node.appendChild(keyNode); 22164 } 22165 }); 22166 } 22167 } 22168 }); 22169 22170}($, _, window.guideBridge, window.guidelib, window.formBridge, window.xfalib)); 22171 22172/* 22173 * *********************************************************************** 22174 * ADOBE CONFIDENTIAL 22175 * __________________ 22176 * 22177 * Copyright 2015 Adobe Systems Incorporated 22178 * All Rights Reserved. 22179 *
22180 * NOTICE: All information contained herein is, and remains 22181 * the property of Adobe Systems Incorporated and its suppliers, 22182 * if any. The intellectual and technical concepts contained 22183 * herein are proprietary to Adobe Systems Incorporated and its 22184 * suppliers and may be covered by U.S. and Foreign Patents, 22185 * patents in process, and are protected by trade secret or copyright law. 22186 * Dissemination of this information or reproduction of this material 22187 * is strictly forbidden unless prior written permission is obtained 22188 * from Adobe Systems Incorporated. 22189 * *********************************************************************** 22190 */ 22191 22192/** 22193 * @package guidelib.model.LiveModel 22194 * @version 0.0.1 22195 */ 22196 22197(function ($, _, guideBridge, guidelib) { 22198 var LiveModel = guidelib.model.LiveModel = xfalib.ut.Class.extend({ 22199 initialize : function () { 22200 LiveModel._super.initialize.call(this); 22201 this._crossFragmentFields = {}; // 2 level map: name => { bindRef => abstract model } 22202 this._dataNodes = {}; 22203 }, 22204 22205 // only called from test framework 22206 destroy : function () { 22207 this._crossFragmentFields = {}; 22208 this._dataNodes = {}; 22209 }, 22210 22211 getCrossFragmentFields : function () { 22212 return this._crossFragmentFields; 22213 }, 22214 22215 add : function (key, model) { 22216 if (key) { 22217 var dn = this._dataNodes[key] || new guidelib.model.DataNode(); 22218 dn.addField(model); 22219 this._dataNodes[key] = dn; 22220 } 22221 }, 22222 22223 isLive : function (key) { 22224 return _.isString(key) && _.has(this._dataNodes, key); 22225 }, 22226 22227 remove : function (key, model) { 22228 if (this.isLive(key)) { 22229 var dn = this._dataNodes[key]; 22230 dn.removeField(model); 22231 } 22232 }, 22233 22234 getAllFieldModels : function (keys) { 22235 return _.flatten(_.map(keys, function (key) { 22236 var result, 22237 dataNode = this._dataNodes[key]; 22238 if (dataNode) { 22239 result = dataNode.getFieldModels(); 22240 } 22241 return result; 22242 }, this)); 22243 }, 22244 22245 getAllAbstractFieldModels : function (keys) { 22246 return _.flatten(_.map(keys, function (key) { 22247 return this._dataNodes[key].getAbstractFieldModels(); 22248 }, this)); 22249 }, 22250 22251 resetData : function () { 22252 // all loaded models in data nodes dataNodes will be reset by the respective fields 22253 // just need to reset the abstract cross frag fields 22254 _.each(this._crossFragmentFields, function (fields) { 22255 _.each(fields, function (abstractField) { 22256 abstractField.resetData(); 22257 }); 22258 }); 22259 }, 22260 22261 createDataNodes : function (duplicateBindRefs) { 22262 _.each(duplicateBindRefs, function (bindRef) { 22263 this.add(bindRef); 22264 }, this); 22265 }, 22266 22267 createCrossFragFields : function (crossFragFields, guide) { 22268 _.each(crossFragFields, function (field) { 22269 var effectiveBindRef = field.bindRef || field.name, 22270 value = field._value || null,// default value, keep null because js is quirky with operations on undefined 22271 absModel = new guidelib.model.AbstractField({ 22272 'name' : field.name, 22273 'className' : field.guideNodeClass, 22274 'bindRef' : field.bindRef, 22275 'dataSom' : field.dataSom, 22276 'afDataSom' : field.afDataSom, 22277 'jsonModel' : { 22278 '_value' : value, 22279 "{default}" : value 22280 }, 22281 '_guideContainer' : guide 22282 }); 22283 22284 if (_.isEmpty(this._crossFragmentFields[field.name])) { 22285 this._crossFragmentFields[field.name] = {}; 22286 } 22287 this._crossFragmentFields[field.name][effectiveBindRef] = absMo
22287del; 22288 22289 this.add(effectiveBindRef, absModel); // unbound globals with same name linked together 22290 22291 }, this); 22292 }, 22293 22294 prefillCrossFragFields : function (guide) { 22295 var dataUtils = guide.internal.liveDataUtils; 22296 if (dataUtils.isLiveDataInitialized()) { 22297 _.each(this._crossFragmentFields, function (fields, name) { 22298 _.each(fields, function (absModel, bindRef) { 22299 var dataContext = dataUtils._getDataContext(absModel, '', ''); 22300 // fill value from prefill data or saved lazy live data 22301 absModel.value = dataUtils.getDataValue(dataContext.indexedXpath, dataContext.xmlSec); 22302 }, this); 22303 }, this); 22304 } 22305 } 22306 }); 22307}($, _, window.guideBridge, window.guidelib)); 22308 22309/** 22310 * @package guidelib.model.FormData 22311 * @version 0.0.1 22312 */ 22313 22314(function ($, _, guidelib) { 22315 22316 /** 22317 * JavaScript class to represent form data 22318 * @class FormData 22319 * @since 6.5.11 22320 */ 22321 var AfFormData = guidelib.model.FormData = xfalib.ut.Class.extend({ 22322 22323 initialize : function () { 22324 AfFormData._super.initialize.call(this); 22325 }, 22326 22327 toJsObject : function() { 22328 return { 22329 "data" : this.data, 22330 "contentType" : this.contentType, 22331 "attachments" : this.attachments 22332 } 22333 }, 22334 22335 /** 22336 * This returns the html form data representation of adaptive form data. This could be used to submit the adaptive form data to 22337 * external end point from the client. The HTML form data contains the following the key / value pairs: 22338 * 1. data -> contains form data represented as string 22339 * 2. contentType -> contains content type of form data (it would be application/xml or application/json) 22340 * 2. fileAttachments -> list of blobs containing the file (in case of fileUrl's the type of blob would be application/json) 22341 * 3. fileAttachmentBindRefs -> list of string containing file bindRef's, this has one to one mapping with fileAttachments 22342 * @returns {*} 22343 */ 22344 toHTMLFormData : function() { 22345 // using native formData class 22346 var formData = new FormData(); 22347 // appending data of adaptive form in data key 22348 // data could be JSON or XML 22349 if (this.contentType) { 22350 formData.append("contentType", this.contentType); 22351 } 22352 formData.append("data", this.data); 22353 for (var index = 0; index < this.attachments.length; index++) { 22354 var fileAttachmentWrapper = this.attachments[index]; 22355 // 2nd parameter should be of blob type, hence adding an explicit check here 22356 // we could have created dataURL for all the files in the client, but this would cause the browser 22357 // to slow down since it would serialize the binary, hence following the below approach 22358 if (fileAttachmentWrapper.isFile()) { 22359 formData.append("fileAttachments", fileAttachmentWrapper.data, fileAttachmentWrapper.name); 22360 } else { 22361 // blob is supported on all major browsers 22362 var urlBlob = new Blob([ 22363 JSON.stringify({ 22364 "data" : fileAttachmentWrapper.data, 22365 "name" : fileAttachmentWrapper.name, 22366 "contentType" : fileAttachmentWrapper.contentType 22367 }) 22368 ], { type: 'application/json' }); 22369 formData.append("fileAttachments", urlBlob); 22370 } 22371 formData.append("fileAttachmentBindRefs", fileAttachmentWrapper.bindRef); 22372 } 22373 return formData; 22374 } 22375 }); 22376 22377 AfFormData.defineProps({ 22378 /** 22379 * Actual form data (could be JSON or xml) 22380 */ 22381 data : { 22382 get : function () { 22383 return this.options.data; 22384 } 22385 }, 22386 22387 /** 22388 * List of {FileAttachmentWrapper} {@link FileAttachmentWrapper} 22389 */ 22390 attachments : { 22391 get : function () { 22392 return this.options.attachments; 22393 } 22394 }, 22395 22396 /** 22397 * Content type of form data (it could be application/xml or application/json) 22398 */ 22399 contentType : { 22400 get : function () { 22401 return this.options.contentType; 22402 } 22403 } 22404 }); 22405 22406 22407}($, _, window.guidelib)); 22408 22409/** 22410 * @package guidelib.model.FileAttachmentWrapper 22411 * @version 0.0.1 22412 */ 22413 22414(function ($, _, guidelib) { 22415 22416 /** 22417 * JavaScript class to represent the each file data present in the form. 22418 * Data could be URI (URI could be a file URL or dataURL) 22419 * @class FileAttachmentWrapper 22420 * @since 6.5.10 22421 */ 22422 var FileAttachmentWrapper = guidelib.model.FileAttachmentWrapper = xfalib.ut.Class.extend({ 22423 22424 initialize : function () { 22425 FileAttachmentWrapper._super.initialize.call(this); 22426 }, 22427 22428 /** 22429 * Converts file attachment wrapper to a javascript object
22430 * @returns {{name: *, contentType: *, bindRef: *, data: *}} 22431 */ 22432 toJsObject : function () { 22433 return { 22434 name : this.name, 22435 contentType : this.contentType, 22436 bindRef : this.bindRef, 22437 data : this.data 22438 } 22439 }, 22440 22441 /** 22442 * Checks if the file data is native JS File object 22443 * @returns {boolean} 22444 */ 22445 isFile : function() { 22446 return this.data instanceof File; 22447 }, 22448 22449 22450 /** 22451 * Returns blob for the data URL present in data 22452 * @returns {*} 22453 */ 22454 dataURLtoBlob : function() { 22455 var dataurl = this.data, // data should be a data url 22456 arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1], 22457 bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); 22458 while(n--){ 22459 u8arr[n] = bstr.charCodeAt(n); 22460 } 22461 return new Blob([u8arr], {type: mime}); 22462 } 22463 }); 22464 22465 FileAttachmentWrapper.defineProps({ 22466 /** 22467 * Actual name of the file associated with data 22468 */ 22469 name : { 22470 get : function () { 22471 return this.options.name; 22472 } 22473 }, 22474 22475 /** 22476 * Content type of file 22477 */ 22478 contentType : { 22479 get : function () { 22480 return this.options.contentType; 22481 } 22482 }, 22483 22484 /** 22485 * This would be effective bindRef meaning bindRef in case of data model or component name in case of unbound data 22486 */ 22487 bindRef : { 22488 get : function () { 22489 return this.options.bindRef; 22490 } 22491 }, 22492 22493 /** 22494 * This would represent the name of the form element to which the file binary is associated. 22495 * In case of unbound form, bindRef and component name would be the same 22496 */ 22497 formElementName : { 22498 get : function () { 22499 return this.options.formElementName || this.options.bindRef; 22500 } 22501 }, 22502 22503 /** 22504 * Data could be URI (URI could be file URL or dataURL) or native JavaScript File object 22505 */ 22506 data : { 22507 get : function () { 22508 return this.options.data; 22509 } 22510 } 22511 }); 22512 22513 22514}($, _, window.guidelib)); 22515/************************************************************************* 22516 * 22517 * ADOBE CONFIDENTIAL 22518 * __________________ 22519 * 22520 * Copyright 2014 Adobe Systems Incorporated 22521 * All Rights Reserved. 22522 *
22523 * NOTICE: All information contained herein is, and remains 22524 * the property of Adobe Systems Incorporated and its suppliers, 22525 * if any. The intellectual and technical concepts contained 22526 * herein are proprietary to Adobe Systems Incorporated and its 22527 * suppliers and may be covered by U.S. and Foreign Patents, 22528 * patents in process, and are protected by trade secret or copyright law. 22529 * Dissemination of this information or reproduction of this material 22530 * is strictly forbidden unless prior written permission is obtained 22531 * from Adobe Systems Incorporated. 22532 **************************************************************************/ 22533 22534 22535(function (_, guidelib) { 22536 22537 22538 var GuideModelEvent = guidelib.event.GuideModelEvent = xfalib.ut.Class.extend({ 22539 msClassName : "guideModelEvent" 22540 }); 22541 22542 GuideModelEvent.defineProps({ 22543 22544 "prevText" : { 22545 get : function () { 22546 return this.jsonModel.prevText; 22547 } 22548 }, 22549 22550 "newText" : { 22551 get : function () { 22552 return this.jsonModel.newText; 22553 } 22554 }, 22555 22556 "name" : { 22557 get : function () { 22558 return this.jsonModel.name; 22559 } 22560 }, 22561 "keyDown" : { 22562 get : function () { 22563 return this.jsonModel.keyDown; 22564 } 22565 }, 22566 "modifier" : { 22567 get : function () { 22568 return this.jsonModel.modifier; 22569 } 22570 }, 22571 22572 "target" : { 22573 get : function () { 22574 return this.jsonModel.target; 22575 } 22576 }, 22577 "shift" : { 22578 get : function () { 22579 return this.jsonModel.shift; 22580 } 22581 }, 22582 "change" : { 22583 get : function () { 22584 return this.jsonModel.change; 22585 }, 22586 set : function (value) { 22587 this.jsonModel.change = value; 22588 } 22589 }, 22590 22591 "_property" : { 22592 get : function () { 22593 return this.jsonModel._property; 22594 } 22595 } 22596 }); 22597 22598 GuideModelEvent.createEvent = function (nm, tgt, prop, oldVal, newVal) { 22599 var evnt = { 22600 name : nm, 22601 target : tgt, 22602 _property : prop, 22603 prevText : oldVal, 22604 newText : newVal 22605 }; 22606 return new GuideModelEvent({"jsonModel" : evnt}); 22607 }; 22608 22609 GuideModelEvent.MODEL_REFRESH = "guide.modelRefresh"; 22610 GuideModelEvent.CHILD_CHANGED = "guide.childChanged"; 22611 GuideModelEvent.MULTIPLE_CHILD_ADDED = "guide.multipleChildAdded"; 22612 GuideModelEvent.MODEL_CHANGED = "guide.modelChanged"; 22613 GuideModelEvent.VALUE_CHANGED = "guide.valueChanged"; 22614 GuideModelEvent.ERROR_CHANGED = "guide.errorChanged"; 22615 GuideModelEvent.ERROR_RESET = "guide.errorReset"; 22616 GuideModelEvent.VISIBLE_CHANGED = "guide.visibleChanged"; 22617 GuideModelEvent.ENABLED_CHANGED = "guide.enabledChanged"; 22618 GuideModelEvent.ITEMS_CHANGED = "guide.itemsChanged"; 22619 GuideModelEvent.OBJECT_DESTROYED = "guide.objectDestroyed"; 22620 GuideModelEvent.NAVIGATE_SECTION = "guide.navigateSection"; 22621 GuideModelEvent.LAZY_LOADED = "guide.lazyLoaded"; 22622}(_, guidelib)); 22623(function ($, _, guidelib) { 22624 var GuideViewRegistry = guidelib.view.GuideViewRegistry = xfalib.ut.Class.extend({ 22625 22626 22627 _findWidget : function (config, name, className) { 22628 var result = _.find(config, function (widgetName, identifier) { 22629 return name === identifier; 22630 }); 22631 if (result === undefined) { 22632 result = _.find(config, function (widgetName, identifier) { 22633 return className === identifier; 22634 }); 22635 } 22636 return result; 22637 }, 22638 22639 22640 _findWidgetNameFromCSS : function (cssClasses) { 22641 var result = null; 22642 if (_.isString(cssClasses)) { 22643 _.find(cssClasses.split(" "), 22644 function (cssClass, index) { 22645 var match = cssClass.match(/^widget_([\w\W]+)$/); 22646 if (match && match.length === 2) { 22647 result = match[1]; 22648 return true; 22649 } 22650 return false;
22651 }); 22652 } 22653 return result; 22654 }, 22655 22656 createView : function (element, parentView) { 22657 var $element = $(element); 22658 var options = { 22659 'element' : $element.get(0), 22660 'widgetName' : $element.data("guideViewWidget"), 22661 'parentView' : parentView 22662 }; 22663 var guideViewBind = $element.data("guideViewBind"); 22664 var model = window.guideBridge._resolveId(guideViewBind); 22665 22666 22667 if (model) { 22668 options.model = model; 22669 var clsName = model.className; 22670 var nodeClass = clsName.charAt(0).toUpperCase() + clsName.substr(1) + "View"; 22671 var viewClass = guidelib.view[nodeClass], 22672 widgetConfig = window.guideBridge.userConfig.widgetConfig; 22673 if (model instanceof guidelib.model.Field || model instanceof guidelib.model.GuideCompositeField) { 22674 options.widgetName = this._findWidgetNameFromCSS(model.cssClassName) 22675 || this._findWidget(widgetConfig, model.name, model.className); 22676 } 22677 if (!viewClass && model instanceof guidelib.model.GuideContainerNode) { 22678 viewClass = guidelib.view.GuideContainerView; 22679 } 22680 if (!viewClass && model instanceof guidelib.model.Field) { 22681 viewClass = guidelib.view.GuideFieldView; 22682 } 22683 if (!viewClass && model instanceof guidelib.model.GuidePanel) { 22684 viewClass = guidelib.view.GuidePanelView; 22685 } 22686 if (!viewClass && model instanceof guidelib.model.GuideItemsContainer) { 22687 viewClass = guidelib.view.GuideItemsView; 22688 } 22689 if (!viewClass) { 22690 viewClass = guidelib.view.GuideBaseView; 22691 } 22692 22693 var bindView = new viewClass(options); 22694 return bindView; 22695 } 22696 } 22697 }); 22698 22699})($, _, guidelib); 22700(function (_, guidelib, xfalib) { 22701 var DataNode = guidelib.model.DataNode = xfalib.ut.Class.extend({ 22702 initialize : function () { 22703 this.linkedFields = []; 22704 this.isUpdateInProgress = false; 22705 }, 22706 22707 addField : function (model) { 22708 if (!_.isEmpty(model) && !_.contains(this.linkedFields, model)) { 22709 this.linkedFields.push(model); 22710 model.on(guidelib.event.GuideModelEvent.VALUE_CHANGED, this); 22711 } 22712 }, 22713 22714 removeField : function (model) { 22715 if (!_.isEmpty(model)) { 22716 model.off(guidelib.event.GuideModelEvent.VALUE_CHANGED, this); 22717 this.linkedFields = _.without(this.linkedFields, model); 22718 } 22719 }, 22720 22721 getFieldModels : function () { 22722 return _.filter(this.linkedFields, function (field) { 22723 return (field instanceof guidelib.model.Field); 22724 }); 22725 }, 22726 22727 getAbstractFieldModels : function () { 22728 return _.filter(this.linkedFields, function (field) { 22729 return (field instanceof guidelib.model.AbstractField); 22730 }); 22731 }, 22732 22733 handleEvent : function (event) { 22734 switch (event.name) { 22735 case guidelib.event.GuideModelEvent.VALUE_CHANGED: 22736 if (!_.contains(['guideButton', 'guideTextDraw', 'guideAdobeSignBlock'], event.target.className)) { 22737 this.updateLinkedFieldsValue(event); 22738 } 22739 break; 22740 default: 22741 event.target.logger().warn("AF", "Unexpected Event type on Data Node", event); 22742 } 22743 }, 22744 22745 updateLinkedFieldsValue : function (event) { 22746 if (this.isUpdateInProgress) { 22747 return; 22748 } 22749 22750 this.isUpdateInProgress = true; 22751 var newValue = event.target._getValue(); 22752 22753 try { 22754 _.each(this.linkedFields, function (field) { 22755 if (field !== event.target) { 22756 field.value = newValue; 22757 } 22758 }, this); 22759 } catch (ex) { 22760 event.target.logger().error("AF", "Unable to set Linked Field value" + ex); 22761 } finally { 22762 this.isUpdateInProgress = false;
22763 } 22764 } 22765 }); 22766 22767}(_, guidelib, xfalib)); 22768(function ($, guidelib, _) { 22769 var GuideBaseView = guidelib.view.GuideBaseView = xfalib.ut.Class.extend({ 22770 guideUtil : guidelib.util.GuideUtil, 22771 _triggerOnBridge : function (eventName, target, property, oldVal, newVal) { 22772 var evnt = guidelib.event.GuideModelEvent.createEvent(eventName, target, 22773 property, oldVal, newVal); 22774 window.guideBridge.trigger(eventName, evnt); 22775 }, 22776 22777 initialize : function () { 22778 GuideBaseView._super.initialize.call(this); 22779 this.$element = $(this.options.element); 22780 this.id = this.$element.attr("id"); 22781 this._model = this.options.model; 22782 this.parentView = this.options.parentView; 22783 this.$element.data("guideView", this); 22784 this._$item = null; 22785 this._$itemNav = null; 22786 22787 if (this._model && this._model != null) { 22788 this._model.on(guidelib.event.GuideModelEvent.MODEL_CHANGED, this.handleModelChanged, this); 22789 } 22790 this._syncPending = true; 22791 this._visibleHelpElement = "none"; 22792 this._polyfills(); 22793 }, 22794 22795 _polyfills: function () { 22796 var IEpolyfillForObjectDotEntries = function() { 22797 if(!Object.entries) { 22798 Object.entries = function (obj) { 22799 var ownProps = Object.keys(obj), 22800 i = ownProps.length, 22801 resArray = new Array(i); 22802 while (i--) 22803 resArray[i] = [ownProps[i], obj[ownProps[i]]]; 22804 22805 return resArray; 22806 }; 22807 } 22808 }; 22809 22810 var polyfills = [IEpolyfillForObjectDotEntries]; 22811 22812 for (var i = 0; i < polyfills.length; ++i) { 22813 polyfills[i](); 22814 } 22815 }, 22816 22817 postInitialize : function () { 22818 }, 22819 22820 _unloadView : function () { 22821 22822 this._model.off(guidelib.event.GuideModelEvent.MODEL_CHANGED, this.handleModelChanged, this); 22823 22824 this.$element = null; 22825 this.$widget = null; 22826 this._model = null; 22827 this._$item = null; 22828 this._$itemNav = null; 22829 this.parentView = null; 22830 }, 22831 22832 handleVisibleChanged : function (event) { 22833 22834 22835 if (!event.newText) { 22836 this.$item.addClass("hidden"); 22837 this.$itemNav.addClass("hidden"); 22838 if (this.parentView.currentActiveItemView == this) { 22839 this.parentView.setActive("nextItem"); 22840 } 22841 if (event.prevText) { 22842 this.announceVisibilityChanged("HIDDEN"); 22843 } 22844 } else { 22845 22846 this.$item.removeClass("hidden"); 22847 this.$itemNav.removeClass("hidden"); 22848 if (!event.prevText) { 22849 this.announceVisibilityChanged("VISIBLE"); 22850 } 22851 } 22852 }, 22853 22854 announceVisibilityChanged : function (visible) { 22855 var $statusAnnounceElement = this.parentView.$element.find('.guideGridFluidLayout2ContainerStatus'); 22856 var $elementLabel = this.$item.find('.guideFieldLabel label'); 22857 if ($statusAnnounceElement && $elementLabel) { 22858 var newStatus = visible === "VISIBLE" ? 22859 this.guideUtil.getLocalizedMessage("", guidelib.i18n.strings.showingField, [$elementLabel.text()]) 22860 : 22861 this.guideUtil.getLocalizedMessage("", guidelib.i18n.strings.hidingField, [$elementLabel.text()]); 22862 $statusAnnounceElement.attr('aria-label', newStatus); 22863 } 22864 }, 22865 22866 handleModelChanged : function (event) { 22867 switch (event._property) { 22868 case "viewVisited": 22869 if (event.newText) { 22870 this.$item.addClass("stepped"); 22871 this.$itemNav.addClass("stepped"); 22872 }else { 22873 this.$item.removeClass("stepped"); 22874 this.$itemNav.removeClass("stepped"); 22875 } 22876 break; 22877 22878 case "visible": 22879 this.handleVisibleChanged(event); 22880 break; 22881 } 22882 }, 22883
22884 setActive : function (activeItemToken, focus, muteScripts) { 22885 if (focus && (this._model.className === "guideNode" || this._model.forceElementFocusChange)) { 22886 if (this.$element !== null && typeof this.$element.focus === "function" && !this._guideView.skipFieldFocus) { 22887 22888 this.$element.focus(); 22889 22890 this._guideView.currentFocusItemSom = this._model.somExpression; 22891 } 22892 } 22893 return true; 22894 }, 22895 22896 focusable : function () { 22897 return this._model.visible; 22898 }, 22899 22900 _find : function (selector) { 22901 return this._guideView.$element.find(selector); 22902 }, 22903 22904 _syncGuideNodeToHtml : function (deepSync) { 22905 this._syncPending = false; 22906 22907 22908 this.handleVisibleChanged(guidelib.event.GuideModelEvent.createEvent( 22909 guidelib.event.GuideModelEvent.MODEL_CHANGED, 22910 this, 22911 "visible", 22912 this._model.visible, 22913 this._model.visible 22914 )); 22915 }, 22916 22917 _updateIds : function ($el, oldId, newId) { 22918 if (oldId == newId) { 22919 return; 22920 } 22921 22922 var idSelector = "#" + oldId, 22923 modelBindSelector = this.guideUtil.modelElSelector(oldId), 22924 attrSelector = '[id^="' + oldId + '"]', 22925 longDescriptionSelector = '[data-guide-longDescription^="' + oldId + '"]', 22926 labelSelector = 'label[for^="' + oldId + '"]', 22927 targetIdSelector = "[data-guide-id^='" + oldId + "']", 22928 $elById = $el.find(idSelector).addBack(idSelector), 22929 selectorAttrObject = { 22930 "id" : attrSelector , 22931 "for" : labelSelector, 22932 "data-guide-longDescription" : longDescriptionSelector, 22933 "data-guide-id" : targetIdSelector 22934 }; 22935 22936 22937 22938 if ($elById.attr(guidelib.util.GuideUtil.DATA_GUIDE_ITEM_CONTAINER) !== undefined) { 22939 $elById.attr(guidelib.util.GuideUtil.DATA_GUIDE_ITEM_CONTAINER, newId + guidelib.util.GuideUtil.GUIDE_ITEM_CONTAINER_SUFFIX); 22940 } 22941 22942 if ($elById.attr(guidelib.util.GuideUtil.DATA_GUIDE_ITEM) !== undefined) { 22943 $elById.attr(guidelib.util.GuideUtil.DATA_GUIDE_ITEM, newId + guidelib.util.GuideUtil.GUIDE_ITEM_SUFFIX); 22944 } 22945 $elById.attr("id", newId); 22946 $el.find(modelBindSelector).addBack(modelBindSelector).attr(this.guideUtil.GUIDE_VIEW_BIND_ATTR, newId); 22947 22948 _.each(_.keys(selectorAttrObject), function (item, index) { 22949 var selector = selectorAttrObject[item]; 22950 $el.find(selector).addBack(selector).each(function () { 22951 22952 var $this = $(this), 22953 prevId = $this.attr(item), 22954 nextId = newId + prevId.substring(oldId.length); 22955 $this.attr(item, nextId); 22956 }); 22957 }, this); 22958 }, 22959 22960 getSiblingItemView : function (siblingType) { 22961 if (this.parentView instanceof guidelib.view.GuidePanelView) { 22962 var siblingItem = this.parentView._model.navigationContext.getItemForNav(siblingType); 22963 if (siblingItem) { 22964 return this.parentView.getQualifiedNamedView(siblingItem._escapeQualifiedName()); 22965 } 22966 } 22967 return null; 22968 } 22969 }); 22970 22971 GuideBaseView.defineProps({ 22972 _guideView : { 22973 get : function () { 22974 return window.guideBridge._guideView; 22975 } 22976 }, 22977 22978 _guide : { 22979 get : function () { 22980 return window.guideBridge._guide; 22981 } 22982 }, 22983 22984 $item : { 22985 get : function () { 22986 if (!this._$item || this._$item.length == 0) { 22987 var itemSelector = this.guideUtil.itemSelector(this._model.id, this._model); 22988 this._$item = this._find(itemSelector); 22989 22990 22991 if (this._$item && this._$item.length == 0) { 22992 return this.$element; 22993 } 22994 } 22995 return this._$item; 22996 } 22997 }, 22998 22999 $itemNav : { 23000 get : function () { 23001 if (!this._$itemNav) { 23002 var itemNavSelector = this.guideUtil.itemNavSelector(this._model.id); 23003 this._$itemNav = this._find(itemNavSelector); 23004 } 23005 return this._$itemNav; 23006 } 23007 }, 23008 visibleHelpElement : { 23009 get : function () { 23010 return this._visibleHelpElement; 23011 }, 23012 set : function (helpType) { 23013 this._visibleHelpElement = helpType; 23014 } 23015 }, 23016 23017 23018 isItem : { 23019 get : function () { 23020 return this._model._isItem; 23021 } 23022 }, 23023 23024 qualifiedName : { 23025 get : function () { 23026 return this._model._escapeQualifiedName(); 23027 } 23028 } 23029 23030 }); 23031}($, guidelib, _)); 23032(function ($, guidelib, _) { 23033 23034 var xfaUtil = xfalib.ut.XfaUtil.prototype, 23035 GuideFieldView = guidelib.view.GuideFieldView = guidelib.view.GuideBaseView.extend({
23036 _defaultWidgetName : "defaultWidget", 23037 23038 23039 autofillFieldKeywordToName : { 23040 "name" : "name", 23041 "given-name" : "fname", 23042 "additional-name" : "mname", 23043 "family-name" : "lname", 23044 "email" : "email", 23045 "street-address" : "address", 23046 "address-line1" : "address", 23047 "address-line2" : "address", 23048 "address-level1" : "state", 23049 "address-level2" : "city", 23050 "postal-code" : "zip", 23051 "country" : "country", 23052 "tel" : "phone", 23053 "cc-name" : "ccname", 23054 "cc-number" : "cardnumber", 23055 "cc-csc" : "cvc", 23056 "cc-exp-month" : "ccmonth", 23057 "cc-exp-year" : "ccyear", 23058 "cc-exp" : "exp-date", 23059 "cc-type" : "card-type" 23060 }, 23061 23062 initialize : function () { 23063 GuideFieldView._super.initialize.call(this); 23064 this._initializeWidget(); 23065 this._defineModelEvents(); 23066 this._markMandatory(); 23067 this._updateEmptyStatus(); 23068 this.oldValue = null; 23069 }, 23070 23071 postInitialize : function () { 23072 this._syncGuideNodeToHtml(true); 23073 }, 23074 23075 createWidgetOptions : function () { 23076 return { 23077 name : this._model.getAttribute("autocomplete") ? this.autofillFieldKeywordToName[this._model.getAttribute("autofillFieldKeyword")] : this._model.id + "_jqName", 23078 value : this._model.value, 23079 displayValue : this._model.formattedValue, 23080 commitEvent : this.getCommitEvent(), 23081 access : this._model.enabled ? "open" : "readOnly", 23082 screenReaderText : this._model._getScreenReaderText(), 23083 mandatory : this._model.mandatory 23084 }; 23085 }, 23086 23087 getCommitEvent : function () { 23088 return xfalib.ut.XfaUtil.prototype.XFA_EXIT_EVENT; 23089 }, 23090 23091 getWidgetName : function () { 23092 var widgetName; 23093 if (this.$widget) { 23094 var $elem = this.$widget.find('[data-af-widgetname]').addBack('[data-af-widgetname]'); 23095 23096 if ($elem && $elem.length > 0) { 23097 widgetName = $elem.attr("data-af-widgetname"); 23098 } 23099 } 23100 if (!widgetName) { 23101 this.logger().warn("AF", "widget name is not specified for field " + this._model.somExpression + 23102 ", falling back to other widget"); 23103 } 23104 return widgetName || this.options.widgetName || this._defaultWidgetName; 23105 }, 23106 23107 _unloadView : function () { 23108 if (this._model) { 23109 this._model.off(guidelib.event.GuideModelEvent.VALUE_CHANGED, this.handleValueChanged, this); 23110 this._model.off(guidelib.event.GuideModelEvent.ERROR_CHANGED, this.handleErrorChanged, this); 23111 this._model.off(guidelib.event.GuideModelEvent.ERROR_RESET, this.handleErrorReset, this); 23112 } 23113 23114 this.jqwidget = null; 23115 GuideFieldView._super._unloadView.apply(this, arguments); 23116 }, 23117 23118 _initializeWidget : function () { 23119 if (this.$element.find('div.guideFieldWidget').length) { 23120 this.$widget = this.$element.find('div.guideFieldWidget'); 23121 } else { 23122 this.$widget = null; 23123 } 23124 23125 23126 if (this.$widget) { 23127 $(this.$widget).on(this.getCommitEvent(), $.proxy(this.handleCommit, this)) 23128 .on(xfaUtil.XFA_CLICK_EVENT, $.proxy(this.handleClick, this)) 23129 .on(xfaUtil.XFA_EXIT_EVENT, $.proxy(this.handleFocusOut, this)) 23130 .on(xfaUtil.XFA_ENTER_EVENT, $.proxy(this.handleEnter, this)); 23131 } 23132 }, 23133 23134 _defineModelEvents : function () { 23135 if (this._model) { 23136 23137 23138 this._model.on(guidelib.event.GuideModelEvent.VALUE_CHANGED, this.handleValueChanged, this); 23139 23140 this._model.on(guidelib.event.GuideModelEvent.ERROR_CHANGED, this.handleErrorChanged, this); 23141 this._model.on(guidelib.event.GuideModelEvent.ERROR_RESET, this.handleErrorReset, this); 23142 23143 } 23144 }, 23145 23146 _syncGuideNodeToHtml : function (deepSync) { 23147 GuideFieldView._super._syncGuideNodeToHtml.apply(this, arguments); 23148 if (this._model) { 23149 var propsToSync = { 23150 "visible" : this._model.visible, 23151 "jcr:title" : this._model.title 23152 }; 23153 _.each(propsToSync, function (value, key, list) { 23154 this.handleModelChanged(guidelib.event.GuideModelEvent.createEvent( 23155 guidelib.event.GuideModelEvent.MODEL_CHANGED, this, key, value, value 23156 )); 23157 }, this); 23158 this.$element.attr("data-disabled", !this._model.enabled + ""); 23159 } 23160 if (this.$widget) { 23161 var widgetOptions = this.createWidgetOptions(); 23162 if (!this.jqwidget) {
23163 this.createWidget(this.getWidgetName(), widgetOptions); 23164 } else { 23165 this.setWidgetOptions(widgetOptions); 23166 } 23167 } 23168 23169 if (this._model.forceErrorShow && this._model._errorText) { 23170 this.handleErrorChanged({prevText : this._model.validationState, newText : this._model._errorText}); 23171 } 23172 23173 23174 23175 23176 23177 if (this._guide.jsonModel.textReplacementMap) { 23178 var footnoteArr = Object.entries(this._guide.jsonModel.textReplacementMap); 23179 var tempArray = []; 23180 for (var i = 0; i < footnoteArr.length; i++) { 23181 23182 23183 23184 if(!tempArray[footnoteArr[i][1]]){ 23185 tempArray[footnoteArr[i][1]] = footnoteArr[i][0]; 23186 } 23187 var selector = $("span[data-af-footnote-id=" + "\"" + footnoteArr[i][0] + "\"]"); 23188 for (var j = 0; j < $(selector).length; j++) { 23189 var supTag = document.createElement("sup"); 23190 var anchorTag = document.createElement("a"); 23191 anchorTag.setAttribute("href", "#" + tempArray[footnoteArr[i][1]] + "_ftn"); 23192 anchorTag.setAttribute("data-footnote-id", tempArray[footnoteArr[i][1]]); 23193 anchorTag.setAttribute("title", $('#' + tempArray[footnoteArr[i][1]]).text()); 23194 anchorTag.innerHTML = footnoteArr[i][1]; 23195 supTag.appendChild(anchorTag); 23196 $($(selector)[j]).html(supTag.outerHTML); 23197 } 23198 } 23199 } 23200 }, 23201 23202 setWidgetOptions : function (widgetOptions) { 23203 this.jqwidget.option(widgetOptions); 23204 23205 }, 23206 23207 23208 _markMandatory : function (value) { 23209 if (this._model.mandatory && this.$element) { 23210 this.$element.attr("data-mandatory", "true"); 23211 } else { 23212 this.$element.removeAttr("data-mandatory"); 23213 23214 if (this._model._failedTest === this.guideUtil.MANDATORY_TEST) { 23215 this._model._guide().runtime.errorManager.unMarkError(this.$element, this._model.somExpression); 23216 } 23217 } 23218 if (this.jqwidget) { 23219 this.setWidgetOptions({ 23220 "mandatory" : value 23221 }); 23222 } 23223 }, 23224 23225 23226 _updateEmptyStatus : function (event) { 23227 var val = event ? event.newText : this._model.value; 23228 if (val == null || typeof val === 'string' && val.length == 0) { 23229 this.$element.removeClass("af-field-filled").addClass("af-field-empty"); 23230 } else { 23231 this.$element.removeClass("af-field-empty").addClass("af-field-filled"); 23232 } 23233 }, 23234 23235 handleValueChanged : function (event) { 23236 switch (event._property) { 23237 case "value": 23238 this.jqwidget.option("value", event.prevText); 23239 this.jqwidget.option("displayValue", event.newText); 23240 break; 23241 } 23242 this._updateEmptyStatus(event); 23243 }, 23244 23245 handleErrorChanged : function (event) { 23246 var value = event.prevText, 23247 errorMessage = event.newText; 23248 if (value === true) { 23249 this._model._guide().runtime.errorManager.unMarkError(this.$element, this._model.somExpression); 23250 this.$element.addClass("validation-success").removeClass("validation-failure"); 23251 this.updateWidgetOption("isValid", true); 23252 } else { 23253 this._model._guide().runtime.errorManager.markError(errorMessage, this.$element, this._model.somExpression, 23254 guideBridge.getValidationContext());
23255 this.$element.addClass("validation-failure").removeClass("validation-success"); 23256 this.updateWidgetOption("isValid", false); 23257 } 23258 }, 23259 23260 handleErrorReset : function (event) { 23261 this._model._guide().runtime.errorManager.unMarkError(this.$element, this._model.somExpression); 23262 this.$element.removeClass("validation-failure").removeClass("validation-success"); 23263 this.updateWidgetOption("isValid", undefined); 23264 }, 23265 23266 handleCommit : function () { 23267 if (this._model.enabled) { 23268 this.commitValue(this.jqwidget.option("value")); 23269 } 23270 }, 23271 23272 handleClick : function (event) { 23273 window.guideBridge.clickedOnWindow = false; 23274 }, 23275 23276 handleFocusOut : function (event) { 23277 var gb = window.guideBridge; 23278 23279 if (this.getCommitEvent() !== xfaUtil.XFA_EXIT_EVENT) { 23280 this._model.executeExpression("exit"); 23281 } 23282 if (gb && gb.clickedOnWindow) { 23283 this._guideView.currentFocusItemSom = null; 23284 } 23285 gb.clickedOnWindow = false; 23286 if (!(this._model.className === 'guideRadioButton' || this._model.className === 'guideCheckBox' || this._model.className === 'guideButton')) { 23287 this._triggerOnBridge("elementFocusOut", "", "", "", ""); 23288 } 23289 23290 if ((this.oldValue !== this._model.value) && this._model._errorText) { 23291 this.handleErrorChanged({prevText : this._model.validationState, newText : this._model._errorText}); 23292 } 23293 this.$element.removeClass('guideActiveField'); 23294 }, 23295 23296 handleModelChanged : function (event) { 23297 switch (event._property) { 23298 case "enabled": 23299 23300 23301 var prop = event.newText ? "open" : "readOnly"; 23302 if (this.jqwidget) { 23303 this.jqwidget.option("access", prop); 23304 } 23305 this.$element.attr("data-disabled", !event.newText + ""); 23306 break; 23307 case "mandatory": 23308 23309 this._markMandatory(this._model.mandatory); 23310 break; 23311 case "validateExpMessage": 23312 var newText = event.jsonModel.newText; 23313 this._changeValidationMessage(newText); 23314 break; 23315 case "jcr:title": 23316 23317 var newText = event.jsonModel.newText; 23318 this._changeTitle(newText); 23319 break; 23320 default: 23321 GuideFieldView._super.handleModelChanged.apply(this, arguments); 23322 } 23323 }, 23324 23325 23326 _changeTitle : function (newText) { 23327 var $field = $("#" + this.id), 23328 $guideFieldLabelDiv = $field.children(".guideFieldLabel"), 23329 $labelDiv = $guideFieldLabelDiv.children("label"); 23330 if ($labelDiv) { 23331 newText = DOMPurify.sanitize(newText); 23332 $labelDiv.html(newText); 23333 } 23334 }, 23335 23336 23337 _changeValidationMessage : function (newText) { 23338 var $fieldNode = $("#" + this.id), 23339 $errorDiv = $fieldNode.children(".guideFieldError"); 23340 $errorDiv.html(newText); 23341 }, 23342 23343 23344 commitValue : function (value) { 23345 this._model.value = value; 23346 var _version = this._model._guide().version; 23347 if (!(_version.isOn(_version.Flags.RUN_VALUE_COMMMIT_ON_SCRIPT_CHANGE))) { 23348 this._model.executeExpression("valueCommitScript"); 23349 } 23350 23351 23352 if (this.getCommitEvent() === xfaUtil.XFA_CHANGE_EVENT) { 23353 this._model.executeExpression("change"); 23354 } else { 23355 this._model.executeExpression("exit"); 23356 } 23357 }, 23358 23359 23360 tempXfaFixes : function () { 23361 23362 23363 23364 if (this.$element) { 23365 this.$element.find("input").css("position", "relative"); 23366 } 23367 this.handleAccessibility(); 23368 }, 23369 23370 handleAccessibility : function () { 23371 23372 if (this._model.mandatory) { 23373 this.$widget.find("input,textarea,select,button").attr("aria-required", true); 23374 } 23375 if(this._model._getToolTip()) { 23376 this.$element.find("input,textarea,select,button").attr("aria-labelledby",this._model.id + "_widget" + " " + this._model.id + "_guideFieldShortDescription"); 23377 } 23378 if (this._model._getScreenReaderText() === this._model._getToolTip()) { 23379 this.$element.find("input,textarea,select,button").removeAttr("aria-label"); 23380 this.$element.find("input,textarea,select,button").attr("aria-labelledby",this._model.id + "_guideFieldShortDescription"); 23381 } 23382 }, 23383 23384 23385 _getWidgetInitialOptions : function ($widget) { 23386 var $elem = $widget.find('[data-af-widgetname]').addBack('[data-af-widgetname]'); 23387 if ($elem.length > 0) { 23388 this.logger().info("AF", "Getting widget options for " + this._model.somExpression); 23389 var optionsMap = $elem.data('af-widgetoptions') || {}; 23390 _.each($elem[0].attributes, function (attr) { 23391 var nm = attr.name.match(/data-af-widgetoption-([^-]+)$/); 23392 if (nm != null && nm.length > 1) { 23393 this.logger().info("AF", "adding option " + nm[1] + " with value " + " "); 23394 optionsMap[nm[1]] = attr.value; 23395 } 23396 }, this); 23397 return optionsMap; 23398 } 23399 return {}; 23400 }, 23401 23402 _newWidget : function (widgetname, options, $widgetElem) { 23403 var jqwidget = null, 23404 fixesRequired = widgetname == this._defaultWidget
23404Name; 23405 try { 23406 23407 $widgetElem[widgetname](options); 23408 23409 23410 jqwidget = $widgetElem.data(widgetname) || $widgetElem.data('xfaWidget-' + widgetname); 23411 } catch (e) { 23412 this.logger().error("AF", "widget " + widgetname + " doesn't exists. Falling back to default widget"); 23413 fixesRequired = true; 23414 jqwidget = $widgetElem[this._defaultWidgetName](options).data('xfaWidget-' + widgetname); 23415 } 23416 23417 if (fixesRequired) { 23418 this.tempXfaFixes(); 23419 } 23420 return jqwidget; 23421 }, 23422 23423 createWidget : function (widgetname, options) { 23424 var initialOptions = this._getWidgetInitialOptions(this.$widget); 23425 var _options = $.extend({}, options, initialOptions); 23426 this.jqwidget = this._newWidget(widgetname, _options, this.$widget); 23427 }, 23428 23429 handleEnter : function () { 23430 this._guideView.currentFocusItemSom = this._model.somExpression; 23431 var gb = window.guideBridge; 23432 if (gb) { 23433 gb.clickedOnWindow = false; 23434 } 23435 if (!(this._model.className === 'guideRadioButton' || this._model.className === 'guideCheckBox' || this._model.className === 'guideButton')) { 23436 this._triggerOnBridge("elementFocus", "", "", "", ""); 23437 } 23438 this.oldValue = this._model.value; 23439 this.$element.addClass('guideActiveField'); 23440 }, 23441 23442 handleChange : function () { 23443 23444 }, 23445
23446 setActive : function (activeItemToken, focus, muteScripts) { 23447 GuideFieldView._super.setActive.call(this, activeItemToken, focus, muteScripts); 23448 if (focus) { 23449 23450 if (!this._guideView.skipFieldFocus && this.jqwidget && this.jqwidget.focus) { 23451 this.jqwidget.focus(); 23452 this._guideView.currentFocusItemSom = this._model.somExpression; 23453 } 23454 } 23455 return true; 23456 }, 23457 23458 updateWidgetOption : function (optionName, optionValue) { 23459 23460 if (this.jqwidget) { 23461 this.jqwidget.option(optionName, optionValue); 23462 } 23463 } 23464 23465 }); 23466}($, guidelib, _)); 23467(function ($, guidelib) { 23468 var GuideCaptchaView = guidelib.view.GuideCaptchaView = guidelib.view.GuideFieldView.extend({ 23469 23470 _defaultWidgetName : "afcaptcha", 23471 23472 syncGuideNodeToHtml : true, 23473 23474 initialize : function () { 23475 23476 if (!FD.isToggleEnabled(guidelib.util.FeatureToggleConstants.FT_TURNSTILE_HCAPTCHA) || this.options.model.isWidgetRecaptcha) { 23477 if ((this.options.model.captchaEnterprise && !this.options.model.checkBoxkey) || 23478 (this.options.model.captchaInvisible && this.options.model.mandatory)) { 23479 this._model = this.options.model; 23480 this.syncGuideNodeToHtml = false; 23481 return; 23482 } else if (this.options.model.captchaInvisible) { 23483 this.options.element.classList.add("af-hideRecaptchaView"); 23484 this.options.model.captchaValidate = false; 23485 } 23486 } else if ((this.options.model.isWidgetTurnstile || this.options.model.isWidgetHcaptcha) && this.options.model.captchaInvisible) { 23487 this._model = this.options.model; 23488 this.syncGuideNodeToHtml = false; 23489 return; 23490 } 23491 23492 GuideCaptchaView._super.initialize.apply(this, arguments); 23493 if (this._model.captchaWidget) { 23494 23495 this._defaultWidgetName = this._model.captchaWidget; 23496 } 23497 }, 23498 23499 _initializeWidget : function () { 23500 GuideCaptchaView._super._initializeWidget.apply(this, arguments); 23501 if (this.$widget.length > 0) { 23502 this.$widget.on("tokenChange.captcha", $.proxy(this.handleTokenChange, this)); 23503 } 23504 }, 23505 23506 _syncGuideNodeToHtml : function (deepSync) { 23507 if(!this.syncGuideNodeToHtml) 23508 return; 23509 GuideCaptchaView._super._syncGuideNodeToHtml.call(this, deepSync); 23510 }, 23511 23512 handleTokenChange : function (event) { 23513 this._model.value = event.token; 23514 }, 23515 23516 createWidgetOptions : function () { 23517 var options = GuideCaptchaView._super.createWidgetOptions.apply(this, arguments); 23518 return $.extend({}, options, { 23519 "captchaConfigData" : this.options.model.jsonModel 23520 }); 23521 }, 23522 23523 handleErrorChanged : function (event) { 23524 var value = event.prevText, 23525 errorMessage = event.newText; 23526 if (value === false) { 23527 this._model._guide().runtime.errorManager.markError(errorMessage, this.$element, this._model.somExpression, 23528 guideBridge.getValidationContext()); 23529 this.$element.addClass("validation-failure"); 23530 } else { 23531 this.$element.removeClass("validation-failure"); 23532 } 23533 } 23534 }); 23535}($, guidelib)); 23536(function ($, guidelib, _) { 23537 var xfaUtil = xfalib.ut.XfaUtil.prototype, 23538 GuideCompositeFieldView = guidelib.view.GuideCompositeFieldView = guidelib.view.GuideFieldView.extend({ 23539 _defaultWidgetName : "defaultField", 23540 23541 23542 getModelNameOptionsMap : function () { 23543 return {}; 23544 }, 23545 23546 initialize : function () { 23547 GuideCompositeFieldView._super.initialize.call(this); 23548 this._defineChildModelEvents(); 23549 }, 23550 23551 postInitialize : function () { 23552 GuideCompositeFieldView._super.postInitialize.call(this); 23553 var _self = this; 23554 if (this.getModelNameOptionsMap()) { 23555 _.each(this.getModelNameOptionsMap(), function (value, modelName) { 23556 var childModel = _self._model[modelName]; 23557 if (childModel._errorText) { 23558 childModel._triggerEvent(guidelib.event.GuideModelEvent.ERROR_CHANGED, 23559 "validationStatus", childModel.validationState, childModel._errorText); 23560 } 23561 }); 23562 } 23563 }, 23564 23565 _unloadView : function () { 23566 var _self = this; 23567 if (this.getModelNameOptionsMap()) { 23568 _.each(this.getModelNameOptionsMap(), function (value, modelName) { 23569 var obj = _self._model[modelName]; 23570 23571 obj.off(guidelib.event.GuideModelEvent.VALUE_CHANGED, _self.handleValueChanged, _self);
23572 if (obj.mandatory || obj.validateExp) { 23573 obj.off(guidelib.event.GuideModelEvent.ERROR_CHANGED, _self.handleErrorChanged, _self); 23574 obj.off(guidelib.event.GuideModelEvent.ERROR_RESET, _self.handleErrorReset, _self); 23575 } 23576 }); 23577 23578 } 23579 GuideCompositeFieldView._super._unloadView.call(_self); 23580 }, 23581 23582 _defineChildModelEvents : function () { 23583 var _self = this; 23584 if (this.getModelNameOptionsMap()) { 23585 _.each(this.getModelNameOptionsMap(), function (value, modelName) { 23586 var obj = _self._model[modelName]; 23587 23588 obj.on(guidelib.event.GuideModelEvent.VALUE_CHANGED, _self.handleValueChanged, _self); 23589 23590 23591 if (obj.mandatory || obj.validateExp) { 23592 obj.on(guidelib.event.GuideModelEvent.ERROR_CHANGED, _self.handleErrorChanged, _self); 23593 obj.on(guidelib.event.GuideModelEvent.ERROR_RESET, _self.handleErrorReset, _self); 23594 } 23595 }); 23596 23597 } 23598 }, 23599 23600 handleCommit : function () { 23601 var _self = this; 23602 if (!_.isEmpty(this.getModelNameOptionsMap())) { 23603 _.each(this.getModelNameOptionsMap(), function (value, modelName) { 23604 var obj = _self._model[modelName]; 23605 if (!_.isUndefined(obj)) { 23606 var val = _self.jqwidget.option(value); 23607 if (_.isArray(val)) { 23608 val = val.join("\n"); 23609 } 23610 obj.value = val; 23611 } 23612 }); 23613 } else { 23614 this._model.value = this.jqwidget.option("value"); 23615 } 23616 this._model.executeExpression("valueCommitScript"); 23617 this.execCommitExpression(); 23618 }, 23619 23620 handleValueChanged : function (event) { 23621 23622 23623 switch (event._property) { 23624 case "value": 23625 var map = this.getModelNameOptionsMap(); 23626 this.jqwidget.option(map[event.target.name], event.prevText); 23627 break; 23628 } 23629 }, 23630 23631 execCommitExpression : function () { 23632 23633 if (this.getCommitEvent() == xfaUtil.XFA_CHANGE_EVENT) { 23634 this._model.executeExpression("change"); 23635 } else { 23636 this._model.executeExpression("exit"); 23637 } 23638 } 23639 }); 23640}($, guidelib, _)); 23641(function ($, guidelib) { 23642 var GuideFileUploadView = guidelib.view.GuideFileUploadView = guidelib.view.GuideCompositeFieldView.extend({ 23643 _defaultWidgetName : "fileUpload", 23644 23645 getModelNameOptionsMap : function () { 23646 var map = GuideFileUploadView._super.getModelNameOptionsMap.apply(this, arguments); 23647 return $.extend({}, map, { 23648 "fileAttachment" : "value", 23649 "comment" : "comment" 23650 }); 23651 }, 23652 23653 createWidgetOptions : function () { 23654 var options = GuideFileUploadView._super.createWidgetOptions.apply(this, arguments), 23655 fileNamesStr = this._model._getFileAttachmentNames(), 23656 fileNamesArr = []; 23657 if (fileNamesStr) { 23658 fileNamesArr = fileNamesStr.split("\n"); 23659 } 23660 return $.extend({}, options, { 23661 fileList : this._model.fileList, 23662 buttonText : this._model.buttonText, 23663 multiSelect : this._model.multiSelection, 23664 fileSizeLimit : this._model.fileSizeLimit, 23665 mimeType : this._model.getOrElse(this._model.jsonModel, "mimeType", ""), 23666 buttonClass : "button.guide-fu-attach-button", 23667 fileItemListClass : "ul.guide-fu-fileItemList",
23668 iframeContainer : "div.guideContainerWrapperNode", 23669 showComment : this._model.showComment, 23670 value : this._model.fileAttachment.value, 23671 fileNames : fileNamesArr, 23672 comment : this._model.comment.value, 23673 _uuidGenerator : function () { return guideBridge._getUUID.apply(this); }, 23674 _filePath : "/tmp/fd/af", 23675 _getUrl : guideBridge._getUrl(""), 23676 disablePreview : false, 23677 uploaderPluginName : guideBridge.userConfig.uploaderPluginName || "adobeFileUploader" 23678 }); 23679 }, 23680 23681 handleCommit : function () { 23682 23683 23684 23685 this._model.fileList = this.jqwidget.option("fileList"); 23686 GuideFileUploadView._super.handleCommit.apply(this, arguments); 23687 }, 23688 23689 handleModelChanged : function (event) { 23690 switch (event._property) { 23691 case "fileList": 23692 this.jqwidget.option("fileList", event.prevText); 23693 break; 23694 default: 23695 GuideFileUploadView._super.handleModelChanged.apply(this, arguments); 23696 break; 23697 } 23698 }, 23699 23700 handleAccessibility : function () { 23701 23702 23703 var isBrowserIE9OrIE10 = ($.browser.msie && ($.browser.version === '9.0' || $.browser.version === '10.0')); 23704 if (isBrowserIE9OrIE10) { 23705 if (this._model.mandatory) { 23706 this.$widget.attr("aria-required", true); 23707 } 23708 if (this._model._getScreenReaderText() === this._model._getToolTip()) { 23709 this.$widget.removeAttr("aria-label"); 23710 this.$widget.attr("aria-labelledby", this._model.id + "_guideFieldShortDescription"); 23711 } 23712 } else { 23713 GuideFileUploadView._super.handleAccessibility.apply(this, arguments); 23714 } 23715 }, 23716 23717 setActive: function(activeItemToken, focus, muteScripts) { 23718 guidelib.view.GuideFieldView._super.setActive.call(this, activeItemToken, focus, muteScripts); 23719 if (focus) { 23720 this._guideView.currentFocusItemSom = this._model.somExpression; 23721 this.$element.find("button").focus(); 23722 } 23723 return true; 23724 }, 23725 23726 23727 23728 tempXfaFixes : function () { 23729 23730 this.handleAccessibility(); 23731 }, 23732 23733 getCommitEvent : function () { 23734 return xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT; 23735 } 23736 }); 23737}($, guidelib)); 23738(function ($, guidelib) { 23739 var GuideTermsAndConditionsView = guidelib.view.GuideTermsAndConditionsView = guidelib.view.GuideCompositeFieldView.extend({ 23740 _defaultWidgetName : "tnc", 23741 23742 getModelNameOptionsMap : function () { 23743 var map = GuideTermsAndConditionsView._super.getModelNameOptionsMap.apply(this, arguments); 23744 return $.extend({}, map, { 23745 "reviewDocument" : "value", 23746 "reviewStatus" : "reviewStatus" 23747 }); 23748 }, 23749 23750 createWidgetOptions : function () { 23751 var options = GuideTermsAndConditionsView._super.createWidgetOptions.apply(this, arguments); 23752 return $.extend({}, options, { 23753 textAreaClass : ".guide-tnc-content", 23754 checkBoxClass : ".guide-tnc-checkbox", 23755 linkClass : ".guide-tnc-link", 23756 checkBoxDisableClass : ".guide-tnc-checkbox-disabled", 23757 checkBoxReviewedClass : ".guide-tnc-checkbox-reviewed", 23758 showLink : this._model.showLink, 23759 showAsPopUp : this._model.showAsPopUp, 23760 value : this._model.reviewDocument.value, 23761 reviewStatus : this._model.reviewStatus.value, 23762 clickStatus : this._model.clickStatus 23763 }); 23764 }, 23765 23766 23767 tempXfaFixes : function () { 23768 23769 23770 23771 if (this.$widget) { 23772 this.$widget.css("position", "relative"); 23773 } 23774 23775 }, 23776 23777 handleCommit : function (event) { 23778 23779 this._model.clickStatus = this.jqwidget.option("clickStatus"); 23780 23781 GuideTermsAndConditionsView._super.handleCommit.apply(this, arguments); 23782 }, 23783 23784 handleModelChanged : function (event) { 23785 23786 23787 switch (event._property) { 23788 case "clickStatus": 23789 this.jqwidget.option("clickStatus", event.prevText); 23790 break; 23791 default: 23792 GuideTermsAndConditionsView._super.handleModelChanged.apply(this, arguments); 23793 break; 23794 } 23795 }, 23796 23797 getCommitEvent : function () { 23798 return xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT; 23799 } 23800 }); 23801}($, guidelib)); 23802(function ($, guidelib) { 23803 var GuideTelephoneView = guidelib.view.GuideTelephoneView = guidelib.view.GuideFieldView.extend({ 23804
23805 _defaultWidgetName : "telephoneWidget", 23806 23807 createWidgetOptions : function () { 23808 var options = GuideTelephoneView._super.createWidgetOptions.apply(this, arguments); 23809 return $.extend({}, options, { 23810 placeholder : this._model.placeholderText 23811 }); 23812 } 23813 23814 }); 23815}($, guidelib)); 23816 23817(function ($, guidelib) { 23818 var GuideTextDrawView = guidelib.view.GuideTextDrawView = guidelib.view.GuideFieldView.extend({ 23819 _defaultWidgetName : "abstractWidget", 23820 23821 initialize : function () { 23822 GuideTextDrawView._super.initialize.call(this); 23823 if (this.$element && this.$element.length > 0) { 23824 $(this.$element) 23825 .on("focus.guideTextDraw", $.proxy(this.handleEnter, this)) 23826 .on("click.guideTextDraw", $.proxy(this.handleClick, this)); 23827 } 23828 }, 23829 23830 _syncGuideNodeToHtml : function (deepSync) { 23831 GuideTextDrawView._super._syncGuideNodeToHtml.call(this, deepSync); 23832 23833 23834 var isFloatingField = this._model._isFloatingField(); 23835 if (this._model.value === this._model.jsonModel._value && this.$element.html() !== this._model.value && !isFloatingField) { 23836 23837 23838 } else { 23839 this.handleValueChanged({ 23840 _property : "value", 23841 newText : this._model.value ? this._model.value : "" 23842 }); 23843 } 23844 }, 23845 23846 handleValueChanged : function (event) { 23847 switch (event._property) { 23848 case "value": 23849 this.$element.html(event.newText); 23850 break; 23851 } 23852 }, 23853 23854 setActive : function (activeItemToken, focus, muteScripts) { 23855 guidelib.view.GuideFieldView._super.setActive.call(this, activeItemToken, focus, muteScripts); 23856 if (focus && !this._guideView.skipFieldFocus) { 23857 if (this.$element) { 23858 this.$element.focus(); 23859 } 23860 this._guideView.currentFocusItemSom = this._model.somExpression; 23861 } 23862 return true; 23863 } 23864 }); 23865}($, guidelib)); 23866 23867 23868(function ($, guidelib) { 23869 var GuideAdobeSignBlockView = guidelib.view.GuideAdobeSignBlockView = guidelib.view.GuideTextDrawView.extend({ 23870 }); 23871}($, guidelib)); 23872(function ($, guidelib) { 23873 var GuideButtonView = guidelib.view.GuideButtonView = guidelib.view.GuideFieldView.extend({ 23874 _defaultWidgetName : "xfaButton", 23875 23876 handleClick : function (event) { 23877 this._triggerOnBridge("elementButtonClicked", this._model, "click", "", ""); 23878 this._model.executeExpression("clickExp"); 23879 GuideButtonView._super.handleClick.call(this); 23880 }, 23881 23882 _changeTitle : function (newText) { 23883 var $fieldTitleSpan = $("#" + this.id + "_widget"); 23884 var $buttonLabel = $fieldTitleSpan.children("[data-guide-button-label]"); 23885 newText = DOMPurify.sanitize(xfalib.ut.XfaUtil.prototype.encodeScriptableTags(newText)); 23886 $buttonLabel.html(newText); 23887 }, 23888 23889 tempXfaFixes : function () { 23890 23891 23892 23893 if (this.$element) { 23894 this.$element.find("button").css("position", "relative"); 23895 } 23896 this.handleAccessibility(); 23897 } 23898 23899 }); 23900}($, guidelib)); 23901(function ($, guidelib, _) { 23902 var fileInputIdCounter = 0; 23903 var GuideListFileAttachmentButtonView = guidelib.view.GuideListFileAttachmentButtonView = guidelib.view.GuideButtonView.extend({ 23904 23905 _clearFileListing : function () { 23906 $('#fileAttachment .modal-list', window.document).children().remove(); 23907 _.each(this._fileListViews, function (childView) { 23908 childView._unloadView(); 23909 }, this); 23910 this._fileListViews = []; 23911 fileInputIdCounter = 0; 23912 }, 23913 _updateFileListing : function (fileAttachmentModel) { 23914 if (fileAttachmentModel.className == "guideFileUpload") { 23915 var $htmlTemplate = this._guideView.$element.find("#" + fileAttachmentModel.id), 23916 inputFileSelector = "#" + fileAttachmentModel.id + "_widget", 23917 23918 23919 23920 23921 23922 $cloneHtmlTemplate = $htmlTemplate.clone(); 23923 23924 $cloneHtmlTemplate.find(inputFileSelector).attr("id", fileAttachmentModel.id + "_widget" + (++fileInputIdCounter)); 23925 this._addSuffixToHelpIds($cloneHtmlTemplate, fileInputIdCounter); 23926 var $fluidDesign = $('<div></div>').addClass("row").append('<div class="col-md-12"></div>');
23927 $('#fileAttachment .modal-list', window.document).append($cloneHtmlTemplate.appendTo($fluidDesign)); 23928 var view = guidelib.view.GuideViewRegistry.prototype.createView($cloneHtmlTemplate, this); 23929 this._fileListViews.push(view); 23930 view.postInitialize(); 23931 23932 } 23933 }, 23934 _addSuffixToHelpIds : function ($html, suffix) { 23935 var $questionMarkElement = $html.find("[data-guide-longDescription]"), 23936 $shortHelpElement; 23937 if ($questionMarkElement.length > 0) { 23938 var idForLongHelp = $questionMarkElement.attr("data-guide-longDescription"), 23939 $longHelpElement = $(".guideFieldDescription.long", $html); 23940 idForLongHelp = idForLongHelp + suffix; 23941 $longHelpElement.attr("id", idForLongHelp); 23942 $questionMarkElement.attr("data-guide-longDescription", idForLongHelp); 23943 } 23944 23945 23946 }, 23947 23948 23949 _markFileListing : function () { 23950 if (this.$element) { 23951 this.$element.find("button").attr("data-guide-fileListing", true); 23952 } 23953 }, 23954 23955 initialize : function () { 23956 GuideListFileAttachmentButtonView._super.initialize.apply(this, arguments); 23957 this._markFileListing(); 23958 23959 23960 this._fileListViews = []; 23961 } 23962 }); 23963}($, guidelib, _)); 23964(function ($, guidelib, _) { 23965 var xfaUtil = xfalib.ut.XfaUtil.prototype, 23966 GuideDropDownListView = guidelib.view.GuideDropDownListView = guidelib.view.GuideFieldView.extend({ 23967 23968 _defaultWidgetName : "dropDownList", 23969 23970 initialize : function () { 23971 GuideDropDownListView._super.initialize.apply(this, arguments); 23972 if (this._model.multiSelect) { 23973 this._defaultWidgetName = "listBox"; 23974 } 23975 }, 23976 23977 _valueToArray : function (value) { 23978 var valueArray; 23979 if (value !== null && !_.isUndefined(value)) { 23980 if (_.isString(value)) { 23981 valueArray = value.split("\n"); 23982 } else if (_.isNumber(value)) { 23983 valueArray = [value.toString()]; 23984 } 23985 } else { 23986 valueArray = [null]; 23987 } 23988 return valueArray; 23989 }, 23990 23991 createWidgetOptions : function () { 23992 var options = GuideDropDownListView._super.createWidgetOptions.apply(this, arguments); 23993 23994 23995 return $.extend({}, options, { 23996 multiSelect : this._model.multiSelect, 23997 editable : false, 23998 items : this._model._getOptionsArray("save", "display"), 23999 value : this._valueToArray(this._model.value), 24000 placeholder : this._model.placeholderText 24001 }); 24002 }, 24003 24004 24005 handleCommit : function () { 24006 var val = this.jqwidget.option("value"); 24007 if (_.isArray(val)) { 24008 val = val.join("\n"); 24009 } 24010 24011 this.commitValue(val); 24012 }, 24013 24014 24015 commitValue : function (value) { 24016 var oldValue = this._model.value; 24017 this._model.value = value; 24018 24019 24020 24021 var _version = this._model._guide().version; 24022 if (!(_version.isOn(_version.Flags.RUN_VALUE_COMMMIT_ON_SCRIPT_CHANGE))) { 24023 this._model.executeExpression("valueCommitScript"); 24024 } 24025 if (this.getCommitEvent() === xfaUtil.XFA_CHANGE_EVENT) { 24026 24027 24028 24029 24030 24031 this._model.executeExpression("change", { 24032 "prevText" : oldValue, 24033 "newText" : this._model.value 24034 }); 24035 } else { 24036 24037 this._model.executeExpression("exit"); 24038 } 24039 }, 24040 24041 handleValueChanged : function (event) { 24042 this.jqwidget.option("value", this._valueToArray(event.prevText)); 24043 this.jqwidget.option("displayValue", this._valueToArray(event.
24043newText)); 24044 this._updateEmptyStatus(event); 24045 }, 24046 24047 getCommitEvent : function () { 24048 return xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT; 24049 }, 24050 24051 handleModelChanged : function (event) { 24052 if (event._property === "addItem") { 24053 this._handleAddItem(event); 24054 } 24055 if (event._property === "clearItems") { 24056 this._handleClearItems(event); 24057 } 24058 if (event._property === "deleteItem") { 24059 this._handleDeleteItem(event); 24060 } else { 24061 GuideDropDownListView._super.handleModelChanged.apply(this, arguments); 24062 } 24063 }, 24064 24065 _handleAddItem : function (event) { 24066 var itemValues = { 24067 sDisplayVal : event.newText, 24068 sSaveVal : event.prevText 24069 }; 24070 this.jqwidget.addItem(itemValues); 24071 }, 24072 24073 _handleClearItems : function (event) { 24074 this.jqwidget.clearItems(); 24075 }, 24076 24077 _handleDeleteItem : function (event) { 24078 this.jqwidget.deleteItem(event.newText); 24079 }, 24080 24081 handleItemsChanged : function (event) { 24082 var items = this._model._getOptionsArray("save", "display"); 24083 this.jqwidget.option("items", items); 24084 this.jqwidget.option("value", this._valueToArray(this._model.jsonModel._value)); 24085 this.jqwidget.option("displayValue", this._valueToArray(this._model.formattedValue)); 24086 }, 24087 24088 _defineModelEvents : function () { 24089 GuideDropDownListView._super._defineModelEvents.apply(this, arguments); 24090 if (this._model) { 24091 24092 this._model.on(guidelib.event.GuideModelEvent.ITEMS_CHANGED, this.handleItemsChanged, this); 24093 } 24094 }, 24095 24096 24097 tempXfaFixes : function () { 24098 24099 24100 if (this.$element) { 24101 if (!this._model.multiSelect) { 24102 this.$element.find("select") 24103 .css("position", "relative") 24104 .attr("id", this._model.id + "_widget") 24105 .attr("aria-describedby", this._model.id + "_widget_desc"); 24106 } else { 24107 24108 if (this._model.height) { 24109 this.$element.find("ol").css("max-height", "none"); 24110 } 24111 this.$element.find("ol") 24112 .css("position", "relative") 24113 .attr("id", this._model.id + "_widget"); 24114 } 24115 } 24116 this.handleAccessibility(); 24117 } 24118 }); 24119 24120}($, guidelib, _)); 24121 24122(function ($, guidelib) { 24123 var GuideNumericBoxView = guidelib.view.GuideNumericBoxView = guidelib.view.GuideFieldView.extend({ 24124 _defaultWidgetName : "numericInput", 24125 createWidgetOptions : function () { 24126 var options = GuideNumericBoxView._super.createWidgetOptions.apply(this, arguments); 24127 return $.extend({}, options, { 24128 dataType : this._model.dataType, 24129 leadDigits : this._model.leadDigits, 24130 fracDigits : this._model.fracDigits, 24131 24132 zero : guidelib.i18n.numberSymbols.zero, 24133 decimal : guidelib.i18n.numberSymbols.decimal, 24134 commitEvent : this.getCommitEvent(), 24135 placeholder : this._model.placeholderText 24136 }); 24137 } 24138 }); 24139 24140}($, guidelib)); 24141(function ($, guidelib) { 24142 var GuidePasswordBoxView = guidelib.view.GuidePasswordBoxView = guidelib.view.GuideFieldView.extend({ 24143 _defaultWidgetName : "defaultWidget", 24144 24145 createWidgetOptions : function () { 24146 var options = GuidePasswordBoxView._super.createWidgetOptions.apply(this, arguments); 24147 24148 return $.extend({}, options, { 24149 placeholder : this._model.placeholderText 24150 }); 24151 } 24152 }); 24153}($, guidelib)); 24154(function ($, guidelib) { 24155 var GuideTextBoxView = guidelib.view.GuideTextBoxView = guidelib.view.GuideFieldView.extend({
24156 _defaultWidgetName : "textField", 24157 24158 initialize : function () { 24159 GuideTextBoxView._super.initialize.apply(this, arguments); 24160 if (this._model.allowRichText) { 24161 this._defaultWidgetName = "richTextField"; 24162 } 24163 }, 24164 24165 createWidgetOptions : function () { 24166 var options = GuideTextBoxView._super.createWidgetOptions.apply(this, arguments), 24167 html5Type = this._model.getAttribute("html5Type"); 24168 return $.extend({}, options, { 24169 multiLine : this._model.multiLine, 24170 minLength : this._model.allowRichText ? null : this._model.minLength, 24171 length : this._model.allowRichText ? null : this._model.length, 24172 maxChars : this._model.allowRichText ? null : this._model.maxChars, 24173 required : this._model.mandatory, 24174 24175 html5Type : html5Type ? html5Type : "", 24176 totalLengthMessage : this.guideUtil.getLocalizedMessage("", guidelib.i18n.strings.totalLengthMessage, [this._model.length]), 24177 minimumLengthMessage : this.guideUtil.getLocalizedMessage("", guidelib.i18n.strings.minimumLengthMessage, [this._model.minLength]), 24178 allowRichText : this._model.allowRichText, 24179 placeholder : this._model.placeholderText 24180 }); 24181 }, 24182 24183 24184 24185 24186 tempXfaFixes : function () { 24187 if (this._model.jsonModel.multiLine) { 24188 this.$element.find("textarea").css("position", "relative"); 24189 this.handleAccessibility(); 24190 } else { 24191 GuideTextBoxView._super.tempXfaFixes.apply(this); 24192 } 24193 }, 24194 24195 handleAccessibility : function () { 24196 GuideTextBoxView._super.handleAccessibility.apply(this); 24197 if (this._model.jsonModel.multiLine) { 24198 this.$element.find("textarea").attr("aria-multiLine", true); 24199 } 24200 } 24201 }); 24202}($, guidelib)); 24203(function ($, guidelib, _) { 24204 var GuideCheckBoxView = guidelib.view.GuideCheckBoxView = guidelib.view.GuideFieldView.extend({ 24205 _defaultWidgetName : "XfaCheckBox", 24206 initialize : function () { 24207 GuideCheckBoxView._super.initialize.apply(this, arguments); 24208 this._setListenersForLabelClick(); 24209 this._setListenersForRadioButtonKeyPress(); 24210 }, 24211 24212 _setListenersForRadioButtonKeyPress : function () { 24213 var self = this; 24214 this.$element 24215 .find(".guideRadioButtonItem") 24216 .each(function (index, item) { 24217 $(item).keypress(function (e){ 24218 if(e.keyCode == "13" || e.keyCode == "32"){ 24219 e.preventDefault(); 24220 if (self._model.enabled) { 24221 self.jqwidget[self.getJQWidgetIdentifier(index)].click(); 24222 } 24223 } 24224 }); 24225 }); 24226 }, 24227 24228 _setListenersForLabelClick : function () { 24229 var self = this; 24230 this.$element 24231 .find(".guideWidgetLabel") 24232 .each(function (index, item) { 24233 $(item).click( 24234 (function (index) { 24235 return function () { 24236 24237 if (self._model.enabled) { 24238 self.jqwidget[self.getJQWidgetIdentifier(index)].click(); 24239 } 24240 }; 24241 }(index)) 24242 ); 24243 }); 24244 }, 24245 _syncGuideNodeToHtml : function (deepSync) { 24246 if (this._model._isStateOverridden("options")) { 24247 this._replaceGroupItemsWithNewOptions(this._model._getOptionsArray(), this._model.getAttribute("alignment")); 24248 24249 24250 24251 24252 this.jqwidget = null; 24253 24254 } 24255 GuideCheckBoxView._super._syncGuideNodeToHtml.apply(this, arguments); 24256 }, 24257 getJQWidgetIdentifier : function (index) { 24258 return index; 24259 }, 24260 24261 createWidgetOptions : function () { 24262 var options = GuideCheckBoxView._super.createWidgetOptions.apply(this, arguments); 24263 24264 return $.extend({}, options, { 24265 states : 2 24266 }); 24267 }, 24268 24269 getCommitEvent : function () { 24270 return xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT; 24271 }, 24272 24273 getStateFromValue : function (value, items) { 24274 if (value === null) { 24275 return 1; 24276 } 24277 var valuesArray = null; 24278 if (value && value.indexOf && value.indexOf("\\,") > -1) { 24279 valuesArray = this.splitOnNonEscapedCommas(value); 24280 } else { 24281 valuesArray = (value + "").split(","); 24282 } 24283 if (valuesArray && valuesArray.indexOf(items[0] + "") !== -1) { 24284 return 0; 24285 } 24286 return 1; 24287 }, 24288 24289 getOnOffValueFromModelValue : function (val, items) {
24290 return items[this.getStateFromValue(val, items)]; 24291 }, 24292 24293 splitOnNonEscapedCommas : function (string) { 24294 var splitArray = []; 24295 var currentSubstring = ''; 24296 var escaped = false; 24297 24298 for (var i = 0; i < string.length; i++) { 24299 var char = string[i]; 24300 24301 if (char === ',' && !escaped) { 24302 splitArray.push(currentSubstring.trim()); 24303 currentSubstring = ''; 24304 } else { 24305 currentSubstring += char; 24306 escaped = (char === '\\' && !escaped); 24307 } 24308 } 24309 splitArray.push(currentSubstring.trim()); 24310 return splitArray; 24311 }, 24312 24313 handleValueChanged : function (event) { 24314 _.each(this.jqwidget, function (jqwidget) { 24315 var setVal = this.getOnOffValueFromModelValue(event.prevText, this._escapeCommas(jqwidget.option("values"))); 24316 setVal = this._unescapeCommas(setVal); 24317 jqwidget.option("value", setVal); 24318 jqwidget.option("displayValue", setVal); 24319 }, this); 24320 this.$widget.find("[checked!=checked]").parents(".guideCheckBoxItem").removeClass('guideItemSelected'); 24321 this.$widget.find("[checked=checked]").parents(".guideCheckBoxItem").addClass('guideItemSelected'); 24322 }, 24323 24324 _escapeCommas : function (items) { 24325 var temp = _.clone(items); 24326 if(temp[0] && temp[0].indexOf && temp[0].indexOf(',') > -1 && temp[0].indexOf('\\,') === -1) { 24327 temp[0] = temp[0].replace(/,/g, "\\,"); 24328 } 24329 return temp; 24330 }, 24331 24332 _unescapeCommas : function (value) { 24333 if(value && value.indexOf && value.indexOf('\\,') > -1) { 24334 value = value.replace(/\\,/g, ','); 24335 } 24336 return value; 24337 }, 24338 24339 handleCommit : function () { 24340 var temp = ""; 24341 _.each(this.jqwidget, function (jqwidget, index) { 24342 var items = this._escapeCommas(jqwidget.option("values")); 24343 if (jqwidget.option("state") === 0) { 24344 24345 temp = temp + items[0] + ","; 24346 } 24347 }, this); 24348 temp = temp.substring(0, temp.length - 1); 24349 this.commitValue(this._unescapeCommas(temp)); 24350 }, 24351 24352 handleEnabledChanged : function (event) { 24353 24354 if (!this.$element.hasClass("dontSyncEnabled")) { 24355 var prop = event.newText ? "open" : "readOnly"; 24356 _.each(this.jqwidget, function (jqwidget) { 24357 jqwidget.option("access", prop); 24358 }); 24359 } 24360 24361 this.$element.attr("data-disabled", !this._model.enabled); 24362 }, 24363 24364 handleModelChanged : function (evnt) { 24365 switch (evnt._property) { 24366 case "enabled": 24367 this.handleEnabledChanged(evnt); 24368 break; 24369 default: 24370 GuideCheckBoxView._super.handleModelChanged.apply(this, arguments); 24371 } 24372 }, 24373 24374 handleItemsChanged : function (event) { 24375 this._replaceGroupItemsWithNewOptions(this._model._getOptionsArray(), this._model.jsonModel.alignment); 24376 this.createWidget(this.getWidgetName(), this.createWidgetOptions()); 24377 }, 24378 24379 _getGroupItemIdentifier : function () { 24380 return '.guideCheckBoxGroupItems'; 24381 }, 24382 24383 _getWidgetType : function () { 24384 return 'checkbox'; 24385 }, 24386 24387 _getItemName : function () { 24388 return "CheckBoxItem"; 24389 }, 24390 24391 _getItemSkeleton : function () { 24392 var guideWidgetItemName = "guide" + this._getItemName(); 24393 var afWidgetItemName = "af" + this._getItemName(); 24394 return '<div class="' + guideWidgetItemName + ' ' + afWidgetItemName + ' {NAME_PLACEHOLDER} {CSS_PLACEHOLDER}" data-original-title="" title="">\n' + 24395 ' <div class="guideFieldWidget left XfaCheckBox" data-id="{COUNTER_PLACEHOLDER}" data-original-title="" title="">\n' + 24396 ' <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' + 24397 ' </div>\n' + 24398 ' <div class="guideWidgetLabel right">\n' + 24399 ' <label>{LABEL_PLACEHOLDER}</label>\n' + 24400 ' </div>\n' + 24401 ' </div>'; 24402 }, 24403 24404 _renderGroupItem : function (options) { 24405 var itemSkeleton = this._getItemSkeleton(), 24406 namePlaceHolder = "{NAME_PLACEHOLDER}", 24407 cssPlaceHolder = "{CSS_PLACEHOLDER}", 24408 counterPlaceHolder = "{COUNTER_PLACEHOLDER}" , 24409 templateIDPlaceHolder = "{TEMPLATE_ID_PLACEHOLDER}", 24410 labelPlaceHolder = "{LABEL_PLACEHOLDER}", 24411 guideUtil = guidelib.util.GuideUtil; 24412 itemSkeleton = guideUtil.replaceAll(itemSkeleton, namePlaceHolder, options.modelName); 24413 itemSkeleton = guideUtil.replaceAll(itemSkeleton, templateIDPlaceHolder, options.modelTemplateId); 24414 itemSkeleton = guideUtil.replaceAll(itemSkeleton, cssPlaceHolder, options.cssValue);
24415 itemSkeleton = guideUtil.replaceAll(itemSkeleton, counterPlaceHolder, options.itemIndex); 24416 itemSkeleton = guideUtil.replaceAll(itemSkeleton, labelPlaceHolder, options.displayValue); 24417 return itemSkeleton; 24418 }, 24419 24420 _replaceGroupItemsWithNewOptions : function (items, cssValue) { 24421 var groupItem = this.$element.find(this._getGroupItemIdentifier()), 24422 options = {}, 24423 widgetName = this.getWidgetName(), 24424 self = this; 24425 24426 24427 groupItem.empty(); 24428 options.widgetType = this._getWidgetType(); 24429 options.modelName = this._model.name; 24430 options.modelTemplateId = this._model.id; 24431 24432 if (this._model.css !== null && !_.isUndefined(this._model.css)) { 24433 cssValue += " " + this._model.css; 24434 } 24435 options.cssValue = cssValue; 24436 24437 _.each(items, function (value, index) { 24438 options.itemIndex = index; 24439 options.displayValue = value.displayValue; 24440 options.saveValue = value.saveValue; 24441 groupItem.append(self._renderGroupItem(options)); 24442 }); 24443 this._initializeWidget(); 24444 this._setListenersForLabelClick(); 24445 }, 24446 24447 _replaceAll : function (stringToReplaceIn, textToReplace, replacementString) { 24448 return stringToReplaceIn.split(textToReplace).join(replacementString); 24449 }, 24450 24451 _defineModelEvents : function () { 24452 GuideCheckBoxView._super._defineModelEvents.apply(this, arguments); 24453 if (this._model) { 24454 24455 this._model.on(guidelib.event.GuideModelEvent.ITEMS_CHANGED, this.handleItemsChanged, this); 24456 } 24457 }, 24458 24459 setWidgetOptions : function (options) { 24460 var index = 0; 24461 _.each(this.jqwidget, function (jqwidget, id) { 24462 this._initOrUpdateWidget(id, this._getOptions(options, index++)); 24463 }, this); 24464 }, 24465 24466 _getOptions : function (options, index) { 24467 var items = this._model.getOnOffValues(index), 24468 val = this.getOnOffValueFromModelValue(this._model.value, items), 24469 optionsCopy = _.extend(options, { 24470 value : val, 24471 displayValue : val, 24472 values : items, 24473 state : this.getStateFromValue(this._model.value, items), 24474 screenReaderText : this._model._getScreenReaderText(index) 24475 }); 24476 return optionsCopy; 24477 }, 24478 24479 _initOrUpdateWidget : function (id, options, widgetname, $widget, initialOptions) { 24480 if (this.jqwidget[id]) { 24481 this.jqwidget[id].option(options); 24482 } else { 24483 var _options = $.extend({}, options, initialOptions); 24484 this.jqwidget[id] = this._newWidget(widgetname, _options, $widget); 24485 } 24486 this.$widget.find("[checked!=checked]").parents(".guideCheckBoxItem").removeClass('guideItemSelected'); 24487 this.$widget.find("[checked=checked]").parents(".guideCheckBoxItem").addClass('guideItemSelected'); 24488 }, 24489 24490 initializeJqWidget : function () { 24491 this.jqwidget = []; 24492 }, 24493 24494 createWidget : function (widgetname, options) { 24495 var self = this; 24496 this.initializeJqWidget(); 24497 if (this.$widget) { 24498 this.$widget.each(function (index, widget) { 24499 self._initOrUpdateWidget(self.getJQWidgetIdentifier(index), 24500 self._getOptions(options, index), 24501 widgetname, 24502 $(widget), 24503 self._getWidgetInitialOptions($(widget))); 24504 }); 24505 this.tempXfaFixes(); 24506 } 24507 }, 24508 24509 setActive : function (activeItemToken, focus, muteScripts) { 24510 guidelib.view.GuideFieldView._super.setActive.call(this, activeItemToken, focus, muteScripts); 24511 if (focus && !this._guideView.skipFieldFocus) { 24512 if (this.jqwidget && this.jqwidget[this.getJQWidgetIdentifier(0)]) { 24513 this.jqwidget[this.getJQWidgetIdentifier(0)].focus(); 24514 } 24515 this._guideView.currentFocusItemSom = this._model.somExpression; 24516 } 24517 return true; 24518 }, 24519 24520 updateWidgetOption : function (optionName, optionValue) { 24521 _.each(this.jqwidget, function (jqwidget, index) { 24522 if (optionName == "isValid") { 24523 jqwidget.option(optionName, optionValue); 24524 } 24525 }, this); 24526 }, 24527 24528 handleAccessibility : function () { 24529 GuideCheckBoxView._super.handleAccessibility.apply(this, arguments); 24530 this.$element.attr("role", "group"); 24531 if (this._model.jsonModel.assistPriority && this._model.jsonModel.custom && this._model.jsonModel.assistPriority === "custom"){ 24532 this.$element.attr("aria-label", this._model.jsonModel.custom[0]); 24533 } else { 24534 var $label = this.$element.find(".guideFieldLabel label"), 24535 label = $label.get(0); 24536 if (label && label.id) { 24537 this.$element.attr("aria-labelledby", label.id); 24538 } 24539 } 24540 } 24541 24542 }); 24543}($, guidelib, window._)); 24544 24545(function ($, guidelib, _) { 24546 var GuideRadioButtonView = guidelib.view.GuideRadioButtonView = guidelib.view.GuideCheckBoxView.extend({ 24547
24548 _defaultWidgetName : "XfaCheckBox", 24549 24550 _prevOnWidget : null, 24551 24552 _getWidgetType : function () { 24553 return 'radio'; 24554 }, 24555 24556 _getItemName : function () { 24557 return "RadioButtonItem"; 24558 }, 24559 24560 _getGroupItemIdentifier : function () { 24561 return '.guideRadioButtonGroupItems'; 24562 }, 24563 24564 getJQWidgetIdentifier : function (index) { 24565 return this._model.getItemIdentifier(index); 24566 }, 24567 24568 handleValueChanged : function (event) { 24569 var somExpression = event.prevText; 24570 if (this.jqwidget[somExpression]) { 24571 this.jqwidget[somExpression].option("value", event.newText); 24572 this.jqwidget[somExpression].option("displayValue", event.newText); 24573 if (event.newText === null) { 24574 this._prevOnWidget = null; 24575 } else { 24576 this._prevOnWidget = this.jqwidget[somExpression]; 24577 } 24578 } 24579 this.$widget.find("[checked!=checked]").parents(".guideRadioButtonItem").removeClass('guideItemSelected'); 24580 this.$widget.find("[checked=checked]").parents(".guideRadioButtonItem").addClass('guideItemSelected'); 24581 this._updateEmptyStatus(); 24582 }, 24583 24584 handleCommit : function () { 24585 var jqwidgettochange = _.find(this.jqwidget, function (jqwidget) { 24586 return jqwidget.option("state") === 0 && jqwidget !== this._prevOnWidget; 24587 }, this); 24588 this.commitValue(jqwidgettochange.option("value")); 24589 this._prevOnWidget = jqwidgettochange; 24590 }, 24591 24592 _initOrUpdateWidget : function (id, options, widgetname, widget) { 24593 GuideRadioButtonView._super._initOrUpdateWidget.apply(this, arguments); 24594 if (options.state === 0) { 24595 this._prevOnWidget = this.jqwidget[id]; 24596 } 24597 this.$widget.find("[checked!=checked]").parents(".guideRadioButtonItem").removeClass('guideItemSelected'); 24598 this.$widget.find("[checked=checked]").parents(".guideRadioButtonItem").addClass('guideItemSelected'); 24599 }, 24600 24601 initializeJqWidget : function () { 24602 this.jqwidget = {}; 24603 24604 24605 24606 this.$widget.find("[checked]").removeAttr("checked"); 24607 this.$widget.find("[checked=checked]").removeAttr("checked"); 24608 24609 }, 24610 24611 handleAccessibility : function () { 24612 GuideRadioButtonView._super.handleAccessibility.apply(this, arguments); 24613 this.$element.attr("role", "radiogroup"); 24614 } 24615 }); 24616}($, guidelib, _)); 24617(function ($, guidelib, _) { 24618 var GuideSwitchView = guidelib.view.GuideSwitchView = guidelib.view.GuideCheckBoxView.extend({ 24619 _defaultWidgetName : "guideSwitch", 24620 24621 createWidgetOptions : function () { 24622 var options = GuideSwitchView._super.createWidgetOptions.apply(this, arguments), 24623 items = this._model.jsonModel.options, checkedLabel, uncheckedLabel; 24624 24625 if (Array.isArray(items) && items.length > 0) { 24626 checkedLabel = items[0]; 24627 } else if (!_.isUndefined(items) && items.length > 0) { 24628 checkedLabel = items; 24629 } else { 24630 checkedLabel = " "; 24631 } 24632 if (Array.isArray(items) && items.length > 1) { 24633 uncheckedLabel = items[1]; 24634 } else { 24635 uncheckedLabel = " "; 24636 } 24637 return $.extend({}, options, { 24638 checkedLabel : checkedLabel.substring(checkedLabel.indexOf("=") + 1), 24639 uncheckedLabel : uncheckedLabel.substring(uncheckedLabel.indexOf("=") + 1) 24640 }); 24641 }, 24642 24643 handleValueChanged : function (event) { 24644 24645 var jqwidget = this.jqwidget[0], 24646 jqwidgetOptions = jqwidget.options; 24647 var setVal = this.getOnOffValueFromModelValue(event.prevText, jqwidget.option("values")); 24648 if (jqwidgetOptions.value !== setVal) { 24649 jqwidget.option("value", setVal); 24650 24651 var userControl = jqwidget.$userControl; 24652 var checked = jqwidgetOptions.value === jqwidgetOptions.values[0]; 24653 userControl.prop("checked", checked); 24654 userControl.parent().toggleClass('ui-state-active', checked); 24655 userControl.change(); 24656 } 24657 }, 24658 24659 handleCommit : function () { 24660 var jqwidget = this.jqwidget[0], 24661 items = jqwidget.option("values"), 24662 state = jqwidget.option("state"); 24663 this.commitValue(items[state]); 24664 } 24665 }); 24666}($, guidelib, _)); 24667(function ($, guidelib) { 24668 var GuideDatePickerView = guidelib.view.GuideDatePickerView = guidelib.view.GuideFieldView.extend({
24669 _defaultWidgetName : "dateTimeEdit", 24670 24671 createWidgetOptions : function () { 24672 var options = GuideDatePickerView._super.createWidgetOptions.apply(this, arguments), 24673 useNativeWidget = (this._model.displayPictureClause === null && this._model.editPictureClause == null); 24674 24675 return $.extend({}, options, { 24676 days : guidelib.i18n.calendarSymbols.abbrdayNames, 24677 months : guidelib.i18n.calendarSymbols.monthNames, 24678 zero : guidelib.i18n.numberSymbols.zero, 24679 clearText : xfalib.locale.Strings.clearText, 24680 useNativeWidget : useNativeWidget, 24681 showCalendarIcon : true, 24682 editPattern : this._model.editPictureClause, 24683 placeholder : this._model.placeholderText, 24684 minValidDate : this._model.minimum, 24685 maxValidDate : this._model.maximum, 24686 exclMaxDate : this._model.exclusiveMaximum, 24687 exclMinDate : this._model.exclusiveMinimum, 24688 allowNonIsoValue : true 24689 }); 24690 }, 24691 24692 24693 tempXfaFixes : function () { 24694 GuideDatePickerView._super.tempXfaFixes.apply(this, arguments); 24695 24696 if (this.$widget) { 24697 this.$widget.children("not:input[type=date]").height("100%"); 24698 } 24699 }, 24700 24701 handleAccessibility : function () { 24702 GuideDatePickerView._super.handleAccessibility.apply(this, arguments); 24703 this.$widget.children("div[tabIndex]").removeAttr("tabIndex"); 24704 if (this.$widget) { 24705 var $icon = this.$widget.find('.datepicker-calendar-icon'); 24706 if ($icon && $icon.length) { 24707 var localizedLabel = (guidelib && guidelib.i18n && guidelib.i18n.strings && guidelib.i18n.strings.showDatePicker) 24708 ? guidelib.i18n.strings.showDatePicker 24709 : 'Show date picker'; 24710 $icon.attr('role', 'button') 24711 .attr('tabindex', '0') 24712 .attr('aria-haspopup', 'dialog') 24713 .attr('aria-label', localizedLabel) 24714 .attr('title', localizedLabel); 24715 } 24716 } 24717 } 24718 }); 24719}($, guidelib)); 24720 24721 (function ($, guidelib) { 24722 var GuideFootnotePlaceHolderView = guidelib.view.GuideFootnotePlaceHolderView = guidelib.view.GuideTextDrawView.extend({ 24723 _defaultWidgetName : "abstractWidget", 24724 24725 initialize : function () { 24726 GuideFootnotePlaceHolderView._super.initialize.call(this); 24727 var that = this; 24728 $(function () { 24729 that._renderFootnotes(); 24730 }) 24731 guideBridge.on("elementNavigationChanged", function(event, payload) { 24732 that._renderFootnotes(); 24733 }) 24734 $(window.document).on('click.guidetab.data-api', '[data-guide-toggle$="accordion-tab"]', 24735 function(e) { 24736 that._renderFootnotes(); 24737 }) 24738 24739 }, 24740 24741 _renderFootnotes: function () { 24742 24743 24744 if(!this.$element.is(":visible")) { 24745 this._model.value = ""; 24746 return; 24747 } 24748 24749 var footnoteMap = this._model.footnoteMap; 24750 var footnoteArr = Object.entries(footnoteMap); 24751 if (footnoteArr.length > 0) { 24752 var value = '<div>'; 24753 var nodes = new Map(); 24754 for (footnoteID in footnoteMap) { 24755 var selector = "a[data-footnote-id=\"" + footnoteID + "\"]"; 24756 var mapKey = $(selector)[0].innerHTML; 24757 if (!nodes.has(mapKey)) { 24758 nodes.set(mapKey, footnoteMap[footnoteID]); 24759 } 24760 }; 24761 var tupleArray = []; 24762 nodes.forEach(function(value, key) { 24763 tupleArray.push([key, value]); 24764 }); 24765 tupleArray.sort(function(a, b) { 24766 return a[0] - b[0]; 24767 }); 24768 tupleArray.forEach(function(el) { 24769 value += el[1]; 24770 }); 24771 value += '</div>'; 24772 this._model.value = value; 24773 } 24774 }, 24775
24776 setActive: function () { 24777 this._renderFootnotes(); 24778 } 24779 }); 24780}($, guidelib)); 24781 24782 24783 24784 24785(function ($, guidelib) { 24786 var GuideScribbleView = guidelib.view.GuideScribbleView = guidelib.view.GuideFieldView.extend({ 24787 _defaultWidgetName : "ScribbleImageField", 24788 24789 createWidgetOptions : function () { 24790 var options = GuideScribbleView._super.createWidgetOptions.apply(this, arguments); 24791 return $.extend({}, options, { 24792 commitProperty : "src", 24793 geoLocMandatoryOnIpad : "false", 24794 aspectRatio : this._valueOfAspectRatioToBeUsed() 24795 }); 24796 }, 24797 24798 _valueOfAspectRatioToBeUsed : function () { 24799 var aspectRatio ; 24800 if (this._model.jsonModel.aspectRatio) { 24801 aspectRatio = this._model.jsonModel.aspectRatio; 24802 } else { 24803 24804 if (!this._presenceOfHeight()) { 24805 aspectRatio = "6.8888"; 24806 } 24807 } 24808 return aspectRatio ; 24809 }, 24810 24811 _presenceOfHeight : function () { 24812 return (this._model.jsonModel.hasOwnProperty('height') && this._model.jsonModel.height.toString().length > 0); 24813 }, 24814 24815 postInitialize : function () { 24816 GuideScribbleView._super.postInitialize.call(this); 24817 var that = this; 24818 24819 if (!this._presenceOfHeight()) { 24820 setTimeout(function () {guidelib.util.GuideUtil._computeHeightAndWidthForScribble(that.$widget);}, guidelib.util.GuideUtil.SCRIBBLE_RESIZE_TIME_INTERVAL); 24821 $(window).off("resize", guidelib.util.GuideUtil._resizeScribbleField); 24822 $(window).on("resize", guidelib.util.GuideUtil._resizeScribbleField); 24823 } 24824 }, 24825 24826 handleAccessibility : function () { 24827 24828 if (this._model.mandatory) { 24829 this.$widget.find("img").attr("aria-required", true); 24830 } 24831 if (this._model._getScreenReaderText() === this._model._getToolTip()) { 24832 this.$element.find("img").removeAttr("aria-label"); 24833 this.$element.find("img").attr("aria-labelledby", this._model.id + "_guideFieldShortDescription"); 24834 } else if (this._model._getAssistPriority() === "none") { 24835 this.$element.find("img").attr("aria-label", " "); 24836 } 24837 }, 24838 24839 24840 tempXfaFixes : function () { 24841 if (this.$widget) { 24842 this.$widget.css("position", "relative").find("img").css("position", "relative"); 24843 } 24844 this.handleAccessibility(); 24845 } 24846 }); 24847}($, guidelib)); 24848(function ($, guidelib) { 24849 var xfaUtil = xfalib.ut.XfaUtil.prototype, 24850 GuideImageView = guidelib.view.GuideImageView = guidelib.view.GuideBaseView.extend({ 24851 initialize : function () { 24852 GuideImageView._super.initialize.call(this); 24853 if (this._model.value != null) { 24854 var srcString = "data:image/*;base64," + this._model.value; 24855 this.$element.children('img').attr('src', srcString); 24856 } 24857 }, 24858 24859 postInitialize : function () { 24860 this._syncGuideNodeToHtml(); 24861 }, 24862
24863 setActive : function (activeItemToken, focus, muteScripts) { 24864 guidelib.view.GuideFieldView._super.setActive.call(this, activeItemToken, focus, muteScripts); 24865 if (focus && !this._guideView.skipFieldFocus) { 24866 if (this.$element) { 24867 this.$element.focus(); 24868 } 24869 this._guideView.currentFocusItemSom = this._model.somExpression; 24870 } 24871 return true; 24872 } 24873 24874 }); 24875}($, guidelib)); 24876 24877(function ($, guidelib) { 24878 var GuideChartView = guidelib.view.GuideChartView = guidelib.view.GuideBaseView.extend({ 24879 24880 initialize : function () { 24881 GuideChartView._super.initialize.call(this); 24882 var chartView = this; 24883 $(window).on("resize orientationchange", function () { 24884 chartView.renderChart.apply(chartView); 24885 }); 24886 }, 24887 24888 postInitialize : function () { 24889 this._syncGuideNodeToHtml(true); 24890 }, 24891 24892 handleModelChanged : function (event) { 24893 switch (event._property) { 24894 case "data": 24895 case "chartType": 24896 this.renderChart(); 24897 break; 24898 24899 case "visible": 24900 this.handleVisibleChanged(event); 24901 break; 24902 } 24903 }, 24904 24905 handleVisibleChanged : function (event) { 24906 24907 24908 if (!event.newText) { 24909 24910 this.$element.addClass("hidden"); 24911 if (this.parentView.currentActiveItemView == this) { 24912 this.parentView.setActive("nextItem"); 24913 } 24914 } else { 24915 24916 this.$element.removeClass("hidden"); 24917 } 24918 }, 24919 24920 _generateChart : function () { 24921 var $chartElement = this.$element, chartModel = this._model, isChartVisible, chart; 24922 24923 var plottedChartSelector = chartModel.jsonModel.isInteractiveCommunicationChartResource ? '.highcharts-container' 24924 : '.dv-chart-container'; 24925 var $plottedChart = $chartElement 24926 .find(plottedChartSelector); 24927 isChartVisible = ($chartElement.parent().width() > 0) 24928 && ($chartElement.width() > 0) ? true : false; 24929 24930 24931 24932 24933 if ((isChartVisible || $plottedChart.length == 0) 24934 && chartModel.repeatableItem) { 24935 try { 24936 24937 $plottedChart.remove(); 24938 if (chartModel.jsonModel.isInteractiveCommunicationChartResource) { 24939 chart = new fd.chart.ChartInstanceGenerator() 24940 .generate(chartModel.jsonModel, 24941 chartModel.jsonModel.data); 24942 Highcharts.chart($chartElement.attr('id'), 24943 chart); 24944 } else { 24945 chart = guidelib.chartUtils.constructChart( 24946 chartModel, $chartElement); 24947 if (chart) { 24948 chart.render(); 24949 } 24950 } 24951 } catch (exception) { 24952 this.logger().error("AF Chart view", 24953 "Error while rendering chart " + exception); 24954 } 24955 } 24956 }, 24957 24958 renderChart : function () { 24959 if (this._model.data) { 24960 var chartView = this; 24961 window.requestAnimationFrame(function () { 24962 chartView._generateChart.apply(chartView); 24963 }); 24964 } 24965 }, 24966 24967 _syncGuideNodeToHtml : function (deepSync) { 24968 this.renderChart(); 24969 guidelib.view.GuideChartView._super._syncGuideNodeToHtml.call(this, deepSync); 24970 }, 24971 24972 setActive : function (activeItemToken, focus, muteScripts) { 24973 guidelib.view.GuideChartView._super.setActive.call(this, activeItemToken, focus, muteScripts); 24974 if (focus && !this._guideView.skipFieldFocus) { 24975 if (this.$element) { 24976 this.$element.focus(); 24977 } 24978 this._guideView.currentFocusItemSom = this._model.somExpression; 24979 } 24980 return true; 24981 } 24982 }); 24983}($, guidelib)); 24984(function ($, guidelib) { 24985 var GuideAdModuleView = guidelib.view.GuideAdModuleView = guidelib.view.GuideBaseView.extend({ 24986 24987 initialize : function () { 24988 GuideAdModuleView._super.initialize.call(this); 24989 if (this._model) { 24990 24991 this._model.on(guidelib.event.GuideModelEvent.VALUE_CHANGED, this.handleValueChanged, this); 24992 } 24993 this.oldValue = null; 24994 }, 24995 24996 postInitialize : function () { 24997 this._syncGuideNodeToHtml(true); 24998 }, 24999 25000 handleValueChanged : function (event) { 25001 switch (event._property) { 25002 case "value": 25003 this.$element.html(event.newText); 25004 break; 25005 } 25006 }, 25007 25008 handleVisibleChanged : function (event) { 25009 25010 25011 if (!event.newText) { 25012 25013 this.$element.addClass("hidden"); 25014 if (this.parentView.currentActiveItemView == this) {
25015 this.parentView.setActive("nextItem"); 25016 } 25017 } else { 25018 25019 this.$element.removeClass("hidden"); 25020 } 25021 }, 25022 25023 handleModelChanged : function (event) { 25024 GuideAdModuleView._super.handleModelChanged.apply(this, arguments); 25025 }, 25026 _syncGuideNodeToHtml : function (deepSync) { 25027 if (this._model.value) { 25028 this.$element 25029 .html(this._model.value) 25030 .find('img') 25031 .attr('src', function (idx, val) { 25032 return Granite.HTTP.externalize(val); 25033 }); 25034 } 25035 25036 if (this._model.layoutConfigs) { 25037 var options = { 25038 $element : this.$element, 25039 layoutConfigs : this._model.layoutConfigs 25040 }; 25041 guidelib.util.AdUtil.applyLayouts(options); 25042 } 25043 if (this._model) { 25044 this.handleModelChanged(guidelib.event.GuideModelEvent.createEvent( 25045 guidelib.event.GuideModelEvent.MODEL_CHANGED, 25046 this, 25047 "visible", 25048 this._model.visible, 25049 this._model.visible 25050 )); 25051 } 25052 }, 25053 25054 setActive : function (activeItemToken, focus, muteScripts) { 25055 guidelib.view.GuideFieldView._super.setActive.call(this, activeItemToken, focus, muteScripts); 25056 if (focus) { 25057 if (this.$element) { 25058 this.$element.focus(); 25059 } 25060 this._guideView.currentFocusItemSom = this._model.somExpression; 25061 } 25062 return true; 25063 } 25064 }); 25065}($, guidelib)); 25066(function ($, _, guidelib) { 25067 var GuideItemsView = guidelib.view.GuideItemsView = guidelib.view.GuideBaseView.extend({ 25068 initialize : function () { 25069 GuideItemsView._super.initialize.call(this); 25070 this.childViews = []; 25071 }, 25072 25073 25074 _unloadView : function () { 25075 if (this._model._selfOrAncestorIsLazyReference) { 25076 var fragmentPlaceHolderSelector = "#" + this.id, 25077 ind; 25078 25079 $(fragmentPlaceHolderSelector).children().remove(); 25080 25081 var queueForLazyItems = this._guideView._queueViewForLazyItems; 25082 25083 if ((ind = _.indexOf(queueForLazyItems, this)) !== -1) { 25084 queueForLazyItems[ind] = undefined; 25085 } 25086 _.each(this.childViews, function (view) { 25087 25088 view._unloadView(); 25089 }, this); 25090 25091 this.childViews = []; 25092 25093 this._currentActiveItemView = null; 25094 25095 this._guideView._domTemplateCacheStore.removeDomElement("#" + this._model.templateId); 25096 25097 this._guideView._reInitializeGuideContainerDom(); 25098 } 25099 }, 25100 postInitialize : function () { 25101 this.childViews = _.reduce(this._model.children, function (childViews, childModel) { 25102 var childView = this._createNonRepeatChildView(childModel); 25103 if (childView) { 25104 childViews.push(childView); 25105 } 25106 return childViews; 25107 }, [], this); 25108 25109 this._syncGuideNodeToHtml(false); 25110 }, 25111 25112 _createNonRepeatChildView : function (childModel) { 25113 25114 25115 25116 25117 var childElSelector = this.guideUtil.modelElSelector(childModel.id); 25118 var $childEl = this.$element.find(childElSelector); 25119 if (!$childEl.length) { 25120 $childEl = this.$element.find(this.guideUtil.modelElSelector(childModel.templateId)); 25121 this._updateIds($childEl, childModel.templateId, childModel.id); 25122 } 25123 if ($childEl.length) { 25124 var childView = guidelib.view.GuideViewRegistry.prototype.createView($childEl, this); 25125 childView.postInitialize(); 25126 return childView; 25127 } 25128 return null; 25129 }, 25130 25131 _syncGuideNodeToHtml : function (deepSync) { 25132 if (deepSync) { 25133 _.each(this.childViews, function (childView) { 25134 childView._syncGuideNodeToHtml(true); 25135 }, this); 25136 } 25137 GuideItemsView._super._syncGuideNodeToHtml.call(this, deepSync); 25138 }, 25139 25140 _findChildView : function (childModel) { 25141 var view = _.find(this.childViews, function (childView) { 25142 return childView._model == childModel; 25143 }, this); 25144 return view; 25145 } 25146 }); 25147 25148 GuideItemsView.defineProps({ 25149 itemsView : { 25150 get : function () { 25151 var views = _.filter(this.childViews, function (childView) { 25152 return childView.isItem; 25153 }, this); 25154 return views; 25155 } 25156 } 25157 }); 25158}($, _, guidelib)); 25159 25160(function ($, _, guidelib, guideBridge) { 25161 25162 var GuideProgressiveSectionView = guidelib.view.GuideProgressiveSectionView = guidelib.view.GuideItemsView.extend({ 25163 25164 initialize : function () { 25165 GuideProgressiveSectionView._super.initialize.call(this); 25166 25167 if (this._model && this._model != null) { 25168 25169 25170 25171 25172 25173 this._model.off(guidelib.event.GuideModelEvent.NAVIGATE_SECTION); 25174 this._model.on(guidelib.event.GuideModelEvent.NAVIGATE_SECTION, this.handleNavigateSection, this); 25175 } 25176 25177 25178 }, 25179 25180 25181 handleNavigateSection : function (event) { 25182 25183 var progressive = guidelib.runtime.progressive, 25184 that = this, 25185 model = this._model, 25186 part = null; 25187 if (event.newText === "next") { 25188 model.currentActivePart++; 25189 } else if (event.newText === "prev") { 25190 model.currentActivePart--; 25191 } 25192 _.each(model._parts, function (item, index) { 25193 if (index == model.currentActivePart) { 25194 _.each(item, function (model, id) { 25195 25196 25197 25198 if (progressive.isFieldVisible(model)) { 25199 progressive.markFieldVisible(window.guideBridge._getGuideDomElement(model.somExpression).parent()); 25200 } else { 25201 progressive.markFieldHidden(window.guideBridge._getGuideDomElement(model.somExpression).parent()); 25202 } 25203 }); 25204 } else { 25205 _.each(item, function (model, id) { 25206 25207 progressive.markFieldHidden(window.guideBridge._getGuideDomElement(model.somExpression).parent()); 25208 }); 25209 } 25210 }); 25211 25212 if (((model.currentActivePart + 1) !== 1) || model._parts.length !== 1) { 25213 25214 25215 if (model._parts.length > 0) { 25216 this._updateSectionTitle(); 25217 } 25218 } 25219 }, 25220 25221 25222 _updateSectionTitle : function () { 25223 var progressive = guidelib.runtime.progressive, 25224 $sectionTitle = this.$element.find(progressive.PROGRESSIVE_CONSTANTS.PDC_SECTION_TIT
25224LE_SELECTOR), 25225 sectionTitle = this._model.sectionTitle, 25226 newSectionTile = sectionTitle + " (" + (this._model.currentActivePart + 1) + "/" + this._model._parts.length + ")"; 25227 $sectionTitle.html(newSectionTile); 25228 }, 25229 25230 postInitialize : function () { 25231 var that = this, 25232 $childEls, 25233 item, 25234 id = null; 25235 25236 if (this.$element && this.$element != null) { 25237 $childEls = this.$element.find(".progressiveSectionField"); 25238 $childEls.each(function (index, childEl) { 25239 25240 25241 item = $(childEl).children("div")[0]; 25242 25243 id = $(item).attr("id"); 25244 25245 25246 25247 var childView = guidelib.view.GuideViewRegistry.prototype.createView(item, that); 25248 childView.postInitialize(); 25249 that.childViews.push(childView); 25250 that.childViewsToId = that.childViewsToId || {}; 25251 that.childViewsToId[id] = childView; 25252 }); 25253 25254 this._calculatePartsOfSection(); 25255 } 25256 }, 25257 25258 _getPdcSizeConfiguration : function () { 25259 return window.guideBridge.userConfig["progressive.pdcSize"]; 25260 }, 25261 25262 _calculatePartsOfSection : function () { 25263 var userConfig = window.guideBridge.userConfig, 25264 progressive = guidelib.runtime.progressive, 25265 $pdc = this.$element.parents(progressive.PROGRESSIVE_CONSTANTS.PDC_SELECTOR); 25266 25267 25268 if (this._getPdcSizeConfiguration()) { 25269 if (this._getPdcSizeConfiguration() && this._getPdcSizeConfiguration().height) { 25270 $pdc.height(this._getPdcSizeConfiguration().height); 25271 } 25272 if (this._getPdcSizeConfiguration() && this._getPdcSizeConfiguration().width) { 25273 $pdc.width(this._getPdcSizeConfiguration().width); 25274 } 25275 25276 } 25277 25278 if (userConfig && userConfig["calculatePartsOfSectionConfig"] && _.isFunction(userConfig["calculatePartsOfSectionConfig"]["calculatePartsOfSectionHandler"])) { 25279 var externalHandler = userConfig["calculatePartsOfSectionConfig"]["calculatePartsOfSectionHandler"], 25280 25281 sectionParts = externalHandler(this._model); 25282 this._updatePartsFromArray(sectionParts); 25283 } else { 25284 var $sectionFieldContainer = this.$element.find(progressive.PROGRESSIVE_CONSTANTS.PDC_SECTION_FIELD_CONTAINER_SELECTOR), 25285 pdcInnerHeight = $pdc.innerHeight(), 25286 pdcTitleHeight = $pdc.find(progressive.PROGRESSIVE_CONSTANTS.PDC_TITLE_SELECTOR).outerHeight(), 25287 pdcControlHeight = $pdc.find("[" + progressive.PROGRESSIVE_CONSTANTS.PDC_CONTROLS + "]").outerHeight(), 25288 sectionTitleHeight = this.$element.find(progressive.PROGRESSIVE_CONSTANTS.PDC_SECTION_TITLE_SELECTOR).outerHeight(), 25289 sectionFieldContainerHeight, 25290 $sectionRepeatableControls = $pdc.find(progressive.PROGRESSIVE_CONSTANTS.PDC_SECTION_REPEATABLE_CONTROLS_SELECTOR), 25291 repeatableControlsHeight = $sectionRepeatableControls.outerHeight() ? $sectionRepeatableControls.outerHeight() + progressive.heightBuffer : 0, 25292 repeatableTitleHeight = $(progressive.PROGRESSIVE_CONSTANTS.PDC_SECTION_TITLE_CONTAINER_SELECTOR).outerHeight() || 0, 25293 availablePanelHeight, 25294 availableFields = this.$element.find(".progressiveSectionField"), 25295 currentActiveFields = $sectionFieldContainer.find('.progressiveSectionField.pdcCurrentPanelField'), 25296 consumeHeight, 25297 that = this, 25298 currentPart = 0, 25299 id, 25300 offsetDivs = $pdc.find("[" + progressive.PROGRESSIVE_CONSTANTS.PDC_OFFSET_SELECTOR + "]"), 25301 hasAtleastOne = false, 25302 trunkRest = false; 25303 $sectionFieldContainer.css('max-height', ''); 25304 sectionFieldContainerHeight = $sectionFieldContainer.height(); 25305 25306 25307 25308 25309 availablePanelHeight = pdcInnerHeight; 25310 _.each(offsetDivs, function (offsetDiv) { 25311 availablePanelHeight -= $(offsetDiv).outerHeight(); 25312 }); 25313 availablePanelHeight -= guidelib.runtime.progressive.heightBuffer; 25314 25315 $sectionFieldContainer.css('max-height', availablePanelHeight + 'px'); 25316 consumeHeight = availablePanelHeight; 25317 25318 25319 if (sectionFieldContainerHeight > availablePanelHeight) { 25320 25321 for (var i = 0; i < availableFields.length; i++) { 25322 var $currentField = $(availableFields[i]), 25323 currentFieldHeight = $currentField.outerHeight() + guidelib.runtime.progressive.fieldHeightBuffer; 25324 if (currentFieldHeight <= consumeHeight && !trunkRest) { 25325 consumeHeight = consumeHeight - currentFieldHeight; 25326 hasAtleastOne = true; 25327 25328 25329 25330 25331 id = $currentField.children("div").first().attr("id"); 25332 this._updateParts(currentPart, id); 25333 } else if (!hasAtleastOne) { 25334 25335 id = $currentField.children("div").first().attr("id"); 25336 this._updateParts(currentPart, id); 25337 hasAtleastOne = true; 25338 trunkRest = true; 25339 } else { 25340 25341 consumeHeight = availablePanelHeight; 25342 currentPart++; 25343 i--; 25344 } 25345 } 25346 } else { 25347 25348 $.each(availableFields, function (index) { 25349 25350 25351 that._updateParts(currentPart, $(this).children("div").first().attr("id")); 25352 }); 25353 } 25354 } 25355 }, 25356 25357 25358 _updatePartsFromArray : function (sectionParts) { 25359 if (_.isArray(sectionParts)) { 25360 _.each(sectionParts, function (part, currentPart) { 25361 if (_.isArray(part)) { 25362 _.each(part, function (item, index) { 25363 25364 this._updateParts(currentPart, item.id); 25365 }); 25366 } 25367 }); 25368 } 25369 }, 25370 25371 _updateParts : function (currentPart, id) { 25372 25373 25374 this._model._parts[currentPart] = this._model._parts[currentPart] || {} ; 25375 this._model._parts[currentPart][id] = this._model._getChildModelFromId(id); 25376 }, 25377 25378 focusable : function () { 25379 25380 return false;
25381 }, 25382 25383 setActive : function (activeItemToken, focus, muteScripts) { 25384 25385 return true; 25386 }, 25387 25388 handleChildChanged : function (event) { 25389 25390 }, 25391 25392 handleModelChanged : function (event) { 25393 25394 }, 25395 25396 handleVisibleChanged : function (event) { 25397 25398 }, 25399 25400 handleAccessibility : function () { 25401 25402 }, 25403 25404 getSiblingItemView : function (siblingType) { 25405 25406 return null; 25407 }, 25408 25409 getQualifiedNamedView : function (qName) { 25410 25411 var view = _.find(this.childViews, function (childView) { 25412 return (childView._model._escapeQualifiedName() == qName); 25413 }, this); 25414 return view; 25415 } 25416 }); 25417 GuideProgressiveSectionView.defineProps({ 25418 $item : { 25419 get : function () { 25420 25421 return null; 25422 } 25423 }, 25424 25425 $itemNav : { 25426 get : function () { 25427 25428 return null; 25429 } 25430 }, 25431 25432 isItem : { 25433 get : function () { 25434 25435 return false; 25436 } 25437 }, 25438 25439 qualifiedName : { 25440 get : function () { 25441 25442 return null; 25443 } 25444 } 25445 }); 25446}($, _, guidelib, window.guideBridge)); 25447 25448(function ($, _, guidelib) { 25449 var GuideProgressiveRepeatableSectionView = guidelib.view.GuideProgressiveRepeatableSectionView = guidelib.view.GuideProgressiveSectionView.extend({ 25450 initialize : function () { 25451 GuideProgressiveRepeatableSectionView._super.initialize.call(this); 25452 25453 this._$summary = null; 25454 if (this._model && this._model != null) { 25455 25456 if (this._model && this._model.instance) { 25457 this._model.instance.off(guidelib.event.GuideModelEvent.MODEL_CHANGED, this.handleModelChanged, this); 25458 this._model.instance.on(guidelib.event.GuideModelEvent.MODEL_CHANGED, this.handleModelChanged, this); 25459 } 25460 this._summarySelector = this.guideUtil.summarySelector(this._model.instance.id); 25461 } 25462 }, 25463 25464 postInitialize : function () { 25465 GuideProgressiveRepeatableSectionView._super.postInitialize.call(this); 25466 this.handleSummaryChanged(); 25467 }, 25468 25469 25470 25471 25472 _updateSectionTitle : function () { 25473 25474 25475 }, 25476 25477 25478 handleRepeatableProgressivePanel : function () { 25479 25480 this._updateIds(this.$element, this._model.repeatablePanelId, this._model.instance.id); 25481 this.childViews = []; 25482 25483 _.each(this._model.children, function (childModel) { 25484 var cTemplateId = childModel.templateId, 25485 childId = childModel.id, 25486 $childItem = this.$element.find('#' + cTemplateId), 25487 view = null, 25488 $childEl; 25489 if (!$childItem.length) { 25490 return; 25491 } 25492 25493 25494 25495 this._updateIds(this.$element, cTemplateId, childId); 25496 }, this 25497 ); 25498 }, 25499 25500 handleNavigateSection : function (event) { 25501 GuideProgressiveRepeatableSectionView._super.handleNavigateSection.apply(this, arguments); 25502 25503 }, 25504 25505 25506 _calculatePartsOfSection : function () { 25507 var userConfig = window.guideBridge.userConfig; 25508 25509 if (userConfig && userConfig["calculatePartsOfSectionConfig"] && _.isFunction(userConfig["calculatePartsOfSectionConfig"]["calculatePartsOfSectionHandler"])) { 25510 var externalHandler = userConfig["calculatePartsOfSectionConfig"]["calculatePartsOfSectionHandler"], 25511 25512 sectionParts = externalHandler(this._model); 25513 this._updatePartsFromArray(sectionParts); 25514 } else { 25515 var progressive = guidelib.runtime.progressive, 25516 $pdc = $(progressive.PROGRESSIVE_CONSTANTS.PDC_SELECTOR), 25517 $sectionRepeatableControls = $pdc.find(progressive.PROGRESSIVE_CONSTANTS.PDC_SECTION_REPEATABLE_CONTROLS_SELECTOR); 25518 25519 $sectionRepeatableControls.find(".hidden").removeClass("hidden"); 25520 var $sectionFieldContainer = this.$element.find(progressive.PROGRESSIVE_CONSTANTS.PDC_SECTION_FIELD_CONTAINER_SELECTOR), 25521 pdcOuterHeight = $pdc.outerHeight(), 25522 pdcTitleHeight = $pdc.find(progressive.PROGRESSIVE_CONSTANTS.PDC_TITLE_SELECTOR).outerHeight(), 25523 25524 25525 repeatableControlsHeight = $sectionRepeatableControls.outerHeight(true) ? $sectionRepeatableControls.outerHeight(true) + progressive.heightBuffer : 0, 25526 repeatableTitleHeight = this.$element.find(progressive.PROGRESSIVE_CONSTANTS.PDC_SECTION_TIT
25526LE_CONTAINER_SELECTOR).outerHeight(true) || 0, 25527 availableFields = this.$element.find(".progressiveSectionField"), 25528 id, 25529 currentPart = 0, 25530 availablePanelHeight; 25531 25532 $sectionRepeatableControls.find("[data-guide-repeatable='back']").addClass("hidden"); 25533 $sectionRepeatableControls.outerHeight(true) ? $sectionRepeatableControls.outerHeight(true) + progressive.heightBuffer : 0, 25534 25535 25536 availablePanelHeight = pdcOuterHeight - pdcTitleHeight - repeatableTitleHeight - 1.5 * guidelib.runtime.progressive.heightBuffer; 25537 25538 $sectionFieldContainer.css('max-height', availablePanelHeight + 'px'); 25539 $sectionFieldContainer.css('overflow', 'auto'); 25540 for (var i = 0; i < availableFields.length; i++) { 25541 var $currentField = $(availableFields[i]); 25542 25543 25544 id = $currentField.children("div").first().attr("id"); 25545 this._updateParts(currentPart, id); 25546 } 25547 } 25548 }, 25549 25550 handleSummaryChanged : function () { 25551 25552 if (this.$summary.length > 0) { 25553 var panelModel = this._model.instance; 25554 25555 if (panelModel == null) { 25556 panelModel = window.guideBridge._resolveId("im_" + this._model.repeatablePanelId).instances[0]; 25557 } 25558 if (panelModel.summary) { 25559 this.$summary.text(panelModel.summary); 25560 } else { 25561 var title = panelModel.title || panelModel.name; 25562 if (this._model.instanceIndex && panelModel.repeatable) { 25563 title += " " + this._model.instanceIndex; 25564 } 25565 this.$summary.text(title); 25566 } 25567 } 25568 }, 25569 25570 handleModelChanged : function (event) { 25571 switch (event._property) { 25572 case "summary": 25573 this.handleSummaryChanged(); 25574 break; 25575 default: 25576 GuideProgressiveRepeatableSectionView._super.handleModelChanged.apply(this, arguments); 25577 } 25578 } 25579 }); 25580 25581 GuideProgressiveRepeatableSectionView.defineProps({ 25582 $summary : { 25583 get : function () { 25584 if (!this._$summary) { 25585 this._$summary = this._find(this._summarySelector); 25586 } 25587 return this._$summary; 25588 } 25589 } 25590 }); 25591}($, _, guidelib)); 25592 25593(function ($, guidelib) { 25594 var GuideAdModuleGroupView = guidelib.view.GuideAdModuleGroupView = guidelib.view.GuideItemsView.extend({ 25595 initialize : function () { 25596 GuideAdModuleGroupView._super.initialize.call(this); 25597 if (this._model) { 25598 25599 this._model.on(guidelib.event.GuideModelEvent.VALUE_CHANGED, this.handleValueChanged, this); 25600 } 25601 }, 25602 25603 postInitialize : function () { 25604 if (this._model.value || this._model.value === "") { 25605 this._syncGuideNodeToHtml(true); 25606 } else { 25607 GuideAdModuleGroupView._super.postInitialize.call(this); 25608 } 25609 }, 25610 25611 handleValueChanged : function (event) { 25612 switch (event._property) { 25613 case "value": 25614 this.$element.html(event.newText); 25615 break; 25616 } 25617 }, 25618 25619 _syncGuideNodeToHtml : function (deepSync) { 25620 if (this._model.value || this._model.value === "") { 25621 this.$element 25622 .html(this._model.value) 25623 .find('img') 25624 .attr('src', function (idx, val) { 25625 return Granite.HTTP.externalize(val); 25626 }); 25627 } else { 25628 GuideAdModuleGroupView._super._syncGuideNodeToHtml.call(this, deepSync); 25629 } 25630 }, 25631
25632 setActive : function (activeItemToken, focus, muteScripts) { 25633 guidelib.view.GuideAdModuleGroupView._super.setActive.call(this, activeItemToken, focus, muteScripts); 25634 if (focus) { 25635 if (this.$element) { 25636 this.$element.focus(); 25637 } 25638 this._guideView.currentFocusItemSom = this._model.somExpression; 25639 } 25640 return true; 25641 } 25642 25643 }); 25644}($, guidelib)); 25645(function ($, _, guidelib) { 25646 25647 var GuidePanelView = guidelib.view.GuidePanelView = guidelib.view.GuideItemsView.extend({ 25648 initialize : function () { 25649 GuidePanelView._super.initialize.call(this); 25650 this._currentActiveItemView = null; 25651 this._$itemsContainer = null; 25652 this._$itemsNavContainer = null; 25653 this._$summary = null; 25654 this._$title = null; 25655 25656 this._childInitializeWaiting = true; 25657 25658 this._model.on(guidelib.event.GuideModelEvent.CHILD_CHANGED, this.handleChildChanged, this); 25659 this._model.on(guidelib.event.GuideModelEvent.MULTIPLE_CHILD_ADDED, this.multipleChildAdded, this); 25660 this._summarySelector = this.guideUtil.summarySelector(this._model.id); 25661 this._titleSelector = this.guideUtil.propSelector("title", this._model.id); 25662 }, 25663 25664 addRemoveTemplateMarker : function () { 25665 var featureToggle = FD.isToggleEnabled(guidelib.util.FeatureToggleConstants.FT_VALID_NAV_UL_CHILDREN) ? true : false; 25666 25667 _.each(this._model.children, function (childModel) { 25668 if (childModel instanceof guidelib.model.GuideInstanceManager) { 25669 25670 var imId = childModel.id, 25671 instanceId = (childModel._instances[0] || {}).id || childModel.instanceTemplateId, 25672 gTemplateMarkerPanel = '<div id="' + imId + 'panel" style="display: none" data-guide-template-marker="true"></div>', 25673 gTemplateMarkerNav = '<'+ (featureToggle ? 'li' : 'div') +' id="' + imId + 'nav" style="display: none" data-guide-template-marker="true"></' + (featureToggle ? 'li' : 'div') + '>', 25674 instanceItem = this.guideUtil.itemSelector(instanceId, childModel), 25675 navItem = this.guideUtil.itemNavSelector(instanceId); 25676 this.$itemsContainer.find(instanceItem).before(gTemplateMarkerPanel); 25677 this.$itemsNavContainer.find(navItem).before(gTemplateMarkerNav); 25678 if (childModel._instances && childModel._instances.length === 0) { 25679 $(navItem, this.$element).remove(); 25680 $(instanceItem, this.$element).remove(); 25681 } 25682 25683 } 25684 }, this); 25685 25686 }, 25687 25688 postInitialize : function () { 25689 25690 25691 25692 25693 this.handleSummaryChanged(); 25694 this.handleTitleChanged(); 25695 if (this._model.repeatable) { 25696 this._toggleAddRemoveButtons(); 25697 } 25698 if (!this.parentView._model.enableLayoutOptimization) { 25699 25700 this._postInitializeChildren(); 25701 } else { 25702 25703 25704 25705 25706 25707 25708 this.handleVisibleChanged(guidelib.event.GuideModelEvent.createEvent( 25709 guidelib.event.GuideModelEvent.MODEL_CHANGED, 25710 this, 25711 "visible", 25712 this._model.visible, 25713 this._model.visible 25714 )); 25715 } 25716 25717 25718 25719 25720 25721 this.addRemoveTemplateMarker(); 25722 }, 25723 25724 _postInitializeChildren : function () { 25725 this._childInitializeWaiting = false; 25726 this._syncGuideNodeToHtml(true); 25727 this.handleAccessibility(); 25728 25729 25730 25731 if (this.parentView.$itemsNavContainer && this.parentView.$itemsNavContainer.filter(":not(.tab-navigators-mobile)").length === 0) { 25732 this.setActive("firstItem", false, true); 25733 } 25734 }, 25735 25736 _syncGuideNodeToHtml : function (deepSync, currentAddedChildIndex) { 25737 if (this._childInitializeWaiting) { 25738 return; 25739 } 25740 25741 25742 25743 25744 25745 25746 25747 25748 var that = this; 25749 var htmlTemplateCache = this._guideView._domTemplateCacheStore; 25750 var oldItems = {}; 25751 var oldNonItems = {}; 25752 var newChildren = {}; 25753 25754 25755 _.each(this.childViews, function (childView) { 25756 if (childView.isItem) { 25757 oldItems[childView.id] = childView; 25758 } else { 25759 oldNonItems[childView.id] = childView; 25760 } 25761 }, this); 25762 25763 25764 25765 25766 25767 25768 25769 25770 _.each(this._model.items, function (childModel) { 25771 var cTemplateId = childModel.templateId; 25772 var childId = childModel.id, 25773 $childItem = null, 25774 $childItemNav = null; 25775 25776 25777 $childItem = this._find(this.guideUtil.itemSelector(childId, childModel)); 25778 $childItemNav = this._find(this.guideUtil.itemNavSelector(childId)); 25779 25780 25781 25782 if (!$childItem.length && !newChildren[cTemplateId] && currentAddedChildIndex !== 0) { 25783 25784 25785 $childItem = this.$itemsContainer.find(this.guideUtil.itemSelector(cTemplateId, childModel)); 25786 $childItemNav = this.$itemsNavContainer.find(this.guideUtil.itemNavSelector(cTemplateId)); 25787 } 25788 if (!$childItem.length) { 25789 25790 $childItem = htmlTemplateCache.cloneDomElement(this.guideUtil.itemSelector(cTemplateId, childModel)); 25791 $childItemNav = htmlTemplateCache.cloneDomElement(this.guideUtil.itemNavSelector(cTemplateId)); 25792 if (!$childItem.length) { 25793 this.logger().error("AF", "Html template could not be found. cTemplateId:" + cTemplateId + ", som:" + childModel.somExpression); 25794 return; 25795 } 25796 } 25797 this._updateIds($childItem, cTemplateId, childId); 25798 this._updateIds($childItemNav, cTemplateId, childId); 25799 25800 25801 $childItem.attr("data-guide-parent-id", this._model.id); 25802 $childItemNav.attr("data-guide-parent-id", this._model.id); 25803 var view = null; 25804 if (oldItems.hasOwnProperty(childId)) { 25805 view = oldItems[childId]; 25806 if (view instanceof guidelib.view.GuidePanel
25806View && view._model.instanceManager.repeatable && !_.isUndefined(that._model.bindNode)) { 25807 25808 this._fixChildDom(view); 25809 } 25810 if (deepSync) { 25811 view._syncGuideNodeToHtml(deepSync); 25812 } 25813 } else { 25814 var $childEl = this._find("#" + childId); 25815 if ($childEl.length) { 25816 view = this._createChild($childEl); 25817 } else { 25818 $childEl = $childItem.find("#" + childId).addBack("#" + childId); 25819 if ($childEl.length) { 25820 view = this._createChild($childEl, $childItem, $childItemNav); 25821 } else { 25822 this.logger().debug("AF", "Skip creating view. could not find el for id:" + childId); 25823 } 25824 } 25825 if (this._model.repeatable) { 25826 guidelib.util.GuideUtil._initializeShortDescription($childEl); 25827 } 25828 } 25829 if (view) { 25830 newChildren[childId] = view; 25831 } 25832 }, this 25833 ); 25834 25835 25836 this.$itemsContainer.find('[data-guide-parent-id="' + that._model.id + '"]').each(function () { 25837 var $this = $(this); 25838 var thisId = $this.attr("id"); 25839 25840 if (thisId.indexOf(that.guideUtil.GUIDE_ITEM_SUFFIX) === -1) { 25841 thisId = $this.attr(that.guideUtil.DATA_GUIDE_ITEM); 25842 } 25843 var childId = thisId.substring(0, thisId.length - that.guideUtil.GUIDE_ITEM_SUFFIX.length); 25844 if (!newChildren.hasOwnProperty(childId) && !window.guideBridge._resolveId(childId)) { 25845 that.logger().log("guideView", 5, "removing element as no corresponding form dom node found. id:" + thisId + ", parent id:" + that.id); 25846 $this.remove(); 25847 that._find(that.guideUtil.itemNavSelector(childId)).remove(); 25848 } 25849 }); 25850 25851 this.childViews = []; 25852 _.each(this._model.children, function (childModel) { 25853 var childIsItem = childModel._isItem; 25854 var childId = childModel.id; 25855 if (childIsItem && newChildren.hasOwnProperty(childId)) { 25856 25857 this.childViews.push(newChildren[childId]); 25858 } else if (!childIsItem) { 25859 var nonItemChildView = null; 25860 if (oldNonItems.hasOwnProperty(childId)) { 25861 nonItemChildView = oldNonItems[childId]; 25862 } else { 25863 nonItemChildView = this._createNonRepeatChildView(childModel); 25864 } 25865 if (nonItemChildView) { 25866 if (deepSync) { 25867 nonItemChildView._syncGuideNodeToHtml(deepSync); 25868 } 25869 this.childViews.push(nonItemChildView); 25870 } 25871 } 25872 }, this); 25873 25874 guidelib.view.GuideBaseView.prototype._syncGuideNodeToHtml.apply(this, arguments); 25875 }, 25876 25877 _createChild : function ($childEl, $item, $itemNav) { 25878 var view = guidelib.view.GuideViewRegistry.prototype.createView($childEl, this); 25879 this._fixChildDom(view, $item, $itemNav); 25880 view.postInitialize(); 25881 return view; 25882 }, 25883 25884 _fixChildDom : function (view, $item, $itemNav) { 25885 25886 25887 25888 var newChild = view._model; 25889 if (!(newChild instanceof guidelib.model.GuidePanel) || !newChild.repeatable) { 25890 return; 25891 } 25892 var $childItem = $item || view.$item; 25893 var $childItemNav = $itemNav || view.$itemNav; 25894 var children = this._model.children; 25895 var insertAfterId = (newChild.instanceIndex > 0) ? children[children.indexOf(newChild) - 1].id : null; 25896 25897 var insertAfterItemSelector = insertAfterId ? this.guideUtil.itemSelector(insertAfterId, newChild) : "#" + newChild.instanceManager.id; 25898 var insertAfterNavSelector = insertAfterId ? this.guideUtil.itemNavSelector(insertAfterId) : "#" + newChild.instanceManager.id; 25899 var that = this; 25900 25901 25902 this.$itemsContainer.each(function (index) { 25903 var insertEl = $childItem.get(index) || $childItem.get(0), 25904 $insertAfterItem = $(this).find(insertAfterItemSelector); 25905 25906 if ($insertAfterItem.length == 0) { 25907 insertAfterItemSelector = "[data-guide-template-marker=" + newChild.instanceManager.id + "]"; 25908 $insertAfterItem = $(this).find(insertAfterItemSelector); 25909 25910 if(newChild.instanceIndex === 0 && $insertAfterItem.length > 0) { 25911 $insertAfterItem.removeAttr("data-guide-template-marker"); 25912 $(insertEl).attr("data-guide-template-marker", newChild.instanceManager.id); 25913 } 25914 } 25915 25916 if ($insertAfterItem.get(0) !== insertEl) { 25917 25918 $insertAfterItem.after($(insertEl)); 25919 } 25920 }); 25921 25922 25923 25924 this.$itemsNavContainer.each(function (index) { 25925 var insertNavEl = $childItemNav.get(index) || $childItemNav.get(0); 25926 $(this).find(insertAfterNavSelector).after($(insertNavEl)); 25927 }); 25928 }, 25929 25930 multipleChildAdded : function (event) { 25931 if (event.jsonModel.newText && event.jsonModel.newText.length > 0) { 25932 this._syncGuideNodeToHtml(true); 25933 this.childViews.forEach(function (childView) { 25934 if (childView._model.repeatable) { 25935 childView._toggleAddRemoveButtons(); 25936 } 25937 }); 25938 } 25939 }, 25940
25941 handleChildChanged : function (event) { 25942 var newlyCreatedInstance = null, 25943 currentAddedInstanceIndex = -1; 25944 if (event._property == "childRemoved") { 25945 var $elementRemoved = this.$element.find("#" + event.prevText.id), 25946 index = $elementRemoved.index(); 25947 } 25948 if (event._property == "childAdded") { 25949 newlyCreatedInstance = event.newText; 25950 currentAddedInstanceIndex = newlyCreatedInstance.instanceIndex; 25951 } 25952 25953 this._syncGuideNodeToHtml(true, currentAddedInstanceIndex); 25954 this.childViews.forEach(function (childView) { 25955 if (childView._model.repeatable) { 25956 childView._toggleAddRemoveButtons(); 25957 } 25958 }); 25959 if (event._property == "childRemoved") { 25960 25961 25962 this.$element.trigger("panelRemoved.af", [$elementRemoved, index]); 25963 if (this.currentActiveItemView && event.prevText == this.currentActiveItemView._model) { 25964 25965 this._currentActiveItemView = null; 25966 this.setActive("nextItem"); 25967 } 25968 } 25969 if (newlyCreatedInstance != null) { 25970 25971 25972 this.$element.trigger("panelAdded.af", [this.$element.find("#" + newlyCreatedInstance.id)]); 25973 } 25974 }, 25975 25976 handleSummaryChanged : function () { 25977 if (this.$summary.length > 0) { 25978 if (this._model.summary) { 25979 this.$summary.text(this._model.summary); 25980 } else { 25981 var title = this._model.title; 25982 if (this._model.instanceIndex && this._model.repeatable) { 25983 title += " " + this._model.instanceIndex; 25984 } 25985 this.$summary.text(title); 25986 } 25987 } 25988 }, 25989 25990 handleTitleChanged : function () { 25991 if (this.$title.length > 0) { 25992 this.$title.text(this._model.title); 25993 } 25994 25995 var isPanelActive = $("#" + this.id + "_guide-item").hasClass("active"); 25996 if (isPanelActive) { 25997 $("[data-target-guide-content]").text(this._model.title); 25998 } 25999 }, 26000 26001 handleModelChanged : function (event) { 26002 switch (event._property) { 26003 case "summary": 26004 this.handleSummaryChanged(); 26005 break; 26006 case "title": 26007 this.handleTitleChanged(); 26008 break; 26009 default: 26010 GuidePanelView._super.handleModelChanged.apply(this, arguments); 26011 } 26012 }, 26013 26014 _createReferredView : function () { 26015 26016 this._postInitializeChildren(); 26017 }, 26018 26019 _loadLazyFragment : function () { 26020 26021 26022 26023 26024 26025 26026 var that = this; 26027 this._model._guide().internal.liveDataUtils.updateLiveData(); 26028 26029 this._guideView._clearInactiveLazyViews(this); 26030 26031 this._viewCreationInProgress = true; 26032 26033 this._model._loadLazyFragment({ 26034 "preFetch" : function () { 26035 $("#loadingPage").addClass("guideLoading"); 26036 }, 26037 "postFetch" : function () { 26038 $("#loadingPage").removeClass("guideLoading"); 26039 }, 26040 "success" : function () { 26041 26042 that._createReferredView(); 26043 26044 26045 that._viewCreationInProgress = undefined; 26046 that._itemsLoaded = true; 26047 } 26048 }); 26049 26050 26051 }, 26052 26053 26054 setActive : function (activeItemToken, focus, muteScripts) { 26055 26056 26057 26058 if (this._model._lazyReference) { 26059 26060 26061 26062 26063 26064 if (_.isUndefined(this._viewCreationInProgress) && _.isUndefined(this._itemsLoaded) 26065 && this._guideView._currentActiveItemView !== this) { 26066 this._loadLazyFragment(); 26067 } 26068 } 26069 26070 var currentActiveItemQName = this.getOrElse(this.currentActiveItemView, "qualifiedName", null); 26071 26072 activeItemToken = activeItemToken || currentActiveItemQName || "firstItem"; 26073 if (activeItemToken != currentActiveItemQName) { 26074 var newActiveItemModel = this._model.navigationContext.getItemForNav(activeItemToken); 26075 if (!newActiveItemModel) { 26076 this.logger().log("AF", "activeItemToken not found:" + activeItemToken + ",currentActiveItem:" + 26077 currentActiveItemQName + ":" + this._model.somExpression); 26078 return false;
26079 } 26080 var newActiveItemView = this.getQualifiedNamedView(newActiveItemModel._escapeQualifiedName()); 26081 if (!muteScripts && this._model.completionExpReq && this.currentActiveItemView && this.currentActiveItemView.focusable() && (this.childViews.indexOf(newActiveItemView) > this.childViews.indexOf(this.currentActiveItemView))) { 26082 var completed = true; 26083 if (this._model.getAttribute("validateOnStepCompletion")) { 26084 completed = window.guideBridge.validate([], this._model.panel.navigationContext.currentItem.somExpression); 26085 } 26086 26087 completed = completed && this._model.executeExpression("completionExp"); 26088 if (!completed) { 26089 return false; 26090 } else if (this.currentActiveItemView) { 26091 this.currentActiveItemView.$item.addClass("completed"); 26092 this.currentActiveItemView.$itemNav.addClass("completed"); 26093 } 26094 } 26095 this.currentActiveItemView = newActiveItemView; 26096 26097 26098 26099 26100 26101 } 26102 if (this.currentActiveItemView) {
26103 this.currentActiveItemView.setActive(null, focus, muteScripts); 26104 } 26105 return true; 26106 }, 26107 26108 _clearInactiveLazyViews : function (that) { 26109 _.each(this.childViews, function (item) { 26110 if (item && item._model.className === "guidePanel" && item._ancestorHasNavigableLayout) { 26111 if (item._model._itemsLoaded && !that._isSelfOrAncestor(item) && !item._hasEffectiveActiveClass() 26112 && item._model._lazyReference) { 26113 item._model._unloadLazyReferenceModel(); 26114 item._unloadView(); 26115 26116 item._itemsLoaded = undefined; 26117 26118 item._model._itemsLoaded = undefined; 26119 } else { 26120 item._clearInactiveLazyViews(that); 26121 } 26122 } 26123 }, this); 26124 }, 26125 26126 _isSelfOrAncestor : function (panelView) { 26127 26128 var selfOrParentView = this; 26129 while (!_.isUndefined(selfOrParentView) && selfOrParentView._model.className !== "rootPanelNode") { 26130 if (panelView === selfOrParentView) { 26131 return true; 26132 } 26133 selfOrParentView = selfOrParentView.parentView; 26134 } 26135 return false; 26136 }, 26137 26138 _hasEffectiveActiveClass : function () { 26139 var hierarchy = this; 26140 while (!_.isUndefined(hierarchy) && this._model.className !== "rootPanelNode") { 26141 if (hierarchy.$item.hasClass("active")) { 26142 hierarchy = hierarchy.parentView; 26143 } else { 26144 return false; 26145 } 26146 } 26147 return true; 26148 }, 26149 26150 handleAccessibility : function () { 26151 var role, screenReaderText; 26152 screenReaderText = this._model._getScreenReaderText(); 26153 role = this._model._getRole(); 26154 if (screenReaderText) { 26155 this.$itemNav.attr("aria-label", screenReaderText); 26156 } 26157 this.$itemNav.find('a').attr("tabindex", function (index, currentValue) { 26158 return (currentValue == -1 ? currentValue : 0); 26159 }); 26160 }, 26161 26162 getQualifiedNamedView : function (qName) { 26163 var view = _.find(this.childViews, function (childView) { 26164 return (childView._model._escapeQualifiedName() == qName); 26165 }, this); 26166 return view; 26167 }, 26168 26169 _toggleAddRemoveButtons : function () { 26170 var panelModel = this._model, 26171 instanceManager = panelModel.instanceManager; 26172 $('[data-guide-id="' + panelModel.id + '"][data-guide-addremove="remove"]').toggleClass("hidden", instanceManager.instanceCount == instanceManager.minOccur); 26173 $('[data-guide-id="' + panelModel.id + '"][data-guide-addremove="add"]').toggleClass("hidden", instanceManager.instanceCount == instanceManager.maxOccur); 26174 } 26175 }); 26176 26177 GuidePanelView.defineProps({ 26178 hasNavigableLayout : { 26179 get : function () { 26180 return this.$itemsNavContainer.length > 0; 26181 } 26182 }, 26183 $itemsContainer : { 26184 get : function () { 26185 26186 if (this._model._selfOrAncestorIsLazyReference || !this._$itemsContainer || this._$itemsContainer.length === 0) { 26187 this._$itemsContainer = this._find(this.guideUtil.itemContainerSelector(this._model.id)); 26188 26189 if (this._$itemsContainer.length === 0) { 26190 this._$itemsContainer = this._find(this.guideUtil.alternateItemContainerSelector(this._model.id)); 26191 } 26192 } 26193 return this._$itemsContainer; 26194 } 26195 }, 26196 $itemsNavContainer : { 26197 get : function () { 26198 if (this._model._selfOrAncestorIsLazyReference || !this._$itemsNavContainer || this._$itemsNavContainer.length === 0) { 26199 this._$itemsNavContainer = this._find(this.guideUtil.itemNavContainerSelector(this._model.id)); 26200 } 26201 return this._$itemsNavContainer; 26202 } 26203 }, 26204 $summary : { 26205 get : function () { 26206 if (!this._$summary) { 26207 this._$summary = this._find(this._summarySelector); 26208 } 26209 return this._$summary; 26210 } 26211 }, 26212 $title : { 26213 get : function () { 26214 if (!this._$title) { 26215 this._$title = this._find(this._titleSelector); 26216 } 26217 return this._$title; 26218 } 26219 }, 26220 currentActiveItemView : { 26221 get : function () { 26222 return this._currentActiveItemView; 26223 }, 26224 set : function (value) { 26225 if (value != this._currentActiveItemView) { 26226 if (this._currentActiveItemView) { 26227 26228 this._currentActiveItemView._model.viewVisited = true; 26229 } 26230 if (!value) { 26231 var itemModel = this._model.navigationContext.firstItem; 26232 if (itemModel) { 26233 value = this.getQualifiedNamedView(itemModel._escapeQualifiedName()); 26234 } 26235 } 26236 this._currentActiveItemView = value; 26237 26238 this._model.navigationContext.currentItem = (this._currentActiveItemView || {})._model; 26239 _.each(this.childViews, function (childView) { 26240 if (childView == this._currentActiveItemView) { 26241 childView.$item.addClass("active"); 26242 childView.$itemNav.addClass("active"); 26243 childView.$itemNav.attr("aria-selected", true); 26244 childView.$itemNav.attr("aria-disabled", false); 26245 childView.$itemNav.removeClass("wizard-tab-disabled"); 26246 } else { 26247 childView.$item.removeClass("active"); 26248 childView.$itemNav.removeClass("active"); 26249 childView.$itemNav.attr("aria-selected", false); 26250 } 26251 }, this); 26252 26253 26254 26255 26256 if (this._currentActiveItemView instanceof guidelib.view.GuidePanel
26256View && this._currentActiveItemView._childInitializeWaiting) { 26257 this._currentActiveItemView._postInitializeChildren(); 26258 } 26259 26260 if (true && _.isUndefined(this._model._ajaxCallDone)) { 26261 26262 26263 var model = this._model; 26264 26265 while (model && !(model instanceof guidelib.model.RootPanelNode)) { 26266 if (model.toolbar) { 26267 model.toolbar.execNavigationChangeExpression(); 26268 } 26269 model = model.parent; 26270 } 26271 26272 if (model && model.toolbar && model instanceof guidelib.model.RootPanelNode) { 26273 model.toolbar.execNavigationChangeExpression(); 26274 } 26275 } 26276 } 26277 } 26278 }, 26279 26280 _ancestorHasNavigableLayout : { 26281 get : function () { 26282 var parentView = this.parentView; 26283 while (parentView) { 26284 if (parentView.$itemsNavContainer && parentView.$itemsNavContainer.length > 0) { 26285 return true; 26286 } 26287 parentView = parentView.parentView; 26288 } 26289 return false; 26290 } 26291 } 26292 }); 26293}($, _, guidelib)); 26294(function ($, _, guidelib) { 26295 26296 var cloneCounter = 0; 26297 26298 var tableMobileLayoutConstants = { 26299 COLLAPSIBLE_COLUMNS : "collapsibleColumns", 26300 HEADERS_LEFT : "headersLeft", 26301 COLLAPSIBLE_COLUMNS_CONTROL_ROW_SELECTOR : "tr.child", 26302 RUNTIME_TABLE_CONTROL : "guideTableRuntimeControls", 26303 RUNTIME_TABLE_RIGHT_CONTROL : "guideTableRuntimeRightControls", 26304 RUNTIME_TABLE_LEFT_CONTROL : "guideTableRuntimeLeftControls", 26305 RUNTIME_TABLE_ADD_CONTROL : "guideTableRuntimeAddControl", 26306 RUNTIME_TABLE_DELETE_CONTROL : "guideTableRuntimeDeleteControl", 26307 RUNTIME_TABLE_EDIT_CONTROL : "guideTableRuntimeEditControl" 26308 }; 26309 26310 var tableSortingComponents = { 26311 GUIDE_INSTANCE_MANAGER : "guideInstanceManager", 26312 WEB_CHANNEL_HEADER_COMPONENT : "fd/ccm/web-channel/components/tableHeader/v1/tableHeader", 26313 AF_TABLE_HEADER_COMPONENT : "fd/af/components/tableHeader", 26314 SORTING_ENABLED : "sortingEnabled" 26315 }; 26316 26317 var GuideTableView = guidelib.view.GuideTableView = guidelib.view.GuidePanelView.extend({ 26318 26319 26320 TABLE_WIDTH_BUFFER : 23, 26321 26322 _getPluginOptions : function () { 26323 var defaultOptions = { 26324 "bAutoWidth" : this.bAutoWidth 26325 }, columnWidthArray = null, 26326 sum = 0, 26327 sWidthArray = null, 26328 numOfTableCol = this.$tableElement.find("th").length; 26329 26330 if (this.bAutoWidth === false) { 26331 columnWidthArray = this._model.columnWidth.split(","); 26332 if (columnWidthArray.length === numOfTableCol) { 26333 26334 _.each(columnWidthArray, function (item) { 26335 sum += parseInt(item, 10); 26336 }); 26337 26338 sWidthArray = _.map(columnWidthArray, function (item) { 26339 return { 26340 "pWidth" : Math.floor((item * 100) / sum) 26341 }; 26342 }); 26343 } 26344 26345 defaultOptions = _.extend({}, defaultOptions, { 26346 aWidthPercentage : sWidthArray, 26347 aWidth : columnWidthArray 26348 }); 26349 } 26350 return defaultOptions; 26351 26352 }, 26353 26354 26355 setAutoWidth : function () { 26356 if (this._model.columnWidth && this._model.columnWidth.length > 0) { 26357 this.bAutoWidth = false; 26358 } else { 26359 this.bAutoWidth = true; 26360 } 26361 }, 26362 26363 26364 createView : function (id) { 26365 var $htmlTemplate = this._guideView._domTemplateCacheStore.cloneDomElement("#" + id), 26366 formElemSelector = "#" + id + "_widget", 26367 counter = ++cloneCounter; 26368 if ($htmlTemplate.length == 0) { 26369 26370 $htmlTemplate = this.$element.find("#" + id).clone(); 26371 } 26372 26373 $htmlTemplate.find(formElemSelector).attr("id", id + "_widget" + counter); 26374 26375 var view = guidelib.view.GuideViewRegistry.prototype.createView($htmlTemplate, this); 26376 view.postInitialize(); 26377 return $htmlTemplate; 26378 }, 26379 26380 initializeTableColumnWidth : function (pluginOptions) { 26381 26382 if (this.bAutoWidth == false && this._model.mobileLayout === tableMobileLayoutConstants.HEADERS_LEFT) { 26383 26384 26385 this.$tableElement.css("table-layout", "fixed"); 26386 var widthArray = pluginOptions["aWidthPercentage"], 26387 numOfTableCol = this.$tableElement.find("th").length; 26388 if (widthArray && widthArray.length == numOfTableCol) { 26389 26390 this.$tableElement.find("th").each(function (index) { 26391 $(this).width(widthArray[index]["pWidth"] + "%"); 26392 }); 26393 } 26394 } 26395 }, 26396 26397 _checkIfTableSortingEnabled : function () { 26398 var jsonModel = this._model.jsonModel; 26399 return (jsonModel[tableSortingComponents.SORTING_ENABLED] === "true"); 26400 }, 26401 26402
26403 handleParentVisibleChanged : function (event) { 26404 switch (event._property) { 26405 case "visible": 26406 this.handleTableShown(); 26407 break; 26408 } 26409 }, 26410 26411 26412 _checkParentModelChanged : function() { 26413 var currentParent = this.parentView; 26414 while(currentParent != null) { 26415 currentParent._model.on(guidelib.event.GuideModelEvent.MODEL_CHANGED, this.handleParentVisibleChanged, this); 26416 currentParent = currentParent.parentView; 26417 } 26418 }, 26419 26420 26421 initialize : function () { 26422 GuideTableView._super.initialize.apply(this, arguments); 26423 26424 this._checkParentModelChanged(); 26425 26426 this.$tableElement = this.$element.find("> table"); 26427 26428 this.setAutoWidth(); 26429 26430 var widgetOptions = this._getPluginOptions(), 26431 that = this; 26432 26433 this.initializeTableColumnWidth(widgetOptions); 26434 this._fixTableControls(true); 26435 if (this._model.mobileLayout === tableMobileLayoutConstants.COLLAPSIBLE_COLUMNS) { 26436 widgetOptions = _.extend({}, widgetOptions, { 26437 26438 bControlRowHiddenCells : false, 26439 26440 26441 bDisableControlRowCells : true, 26442 26443 viewCallback : $.proxy(this.createView, this), 26444 26445 tableRuntimeEditControlClass : tableMobileLayoutConstants.RUNTIME_TABLE_EDIT_CONTROL, 26446 26447 fixTableControls : $.proxy(this._fixTableControls, this) 26448 }); 26449 26450 this.jqwidget = this.$tableElement.responsiveTablePlugin(widgetOptions).data("responsiveTablePlugin"); 26451 } else { 26452 26453 $(window).on("resize orientationchange", function (event) { 26454 that._fixTableControls(event); 26455 }); 26456 } 26457 26458 if (this._checkIfTableSortingEnabled()) { 26459 this.$tableElement.tableSorting = this.guideTableSorter.initialize; 26460 this.$tableElement.tableSorting({ 26461 model : this._model, 26462 tableContext : this 26463 }); 26464 } 26465 }, 26466 26467 handleVisibleChanged : function (event) { 26468 GuideTableView._super.handleVisibleChanged.apply(this, arguments); 26469 26470 this.handleTableShown(); 26471 this._resetTableCellWidth(); 26472 }, 26473 26474 handleTableShown : function () { 26475 if (this._model.mobileLayout === tableMobileLayoutConstants.COLLAPSIBLE_COLUMNS) { 26476 26477 this.jqwidget._initializeColumnVisibility(); 26478 26479 if (this.jqwidget.isColumnHidden()) { 26480 26481 this.$tableElement.find(".guideFieldNode").addClass("dontSyncEnabled"); 26482 26483 this.$tableElement.find("input, select, textarea, button").attr("disabled", "disabled"); 26484 } 26485 } 26486 }, 26487 26488 _resetTableCellWidth : function () { 26489 var that = this, 26490 tableWidthBuffer = this.TABLE_WIDTH_BUFFER; 26491 26492 this.$tableElement.find("." + tableMobileLayoutConstants.RUNTIME_TABLE_CONTROL).each(function () { 26493 var element = this; 26494 setTimeout(function () { 26495 that._resetTableCell($(element), tableWidthBuffer); 26496 }, 1); 26497 }); 26498 }, 26499 26500 _resetTableCell : function ($element, tableWidthBuffer) { 26501 var componentWidth; 26502 26503 if ($element.hasClass(tableMobileLayoutConstants.RUNTIME_TABLE_RIGHT_CONTROL)) { 26504 var $component = $element.prev(), 26505 $td = $element.parent(); 26506 26507 26508 if ($element.is(":visible")) { 26509 26510 $component.css("display", "inline-block"); 26511 $component.css("float", "left"); 26512 componentWidth = $td.width() - $element.outerWidth() - tableWidthBuffer; 26513 var percentage = ((componentWidth / $td.width()) * 100); 26514 26515 26516 $component.width(percentage + "%"); 26517 } else { 26518 26519 26520 $component.css("display", "block"); 26521 $component.css("float", "none"); 26522 $component.width($td.width()); 26523 } 26524 } else if ($element.hasClass(tableMobileLayoutConstants.RUNTIME_TABLE_LEFT_CONTROL)) { 26525 26526 if ($element.is(":visible")) { 26527 $element.next().css("display", "inline-block"); 26528 componentWidth = $element.parent().width() - $element.outerWidth() - tableWidthBuffer; 26529 var percentage = ((componentWidth / $element.parent().width()) * 100); 26530 $element.next().width(percentage + "%"); 26531 } else { 26532 26533 $element.next().css("display", "block"); 26534 } 26535 } 26536 }, 26537 26538 _fixTableControls : function (event) { 26539 26540 26541 26542 if ((this._model.mobileLayout === tableMobileLayoutConstants.COLLAPSIBLE_COLUMNS) && (this.jqwidget)) { 26543 26544 if (this.jqwidget.isColumnHidden()) { 26545 26546 this.$tableElement.find("tr:not(.child)").find(".guideFieldNode").addClass("dontSyncEnabled"); 26547 26548 this.$tableElement.find("tr:not(.child)").find("input, select, textarea, button").attr("disabled", "disabled"); 26549 } else { 26550 26551 this.$tableElement.find(".guideFieldNode").removeClass("dontSyncEnabled"); 26552 26553 this.$tableElement.find("input, select, textarea, button").removeAttr("disabled"); 26554 } 26555 } 26556 26557 26558 if (event) { 26559 this._resetTableCellWidth(); 26560 } 26561 }, 26562 26563 26564 _fixChildDom : function (view, $item, $itemNav) { 26565 GuideTableView._super._fixChildDom.apply(this, arguments); 26566 26567 26568 if (this._model.mobileLayout === tableMobileLayoutConstants.COLLAPSIBLE_COLUMNS) { 26569 26570 this.jqwidget._fixControlRows(); 26571 } 26572 26573 this._fixTableControls(); 26574 26575 this._resetTableCellWidth(); 26576 }, 26577 26578 _postInitializeChildren : function () { 26579 26580 GuideTableView._super._postInitializeChildren.call(this); 26581 26582 26583 26584 26585 26586 if (this._model.mobileLayout === tableMobileLayoutConstants.COLLAPSIBLE_COLUMNS) { 26587 26588 this.handleTableShown(); 26589 } 26590 26591 26592 else if (this._model.mobileLayout === tableMobileLayoutConstants.HEADERS_LEFT) { 26593 this._fixTableCellForHeaderLeftLayout(); 26594 } 26595 this._resetTableCellWidth(); 26596 }, 26597 26598 _fixTableCellForHeaderLeftLayout : function () { 26599 var that = this, 26600 guideUtil = guidelib.util.GuideUtil; 26601 this.$tableElement.find("tr td").each(function () { 26602 guideUtil._setGuideDataHeader($(this), that.$tableElement); 26603 }); 26604 }, 26605 26606
26607 handleChildChanged : function (event) { 26608 GuideTableView._super.handleChildChanged.apply(this, arguments); 26609 26610 26611 if (this._model.mobileLayout === tableMobileLayoutConstants.HEADERS_LEFT) { 26612 this._fixTableCellForHeaderLeftLayout(); 26613 } 26614 if (event._property == "childAdded") { 26615 this._resetTableCellWidth(); 26616 } 26617 }, 26618 26619 addRemoveTemplateMarker : function () { 26620 26621 _.each(this._model.children, function (childModel) { 26622 if (childModel instanceof guidelib.model.GuideInstanceManager) { 26623 26624 var imId = childModel.id, 26625 instanceId = (childModel._instances[0] || {}).id || childModel.instanceTemplateId, 26626 gTemplateMarker = null, 26627 26628 instanceItem = this.guideUtil.itemSelector(instanceId, childModel._instances[0]), 26629 navItem = this.guideUtil.itemNavSelector(instanceId), 26630 $instanceItem = this.$itemsContainer.find(instanceItem); 26631 if ($instanceItem.is("tr")) { 26632 $instanceItem.attr("data-guide-template-marker", imId); 26633 } 26634 26635 26636 26637 26638 26639 } 26640 }, this); 26641 }, 26642 26643 tableSortComparator : { 26644 DATE : function (tableModelDataRows, sortList, tableContext) { 26645 return tableModelDataRows.sort(function (a, b) { 26646 var currColumn = sortList[0][0], currOrder = sortList[0][1], 26647 guideTableSorter = tableContext.guideTableSorter, 26648 value_a = guideTableSorter.formatDateValue(guideTableSorter.getValueFromJsonModel(a, currColumn)), 26649 value_b = guideTableSorter.formatDateValue(guideTableSorter.getValueFromJsonModel(b, currColumn)); 26650 return guideTableSorter.ComparedOrder(value_a, value_b, currOrder); 26651 }); 26652 }, 26653 NUMBER : function (tableModelDataRows, sortList, tableContext) { 26654 return tableModelDataRows.sort(function (a, b) { 26655 var currColumn = sortList[0][0], currOrder = sortList[0][1], 26656 guideTableSorter = tableContext.guideTableSorter, 26657 value_a = guideTableSorter.formatRegexFloatData(guideTableSorter.getValueFromJsonModel(a, currColumn)), 26658 value_b = guideTableSorter.formatRegexFloatData(guideTableSorter.getValueFromJsonModel(b, currColumn)); 26659 return guideTableSorter.ComparedOrder(value_a, value_b, currOrder); 26660 }); 26661 26662 }, 26663 STRING : function (tableModelDataRows, sortList, tableContext) { 26664 return tableModelDataRows.sort(function (a, b) { 26665 var currColumn = sortList[0][0], currOrder = sortList[0][1], 26666 guideTableSorter = tableContext.guideTableSorter, 26667 value_a = guideTableSorter.formatRichTextString(guideTableSorter.getValueFromJsonModel(a, currColumn, true)), 26668 value_b = guideTableSorter.formatRichTextString(guideTableSorter.getValueFromJsonModel(b, currColumn, true)); 26669 return guideTableSorter.ComparedOrder(value_a, value_b, currOrder); 26670 }); 26671 } 26672 }, 26673 26674 26675 guideTableSorter : new function () { 26676 this.initialize = function (tableSortingConfig) { 26677 return this.each(function () { 26678 this.tableConfig = {}; 26679 var defaultSortingConfig = {sortList : [], selectorsHeaders : 'thead th', 26680 headerCss : {asc : "asc", desc : "desc", random : "random"} 26681 }; 26682 if (!this.tHead || !this.tBodies) {return;} 26683 var table = $(this), tableConfig = {}; 26684 tableConfig = $.extend(this.tableConfig, defaultSortingConfig, tableSortingConfig); 26685 var tableHeaderModel, tableModel = tableConfig.model; 26686 for (var index = 0 ; index < tableModel.children.length ; index++) { 26687 if (isTableHeaderRow(tableModel.children[index])) { 26688 tableHeaderModel = tableModel.children[index]; 26689 tableConfig.tableHeader = tableHeaderModel; 26690 break; 26691 } 26692 } 26693 var $tableHeaders = filterSortableHeaders(tableConfig, this); 26694 $tableHeaders.click(function () { 26695 if (this.sortingAllowed) { 26696 sortCurrentColumn(this, table, tableConfig, $tableHeaders); 26697 } 26698 }); 26699 26700 $tableHeaders.each(function (index) { 26701 if (this.sortingAllowed) {
26702 sortOnFirstColumn(this, tableModel); 26703 return false; 26704 } 26705 }); 26706 }); 26707 }; 26708 26709 26710 function sortOnFirstColumn(firstColumn, tableModel) { 26711 if (typeof tableModel._guide !== "undefined" && tableModel._guide()) { 26712 var isSubmittedData = guidelib.util.GuideUtil._fetchJSONNodeValue(tableModel._guide().runtime.guideContext.guidePrefillJson, "afSubmissionInfo"); 26713 isSubmittedData = isSubmittedData || guidelib.util.GuideUtil.fetchXMLNodeValue(tableModel._guide().runtime.guideContext.guidePrefillXml, "afSubmissionInfo"); 26714 if (!isSubmittedData) { 26715 $(firstColumn).trigger("click"); 26716 } 26717 } 26718 } 26719 26720 26721 function filterSortableHeaders(tableConfig, tableDom) { 26722 var $tableHeaders = $(tableConfig.selectorsHeaders, tableDom).each(function (index) { 26723 this.column = index; 26724 this.order = 1; 26725 }); 26726 for (var column = 0 ; column < tableConfig.tableHeader.children.length ; column++) { 26727 var currColumnModel = tableConfig.tableHeader.children[column]; 26728 $tableHeaders[column].sortingAllowed = true; 26729 var sortDataType = currColumnModel.jsonModel["sortingDataType"]; 26730 sortDataType = !sortDataType ? "STRING" : sortDataType; 26731 currColumnModel.jsonModel.sortingDataType = sortDataType; 26732 if (!tableConfig.tableHeader.visible || sortDataType === "noSort") { 26733 $tableHeaders[column].sortingAllowed = false; 26734 $($tableHeaders[column]).removeClass("sortEnabled"); 26735 var $sortingButton = $($tableHeaders[column]).find(".sortingButton").remove(); 26736 } 26737 } 26738 return $tableHeaders; 26739 } 26740 26741 26742 function sortCurrentColumn(currentHeader, table, tableConfig, $tableHeaders) { 26743 var tableRows = (table[0].tBodies[0] && table[0].tBodies[0].rows.length) || 0; 26744 if (tableRows > 0) { 26745 currentHeader.order = (++(currentHeader.order) % 2); 26746 tableConfig.sortList = []; 26747 tableConfig.sortList.push([currentHeader.column, currentHeader.order]); 26748 setTimeout(function () { 26749 updateTableHeaderStyles($tableHeaders, tableConfig.sortList, tableConfig); 26750 sortGuideTableDataModel(tableConfig, tableConfig.sortList, tableConfig.model); 26751 }, 1); 26752 } 26753 } 26754 26755 26756 function updateTableHeaderStyles($headers, sortingList, tableConfig) { 26757 var order, headerCSS = [tableConfig.headerCss.asc, tableConfig.headerCss.desc, tableConfig.headerCss.random]; 26758 $headers.each(function (index) { 26759 var $sortingButton = $(this).find(".sortingButton"); 26760 $sortingButton.removeClass(headerCSS[0]).removeClass(headerCSS[1]).removeClass(headerCSS[2]); 26761 if ($headers[index].sortingAllowed) { 26762 if (index === sortingList[0][0]) { 26763 order = sortingList[0][1]; 26764 $sortingButton.addClass(headerCSS[order]); 26765 } else { 26766 $sortingButton.addClass(tableConfig.headerCss.random); 26767 } 26768 } 26769 }); 26770 } 26771 26772 26773 function sortGuideTableDataModel(tableConfig, sortList, tableModel) { 26774 var i,j = 0,tableModelChildren = tableModel.children, tableDataRows = [], prevTableModel = tableModel, 26775 modifiedGuideTableModel = [], tableContext = tableConfig.tableContext; 26776 26777 for (i = 0; i < tableModelChildren.length; i++) { 26778 if (tableModelChildren[i].className !== tableSortingComponents.GUIDE_INSTANCE_MANAGER) { 26779 if (isTableRowsWithData(tableModelChildren[i])) { 26780 tableDataRows.push(tableModelChildren[i]); 26781 } 26782 } 26783 } 26784 var dataType = tableConfig.tableHeader.children[[sortList[0][0]]].jsonModel.sortingDataType; 26785 tableDataRows = tableContext.tableSortComparator[dataType].call(tableConfig, tableDataRows, sortList, tableContext); 26786 for (i = 0; i < tableModel.children.length; i++) { 26787 if (isTableRowsWithData(tableModel.children[i])) { 26788 modifiedGuideTableModel.push(tableDataRows[j]); 26789 j++; 26790 } else { 26791 modifiedGuideTableModel.push(tableModel.children[i]); 26792 } 26793 } 26794 tableModel.children = modifiedGuideTableModel; 26795 tableModel._triggerEvent(guidelib.event.GuideModelEvent.MODEL_CHANGED, "tableModelSorted", prevTableModel, tableModel); 26796 syncNewModelToHTML(tableConfig.tableContext, tableModel); 26797 } 26798 26799 26800 function isTableRowsWithData(tableModelChildElement) { 26801 var resourceType = tableModelChildElement.options.jsonModel["sling:resourceType"], 26802 childElementClassName = tableModelChildElement.className; 26803 return !((childElementClassName === tableSortingComponents.GUIDE_INSTANCE_MANAGER) || (resourceType === tableSortingComponents.AF_TABLE_HEADER_COMPONENT) || (resourceType === tableSortingComponents.WEB_CHANNEL_HEADER_COMPONENT)); 26804 } 26805 26806 function isTableHeaderRow(tableModelChildElement) { 26807 var resourceType = tableModelChildElement.options.jsonModel["sling:resourceType"]; 26808 return ((resourceType === tableSortingComponents.AF_TABLE_HEADER_COMPONENT) || (resourceType === tableSortingComponents.WEB_CHANNEL_HEADER_COMPONENT)); 26809 } 26810 26811 this.formatRegexFloatData = function (data) { 26812 return (isNaN(parseFloat(data))) ? 0 : parseFloat(data); 26813 }; 26814 26815 this.formatDateValue = function (data) { 26816 return (isNaN(new Date(data).getTime())) ? 0 : new Date(data).getTime(); 26817 }; 26818 26819 this.formatRichTextString = function (data) { 26820 data = "<div>" + data + "</div>"; 26821 return $(data).text().trim(); 26822 }; 26823 26824 this.ComparedOrder = function (value_a, value_b, currOrder) { 26825 if (value_a > value_b) { 26826 return (currOrder === 0) ? 1 : -1; 26827 } else if (value_a < value_b) { 26828 return (currOrder === 0) ? -1 : 1; 26829 } else { 26830 return -1; 26831 } 26832 }; 26833 26834 this.getValueFromJsonModel = function (tableRow, currColumn, isString) { 26835 var jsonModel = tableRow.children[getValidCurrentColumn(tableRow.children, currColumn)].jsonModel, value = null; 26836 if (!isString && jsonModel.defaultValue && jsonModel.defaultValue.length === 1) { 26837 value = jsonModel.defaultValue[0]; 26838 } 26839 if (!value) { 26840 value = jsonModel._value; 26841 } 26842 return value === null ? "" : this.formatRichTextString(value); 26843 }; 26844 26845 26846 function getValidCurrentColumn(tableRowModel, currColumn) {
26847 var validCurrColumn = currColumn, index = 0 ; 26848 while (currColumn > 0) { 26849 if (tableRowModel[index].jsonModel.guideNodeClass === tableSortingComponents.GUIDE_INSTANCE_MANAGER) { 26850 validCurrColumn++; 26851 } else { 26852 currColumn--; 26853 } 26854 index++; 26855 } 26856 return validCurrColumn; 26857 } 26858 26859 26860 function syncNewModelToHTML(tableContext, tableModel) { 26861 var tableItemsViews = {}, childView, index; 26862 26863 for (index = 0; index < tableContext.childViews.length; index++) { 26864 childView = tableContext.childViews[index]; 26865 if (childView.isItem) { 26866 tableItemsViews[childView.id] = childView; 26867 } 26868 } 26869 for (index = 1; index < tableContext._model.items.length; index++) { 26870 var childModel = tableContext._model.items[index], childId = childModel.id, view = tableItemsViews[childId],newChild = view._model, 26871 $childItem = view.$item, $childItemNav = view.$itemNav, insertBeforeId, insertAfterId; 26872 if (index === 1) { 26873 if (tableModel.items.length > 2) { 26874 insertBeforeId = tableModel.items[index + 1].id; 26875 } 26876 } else { 26877 insertAfterId = tableModel.items[index - 1].id; 26878 } 26879 var insertAfterItemSelector = insertAfterId ? tableContext.guideUtil.itemSelector(insertAfterId, newChild) : "#" + newChild.instanceManager.id, 26880 insertBeforeItemSelector = insertBeforeId ? tableContext.guideUtil.itemSelector(insertBeforeId, newChild) : "#" + newChild.instanceManager.id; 26881 tableContext.$itemsContainer.each(function (index) { 26882 var insertEl = $childItem.get(index) || $childItem.get(0), 26883 $insertBeforeItem, 26884 $insertAfterItem = $(this).find(insertAfterItemSelector); 26885 if ($insertAfterItem.get(0) !== insertEl) { 26886 $insertAfterItem.after($(insertEl)); 26887 } else { 26888 $insertBeforeItem = $(this).find(insertBeforeItemSelector); 26889 $insertBeforeItem.before($(insertEl)); 26890 } 26891 }); 26892 } 26893 } 26894 } 26895 }); 26896}($, _, guidelib)); 26897 26898(function ($, guidelib) { 26899 var GuideTableRowView = guidelib.view.GuideTableRowView = guidelib.view.GuidePanelView.extend({ 26900 26901 handleChildChanged : function (event) { 26902 26903 } 26904 26905 }); 26906}($, guidelib)); 26907(function ($, guidelib, _) { 26908 var GuideContainerView = guidelib.view.GuideContainerView = guidelib.view.GuideItemsView.extend({ 26909 initialize : function () { 26910 this._queueViewForLazyItems = []; 26911 26912 window.guideBridge._guideView = this; 26913 var $htmlTemplateDom = $(this.options.element).clone(); 26914 this._domTemplateCacheStore = 26915 new guidelib.view.util.DomTemplateCacheStore({$htmlTemplateDom : $htmlTemplateDom}); 26916 this._lastFocussedPanelForNonActionFields = null; 26917 GuideContainerView._super.initialize.call(this); 26918 this._currentFocusItemSom = null; 26919 26920 26921 this._previousFocusItemSom = "FIRST_TIME"; 26922 $(window).on("keydown.guides", $.proxy(this.hotKeys, this)); 26923 this.postInitialize(); 26924 this._model.on(guidelib.event.GuideModelEvent.MODEL_REFRESH, function (evnt) { 26925 switch (evnt._property) { 26926 case "jsonModel": 26927 this._syncGuideNodeToHtml(true); 26928 break; 26929 default: 26930 this._model.logger().error("unexpected event property " + evnt._property); 26931 } 26932 }, this); 26933 }, 26934 26935 _reInitializeGuideContainerDom : function () { 26936 var $guideContainerDom = $('div.guideContainerWrapperNode'); 26937 this.$element = $guideContainerDom; 26938 }, 26939 26940 setFocus : function (somExp, focusOpt, runNavScr) { 26941 var options, 26942 focusOption, 26943 runNavScript, 26944 somExpression, 26945 muteScripts; 26946 if (_.isObject(somExp)) { 26947 options = somExp; 26948 somExpression = options.somExpression; 26949 focusOption = options.focusOption; 26950 runNavScript = options.runCompletionScript; 26951 } else { 26952 somExpression = somExp; 26953 focusOption = focusOpt; 26954 runNavScript = runNavScr; 26955 } 26956 muteScripts = !runNavScript; 26957 if (focusOption == "nextItemDeep" || focusOption == "prevItemDeep") { 26958 26959 if (somExpression) { 26960 this.logger().warn("AF", "somExpression is currently not supported for deepNavigation:" + somExpression + ":" + focusOption); 26961 return false;
26962 } 26963 var existingFocusNavItem = this.getSomOnNavigableAncestor(this._lastFocussedPanelForNonActionFields); 26964 var existingNavView = this.getView(existingFocusNavItem); 26965 var siblingNavName = (focusOption == "nextItemDeep") ? "nextItem" : "prevItem"; 26966 26967 while (existingNavView && (existingNavView.parentView != this) && !existingNavView.getSiblingItemView(siblingNavName)) { 26968 var navigableParentItem = this.getSomOnNavigableAncestor(existingNavView.parentView._model.somExpression); 26969 existingNavView = this.getView(navigableParentItem); 26970 } 26971 if (existingNavView && existingNavView.parentView != this && existingNavView.getSiblingItemView(siblingNavName)) { 26972 var madeActive = existingNavView.parentView.setActive(siblingNavName, false, muteScripts); 26973 if (!madeActive) { 26974 this.logger().log("AF", "could not setActive for the deepNav:" + existingNavView._model.somExpression); 26975 return false; 26976 } 26977 26978 var deepChildNav = (siblingNavName == "nextItem") ? "firstItem" : "lastItem"; 26979 var currentActiveChildView = existingNavView.parentView.currentActiveItemView; 26980 while (currentActiveChildView) { 26981 currentActiveChildView.setActive(deepChildNav, !currentActiveChildView.currentActiveItemView, true); 26982 currentActiveChildView = currentActiveChildView.currentActiveItemView; 26983 } 26984 return true; 26985 } else { 26986 this.logger().warn("AF", "could not locate view for given somExpression:" + somExpression + ":" + focusOption); 26987 return false; 26988 } 26989 } 26990 26991 if (!somExpression) { 26992 26993 somExpression = this.guideModel.rootPanel.somExpression; 26994 } 26995 var currentView = this.rootPanelView; 26996 26997 26998 if (currentView) { 26999 var relativeSom = this.guideUtil.relativeSom(this.guideModel.rootPanel.somExpression, somExpression); 27000 if (relativeSom) { 27001 var somTokens = relativeSom.split("."); 27002 var error = 27003 _.find(somTokens, function (qName) { 27004 currentView.setActive(qName, false, muteScripts); 27005 if (currentView instanceof guidelib.view.GuidePanelView && (currentView.currentActiveItemView == null || currentView.currentActiveItemView.qualifiedName != qName)) { 27006 this.logger().log("AF", "could not find token:" + qName + ", som:" + somExpression); 27007 return true; 27008 } else { 27009 if (currentView.currentActiveItemView != null){ 27010 currentView = currentView.currentActiveItemView; 27011 } 27012 } 27013 }, this); 27014 if (error) { 27015 return false; 27016 } 27017 } 27018 } else { 27019 27020 var $element = this._getGuideDomElement(somExpression); 27021 27022 27023 if ($element && $element.length > 0) { 27024 27025 27026 currentView = $element.data("guideView"); 27027 } 27028 } 27029 27030 if (currentView) { 27031 return currentView.setActive(focusOption, true, muteScripts); 27032 } else { 27033 return false; 27034 } 27035 }, 27036 27037 _getGuideDomElement : function (somExpression, option) { 27038 var nav = "", res, node, nodeElSelector; 27039 if (somExpression && typeof somExpression === 'string') { 27040 node = this.guideModel.resolveNode(somExpression); 27041 if (!node) { 27042 return; 27043 } 27044 nodeElSelector = "#" + node.id; 27045 if (option === "nav") { 27046 nodeElSelector = this.guideUtil.itemNavSelector(node.id); 27047 } 27048 res = this.$element.find(nodeElSelector); 27049 return res; 27050 } 27051 }, 27052 27053 getView : function (somExpression) { 27054 if (!somExpression) { 27055 return null; 27056 }
27057 var $focusEl = this._getGuideDomElement(somExpression), 27058 view = null, 27059 ancestorView = null; 27060 if ($focusEl && $focusEl.length > 0) { 27061 if (!$focusEl.data("guideView")) { 27062 var rootPanelSom = this.guideModel.rootPanel.somExpression; 27063 var relativeSom = guidelib.util.GuideUtil.relativeSom(rootPanelSom, somExpression) || ""; 27064 27065 _.reduce(relativeSom.split("."), function (currentSom, somToken) { 27066 currentSom = currentSom ? currentSom + "." + somToken : somToken; 27067 ancestorView = this.getView(currentSom); 27068 if (ancestorView instanceof guidelib.view.GuidePanelView && ancestorView._childInitializeWaiting) { 27069 ancestorView._postInitializeChildren(); 27070 } 27071 return currentSom; 27072 }, rootPanelSom, this); 27073 } 27074 view = $focusEl.data("guideView"); 27075 if (view instanceof guidelib.view.GuidePanelView && view._childInitializeWaiting) { 27076 view._postInitializeChildren(); 27077 } 27078 27079 return view; 27080 } 27081 return null; 27082 }, 27083 27084 hotKeys : function (evnt) { 27085 var handled = false, currentFocusItemSom; 27086 27087 switch (evnt.keyCode) { 27088 case 37: 27089 if (evnt.altKey) { 27090 window.guideBridge.setFocus(null, 'prevItemDeep', true); 27091 handled = true; 27092 } 27093 break; 27094 case 39: 27095 if (evnt.altKey) { 27096 window.guideBridge.setFocus(null, 'nextItemDeep', true); 27097 handled = true; 27098 } 27099 break; 27100 case 82: 27101 if (evnt.altKey) { 27102 window.guideBridge.reset(); 27103 handled = true; 27104 } 27105 break; 27106 case 83: 27107 if (evnt.altKey) { 27108 window.guideBridge.submit(); 27109 handled = true; 27110 } 27111 break; 27112 } 27113 if (handled) { 27114 evnt.preventDefault(); 27115 } 27116 }, 27117 27118 getSomOnNavigableAncestor : function (somExpression) { 27119 if (!somExpression || somExpression === "") { 27120 return null; 27121 } 27122 27123 var index, parentView, parentSom, isNavigable; 27124 index = somExpression.lastIndexOf("."); 27125 27126 if (index !== -1) { 27127 parentSom = somExpression.substring(0, index); 27128 parentView = this.getView(parentSom); 27129 if (parentView) { 27130 isNavigable = parentView.hasNavigableLayout; 27131 } 27132 if (isNavigable) { 27133 return somExpression; 27134 } 27135 return this.getSomOnNavigableAncestor(parentSom); 27136 } 27137 27138 return this.guideModel.rootPanel.somExpression; 27139 }, 27140 27141 __printSyncPending : function () { 27142 27143 _.each(this.childViews, function (childView) { 27144 if (childView._syncPending) { 27145 this.logger().error("AF", childView._model.somExpression); 27146 } else { 27147 GuideContainerView.prototype.__printSyncPending.call(childView); 27148 } 27149 }, this); 27150 }, 27151 27152 _clearInactiveLazyViews : function (that) { 27153 _.each(this.childViews, function (item) { 27154 if (item._model.className === "rootPanelNode") { 27155 item._clearInactiveLazyViews(that); 27156 } 27157 }); 27158 } 27159 27160 }); 27161 27162 GuideContainerView.defineProps({ 27163 guideModel : { 27164 get : function () { 27165 return this._model; 27166 } 27167 }, 27168 27169 rootPanelView : { 27170 get : function () { 27171 return this._findChildView(this.guideModel.rootPanel); 27172 } 27173 }, 27174 27175 currentFocusItemSom : { 27176 get : function () { 27177 return this._currentFocusItemSom; 27178 }, 27179 set : function (newSom) { 27180 if (this._currentFocusItemSom !== newSom) { 27181 var oldValue = this._currentFocusItemSom; 27182 if (oldValue) { 27183 this._previousFocusItemSom = oldValue; 27184 } 27185 this._currentFocusItemSom = newSom; 27186 27187 if (!this._model._guide().runtime.progressive && newSom != null && this._model.resolveNode(newSom).parent.className !== "guideToolbar") { 27188 this._lastFocussedPanelForNonActionFields = this.get
27188SomOnNavigableAncestor(this._currentFocusItemSom); 27189 27190 27191 this._model._currentNavigablePanelSom = this._lastFocussedPanelForNonActionFields; 27192 } 27193 if (newSom) { 27194 this._triggerOnBridge("elementFocusChanged", this._model.resolveNode(newSom), "focus", this._previousFocusItemSom, newSom); 27195 if (this._previousFocusItemSom && !this._model._guide().runtime.progressive) { 27196 var getPreviousItemNavigableSom = this.getSomOnNavigableAncestor(this._previousFocusItemSom), 27197 getCurrentItemNavigableSom = this.getSomOnNavigableAncestor(newSom); 27198 if (getCurrentItemNavigableSom !== getPreviousItemNavigableSom) { 27199 this._triggerOnBridge("elementNavigationChanged", this._model.resolveNode(getCurrentItemNavigableSom), 27200 "navigate", getPreviousItemNavigableSom, getCurrentItemNavigableSom); 27201 } 27202 } 27203 } 27204 } 27205 } 27206 }, 27207 27208 skipFieldFocus : { 27209 27210 get : function () { 27211 return this._skipFieldFocus; 27212 }, 27213 27214 set : function (newVal) { 27215 this._skipFieldFocus = newVal; 27216 } 27217 } 27218 }); 27219}($, guidelib, _)); 27220(function ($, guidelib) { 27221 var DomTemplateCacheStore = guidelib.view.util.DomTemplateCacheStore = xfalib.ut.Class.extend({ 27222 cloneDomElement : function (htmlId) { 27223 return this.$htmlTemplateDom.find(htmlId).clone(); 27224 }, 27225 27226 putDomElement : function (parentIdSelector, $child) { 27227 27228 this.$htmlTemplateDom.find(parentIdSelector).eq(0).append($child); 27229 }, 27230 27231 removeDomElement : function (parentIdSelector) { 27232 27233 this.$htmlTemplateDom.find(parentIdSelector).children().remove(); 27234 } 27235 }); 27236 27237 DomTemplateCacheStore.defineProps({ 27238 $htmlTemplateDom : { 27239 get : function () { 27240 return this.options.$htmlTemplateDom;
27241 } 27242 } 27243 }); 27244}($, guidelib)); 27245(function (_, guidelib) { 27246 27247 var AddMinMaxValidation = guidelib.model.mixin.AddMinMaxValidation = { 27248 normalProperties : { 27249 27250 _runMaximumValueTest : function () { 27251 if (this.exclusiveMaximum) { 27252 return this.value < this.maximum; 27253 } else { 27254 return this.value <= this.maximum; 27255 } 27256 }, 27257 27258 _runMinimumValueTest : function () { 27259 if (this.exclusiveMinimum) { 27260 return this.value > this.minimum; 27261 } else { 27262 return this.value >= this.minimum; 27263 } 27264 }, 27265 27266 27267 _minMaxValidation : function (value, obj) { 27268 if (value != null && obj.validFlag) { 27269 27270 if (this.maximum) { 27271 obj.validFlag = this._runMaximumValueTest(); 27272 if (!obj.validFlag) { 27273 var maxFormattedValue = this._getFormattedValue(this.maximum); 27274 this._errorText = this.exclusiveMaximum ? this.guideUtil.getLocalizedMessage("", guidelib.i18n.strings.exclusiveMaxValErrorMessage, [maxFormattedValue]) : 27275 this.guideUtil.getLocalizedMessage("", guidelib.i18n.strings.maxValErrorMessage, [maxFormattedValue]); 27276 this._failedTest = this.guideUtil.MAXIMUM_VALUE_TEST; 27277 } 27278 } 27279 27280 if (obj.validFlag && this.minimum !== null) { 27281 obj.validFlag = this._runMinimumValueTest(); 27282 if (!obj.validFlag) { 27283 var minFormattedValue = this._getFormattedValue(this.minimum); 27284 this._errorText = this.exclusiveMinimum ? this.guideUtil.getLocalizedMessage("", guidelib.i18n.strings.exclusiveMinValErrorMessage, [minFormattedValue]) : 27285 this.guideUtil.getLocalizedMessage("", guidelib.i18n.strings.minValErrorMessage, [minFormattedValue]); 27286 this._failedTest = this.guideUtil.MINIMUM_VALUE_TEST; 27287 } 27288 } 27289 } 27290 } 27291 27292 }, 27293 propertyDescriptors : { 27294 27295 maximum : { 27296 get : function () { 27297 return this.getAttribute("maximum"); 27298 } 27299 }, 27300 27301 27302 minimum : { 27303 get : function () { 27304 return this.getAttribute("minimum"); 27305 } 27306 }, 27307 27308 27309 exclusiveMaximum : { 27310 get : function () { 27311 return this.getAttribute("exclusiveMaximum"); 27312 } 27313 }, 27314 27315 27316 exclusiveMinimum : { 27317 get : function () { 27318 return this.getAttribute("exclusiveMinimum"); 27319 } 27320 } 27321 27322 } 27323 }; 27324 27325}(_, guidelib)); 27326(function (_, guidelib) { 27327 guidelib.model.mixin.ChoiceGroupOptionHandler = { 27328 normalProperties : { 27329 27330 _getOptionsArray : function (saveValueKey, displayValueKey) { 27331 var items = [], items1 = this.items; 27332 saveValueKey = saveValueKey || "saveValue"; 27333 displayValueKey = displayValueKey || "displayValue"; 27334 if (_.isArray(items1)) { 27335 _.each(items1, function (val) { 27336 27337 27338 var temp = val.split('='), 27339 obj = {}; 27340 obj[saveValueKey] = temp[0]; 27341 obj[displayValueKey] = temp[1] || temp[0]; 27342 items.push(obj); 27343 }); 27344 } 27345 return items; 27346 }, 27347 27348 27349 _getPossibleValueArray : function () { 27350 var values = [], items1 = this.items; 27351 if (_.isArray(items1)) { 27352 _.each(items1, function (val) { 27353 27354 var temp = val.split('='); 27355 values.push(temp[0]); 27356 }); 27357 } 27358 return values; 27359 }, 27360 27361 27362 _triggerItemsChange : function (oldValue, newValue) { 27363 this.trigger(guidelib.event.GuideModelEvent.ITEMS_CHANGED, 27364 guidelib.event.GuideModelEvent.createEvent( 27365 guidelib.event.GuideModelEvent.ITEMS_CHANGED, 27366 this, 27367 "items", 27368 oldValue, 27369 newValue 27370 ) 27371 ); 27372 }, 27373 27374 _resetModelValueForOptionChange : function () { 27375 if (!_.isUndefined(this.jsonModel._value) && this.jsonModel._value != null) { 27376 var valueArr = this.jsonModel._value.split(","); 27377 var possibleValues = this._getPossibleValueArray(); 27378 var modelValue = ""; 27379 _.each(valueArr, function (val) { 27380 if ($.inArray(val, possibleValues, 0) !== -1) { 27381 modelValue += val + ","; 27382 } 27383 }, this); 27384 if (modelValue.length > 0) { 27385 modelValue = modelValue.substring(0, modelValue.length - 1); 27386 } 27387 this.jsonModel._value = modelValue; 27388 } 27389 } 27390 } 27391 }; 27392 27393}(_, guidelib)); 27394 27395(function ($) { 27396 var xfaUtil = xfalib.ut.XfaUtil.prototype; 27397 $.widget("xfaWidget.imageCheckButtonWidget", $.xfaWidget.XfaCheckBox, { 27398 27399 _widgetName : "imageCheckButtonWidget", 27400 27401 getOptionsMap : function () { 27402 var parentOptionsMap = $.xfaWidget.XfaCheckBox.prototype.getOptionsMap.apply(this, arguments); 27403 return $.extend({}, parentOptionsMap, { 27404 "displayValue" : function (val) { 27405 parentOptionsMap.displayValue.apply(this, arguments); 27406 var rbParent = this.$userControl.parents('.guideRadioButtonItem, .guideCheckBoxItem'); 27407 if (rbParent) { 27408 rbParent.toggleClass('imageCheckButtonChecked', this.checkedState); 27409 } 27410 if (this.$userControl.attr('disabled') === 'disabled') { 27411 rbParent.addClass('imageCheckButtonDisabled'); 27412 } 27413 } 27414 }); 27415 } 27416 }); 27417})($); 27418(function (_, guidelib) { 27419 var GuideModelRegistry = guidelib.model.GuideModelRegistry = xfalib.ut.Class.extend({ 27420 27421 _nodeClassToFactoryMap : { 27422 27423 }, 27424 27425 createModel : function (jsonModel, options) { 27426 var model = null; 27427 var guideNodeClassTag = "GuideNode"; 27428 if (jsonModel.guideNodeClass && jsonModel.guideNodeClass.length > 0) {
27429 guideNodeClassTag = jsonModel.guideNodeClass.charAt(0).toUpperCase() + jsonModel.guideNodeClass.substr(1); 27430 } 27431 var factoryFnName = "create" + guideNodeClassTag ; 27432 if (jsonModel.guideNodeClass && this._nodeClassToFactoryMap[jsonModel.guideNodeClass]) { 27433 factoryFnName = this._nodeClassToFactoryMap[jsonModel.guideNodeClass]; 27434 } 27435 if (this[factoryFnName]) { 27436 model = this[factoryFnName].call(this, jsonModel, options); 27437 } 27438 27439 if (!model && guidelib.model[guideNodeClassTag]) { 27440 model = new guidelib.model[guideNodeClassTag](this._getOptions(jsonModel, options)); 27441 } 27442 27443 if (!model) { 27444 if (jsonModel.items) { 27445 model = new guidelib.model.GuideItemsContainer(this._getOptions(jsonModel, options)); 27446 } else { 27447 model = new guidelib.model.GuideNode(this._getOptions(jsonModel, options)); 27448 } 27449 } 27450 return model; 27451 }, 27452 27453 _getOptions : function (jsonModel, options) { 27454 return _.extend({}, options, {"jsonModel" : jsonModel}); 27455 }, 27456 27457 createInstanceManager : function (guidePanelModel) { 27458 var name = guidePanelModel.getAttribute("name"), 27459 imJson = { 27460 guideNodeClass : "guideInstanceManager", 27461 minOccur : guidePanelModel.minOccur, 27462 maxOccur : guidePanelModel.maxOccur, 27463 initialOccur : guidePanelModel.initialOccur, 27464 instanceTemplateId : guidePanelModel.templateId, 27465 name : "_" + name, 27466 instanceName : name, 27467 templateId : "im_" + guidePanelModel.templateId, 27468 id : "im_" + guidePanelModel.id 27469 }; 27470 var options = {}; 27471 if (guidePanelModel.options._guideContainer) { 27472 options = _.extend({}, options, {"_guideContainer" : guidePanelModel.options._guideContainer}); 27473 } 27474 return guidelib.model.GuideModelRegistry.prototype.createModel(imJson, options); 27475 } 27476 }); 27477})(_, guidelib); 27478(function (_, $) { 27479 "use strict"; 27480 27481 27482 var isBrowserIE = xfalib.ut.XfaUtil.prototype.detectIE(); 27483 27484 var _defaults = { 27485 'showLink' : false, 27486 'scrollMode' : 'vertical', 27487 textAreaClass : ".guide-tnc-content", 27488 checkBoxClass : ".guide-tnc-checkbox", 27489 checkBoxDisableClass : ".guide-tnc-checkbox-disabled", 27490 checkBoxReviewedClass : ".guide-tnc-checkbox-reviewed", 27491 linkClass : ".guide-tnc-link", 27492 documentVisitedClass : ".guide-tnc-document-visited", 27493 documentUnVisitedClass : ".guide-tnc-document-unvisited" 27494 }; 27495 27496 var _reviewStatusMap = { 27497 REVIEWED : "reviewed", 27498 UNREVIEWD : "unreviewed", 27499 AGREE : "agree" 27500 }; 27501 27502 var AfTnc = function (element, options) { 27503 this.options = options; 27504 this.$element = $(element); 27505 27506 27507 this.enters = this.leaves = 0; 27508 this.inside = false;
27509 27510 27511 this.reviewdoc = this.status = _reviewStatusMap.UNREVIEWD; 27512 27513 27514 this.$elementCheckBox = this.$element.find(this.options.checkBoxClass || _defaults.checkBoxClass); 27515 27516 this.$elementTextArea = $(this.textArea()); 27517 27518 this.$elementLink = $(this.link()); 27519 27520 this.isTextContentVisible = false; 27521 27522 if (this.options.showLink) { 27523 27524 this.$elementLink.find('a').click($.proxy(this.handleReviewStatusChange, this)); 27525 } else { 27526 var setCheckBoxState = function () { 27527 if (this.hasScrollBar(this.$elementTextArea.parent().get(0))) { 27528 27529 27530 this.$elementTextArea.parent().scroll($.proxy(this.handleReviewStatusChange, this)); 27531 } else { 27532 27533 if (this.$elementTextArea.css('display') !== 'none') { 27534 this.status = _reviewStatusMap.REVIEWED; 27535 this.isTextContentVisible = true; 27536 27537 if (!this.options.showAsPopUp) { 27538 this.enableCheckBox(); 27539 } 27540 this.reviewDoc = this.$elementTextArea.text(); 27541 } 27542 } 27543 }; 27544 27545 27546 if (document.readyState === "complete") { 27547 setCheckBoxState.call(this); 27548 } else { 27549 27550 27551 $($.proxy(setCheckBoxState, this)); 27552 } 27553 } 27554 27555 27556 if (this.options.showAsPopUp) { 27557 var unvisitedClass = this.options.documentUnVisitedClass || _defaults.documentUnVisitedClass, 27558 visitedClass = this.options.documentVisitedClass || _defaults.documentVisitedClass; 27559 var _self = this, 27560 dialogId = this.$elementCheckBox.find('a') 27561 .keydown(function (e) { 27562 if (e.keyCode === 13 || e.which == 13 || e.charCode === 32) { 27563 $(this).click(); 27564 return false; 27565 } 27566 }) 27567 .click(function (event) { 27568 if ($(this).hasClass(unvisitedClass.substring(1))) { 27569 $(this).toggleClass(visitedClass.substring(1) + " " + unvisitedClass.substring(1)); 27570 } 27571 27572 27573 if (isBrowserIE || _self.isTextContentVisible) { 27574 _self.enableCheckBox(); 27575 } 27576 }).attr("href"); 27577 27578 $(dialogId).on('hidden.bs.modal', function (e) { 27579 _self.$elementCheckBox.find('input').focus(); 27580 }); 27581 } else { 27582 27583 this._updateScreenReaderText(); 27584 } 27585 27586 27587 this.$elementCheckBox.find('input').change($.proxy(this.handleCheckBoxChange, this)); 27588 }; 27589 27590 AfTnc.prototype = { 27591 27592 clear : function () { 27593 this.$element.val(''); 27594 }, 27595 27596 destroy : function () { 27597 this.$element.val(''); 27598 this.$element.empty(); 27599 }, 27600 27601 _updateScreenReaderText : function () { 27602 if (!this.options.showAsPopUp) { 27603 var _self = this; 27604 27605 this.$element.find(".guide-tnc-sr-only").each(function (i, obj) { 27606 $(this).html(_self.options.screenReaderText); 27607 }); 27608 } 27609 }, 27610 27611 _restoreClickState : function (value) { 27612 if (this.options.showLink) { 27613 var arr = value.split("\n"), 27614 linkState = []; 27615 27616 _.each(arr, function (linkText, index) { 27617 27618 linkState.push(_.last(linkText.split('='))); 27619 }); 27620 var unvisitedClass = this.options.documentUnVisitedClass || _defaults.documentUnVisitedClass, 27621 visitedClass = this.options.documentVisitedClass || _defaults.documentVisitedClass; 27622 this.$elementLink.find('a').each(function (index) { 27623 $(this).data("clicked", linkState[index]); 27624 if (linkState[index] === "1") { 27625 $(this).addClass(visitedClass.substring(1)); 27626 } else { 27627 $(this).addClass(unvisitedClass.substring(1)); 27628 } 27629 }); 27630 } 27631 }, 27632 27633 value : function (value) { 27634 if (value) { 27635 27636 if (this.options.showLink) { 27637 this._restoreClickState(value); 27638 } 27639 this.reviewDoc = value; 27640 } else { 27641 return this.reviewDoc; 27642 } 27643 27644 }, 27645 27646 reviewStatus : function (value) { 27647 var val = this.getClickState(); 27648 if (!_.isUndefined(value)) { 27649 if (value == "true") { 27650 this.enableCheckBox(); 27651 this.$elementCheckBox.find('input').attr("checked", "checked"); 27652 this.$elementCheckBox.find('input').prop("checked", true); 27653 } else if (value == null || value == "false") { 27654 27655 this.$elementCheckBox.find('input').removeAttr("checked"); 27656 this.$elementCheckBox.find('input').removeProp("checked"); 27657 } 27658 this.approvalStatus = value; 27659 } else { 27660 if (this.status == _reviewStatusMap.REVIEWED || this.status == _reviewStatusMap.UNREVIEWD) { 27661 return null; 27662 } else if (this.status == _reviewStatusMap.AGREE) { 27663 return true; 27664 } 27665 } 27666 }, 27667 27668 clickStatus : function (value) { 27669 if (value) { 27670 if (value === _reviewStatusMap.REVIEWED) { 27671 var arr = this.getClickState(); 27672 if (_.isArray(arr) && arr.length > 0) { 27673 arr = arr.join("\n"); 27674 this._restoreClickState(arr); 27675 } 27676 this.enableCheckBox(); 27677 } 27678 this.status = value; 27679 } else { 27680 return this.status; 27681 } 27682 }, 27683 27684 showLink : function (value) { 27685 if (value !== undefined) { 27686 this.options.showLink = value; 27687 } else { 27688 return this.options.showLink; 27689 } 27690 }, 27691 27692 access : function (value) { 27693 this.accessOption = value; 27694 if (value == "readOnly") { 27695 this.disableCheckBox(); 27696 if (this.options.showLink) { 27697 this.$elementLink.find('a').each(function (index, elem) {
27698 $(elem).css('pointer-events', 'none'); 27699 27700 $(elem).attr('disabled', 'disabled'); 27701 }); 27702 } 27703 } else if (value == "open") { 27704 27705 27706 if ((this.status == _reviewStatusMap.REVIEWED || this.status == _reviewStatusMap.AGREE) && !this.options.showAsPopUp) { 27707 this.enableCheckBox(); 27708 } 27709 if (this.options.showLink) { 27710 this.$element.find('a').each(function (index, elem) { 27711 $(elem).css('pointer-events', ''); 27712 $(elem).removeAttr('disabled'); 27713 }); 27714 } 27715 } 27716 }, 27717 27718 link : function () { 27719 return this.$element.find(this.options.linkClass || _defaults.linkClass); 27720 }, 27721 27722 textArea : function () { 27723 return this.$element.find(this.options.textAreaClass || _defaults.textAreaClass); 27724 }, 27725 27726 getClickState : function () { 27727 if (this.options.showLink) { 27728 var arr = []; 27729 this.$elementLink.find('a').each(function (index) { 27730 arr.push({ 27731 'displayText' : $(this).text(), 27732 'linkText' : $(this).attr('href'), 27733 'clicked' : $(this).data("clicked") 27734 }); 27735 }); 27736 return arr; 27737 } 27738 }, 27739 27740 enableCheckBox : function () { 27741 if (this.accessOption !== "readOnly") { 27742 this.$elementCheckBox.find('input').removeAttr("disabled"); 27743 this.$elementCheckBox.removeClass(this.options.checkBoxDisableClass.substring(1)); 27744 } 27745 }, 27746 27747 disableCheckBox : function () { 27748 this.$elementCheckBox.find('input').attr('disabled', 'disabled'); 27749 this.$elementCheckBox.addClass(this.options.checkBoxDisableClass.substring(1)); 27750 }, 27751 27752 handleReviewStatusChange : function (event) { 27753 var arr = [], 27754 visitedClass = this.options.documentVisitedClass || _defaults.documentVisitedClass; 27755 if (this.options.showLink) { 27756 this.status = _reviewStatusMap.REVIEWED; 27757 27758 $(event.target).data("clicked", 1); 27759 $(event.target).addClass(visitedClass.substring(1)); 27760 this.linkStateMap = this.getClickState(); 27761 _.each(this.linkStateMap, function (element, index) { 27762 if (!element.clicked) { 27763 this.status = _reviewStatusMap.UNREVIEWD; 27764 } 27765 27766 arr.push(element.displayText + "=" + element.linkText + "=" + (_.isUndefined(element.clicked) ? "0" : "1")); 27767 }, this); 27768 if (arr.length > 0) { 27769 this.reviewDoc = arr.join("\n"); 27770 } 27771 27772 if (this.status == _reviewStatusMap.REVIEWED) { 27773 this.enableCheckBox(); 27774 } 27775 27776 27777 this.$element.trigger('reviewComplete.tnc'); 27778 27779 } else { 27780 27781 var position = this.getScroll(this.$elementTextArea.parent().get(0)), 27782 xy = position[this.options.scrollMode == 'vertical' ? 'y' : 'x']; 27783 var isScrolledToEnd = this.getScrollSize(this.$elementTextArea.parent().get(0)).y <= (this.getSize(this.$elementTextArea.parent().get(0)).y + xy); 27784 27785 this.reviewDoc = this.$elementTextArea.text(); 27786 27787 27788 if (isScrolledToEnd) { 27789 27790 if (!this.inside) { 27791 27792 this.inside = true; 27793 this.enters++; 27794 27795 this.status = _reviewStatusMap.REVIEWED; 27796 this.enableCheckBox(); 27797 27798 this.$element.trigger('reviewComplete.tnc', [position,this.enters,event]); 27799 27800 } 27801 } 27802 27803 else if (this.inside) { 27804 this.inside = false;
27805 this.leaves++; 27806 27807 } 27808 } 27809 27810 }, 27811 27812 handleCheckBoxChange : function (event) { 27813 if ($(event.target).is(':checked')) { 27814 this.status = _reviewStatusMap.AGREE; 27815 this.$elementCheckBox.addClass(this.options.checkBoxReviewedClass.substring(1)); 27816 } else { 27817 this.status = _reviewStatusMap.UNREVIEWD; 27818 this.$elementCheckBox.removeClass(this.options.checkBoxReviewedClass.substring(1)); 27819 } 27820 this.$element.trigger('checkboxStateChange.tnc'); 27821 }, 27822 27823 getScrollSize : function (elem) { 27824 return {x : elem.scrollWidth, y : elem.scrollHeight}; 27825 }, 27826 27827 getScroll : function (elem) { 27828 return {x : elem.scrollLeft, y : elem.scrollTop}; 27829 }, 27830 27831 getSize : function (elem) { 27832 return {x : elem.offsetWidth, y : elem.offsetHeight}; 27833 }, 27834 27835 hasScrollBar : function (container) { 27836 27837 if (isBrowserIE) { 27838 27839 return ((container.scrollHeight - 2) > container.clientHeight) || ((container.scrollWidth - 2) > container.clientWidth); 27840 } else { 27841 return container.scrollHeight > container.clientHeight || container.scrollWidth > container.clientWidth; 27842 } 27843 } 27844 }; 27845 27846 $.fn.afTnc = function (option, value) { 27847 var get = '', 27848 element = this.each(function () { 27849 27850 var $this = $(this), 27851 data = $this.data('AfTnc'), 27852 options = $.extend({}, _defaults, typeof option === 'object' && option); 27853 27854 27855 if (!data) { 27856 $this.data('AfTnc', (data = new AfTnc(this, options))); 27857 } 27858 27859 27860 if (typeof option === 'string') { 27861 get = data[option](value); 27862 } 27863 }); 27864 27865 if (typeof get !== undefined) { 27866 return get; 27867 } else { 27868 return element; 27869 } 27870 }; 27871 27872})(_, $); 27873(function ($) { 27874 var xfaUtil = xfalib.ut.XfaUtil.prototype; 27875 $.widget("xfaWidget.tnc", $.xfaWidget.abstractWidget, { 27876 27877 _widgetName : "tnc", 27878 _superPrototype : $.xfaWidget.abstractWidget.prototype, 27879 getOptionsMap : function () { 27880 var parentOptionsMap = this._superPrototype.getOptionsMap.apply(this, arguments), 27881 newMap = $.extend({}, parentOptionsMap, $.extend({}, this.options, { 27882 "value" : function (value) { 27883 this.$userControl.afTnc("value", value); 27884 }, 27885 "reviewStatus" : function (value) { 27886 this.$userControl.afTnc("reviewStatus", value); 27887 }, 27888 27889 "clickStatus" : function (value) { 27890 this.$userControl.afTnc("clickStatus", value); 27891 }, 27892 27893 "access" : function (value) { 27894 this.$userControl.afTnc("access", value); 27895 } 27896 })); 27897 return newMap; 27898 }, 27899 27900 _getReviewStatus : function () { 27901 return $(this.element).afTnc("reviewStatus"); 27902 }, 27903 27904 _getClickStatus : function () { 27905 return $(this.element).afTnc("clickStatus"); 27906 }, 27907 27908 getEventMap : function () { 27909 var parentEventMap = this._superPrototype.getEventMap.apply(this, arguments), 27910 newMap = $.extend({}, parentEventMap, 27911 { 27912 "change" : null, 27913 "reviewComplete.tnc" : xfaUtil.XFA_CHANGE_EVENT, 27914 "checkboxStateChange.tnc" : xfaUtil.XFA_CHANGE_EVENT 27915 }); 27916 return newMap; 27917 }, 27918 render : function () { 27919 this._superPrototype.render.apply(this, arguments); 27920 $(this.element).afTnc(this.getOptionsMap()); 27921 return $(this.element); 27922 }, 27923 showDisplayValue : function () { 27924 27925 }, 27926 showValue : function () { 27927 27928 }, 27929 getCommitValue : function () { 27930 this.options.reviewStatus = this._getReviewStatus(); 27931 this.options.clickStatus = this._getClickStatus(); 27932 return $(this.element).afTnc("value"); 27933 } 27934 }); 27935})($); 27936 27937(function (_, guidelib) { 27938 var orderGetAttribute = { 27939 "Guide" : "XFA", 27940 "XFA" : "Guide" 27941 }, 27942 27943 newlyAddedProperties = ["enabled", "visible"]; 27944 27945 var GuideNode = guidelib.model.GuideNode = xfalib.ut.EventClass.extend({ 27946 msClassName : "guideNode", 27947 guideUtil : guidelib.util.GuideUtil, 27948 27949 initialize : function () { 27950 27951 27952 this.className = this.jsonModel.guideNodeClass || this.msClassName; 27953 this.parent = null; 27954 this._isItem = false;
27955 this._index = 0; 27956 }, 27957 27958 _postInitialize : function () { 27959 27960 }, 27961 27962 _triggerOnBridge : function (eventName, target, property, oldVal, newVal) { 27963 if (window.guideBridge) { 27964 window.guideBridge.trigger(eventName, 27965 guidelib.event.GuideModelEvent.createEvent(eventName, target, property, 27966 oldVal, newVal)); 27967 } 27968 }, 27969 27970 _getEffectiveBindRef : function() { 27971 return this.bindRef || this.getAttribute("name"); 27972 }, 27973 27974 validate : function (errorList) { 27975 27976 }, 27977 27978 27979 27980 _getXFAOptionStringFromGuideItems : function (guideItems) { 27981 var optionsStr = "", indexOfSeparator = 0; 27982 if (!_.isEmpty(guideItems) && !_.isArray(guideItems)) { 27983 guideItems = [guideItems]; 27984 } 27985 _.each(guideItems, function (item, index, list) { 27986 if(item.indexOf(",") > -1){ 27987 item = item.replace(/,/g, "\\,"); 27988 } 27989 indexOfSeparator = item.indexOf('='); 27990 27991 27992 if (indexOfSeparator > -1) { 27993 optionsStr += item.substring(indexOfSeparator + 1) + "," + item.substring(0, indexOfSeparator); 27994 } else { 27995 optionsStr += item + "," + item; 27996 } 27997 if (index < guideItems.length - 1) { 27998 optionsStr += ","; 27999 } 28000 }); 28001 return optionsStr; 28002 }, 28003 28004 _compareXFAItemsWithGuideItems : function (xfaItems, guideItems) { 28005 var match = true; 28006 if (xfaItems.length !== guideItems.length) { 28007 match = false; 28008 } 28009 if (match) { 28010 var bndNode = this.bindNode; 28011 _.each(guideItems, function (item, index, list) { 28012 if (item.indexOf('=') > -1) { 28013 if ((bndNode.getSaveItem(index) + "=" + bndNode.getDisplayItem(index)) == item) { 28014 match = false; 28015 } 28016 } else { 28017 if ((bndNode.getSaveItem(index) + "=" + bndNode.getDisplayItem(index)) == (item + "=" + item)) { 28018 match = false; 28019 } 28020 } 28021 }); 28022 } 28023 return match; 28024 }, 28025 28026 28027 syncXFAProps : function () { 28028 if (this.bindNode) { 28029 _.each(this._guide()._guideSchema.getAttributes(this.className), 28030 function (attr, attrName) { 28031 var xfaProp = attr.xfaProp, 28032 propChain = (xfaProp || "").split("."), 28033 xfaAttr = propChain.length > 0 ? propChain[propChain.length - 1] 28034 : undefined; 28035 28036 28037 28038 28039 28040 28041 if (!xfaAttr || (newlyAddedProperties.indexOf(attrName) != -1 && _.isUndefined(this.jsonModel[attrName]))) { 28042 return; 28043 } 28044 var objChain = propChain.splice(0, propChain.length - 1), 28045 obj = _.reduce(objChain, 28046 function (obj, prop) { 28047 if (_.isObject(obj)) { 28048 return obj[prop]; 28049 } 28050 return undefined; 28051 }, this.bindNode), 28052 val = this.getGuideProp(attrName, attr), 28053 convertor = this._guide()._guideSchema.getConvertor(attrName), 28054 cVal = convertor ? convertor.guideToXfa.apply(this, [val]) : val, 28055 xfaVal; 28056 try { 28057 if (obj) { 28058 xfaVal = obj[xfaAttr]; 28059 if (cVal !== undefined) { 28060 if (xfaAttr === "items") { 28061 var match = this._compareXFAItemsWithGuideItems(obj, cVal); 28062 var SET_ITEMS_INSERT_MODE_PAIR = 2; 28063 if (!match) { 28064 var optionsStr = this._getXFAOptionStringFromGuideItems(cVal); 28065 if (optionsStr !== "") { 28066 obj.setItems(optionsStr, SET_ITEMS_INSERT_MODE_PAIR); 28067 } else { 28068 obj.clearItems(); 28069 } 28070 } 28071 } else if (cVal !== xfaVal) { 28072 obj[xfaAttr] = cVal; 28073 } 28074 } 28075 } 28076 } catch (e) { 28077 this.logger().error("AF", "setting {0}(guide {1}) for {2} is not supported in xfa", 28078 [xfaProp, attrName, this.bindNode.somExpression]); 28079 if (e.stack) { 28080 this.logger().error("AF", e.stack); 28081 } 28082 } 28083 }, this); 28084 } 28085 }, 28086 28087 28088 prepare : function () { 28089 28090 }, 28091 28092 28093 nakedChildReferences : function (nIndex, obj) { 28094 return; 28095 }, 28096 28097 28098 getNaked : function (nIndex, container, scope) { 28099 var nodeName = this.getAttribute("name"), 28100 oldReference = container._private["_" + nodeName + "_"],
28101 canOverride = (container._isOverriden && !container._isOverriden["_" + nodeName + "_"]), 28102 isGlobalFieldRef = this.isGlobal && (container === guidelib.__runtime__ || container === this._guide().runtime) 28103 && (container[nodeName] instanceof guidelib.model.AbstractField); 28104 28105 if ((scope && scope._nameArray[nodeName] === 1) || (nIndex === this.index)) { 28106 if (oldReference === null || oldReference === undefined || canOverride || isGlobalFieldRef) { 28107 guidelib.util.GuideUtil._createGetterSetter(container, nodeName, this); 28108 if (canOverride === true) { 28109 container._isOverriden["_" + nodeName + "_"] = true; 28110 } 28111 } 28112 } 28113 }, 28114 28115 _getReducedJSON : function () { 28116 var whitelistedProperties = ["name", "templateId", "_value", "guideNodeClass"], 28117 reducedJsonObject = {}; 28118 guidelib.model.util.CommonUtils.returnMinimalJSON(whitelistedProperties, reducedJsonObject, this); 28119 return reducedJsonObject; 28120 }, 28121 28122 _getNakedThis : function () { 28123 return this; 28124 }, 28125 28126 _xfa : function () { 28127 if (window.xfalib) { 28128 return window.xfalib.runtime.xfa; 28129 } 28130 return null; 28131 }, 28132 28133 _guide : function () { 28134 return this.options._guideContainer; 28135 }, 28136 28137 28138 playJson : function (pJsonModel) { 28139 28140 }, 28141 28142 28143 28144 visit : function (callback, context) { 28145 callback.apply(context, [this]); 28146 }, 28147 28148 _collectValues : function (keyValue) { 28149 28150 }, 28151 28152 _setParentAccess : function (value) { 28153 28154 }, 28155 28156 _unloadModel : function () { 28157 this.trigger(guidelib.event.GuideModelEvent.OBJECT_DESTROYED, 28158 guidelib.event.GuideModelEvent.createEvent( 28159 guidelib.event.GuideModelEvent.OBJECT_DESTROYED, 28160 this, 28161 "destroy", 28162 null, 28163 this 28164 ) 28165 ); 28166 this._guide()._modelTemplateCacheStore.removeModel(this.id); 28167 this.off(); 28168 28169 if (_.isObject(guidelib.__runtime__[this.name]) && (guidelib.__runtime__[this.name] === this || guidelib.__runtime__[this.name].somExpression === this.somExpression)) { 28170 guidelib.__runtime__[this.name] = undefined; 28171 if (_.isObject(guidelib.__runtime__._private['_' + this.name + '_'])) { 28172 guidelib.__runtime__._private['_' + this.name + '_'] = undefined; 28173 } 28174 } 28175 28176 if (_.isObject(this._guide().runtime[this.name]) && (this._guide().runtime[this.name] === this || this._guide().runtime[this.name].somExpression === this.somExpression)) { 28177 this._guide().runtime[this.name] = undefined; 28178 if (_.isObject(this._guide().runtime._private['_' + this.name + '_'])) { 28179 this._guide().runtime._private['_' + this.name + '_'] = undefined; 28180 } 28181 } 28182 }, 28183 28184 _triggerEvent : function (event, propName, prevText, newText) { 28185 this.trigger(event, 28186 guidelib.event.GuideModelEvent.createEvent(event, this, propName, 28187 prevText, newText)); 28188 }, 28189 28190 28191 dispatchEvent : function (eventName, payload) { 28192 this._triggerEvent(eventName, payload); 28193 if(this.parent !== null){ 28194 this.parent.dispatchEvent(eventName, payload); 28195 } 28196 }, 28197 28198 28199 setAttribute : function (value, attrName) { 28200 if (this.jsonModel[attrName] !== value) { 28201 var oldValue = this.jsonModel[attrName]; 28202 this.jsonModel[attrName] = value; 28203 this._triggerEvent(guidelib.event.GuideModelEvent.MODEL_CHANGED, attrName, oldValue, value); 28204 } 28205 }, 28206 28207 _getSomExpression : function () { 28208 if (this.parent == null) { 28209 return "guide[0]." + this._escapeQualifiedName(); 28210 } else { 28211 return this.parent.somExpression + "." + this._escapeQualifiedName(); 28212 } 28213 }, 28214 28215 _escapeQualifiedName : function () { 28216 var name = this.getAttribute("name"); 28217 var index = this._index; 28218 var qname = name + "[" + index + "]"; 28219 return qname.replace(/\./, "\\."); 28220 }, 28221 28222 28223 getGuideProp : function (attrName, attr) { 28224 var val = this.getOrElse(this.jsonModel, attrName, attr["default"]); 28225 if (val === undefined) { 28226 return undefined; 28227 } 28228 return guidelib.model.GuideSchema.prototype.getTypedValue(attr.type, val); 28229 28230 }, 28231 28232 28233 getXFAProp : function (attrName, attr) { 28234 var xfaName = attr.xfaProp, 28235 convertor = guidelib.model.GuideSchema.prototype.getConvertor(attrName), 28236 val; 28237 if (this.bindNode && xfaName !== undefined) { 28238 val = this.bindNode.getOrElse(this.bindNode, xfaName, undefined); 28239 if (convertor) { 28240 val = convertor.xfaToGuide.apply(this, [val]); 28241 } 28242 if (val !== undefined) { 28243 return val; 28244 } 28245 } 28246 return undefined; 28247 }, 28248 28249 28250 getAttribute : function (attrName) { 28251 var attr = guidelib.model.GuideSchema.prototype.getAttributeProps(this.className, attrName), 28252 priority = attr.priority || (attr.xfaProp !== undefined ? "XFA" : "Guide"), 28253 28254 val = this["get" + priority + "Prop"].apply(this, [attrName, attr]); 28255 28256 if (val === undefined) { 28257 28258 val = this["get" + orderGetAttribute[priority] + "Prop"].apply(this, [attrName, attr]); 28259 } 28260 return val; 28261 }, 28262 28263 28264 resetData : function () { 28265 28266 } 28267 }); 28268 28269 GuideNode.defineProps({ 28270 28271 28272 "name" : { 28273 get : function () { 28274 return (this.getAttribute("name") || "").replace(/\s+/g, ''); 28275 } 28276 }, 28277 28278 "templateId" : { 28279 get : function () { 28280 return this.getAttribute("templateId"); 28281 } 28282 }, 28283 28284 28285 "id" : { 28286 get : function () { 28287 return this.getAttribute("id") || this.templateId; 28288 } 28289 }, 28290 28291 28292 somExpression : { 28293 get : function () { 28294 return this._getSomExpression(); 28295 } 28296 }, 28297 28298 28299 "title" : { 28300 get : function () { 28301 return this.getAttribute("jcr:title"); 28302 } 28303 }, 28304 28305 28306 "nonLocalizedTitle" : { 28307 get : function () { 28308 return this.getAttribute("nonLocalizedTitle"); 28309 } 28310 }, 28311 28312 28313 panel : { 28314 get : function () { 28315 return this.parent.panel; 28316 } 28317 }, 28318 28319 viewVisited : { 28320 get : function () { 28321 return this.getAttribute("viewVisited"); 28322 }, 28323 set : function (visit) { 28324 this.setAttribute(visit, "viewVisited"); 28325 } 28326 }, 28327 28328 28329 index : { 28330 get : function () { 28331 return this._index; 28332 } 28333 }, 28334 28335 28336 visible : { 28337 get : function () { 28338 return true; 28339 }, 28340 set : function (value) { 28341 28342 } 28343 }, 28344 28345 28346 enabled : { 28347 get : function () { 28348 return true; 28349 }, 28350 set : function (value) { 28351 28352 } 28353 }, 28354 28355 28356 cssClassName : { 28357 get : function () { 28358 return this.getAttribute("css"); 28359 } 28360 }, 28361 28362 enableLayoutOptimization : { 28363 get : function () { 28364 return false;
28365 } 28366 }, 28367 28368 jcrPath : { 28369 get : function () { 28370 return this.jsonModel["jcr:path"]; 28371 } 28372 }, 28373 28374 28375 targetVersion : { 28376 get : function () { 28377 return this.getAttribute("fd:targetVersion"); 28378 } 28379 } 28380 }); 28381}(_, guidelib)); 28382(function (_, guidelib) { 28383 var Esign = guidelib.model.Esign = guidelib.model.GuideNode.extend({ 28384 msClassName : "esign", 28385 28386 initialize : function () { 28387 Esign._super.initialize.call(this); 28388 this.validationStatus = true; 28389 }, 28390 28391 validate : function (errorList) { 28392 28393 28394 var validationStatus = true; 28395 if (FD.AFaddon.Signing !== undefined && FD.AFaddon.Signing !== null) { 28396 validationStatus = FD.AFaddon.Signing.isDocumentSigned(this.jsonModel.signingService); 28397 if (!validationStatus) { 28398 errorList.push({som : this.somExpression, errorText : "Signing not complete."}); 28399 } 28400 } 28401 28402 this.validationStatus = validationStatus; 28403 return validationStatus; 28404 } 28405 }); 28406 Esign.defineProps({ 28407 forceElementFocusChange : { 28408 get : function () { 28409 return true; 28410 } 28411 } 28412 }); 28413})(_, guidelib); 28414(function (_, guidelib, $) { 28415 var Verify = guidelib.model.Verify = guidelib.model.GuideNode.extend({ 28416 msClassName : "verify", 28417 28418 initialize : function () { 28419 Verify._super.initialize.call(this); 28420 this.validationStatus = true; 28421 }, 28422 28423 validate : function (errorList) { 28424 28425 28426 var iframeFormBridge = null, validationStatus = true; 28427 28428 if (this.jsonModel.interactive !== undefined && this.jsonModel.interactive === "true") { 28429 28430 28431 28432 28433 28434 if (guideBridge.hostName === "client") { 28435 iframeFormBridge = $('#verifiable_form').get(0).contentWindow.formBridge; 28436 } 28437 28438 28439 if (iframeFormBridge !== undefined && iframeFormBridge !== null) { 28440 validationStatus = iframeFormBridge.validateForm(); 28441 if (!validationStatus) { 28442 errorList.push({som : this.somExpression, errorText : "XFA validation errors."}); 28443 } 28444 this.validationStatus = validationStatus; 28445 } 28446 } 28447 28448 return validationStatus; 28449 } 28450 }); 28451 Verify.defineProps({ 28452 forceElementFocusChange : { 28453 get : function () { 28454 return true; 28455 } 28456 } 28457 }); 28458})(_, guidelib, $); 28459(function (_, xfalib, guidelib) { 28460 28461 var expressionContent = "with(this) {" + 28462 "\n\t with(guidelib.__runtime__) {" + 28463 "\n\t with(this._guide().runtime) {" + 28464 "\n\t\t var _guide_result = this[${affectedProp}] = eval(\"${expression}\");" + 28465 "\n\t\t return _guide_result ;" + 28466 "\n\t }" + 28467 "\n}};", 28468 scriptContent = "with(this) {" + 28469 "\n\t with(guidelib.__runtime__) {" + 28470 "\n\t with(this._guide().runtime) {" + 28471 "\n\t var result = eval(\"${expression}\");" + 28472 "\n\t\t return result; " + 28473 "\n\t }" + 28474 "\n}}"; 28475 28476 var Scriptable = guidelib.model.Scriptable = guidelib.model.GuideNode.extend({ 28477 msClassName : "scriptable", 28478 28479 initialize : function () { 28480 Scriptable._super.initialize.call(this); 28481 28482 this.className = this.jsonModel.guideNodeClass || this.msClassName; 28483 this._compiledExpressions = {}; 28484 this._compiledScripts = {}; 28485 this.mActiveEvents = []; 28486 this.dependants = []; 28487 28488 if (this.initScript) { 28489 this._isInitScriptExecuted = false;
28490 } 28491 this._collectExpressions(); 28492 }, 28493 28494 _postInitialize : function () { 28495 28496 if (this._isXfaNode()) { 28497 this.bindNode = this.options.bindNode || this._getBindNode(); 28498 if (this.bindNode) { 28499 this.bindNode.on(xfalib.script.XfaModelEvent.FORM_MODEL_CHANGED, this); 28500 } 28501 } 28502 28503 this._parentAccess = this.getOrElse(this, "parent.enabled", true); 28504 }, 28505 28506 _unloadModel : function () { 28507 if (this._isXfaNode && this._isXfaNode()) { 28508 if (this.bindNode) { 28509 this.bindNode.off(xfalib.script.XfaModelEvent.FORM_MODEL_CHANGED, this); 28510 } 28511 } 28512 28513 Scriptable._super._unloadModel.call(this); 28514 }, 28515 28516 _collectExpressions : function () { 28517 if (this.visibleExp) { 28518 this._compiledExpressions["visibleExp"] = this._compileExpression(this.visibleExp, "visible"); 28519 } 28520 if (this.enabledExp) { 28521 this._compiledExpressions["enabledExp"] = this._compileExpression(this.enabledExp, "enabled"); 28522 } 28523 28524 if (this.initScript) { 28525 this._compiledScripts.initScript = this._compileExpression(this.initScript, null); 28526 } 28527 }, 28528 28529 _compileExpression : function (expression, affectedProp) { 28530 if (expression) { 28531 try { 28532 28533 var content = affectedProp ? expressionContent.replace(/\${affectedProp}/g, '"' + affectedProp + '"') 28534 .replace(/\${expression}/g, expression.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/(?:\r\n|\r|\n)/g, " ")) 28535 : scriptContent.replace(/\${expression}/g, 28536 expression.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/(?:\r\n|\r|\n)/g, " ")); 28537 28538 return new Function(content); 28539 } catch (exception) { 28540 this.logger().error("AF", "Error in compiling expression:" + expression); 28541 } 28542 } 28543 return null; 28544 }, 28545 28546 _isXfaNode : function () { 28547 return (this._xfa() && this.getOrElse(this, "jsonModel.bindRef", "").indexOf("xfa[0].form[0].") === 0); 28548 }, 28549 28550 _xfa : function () { 28551 return this.getOrElse(window, "xfalib.runtime.xfa", null); 28552 }, 28553 28554 prepare : function () { 28555 Scriptable._super.prepare.apply(this); 28556 28557 28558 28559 28560 28561 if (this.initScript && !this._isInitScriptExecuted) { 28562 this.executeExpression("initScript"); 28563 this._isInitScriptExecuted = true; 28564 } 28565 var expressionTypes = _.keys(this._compiledExpressions); 28566 this._guide().queueExpressions(this, expressionTypes); 28567 }, 28568 28569 28570 handleEvent : function (evnt) { 28571 if (evnt instanceof xfalib.script.XfaModelEvent) { 28572 switch (evnt.name) { 28573 case xfalib.script.XfaModelEvent.FORM_MODEL_CHANGED: 28574 this._handleXfaModelChanged(evnt); 28575 break; 28576 default: 28577 28578 } 28579 } else if (evnt instanceof guidelib.event.GuideModelEvent) { 28580 this.handleGuideEvent(evnt); 28581 } 28582 }, 28583 28584 handleGuideEvent : function (evnt) { 28585 }, 28586 28587 28588 executeExpression : function (eventName, detail) { 28589 var guideContainerNode = this._guide(); 28590 if (this._isXfaNode() && this.bindNode instanceof xfalib.script.EventContainerNode) { 28591 if (guidelib.util.GuideUtil.xfaExprMap[eventName] !== null) { 28592 this.bindNode.execEvent(guidelib.util.GuideUtil.xfaExprMap[eventName] || eventName, detail); 28593 } 28594 } 28595 if (_.isUndefined(this._compiledExpressions[eventName]) && _.isUndefined(this._compiledScripts[eventName])) { 28596 if (!guideContainerNode._currentContext) { 28597 guideContainerNode.runPendingExpressions(); 28598 } else { 28599 this.logger().log("AF", "executeExpression called withing from another executeExpression. Should NEVER happen "); 28600 } 28601 return true; 28602 } 28603 28604 if (this.mActiveEvents[eventName]) { 28605 return; 28606 } 28607 this.mActiveEvents[eventName] = true; 28608 var managedExp = this._compiledExpressions[eventName] ? true : false, 28609 oldContext = guideContainerNode._currentContext; 28610 28611 guideContainerNode._currentContext = {contextNode : this, expression : eventName, managedExp : managedExp}; 28612 this._setExpressionContext(this, this.index); 28613 var $event = { 28614 name : eventName, 28615 target : this, 28616 data : detail 28617 }; 28618 guideContainerNode.runtime.$event = $event;
28619 var expResult = this._expressionHandler(eventName); 28620 this.mActiveEvents[eventName] = false; 28621 28622 28623 guideContainerNode._currentContext = oldContext; 28624 if (oldContext && oldContext.contextNode) { 28625 oldContext.contextNode._setExpressionContext(oldContext.contextNode, oldContext.contextNode.index); 28626 } 28627 guideContainerNode.runtime.$event = null; 28628 guideContainerNode.runPendingExpressions(); 28629 return expResult; 28630 }, 28631 28632 _setExpressionContext : function (startNode, currentIndex) { 28633 28634 var currentSom = this.somExpression; 28635 function somCommonPrefixLen(field) { 28636 return guidelib.util.GuideUtil.commonPrefixLen(currentSom, field.somExpression); 28637 } 28638 28639 if (this._guide().internal.liveModel) { 28640 _.each(this._guide().internal.liveModel.getCrossFragmentFields(), function (fields, name) { 28641 var loadedFields, 28642 nearestField; 28643 28644 28645 loadedFields = this._guide().internal.liveModel.getAllFieldModels(_.keys(fields)); 28646 28647 28648 if (!_.isEmpty(loadedFields)) { 28649 nearestField = _.max(loadedFields, somCommonPrefixLen); 28650 } 28651 28652 28653 28654 28655 28656 guidelib.util.GuideUtil._createGetterSetter(guidelib.__runtime__, name, nearestField || fields[_.keys(fields)[0]]); 28657 guidelib.util.GuideUtil._createGetterSetter(this._guide().runtime, name, nearestField || fields[_.keys(fields)[0]]); 28658 }, this); 28659 } 28660 28661 28662 this._guide().runtime._isOverriden = {}; 28663 guidelib.__runtime__._isOverriden = {}; 28664 while (startNode) { 28665 28666 startNode.nakedChildReferences(currentIndex, guidelib.__runtime__); 28667 startNode.nakedChildReferences(currentIndex, this._guide().runtime); 28668 currentIndex = startNode.index; 28669 startNode = startNode.parent; 28670 } 28671 }, 28672
28673 _expressionHandler : function (expressionName) { 28674 var expFn, returnValue; 28675 if (this._compiledExpressions[expressionName]) { 28676 expFn = this._compiledExpressions[expressionName]; 28677 try { 28678 returnValue = expFn.apply(this); 28679 } catch (exception) { 28680 28681 this.logger().error("AF", "Error in compiling expression:" + this.name + ":" + expressionName + ":" + exception.stack); 28682 } 28683 } else if (this._compiledScripts[expressionName]) { 28684 expFn = this._compiledScripts[expressionName]; 28685 try { 28686 return expFn.apply(this); 28687 } catch (scriptException) { 28688 28689 this.logger().error("AF", "Error in compiling expression:" + this.name + ":" + expressionName + ":" + scriptException.stack); 28690 } 28691 } 28692 return returnValue; 28693 }, 28694 28695 _handleXfaModelChanged : function (event) { 28696 if (event._property == "presence") { 28697 28698 var newText = !(event.newText != "visible"); 28699 this._triggerEvent(guidelib.event.GuideModelEvent.MODEL_CHANGED, "visible", event.prevText, newText); 28700 } else if (event._property == "access") { 28701 this.trigger(guidelib.event.GuideModelEvent.MODEL_CHANGED, 28702 guidelib.event.GuideModelEvent.createEvent( 28703 guidelib.event.GuideModelEvent.MODEL_CHANGED, 28704 this, 28705 "enabled", 28706 event.prevText == "open", 28707 event.newText == "open" 28708 ) 28709 ); 28710 } 28711 }, 28712 28713 _getScreenReaderText : function (index) { 28714 var screenReaderText, assistPriority = this._getAssistPriority(); 28715 if (assistPriority == "custom") { 28716 screenReaderText = this._getCustomAssist(index) || this._getToolTip(index) || this._getCaption(index) || this._getName(index); 28717 } else if (assistPriority == "shortDescription") { 28718 screenReaderText = this._getToolTip(index) || this._getCaption(index) || this._getName(index); 28719 } else if (assistPriority == "label") { 28720 screenReaderText = this._getCaption(index) || this._getName(index); 28721 } else if (assistPriority == "name") { 28722 screenReaderText = this._getName(index); 28723 } 28724 return screenReaderText; 28725 }, 28726 28727 _getAssistPriority : function () { 28728 28729 return this.getAttribute("assistPriority") || "custom"; 28730 }, 28731 28732 _getCustomAssist : function () { 28733 var customAssist; 28734 if (this.bindNode && this.bindNode.assist && this.bindNode.assist.speak && this.bindNode.assist.speak.value) { 28735 customAssist = this.bindNode.assist.speak.value; 28736 } else if (this.jsonModel.custom) { 28737 customAssist = this.jsonModel.custom; 28738 } 28739 return customAssist; 28740 }, 28741 28742 _getToolTip : function () { 28743 return this.shortDescription; 28744 }, 28745 28746 _getCaption : function () { 28747 return this.getAttribute("jcr:title"); 28748 }, 28749 28750 _getName : function (index) { 28751 return this.getAttribute("name"); 28752 }, 28753 28754 _getBindNode : function () { 28755 var bindRef = this.getAttribute("bindRef"); 28756 if (!bindRef) { 28757 return null; 28758 } 28759 var bindNode = null; 28760 var bindParent = this.parent ? this.parent._bindParent() : null; 28761 if (bindParent) { 28762 var bindParentRef = bindParent.getAttribute("bindRef"); 28763 if (bindRef.substring(0, bindParentRef.length) == bindParentRef) { 28764 28765 28766 var relativeBindRef = bindRef.substring(bindParentRef.length + 1);
28767 bindNode = bindParent.bindNode.resolveNode(relativeBindRef); 28768 } 28769 } 28770 if (!bindNode && this._isXfaNode()) { 28771 bindNode = this._xfa().resolveNode(bindRef); 28772 } 28773 return bindNode; 28774 }, 28775 28776 _bindParent : function () { 28777 if (this.bindNode) { 28778 return this; 28779 } else if (this.parent) { 28780 return this.parent._bindParent(); 28781 } 28782 return null; 28783 }, 28784 28785 28786 _getEnabled : function () { 28787 if (this.bindNode) { 28788 return this.bindNode.access == "open"; 28789 } else { 28790 return this.getAttribute("enabled") && this._parentAccess; 28791 } 28792 }, 28793 28794 28795 _setEnabled : function (value) { 28796 if (!this.bindNode) { 28797 if (this.getAttribute("enabled") !== value) { 28798 var oldEnabled = this.getAttribute("enabled"); 28799 this.setAttribute(value, "enabled"); 28800 this.trigger(guidelib.event.GuideModelEvent.MODEL_CHANGED, 28801 guidelib.event.GuideModelEvent.createEvent( 28802 guidelib.event.GuideModelEvent.MODEL_CHANGED, 28803 this, 28804 "enabled", 28805 oldEnabled, 28806 this.jsonModel.enabled 28807 ) 28808 ); 28809 this._triggerOnBridge("elementEnableChanged", this, "enablement", oldEnabled, this.jsonModel.enabled); 28810 } 28811 28812 } else { 28813 var convertor = this._guide()._guideSchema.getConvertor("enabled"); 28814 if (convertor) { 28815 this.bindNode.access = convertor.guideToXfa.apply(this, [value]); 28816 } 28817 } 28818 }, 28819 28820 28821 _setParentAccess : function (value) { 28822 var oldValue = this._parentAccess; 28823 this._parentAccess = value; 28824 this.trigger(guidelib.event.GuideModelEvent.MODEL_CHANGED, 28825 guidelib.event.GuideModelEvent.createEvent( 28826 guidelib.event.GuideModelEvent.MODEL_CHANGED, 28827 this, 28828 "enabled", 28829 oldValue, 28830 this.enabled 28831 ) 28832 ); 28833 }, 28834 28835 28836 _addStateOverride : function (key, values) { 28837 if (key !== null && _.isString(key) && values !== null) { 28838 var somExpr = this.somExpression; 28839 somExpr = somExpr.substring(this._guide().somExpression.length + 1); 28840 this.jsonModel.stateOverrides = this.jsonModel.stateOverrides || {"somExpr" : somExpr}; 28841 this.jsonModel.stateOverrides[key] = values; 28842 this._guide()._addToStateOverrideMap(this.id + this.name, this.jsonModel.stateOverrides); 28843 } 28844 } 28845 }); 28846 28847 Scriptable.defineProps({ 28848 28849 shortDescription : { 28850 get : function () { 28851 return this.getAttribute("shortDescription"); 28852 } 28853 }, 28854 28855 28856 longDescription : { 28857 get : function () { 28858 return this.getAttribute("longDescription"); 28859 } 28860 }, 28861 28862 visibleExp : { 28863 get : function () { 28864 return this.getAttribute("visibleExp"); 28865 } 28866 }, 28867 28868 initScript : { 28869 get : function () { 28870 return this.jsonModel.initScript; 28871 } 28872 }, 28873 28874 enabledExp : { 28875 get : function () { 28876 return this.getAttribute("enabledExp"); 28877 } 28878 }, 28879 28880 28881 visible : { 28882 get : function () { 28883 return this.getAttribute("visible"); 28884 }, 28885 28886 set : function (value) { 28887 if (!this.bindNode) { 28888 if (this.getAttribute("visible") !== value) { 28889 var oldVisible = this.getAttribute("visible"), 28890 dorExclusionFlag; 28891 this.setAttribute(value, "visible"); 28892 28893 28894 if (this.getAttribute("dorExclusion") !== null) { 28895 if ((this._guide().getAttribute("excludeFromDoRIfHidden") === "true") 28896 || (this._guide().print 28897 && this._guide().print["excludeFromDoRIfHidden"] === "true")) { 28898 dorExclusionFlag = !value; 28899 28900 28901 this.dorExclusion = dorExclusionFlag; 28902 } 28903 } 28904 this.trigger(guidelib.event.GuideModelEvent.MODEL_CHANGED, 28905 guidelib.event.GuideModelEvent.createEvent( 28906 guidelib.event.GuideModelEvent.MODEL_CHANGED, 28907 this, 28908 "visible", 28909 oldVisible, 28910 this.jsonModel.visible 28911 ) 28912 ); 28913 this._triggerOnBridge("elementVisibleChanged", this, "visible", oldVisible, this.jsonModel.visible); 28914 28915 } 28916 } else { 28917 if (value == true) { 28918 this.bindNode.presence = "visible"; 28919 } else { 28920 this.bindNode.presence = "hidden"; 28921 } 28922 } 28923 } 28924 }, 28925 28926 28927 dorExclusion : { 28928 get : function () { 28929 28930 if (this.jsonModel.dorExclusion != null) { 28931 if (_.isString(this.jsonModel.dorExclusion)) { 28932 28933 return this.jsonModel.dorExclusion === "true"; 28934 } else { 28935 return this.jsonModel.dorExclusion; 28936 } 28937 } 28938 28939 else if ((this._guide().getAttribute("excludeFromDoRIfHidden") === "true") 28940 || (this._guide().print 28941 && this._guide().print["excludeFromDoRIfHidden"] === "true")) { 28942 return !this.visible; 28943 } else { 28944 28945 return false;
28946 } 28947 }, 28948 28949 set : function (value) { 28950 28951 28952 28953 var somExpr = this.somExpression; 28954 somExpr = somExpr.substring(this._guide().somExpression.length + 1); 28955 this._guide()._addToExcludeFromDorMap(somExpr, value); 28956 this.jsonModel.dorExclusion = value; 28957 } 28958 }, 28959 28960 28961 stateOverrides : { 28962 get : function () { 28963 return this.jsonModel.stateOverrides; 28964 } 28965 }, 28966 28967 28968 enabled : { 28969 get : function () { 28970 return this._getEnabled(); 28971 }, 28972 28973 set : function (value) { 28974 28975 this._setEnabled(!!value); 28976 } 28977 }, 28978 28979 28980 bindRef : { 28981 get : function () { 28982 return (this.getAttribute("bindRef") || "").replace(/\s+/g, ''); 28983 } 28984 }, 28985 28986 28987 isXsd : { 28988 28989 get : function () { 28990 return _.isString(guideBridge._guide.xsdRef) && !_.isEmpty(this.bindRef) && this.bindRef[0] === '/'; 28991 } 28992 } 28993 }); 28994})(_, window.xfalib, guidelib); 28995(function (_, guidelib) { 28996 var GuideImage = guidelib.model.GuideImage = guidelib.model.Scriptable.extend({ 28997 msClassName : "guideImage" 28998 }); 28999 29000 GuideImage.defineProps({ 29001 value : { 29002 get : function () { 29003 if (this.bindNode) { 29004 return this.bindNode.rawValue; 29005 } else { 29006 return null; 29007 } 29008 } 29009 } 29010 }); 29011})(_, guidelib); 29012(function (_, guidelib) { 29013 var GuideAdModule = guidelib.model.GuideAdModule = guidelib.model.Scriptable.extend({ 29014 msClassName : "guideAdModule", 29015 29016 initialize : function () { 29017 GuideAdModule._super.initialize.call(this); 29018 this.jsonModel["{default}"] = this.getOrElse(this.jsonModel, "{default}", this.jsonModel._value); 29019 this.layoutConfigs = []; 29020 29021 if (typeof this.jsonModel.layoutConfig === "string") { 29022 this.layoutConfigs.push(JSON.parse(this.jsonModel.layoutConfig)); 29023 } else { 29024 _.each(this.jsonModel.layoutConfig, function (layoutConfig) { 29025 this.layoutConfigs.push(JSON.parse(layoutConfig)); 29026 }, this); 29027 } 29028 }, 29029 29030 _getTypedValue : function (value) { 29031 if (_.isUndefined(value) || value === null || value === "") { 29032 return null; 29033 } 29034 return value + ""; 29035 }, 29036 29037 playJson : function (pJsonModel) { 29038 var olval = this.jsonModel._value; 29039 this.jsonModel._value = pJsonModel._value; 29040 this._triggerOnBridge("elementValueChanged", this, "value", olval, this.jsonModel._value); 29041 } 29042 }); 29043 29044 GuideAdModule.defineProps({ 29045 29046 value : { 29047 get : function () { 29048 return this._getTypedValue(this.jsonModel._value); 29049 }, 29050 set : function (newValue) { 29051 var oldValue = this._getTypedValue(this.jsonModel._value), 29052 newTypedValue = this._getTypedValue(newValue); 29053 29054 if (newTypedValue !== undefined && (newTypedValue !== oldValue)) { 29055 if (this.jsonModel._value !== newValue) { 29056 this.jsonModel._value = newTypedValue || ""; 29057 } 29058 this._triggerOnBridge("elementValueChanged", this, "value", oldValue, newTypedValue); 29059 } 29060 } 29061 } 29062 }); 29063}(_, guidelib)); 29064(function (_, $) { 29065 29066 var Responsive = { 29067 breakpoints : [], 29068 controlRowDefaults : {} 29069 }, 29070 isPad = navigator.userAgent.match(/iPad/i) !== null, 29071 isIphone = (navigator.userAgent.match(/iPhone/i) !== null) || (navigator.userAgent.match(/iPod/i) !== null), 29072 isIphoneOrIpad = isPad || isIphone; 29073 29074 Responsive.breakpoints = [ 29075 { 29076 name : 'desktop', 29077 width : Infinity 29078 }, 29079 { 29080 name : 'tablet-landscape', 29081 width : 1024 29082 }, 29083 { 29084 name : 'tablet-potrait', 29085 width : 768 29086 }, 29087 { 29088 name : 'mobile-landscape', 29089 width : 480 29090 }, 29091 { 29092 name : 'mobile-potrait', 29093 width : 320 29094 } 29095 ]; 29096 29097 29098 Responsive.controlRowDefaults = { 29099 29100 breakpoints : Responsive.breakpoints, 29101 29102
29103 controlRowDetails : { 29104 renderer : function (tablePlugin, row) { 29105 var cells = null; 29106 if (tablePlugin.options.bControlRowHiddenCells) { 29107 cells = row.$tableRowElement.find("td:hidden"); 29108 } else { 29109 cells = row.$tableRowElement.find("td"); 29110 29111 if (tablePlugin.options.bDisableControlRowCells) { 29112 29113 row.$tableRowElement.find("input, select, textarea, button").attr("disabled", "disabled"); 29114 } 29115 } 29116 var data = cells.map(function (index, cell) { 29117 var $cell = $(cell), 29118 header = tablePlugin.header($cell), 29119 $clickedTableRow = row.$tableRowElement, 29120 cellIdx = null, 29121 cellData = null; 29122 cellIdx = { 29123 29124 row : $clickedTableRow.index(), 29125 column : $cell.index() 29126 }; 29127 29128 cellData = tablePlugin._getCellData(cellIdx); 29129 return $("<li></li>").attr("data-rtp-index", cellIdx.column).addClass("clearfix").append( 29130 $("<div></div>").addClass("rtp-title").text($.trim(header.text())) 29131 ).append( 29132 $("<div></div>").addClass("rtp-data").append(cellData) 29133 ); 29134 }); 29135 29136 return $('<ul data-rtp-index="' + row.index + '"></ul>').append(data.get()); 29137 }, 29138 29139 target : 0, 29140 29141 type : 'inline' 29142 } 29143 }; 29144 29145 var ResponsiveTablePlugin = function (element, options) { 29146 this.options = options; 29147 this.$element = $(element); 29148 this.columns = []; 29149 }; 29150 29151 29152 var TableColumn = function ($tableElement, colIdx, bIsResize) { 29153 var $colHeaderElement = $tableElement.find("th").eq(colIdx); 29154 29155 this.minWidth = (bIsResize ? (parseInt($colHeaderElement.css("min-width"), 10)) : $colHeaderElement.outerWidth()); 29156 this.header = $colHeaderElement; 29157 this.colIndex = colIdx; 29158 this.$tableElement = $tableElement; 29159 }; 29160 29161 29162 TableColumn.prototype = { 29163 29164 cells : function () { 29165 29166 var headerValue = this.header.attr("id"); 29167 return this.$tableElement.find("tr td").filter(function () { 29168 var id = $(this).attr("headers"); 29169 if (id) { 29170 if (id.indexOf(headerValue) > -1) { 29171 return $(this); 29172 } 29173 } 29174 }); 29175 }, 29176 29177 visible : function (bFlag) { 29178 var cells = this.cells(); 29179 this.isVisible = bFlag; 29180 if (bFlag === true) { 29181 cells.show(); 29182 this.header.show(); 29183 } else { 29184 this.header.hide(); 29185 29186 var headers = this.header.prevAll().filter(":visible"), 29187 headerLen = headers.length; 29188 29189 $.each(cells, function () { 29190 if (!$(this).data("shown")) { 29191 $(this).hide(); 29192 } 29193 var colSpan = $(this).data("colspan") || $(this).attr("colspan"); 29194 29195 if (colSpan > 1) { 29196 var totalColSpan = 0; 29197 $(this).prevAll().each(function () { 29198 totalColSpan += (+($(this).data("colspan") || $(this).attr("colspan"))); 29199 }); 29200 29201 if (totalColSpan == 0) { 29202 $(this).show(); 29203 $(this).data("shown", true); 29204 29205 if ($(this).data("colspan") == null) { 29206 $(this).data("colspan", $(this).attr("colspan")); 29207 } 29208 $(this).attr("colspan", headerLen); 29209 } 29210 29211 else if (totalColSpan < headerLen) { 29212 $(this).show(); 29213 $(this).data("shown", true);
29214 if ($(this).data("colspan") == null) { 29215 $(this).data("colspan", $(this).attr("colspan")); 29216 } 29217 $(this).attr("colspan", (headerLen - totalColSpan)); 29218 } 29219 } 29220 }); 29221 } 29222 } 29223 }; 29224 29225 29226 var TableRow = function ($tableRowElement) { 29227 this.$tableRowElement = $tableRowElement; 29228 this.index = $tableRowElement.index(); 29229 29230 this.child = { 29231 $element : null, 29232 isShown : false 29233 }; 29234 $tableRowElement.data("tableRow", this); 29235 }; 29236 29237 TableRow.prototype = { 29238 29239 updateChild : function (info, colSpan) { 29240 29241 if (this.child.$element && this.child.$element.length > 0) { 29242 this.child.$element.empty(); 29243 this.child.$element.append($("<td></td>").addClass(ResponsiveTablePlugin.prototype.defaults.CONTROL_ROW_CLASS).attr("colspan", colSpan).append($(info))); 29244 } else if (this.$tableRowElement.next(ResponsiveTablePlugin.prototype.defaults.CONTROL_ROW_SELECTOR).length > 0) { 29245 this.child.$element = this.$tableRowElement.next(); 29246 this.child.$element.append($("<td></td>").addClass(ResponsiveTablePlugin.prototype.defaults.CONTROL_ROW_CLASS).attr("colspan", colSpan).append($(info))); 29247 } else { 29248 29249 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))); 29250 29251 this.$tableRowElement.after(this.child.$element); 29252 } 29253 29254 }, 29255 29256 showChild : function () { 29257 29258 this.child.$element.get(0).style.display = ""; 29259 this.child.isShown = true; 29260 }, 29261 29262 hideChild : function () { 29263 this.child.$element.hide(); 29264 this.child.isShown = false; 29265 } 29266 }; 29267 29268 ResponsiveTablePlugin.prototype = { 29269 29270 _getCellData : function (index) { 29271 29272 var tableRow = this.$element.find("tbody tr").eq(index.row), 29273 tableCell = tableRow.find("td").eq(index.column); 29274 29275 if (this.options.viewCallback) { 29276 29277 var id = tableCell.find(ResponsiveTablePlugin.prototype.defaults.GUIDE_ID_SELECTOR).attr("id"); 29278 29279 return this.options.viewCallback(id); 29280 } else { 29281 return tableCell.html(); 29282 } 29283 }, 29284 29285 29286 header : function (cell) { 29287 29288 29289 var id = cell.attr("headers").split(" ")[0]; 29290 29291 return this.$element.find("#" + id); 29292 }, 29293 29294 initializeColumns : function (bIsResize) { 29295 var columns = []; 29296 29297 29298 29299 this.colLength = this.$element.find("th").length; 29300 for (var colIdx = 0; colIdx < this.colLength; colIdx++) { 29301 29302 29303 columns.push(new TableColumn(this.$element, colIdx, bIsResize)); 29304 } 29305 return columns; 29306 }, 29307 29308 29309 _initializeColumnWidth : function () { 29310 29311 29312 29313 var display = this._getColumnsVisibility(), 29314 29315 visibleColumns = _.filter(display, function (item) { 29316 return item == true; 29317 }).length, 29318 $allTableHeaders = this.$element.find("th"), 29319 $tableHeader = null, 29320 width = null, 29321 sum = 0; 29322 if (!this.options.bAutoWidth) { 29323 29324 29325 for (var i = 0; i < visibleColumns; i++) { 29326 sum += parseInt(this.options.aWidth[i], 10); 29327 } 29328 } else { 29329 sum = visibleColumns; 29330 } 29331 29332 if (display.length == this.colLength) { 29333 for (var i = 0; i < visibleColumns; i++) { 29334 if (this.options.aWidth) { 29335 29336 width = ((Math.floor((this.options.aWidth[i] * 100) / sum)) + "%"); 29337 } else { 29338 width = ((Math.floor((1 * 100) / sum)) + "%"); 29339 } 29340 $tableHeader = $allTableHeaders.eq(i); 29341 29342 29343 $tableHeader[0].style.width = width; 29344 } 29345 } 29346 }, 29347 29348 _constructor : function () { 29349 var that = this; 29350 29351 this.controlRow = $.extend(true, {}, Responsive.controlRowDefaults); 29352 this.columns = this.initializeColumns(); 29353 29354 $(window).on("resize orientationchange", function (event) { 29355 that._initializeColumnVisibility(event); 29356 }); 29357 29358 29359 29360 this.controlRow.breakpoints.sort(function (a, b) { 29361 return a.width < b.width ? 1 : 29362 a.width > b.width ? -1 : 0; 29363 }); 29364 this._initializeColumnVisibility(); 29365 29366 this._controlRowInitialization(); 29367 }, 29368 29369 _initializeColumnVisibility : function (event) { 29370 var that = this; 29371 29372 if (event) { 29373 29374 29375 this.$element.find("td").each(function () { 29376 $(this).removeData("shown"); 29377
29378 if ($(this).data("colspan") != null) { 29379 29380 $(this).attr("colspan", $(this).data("colspan")); 29381 } 29382 }); 29383 29384 29385 29386 this.columns = this.initializeColumns(event); 29387 } 29388 29389 29390 29391 29392 this._initializeColumnWidth(); 29393 this.display = this._resize(); 29394 29395 29396 this.$element.find("tbody tr:not(.child)").each(function () { 29397 if ($(this).next(ResponsiveTablePlugin.prototype.defaults.CONTROL_ROW_SELECTOR).length == 0) { 29398 $(this).after($("<tr></tr>").addClass(ResponsiveTablePlugin.prototype.defaults.CONTROL_ROW_CLASS).hide()); 29399 } 29400 }); 29401 29402 29403 var details = this.controlRow.controlRowDetails; 29404 29405 if (details.type) { 29406 29407 this._controlRowVisibility(event); 29408 29409 29410 this.$element.on(ResponsiveTablePlugin.prototype.defaults.EVENT_COLUMN_VISIBILITY, function () { 29411 that._controlRowVisibility(); 29412 }); 29413 29414 this.$element.addClass('rtp-' + details.type); 29415 } 29416 29417 if (this.options.fixTableControls) { 29418 29419 29420 29421 if (_.isUndefined(event) || event.type === "orientationchange" || (event.type === "resize" && !isIphoneOrIpad)) { 29422 29423 this.options.fixTableControls(event); 29424 } 29425 } 29426 }, 29427 29428 29429 _fixControlRows : function () { 29430 this.$element.find(ResponsiveTablePlugin.prototype.defaults.CONTROL_ROW_SELECTOR).remove(); 29431 }, 29432 29433 29434 isColumnHidden : function () { 29435 return this.bColumnHidden || false; 29436 }, 29437 29438 29439 _rearrangeTableRuntimeControls : function (lastVisibleColumn, event) { 29440 29441 29442 var $runtimeAddControls = this.$element.find(".guideTableRuntimeControls .guideTableRuntimeAddControl"), 29443 runtimeControlIndex = 0, 29444 that = this, 29445 index = null; 29446 $runtimeAddControls.each(function () { 29447 29448 if ($(this).is(":visible")) { 29449 runtimeControlIndex = $(this).closest("td").index(); 29450 return false; 29451 } 29452 }); 29453 29454 if ((runtimeControlIndex <= lastVisibleColumn)) { 29455 29456 29457 $runtimeAddControls.each(function () { 29458 29459 29460 var $runtimeControl = $(this).closest(".guideTableRuntimeControls"), 29461 $runtimeControlTableRow = $(this).closest("tr"); 29462 if ($runtimeControl.hasClass("guideTableRuntimeRightControls")) { 29463 29464 $runtimeControl.appendTo($runtimeControlTableRow.find("td").eq(lastVisibleColumn)); 29465 if (runtimeControlIndex !== lastVisibleColumn) { 29466 var $component = $runtimeControl.prev(); 29467 $component.css("display", "block"); 29468 $component.css("float", "none"); 29469 } 29470 } 29471 29472 }); 29473 } 29474 }, 29475 29476 29477 _controlRowVisibility : function (event) { 29478 var that = this, 29479 29480 hiddenColumns = _.filter(this.columns, function (element) { 29481 return (element.isVisible) !== true; 29482 }), 29483 lastVisibleColumn = this.columns.length - hiddenColumns.length; 29484 29485 29486 this._rearrangeTableRuntimeControls(lastVisibleColumn - 1, event); 29487 29488 if (hiddenColumns && hiddenColumns.length > 0) { 29489 29490 this.$element.addClass('collapsed'); 29491 29492 this.bColumnHidden = true; } else { 29493 29494 this.$element.removeClass('collapsed'); 29495 29496 this.bColumnHidden = false;
29497 } 29498 }, 29499 29500 29501 _controlRowInitialization : function () { 29502 var that = this; 29503 var details = this.controlRow.controlRowDetails; 29504 29505 29506 if (details.type === 'inline') { 29507 29508 details.target = ("." + (this.options.tableRuntimeEditControlClass || "tableRuntimeEditControl")); 29509 } 29510 29511 29512 29513 29514 var target = details.target; 29515 var selector = typeof target === 'string' ? target : 'td'; 29516 29517 29518 this.$element.on('click keypress', selector, function (e) { 29519 29520 29521 if ((e.type == "keypress" && e.keyCode == 13) || e.type == "click") { 29522 29523 if (!that.$element.hasClass('collapsed')) { 29524 return; 29525 } 29526 29527 var $row = $(this).closest('tr'), 29528 rowData = $row.data("tableRow"), 29529 row = rowData; 29530 29531 29532 29533 if (row == null || row.child.$element.parent().length === 0) { 29534 row = new TableRow($row); 29535 $row.data("tableRow", row); 29536 } 29537 if (row.child.isShown) { 29538 row.hideChild(); 29539 row.$tableRowElement.removeClass('parent'); 29540 } else { 29541 var info = that.controlRow.controlRowDetails.renderer(that, row); 29542 row.updateChild(info, that.colLength); 29543 row.showChild(); 29544 row.$tableRowElement.addClass('parent'); 29545 29546 row.child.$element.find("input, select, textarea, button").eq(0).focus(); 29547 } 29548 } 29549 }); 29550 }, 29551 29552 29553 _resize : function () { 29554 var width = $(window).width(); 29555 var breakpoints = this.controlRow.breakpoints; 29556 var breakpoint = breakpoints[0].name; 29557 29558 29559 for (var i = breakpoints.length - 1 ; i >= 0 ; i--) { 29560 if (width <= breakpoints[i].width) { 29561 breakpoint = breakpoints[i].name; 29562 break; 29563 } 29564 } 29565 29566 29567 var display = this._getColumnsVisibility(breakpoint); 29568 29569 _.each(this.columns, function (item, index) { 29570 item.visible(display[index]); 29571 }); 29572 29573 return display; 29574 }, 29575 29576 29577 _getColumnsVisibility : function (breakpoint) { 29578 var columns = this.columns, 29579 i, 29580 len = this.$element.find("th"), 29581 display = []; 29582 29583 29584 var widthAvailable = this.$element.parent().outerWidth(); 29585 var usedWidth = widthAvailable; 29586 29587 29588 29589 display = _.map(columns, function (item) { 29590 usedWidth -= item.minWidth; 29591 return ((usedWidth < 0) ? false : true); 29592 }); 29593 29594 29595 display[0] = true; 29596 return display; 29597 } 29598 29599 }; 29600 29601 $.fn.responsiveTablePlugin = function (option, value) { 29602 var get = '', 29603 element = this.each(function () { 29604 29605 if ($(this).is('table') === true) { 29606 var $this = $(this), 29607 data = $this.data('responsiveTablePlugin'), 29608 options = $.extend({}, ResponsiveTablePlugin.prototype.defaults, typeof option === 'object' && option); 29609 29610 29611 if (!data) { 29612 $this.data('responsiveTablePlugin', (data = new ResponsiveTablePlugin(this, options))); 29613 data._constructor(); 29614 } 29615 29616 29617 if (typeof option === 'string') { 29618 get = data[option](value); 29619 } 29620 } 29621 }); 29622 29623 if (get != "") { 29624 return get; 29625 } else { 29626 return element; 29627 } 29628 }; 29629 29630 ResponsiveTablePlugin.prototype.defaults = { 29631 29632 EVENT_COLUMN_VISIBILITY : "responsiveTablePlugin.columnVisibility", 29633 GUIDE_ID_SELECTOR : "div[data-guide-view-bind]", 29634 CONTROL_ROW_CLASS : "child", 29635 CONTROL_ROW_SELECTOR : "tr.child" 29636 }; 29637 29638})(_, $); 29639(function ($, _, guidelib) { 29640 29641 29642 var getPanelsWithNumericFields = function (panels, fieldName) { 29643 if (_.isUndefined(panels) || panels === null) { 29644 return []; 29645 } 29646 if (!_.isArray(panels)) { 29647 panels = [panels]; 29648 } 29649 return _.filter(panels, function (panel) { 29650 return panel instanceof guidelib.model.GuidePanel 29651 && panel[fieldName] instanceof guidelib.model.GuideNumericBox; 29652 }); 29653 }, 29654 29655 sum = function (numPanels, fieldName) { 29656 return _.reduce(numPanels, 29657 function (memo, currentItem) { 29658 var curValue = parseFloat(currentItem.getOrElse(currentItem, fieldName + ".value", 0)); 29659 if (isNaN(curValue)) { 29660 curValue = 0; 29661 } 29662 return memo + curValue; 29663 }, 0); 29664 }; 29665 29666 29667 guidelib.__runtime__.af.sum = function (panels, fieldName) { 29668 return sum(getPanelsWithNumericFields(panels, fieldName), fieldName); 29669 }; 29670 29671 29672 guidelib.__runtime__.af.avg = function (panels, fieldName) { 29673 var n_panels = getPanelsWithNumericFields(panels, fieldName), 29674 total = sum(n_panels, fieldName); 29675 if (n_panels.length === 0) { 29676 return 0; 29677 } 29678 return total / n_panels.length; 29679 }; 29680 29681 29682 guidelib.__runtime__.af.max = function (panels, fieldName) { 29683 var panel = _.max(getPanelsWithNumericFields(panels, fieldName), function (panel) { 29684 return panel.getOrElse(panel, fieldName + ".value", Number.NEGATIVE_INFINITY); 29685 }); 29686 if (panel instanceof guidelib.model.GuidePanel) { 29687 return panel[fieldName]; 29688 } 29689 return null; 29690 }; 29691 29692 29693 guidelib.__runtime__.af.min = function (panels, fieldName) { 29694 var panel = _.min(getPanelsWithNumericFields(panels, fieldName), function (panel) { 29695 return panel.getOrElse(panel, fieldName + ".value", Number.POSITIVE_INFINITY); 29696 }); 29697 if (panel instanceof guidelib.model.GuidePanel) { 29698 return panel[fieldName]; 29699 } 29700 return null; 29701 }; 29702 29703}($, _, guidelib)); 29704(function (_, guidelib) { 29705 29706 29707 var GuideProgressiveSection = guidelib.model.GuideProgressiveSection = xfalib.ut.EventClass.extend({ 29708 msClassName : "guideProgressiveSection", 29709 29710 initialize : function () { 29711 29712 this.jsonModel = this.options.jsonModel; 29713 this.instanceIndex = this.options.instanceIndex; 29714 this.instance = this.options.instance; 29715 29716 29717 this.parent = this.options.parent; 29718 29719 29720 this._currActivePart = 0; 29721 29722 this.className = this.jsonModel.guideNodeClass || this.msClassName; 29723 29724 this._parts = []; 29725 29726 this.initializeChildren(); 29727 29728 }, 29729 29730 _getChildModelFromId : function (id) { 29731 return this.childIdToModel[id]; 29732 }, 29733 29734 initializeChildren : function () { 29735 var that = this, 29736 29737 fields = this.jsonModel.fields; 29738 this.children = this.children || []; 29739 this.childIdToModel = this.childIdToModel || {}; 29740 29741 29742 _.each(fields, function (item) { 29743 var model = guideBridge._resolveId(item.id); 29744 that.children.push(model); 29745 that.childIdToModel[item.id] = model; 29746 }); 29747 }, 29748 29749 setFocus : function () { 29750 29751 this._triggerEvent(guidelib.event.GuideModelEvent.NAVIGATE_SECTION, "navigateWithinSection", 29752 null, null); 29753 }, 29754 29755 _triggerEvent : function (event, propName, prevText, newText) { 29756 guidelib.model.GuideNode.prototype._triggerEvent.apply(this, arguments); 29757 }, 29758 29759 playJson : function (pJsonModel) { 29760 29761 29762 this.jsonModel = _.extend({}, pJsonModel); 29763 } 29764 29765 }); 29766 29767 GuideProgressiveSection.defineProps({ 29768 sectionId : { 29769 get : function () { 29770 return this.jsonModel.id; 29771 } 29772 }, 29773 29774 29775 activePart : { 29776 get : function () { 29777 return this._parts[this._currActivePart]; 29778 } 29779 }, 29780 29781 isLastPart : { 29782 get : function () { 29783 return (this._currActivePart === (this._parts.length - 1)); 29784 } 29785 }, 29786 29787 isFirstPart : { 29788 get : function () { 29789 return this._currActivePart === 0; 29790 } 29791 }, 29792 29793 29794 currentActivePart : { 29795 29796 29797 set : function (activePartIndex) { 29798 this._currActivePart = activePartIndex; 29799 }, 29800 29801 get : function () { 29802 return this._currActivePart; 29803 } 29804 }, 29805 29806 sectionTitle : { 29807 get : function () { 29808 return this.jsonModel.title; 29809 } 29810 }, 29811 29812 29813 sectionName : { 29814 get : function () { 29815 return this.jsonModel.name; 29816 } 29817 }, 29818 29819 sectionFields : { 29820 get : function () { 29821 return this.jsonModel.fields; 29822 } 29823 }, 29824 29825 29826 fetchedFromService : { 29827 29828 get : function () { 29829 return this.jsonModel.fetchedFromService === "true"; 29830 } 29831 }, 29832 29833 repeatablePanelPath : { 29834 get : function () { 29835 return this.jsonModel.repeatablePanelPath; 29836 } 29837 }, 29838 29839 repeatablePanelId : { 29840 get : function () { 29841 return this.jsonModel.repeatablePanelId; 29842 } 29843 } 29844 29845 }); 29846})(_, guidelib); 29847 29848(function (_, guidelib) { 29849 29850 29851 var GuideProgressiveCompletionSection = guidelib.model.GuideProgressiveCompletionSection = guidelib.model.GuideProgressiveSection.extend({ 29852 msClassName : "guideProgressiveCompletionSection" 29853 29854 }); 29855 29856 GuideProgressiveCompletionSection.defineProps({ 29857 sectionId : { 29858 get : function () { 29859 return this.jsonModel.id; 29860 } 29861 }, 29862 29863 sectionTitle : { 29864 get : function () { 29865 return this.jsonModel.completionTitle; 29866 } 29867 }, 29868 29869 completionScript : { 29870 get : function () { 29871 return this.jsonModel.completionScript; 29872 } 29873 }, 29874 29875 completionBeforeMessage : { 29876 get : function () { 29877 return this.jsonModel.completionBeforeMessage; 29878 } 29879 }, 29880 29881 completionAfterMessage : { 29882 get : function () { 29883 return this.jsonModel.completionAfterMessage; 29884 } 29885 }, 29886 29887 completionSuccessScript : { 29888 get : function () { 29889 return this.jsonModel.completionSuccessScript; 29890 } 29891 }, 29892 29893 completionFailureScript : { 29894 get : function () { 29895 return this.jsonModel.completionFailureScript; 29896 } 29897 } 29898 29899 }); 29900})(_, guidelib); 29901 29902(function (_, guidelib) { 29903 29904 var currActivePart = 0; 29905 29906 29907 var GuideProgressiveRepeatableSectionManager = guidelib.model.GuideProgressiveRepeatableSectionManager = guidelib.model.GuideProgressiveSection.extend({ 29908 msClassName : "guideProgressiveRepeatableSectionManager", 29909 29910 initialize : function () { 29911 GuideProgressiveRepeatableSectionManager._super.initialize.apply(this, arguments); 29912 this.isRepeatable = true; 29913 this._instances = this._instances || []; 29914 29915 this._initializeRepeatability(); 29916 29917 }, 29918 29919 _getSectionFromPanelId : function (panel) { 29920 return _.find(this._instances, function (item) { 29921 return item.instance.id === panel.id; 29922 }); 29923 }, 29924 29925 insertInstance : function (index) { 29926 29927 29928 var insertedInstance = this.instanceManager.insertInstance(index), 29929 section; 29930 29931 if (insertedInstance != null) { 29932 section = this._getSection(insertedInstance); 29933 if (section != null) { 29934 29935 this._instances.splice(index, 0, section); 29936 29937 guidelib.runtime.progressive.addRepeatable(section); 29938 } 29939 } 29940 }, 29941 29942 removeInstance : function (panel) { 29943 var id = panel.id, 29944 index = panel.instanceIndex; 29945 29946 if (index > -1 29947 && this.instanceManager.instanceCount > this.instanceManager.minOccur 29948 && index < this.instanceManager.instanceCount) { 29949 29950 this.instanceManager.removeInstance(index); 29951 29952 this._instances.splice(index, 1); 29953 29954 guidelib.runtime.progressive.deleteRepeatable(id); 29955 } 29956 }, 29957 29958 29959 _getSection : function (panel) { 29960 var section = null, 29961 clonedJson = {}, 29962 id = panel.id, 29963 templateId = panel.templateId, 29964 uniquePrefix = null; 29965 if (id !== templateId) { 29966 29967 29968 uniquePrefix = id.substring(0, id.indexOf(templateId) - 2); 29969 29970 this.copyObject(this.jsonModel, clonedJson, 29971 { 29972 transformMaps : { 29973 "id" : function (srcValue, options, parentObj) { 29974 29975
29976 if (parentObj.guideNodeClass && parentObj.guideNodeClass.indexOf("Progressive") !== -1) { 29977 return srcValue; 29978 } else { 29979 29980 return uniquePrefix + "__" + srcValue; 29981 } 29982 } 29983 } 29984 } 29985 ); 29986 } else { 29987 clonedJson = _.extend({}, this.jsonModel); 29988 } 29989 if (panel != null) { 29990 section = new guidelib.model.GuideProgressiveSection({ 29991 "jsonModel" : clonedJson, 29992 "instanceIndex" : panel.instanceIndex, 29993 "parent" : this, 29994 "instance" : this.instanceManager.instances[panel.instanceIndex] 29995 }); 29996 } 29997 return section; 29998 }, 29999 30000 _initializeRepeatability : function () { 30001 var model = guideBridge._resolveId(this.repeatablePanelId), 30002 oneActive = true, 30003 that = this, 30004 childView; 30005 30006 this.activeInstanceIndex = 0; 30007 30008 30009 30010 30011 30012 if (model == null) { 30013 30014 this.instanceManager = guideBridge._resolveId("im_" + this.repeatablePanelId); 30015 } else { 30016 this.instanceManager = model.instanceManager; 30017 } 30018 30019 if (this.instanceManager != null && this.instanceManager.instances && this.instanceManager.instances.length > 0) { 30020 30021 _.each(this.instanceManager.instances, function (modelInstance) { 30022 30023 that._instances.push(that._getSection(modelInstance)); 30024 }); 30025 } 30026 }, 30027 30028 _getChildModelFromId : function (id) { 30029 return this.childIdToModel[id]; 30030 }, 30031 30032 initializeChildren : function () { 30033 var that = this; 30034 this.children = this.children || []; 30035 this.childIdToModel = this.childIdToModel || {}; 30036 30037 _.each(this.jsonModel.fields, function (item) { 30038 var model = guideBridge._resolveId(item.id); 30039 that.children.push(model); 30040 that.childIdToModel[item.id] = model; 30041 }); 30042 }, 30043 30044 setFocus : function () { 30045 30046 this._triggerEvent(guidelib.event.GuideModelEvent.NAVIGATE_SECTION, "navigateWithinSection", 30047 null, null); 30048 }, 30049 30050 playJson : function (pJsonModel) { 30051 30052 30053 this.jsonModel = _.extend({}, pJsonModel); 30054 } 30055 }); 30056 GuideProgressiveRepeatableSectionManager.defineProps({ 30057 activeInstance : { 30058 set : function (panelId) { 30059 this.activeInstanceIndex = guideBridge._resolveId(panelId).instanceIndex; 30060 }, 30061 30062 get : function () { 30063 return this._instances[this.activeInstanceIndex]; 30064 } 30065 } 30066 30067 }); 30068 30069})(_, guidelib); 30070 30071(function ($, _, guidelib) { 30072 30073 30074 30075 guidelib.__runtime__.af.reduce = function (panels, fieldName, iterator, memo, context) { 30076 if (!_.isArray(panels)) { 30077 panels = [panels]; 30078 } 30079 return _.reduce(panels, function (memo, panel) { 30080 if (panel instanceof guidelib.model.GuidePanel && !_.isUndefined(panel[fieldName])) { 30081 if (_.isFunction(iterator)) { 30082 return iterator.apply(context, [memo, panel, panel[fieldName]]); 30083 } 30084 } 30085 return memo; 30086 }, memo); 30087 }; 30088 30089 30090 30091 guidelib.__runtime__.af.filter = function (panels, fieldName, predicate, context) { 30092 if (!_.isArray(panels)) { 30093 panels = [panels]; 30094 } 30095 return _.map( 30096 _.filter(panels, function (panel) { 30097 if (panel instanceof guidelib.model.GuidePanel && !_.isUndefined(panel[fieldName])) { 30098 if (_.isFunction(predicate)) { 30099 return predicate.apply(context, [panel, panel[fieldName]]); 30100 } 30101 return false;
30102 } 30103 }), 30104 function (panel) { 30105 return panel[fieldName]; 30106 } 30107 ); 30108 }; 30109 30110 guidelib.__runtime__.af.formatDateToISOString = function (dateObject) { 30111 var day, month, year; 30112 if (!_.isUndefined(dateObject) && _.isObject(dateObject)) { 30113 day = dateObject.getDate().toString(); 30114 30115 month = (dateObject.getMonth() + 1).toString(); 30116 year = dateObject.getFullYear().toString(); 30117 if (month.length === 1) { 30118 month = "0" + month.toString(); 30119 } 30120 30121 return year + "-" + month + "-" + day; 30122 30123 } 30124 }; 30125}($, _, guidelib)); 30126(function (_, guidelib) { 30127 30128 var GuideNavigationContext = guidelib.model.util.GuideNavigationContext = xfalib.ut.Class.extend({ 30129 msClassName : "guideNavigationContext", 30130 initialize : function () { 30131 GuideNavigationContext._super.initialize.call(this); 30132 this._currentItem = this.options.currentItem; 30133 this._parentPanel = this.options.parentPanel; 30134 this.guideUtil = guidelib.util.GuideUtil; 30135 }, 30136 30137 getQualifiedNamedItem : function (qName) { 30138 var navItems = this._getNavigableItems(); 30139 var qItem = _.find(navItems, function (item) { 30140 return (item._escapeQualifiedName() == qName); 30141 }, this); 30142 return qItem; 30143 }, 30144 30145 getItemForNav : function (navToken) { 30146 if (navToken == "prevItem" || navToken == "nextItem" || navToken == "firstItem" || navToken == "lastItem") { 30147 return this[navToken]; 30148 } else { 30149 return this.getQualifiedNamedItem(navToken); 30150 } 30151 }, 30152 30153 30154 _isNavigableItem : function (item) { 30155 return item.visible; 30156 }, 30157 30158 30159 _isNavigablePanel : function (item) { 30160 if (item && item instanceof guidelib.model.GuidePanel) { 30161 return item.visible && item.isNavigable; 30162 } 30163 }, 30164 30165 _getNavigableItems : function () { 30166 var navItems = _.filter(this._parentPanel.items, function (item) { 30167 return this._isNavigableItem(item); 30168 }, this); 30169 return navItems; 30170 }, 30171 30172 _getNavigableDescendant : function (navigableAncestor) { 30173 30174 30175 if (navigableAncestor && navigableAncestor != this._parentPanel) { 30176 var currentItem = navigableAncestor.parent._navigationContext.currentItem, 30177 deepItem = null; 30178 while (currentItem instanceof guidelib.model.GuidePanel) { 30179 deepItem = currentItem; 30180 currentItem = currentItem._navigationContext.currentItem; 30181 } 30182 return deepItem; 30183 } 30184 return null; 30185 }, 30186 30187 30188 _getSomOnNavigableAncestor : function (somExpression) { 30189 if (_.isEmpty(somExpression)) { 30190 return null; 30191 } 30192 30193 var index = somExpression.lastIndexOf("."), 30194 parentModel, 30195 parentSom, 30196 isNavigable, 30197 guideModel = this._parentPanel._guide(); 30198 30199 if (index !== -1) { 30200 parentSom = somExpression.substring(0, index); 30201 parentModel = guideModel.resolveNode(parentSom); 30202 if (parentModel) { 30203 isNavigable = this._isNavigablePanel(parentModel); 30204 } 30205 if (isNavigable) { 30206 return somExpression; 30207 } 30208 return this._getSomOnNavigableAncestor(parentSom); 30209 } 30210 30211 return guideModel.rootPanel.somExpression; 30212 }, 30213 30214 30215 _getNavigableAncestor : function (navOrder) { 30216 30217 30218 30219 var guideModel = this._parentPanel._guide(), 30220 navigableAncestorSom = this._getSomOnNavigableAncestor(guideModel._currentNavigablePanelSom), 30221 navigableAncestorItem = guideModel.resolveNode(navigableAncestorSom); 30222 30223 while (navigableAncestorItem 30224 && navigableAncestorItem != this._parentPanel && !navigableAncestorItem.parent._navigationContext[navOrder] 30225 && this.guideUtil.isChildPartOfContainer(this._parentPanel, navigableAncestorItem)) { 30226 30227 var navigableParentItemSom = this._getSomOnNavigableAncestor(navigableAncestorItem.parent.somExpression); 30228 navigableAncestorItem = guideModel.resolveNode(navigableParentItemSom); 30229 } 30230 return navigableAncestorItem; 30231 }, 30232 30233 _getNakedThis : function () { 30234 return this; 30235 } 30236 }); 30237 30238 GuideNavigationContext.defineProps({ 30239 30240 currentItem : { 30241 get : function () { 30242 if (this._currentItem) { 30243 return this._currentItem; 30244 } else { 30245 return this.firstItem; 30246 } 30247 }, 30248 set : function (value) { 30249 this._currentItem = value; 30250 } 30251 }, 30252 30253 prevItem : { 30254 get : function () { 30255 var navItems = this._getNavigableItems(); 30256 var item = this.currentItem; 30257 if (navItems.indexOf(item) > 0) { 30258 return navItems[navItems.indexOf(item) - 1]; 30259 } else { 30260 return null; 30261 } 30262 } 30263 }, 30264 30265 nextItem : { 30266 get : function () { 30267 var navItems = this._getNavigableItems(); 30268 var item = this.currentItem; 30269 if (navItems.indexOf(item) < (navItems.length - 1)) { 30270 return navItems[navItems.indexOf(item) + 1]; 30271 } else { 30272 return null; 30273 } 30274 } 30275 }, 30276 30277 nextNavigablePanel : { 30278 get : function () { 30279 var navigableAncestor = this._getNavigableAncestor("nextItem"), 30280 30281 navigableDescendant = this._getNavigableDescendant(navigableAncestor); 30282 return navigableDescendant; 30283 } 30284 }, 30285 30286 30287 prevNavigablePanel : { 30288 get : function () { 30289 var navigableAncestor = this._getNavigableAncestor("prevItem"), 30290 30291 navigableDescendant = this._getNavigableDescendant(navigableAncestor); 30292 return navigableDescendant; 30293 } 30294 }, 30295 30296 30297 firstItem : { 30298 get : function () { 30299 var navItems = this._getNavigableItems(); 30300 return navItems[0] || null; 30301 } 30302 }, 30303 30304 lastItem : { 30305 get : function () { 30306 var navItems = this._getNavigableItems(); 30307 if (navItems.length) { 30308 return navItems[navItems.length - 1]; 30309 } else { 30310 return null; 30311 } 30312 } 30313 }, 30314 30315 hasNextItem : { 30316 get : function () { 30317 return this.nextItem != null; 30318 } 30319 }, 30320 30321 hasPrevItem : { 30322 get : function () { 30323 return this.prevItem != null; 30324 } 30325 }, 30326 30327 30328 hasNextNavigablePanel : { 30329 get : function () { 30330 return this.nextNavigablePanel != null; 30331 } 30332 }, 30333 30334 30335 hasPrevNavigablePanel : { 30336 get : function () { 30337 return this.prevNavigablePanel != null; 30338 } 30339 }, 30340 30341 30342 isFirstItem : { 30343 get : function () { 30344 return this.currentItem == this.firstItem; 30345 } 30346 }, 30347 30348 isLastItem : { 30349 get : function () { 30350 return this.currentItem == this.lastItem; 30351 } 30352 } 30353 }); 30354 30355})(_, guidelib); 30356 30357 30358(function (guidelib, $) { 30359 30360 var VERSION_AEM_61 = "AEM6.1", 30361 VERSION_AEM_62 = "AEM6.2", 30362 VERSION_AEM_63 = "AEM6.3", 30363 VERSION_AEM_65 = "AEM6.5", 30364 flagsStatus = {}, 30365 getMinorMajor = function (version) { 30366 var match = version.match(/AEM(\d+)(?:\.(\d+))?/); 30367 if (match == null) { 30368 return null; 30369 } 30370 return { 30371 major : match[1], 30372 minor : match[2] === undefined ? "0" : match[2] 30373 }; 30374 }, 30375 compareNumbers = function (num1, num2) { 30376 return (num1 - num2); 30377 }, 30378 compareVersions = function (version1, version2) { 30379 if (typeof version1 !== "string" || typeof version2 !== "string") { 30380 throw "Comparing Invalid Versions"; 30381 } 30382 var v1 = getMinorMajor(version1), 30383 v2 = getMinorMajor(version2); 30384 if (v1 == null || v2 == null) { 30385 throw "Comparing Invalid Versions"; 30386 } 30387 var c = compareNumbers(+v1.major, +v2.major); 30388 return c !== 0 ? c : compareNumbers(+v1.minor, +v2.minor); 30389 }, 30390 Version = guidelib.util.Version = xfalib.ut.Class.extend({ 30391 initialize : function (options) { 30392 flagsStatus = {}; 30393 var compat = options.scriptingBehaviourVersion; 30394 if (compat === "None") { 30395 compat = this.current(); 30396 } 30397 this.scriptingBehaviourVersion = compat || VERSION_AEM_65; 30398 var majorMinor = getMinorMajor(this.scriptingBehaviourVersion); 30399 if (majorMinor == null) { 30400 throw "Invalid Version number"; 30401 } 30402 this.major = majorMinor.major; 30403 this.minor = majorMinor.minor; 30404 }, 30405 30406 current : function () { 30407 return VERSION_AEM_65; 30408 }, 30409 30410 compatibleVersion : function () { 30411 return this.scriptingBehaviourVersion; 30412 }, 30413 30414 isPrevious : function (version) { 30415 return compareVersions(this.scriptingBehaviourVersion, version) < 0; 30416 }, 30417 30418 isPreviousOrSame : function (version) { 30419 var c = compareVersions(this.scriptingBehaviourVersion, version); 30420 return c < 0 || c == 0; 30421 }, 30422 30423 isAfter : function (version) { 30424 return compareVersions(this.scriptingBehaviourVersion, version) > 0; 30425 }, 30426 30427 isAfterOrSame : function (version) { 30428 var c = compareVersions(this.scriptingBehaviourVersion, version); 30429 return c > 0 || c == 0; 30430 }, 30431 30432 isSame : function (version) { 30433 return compareVersions(this.scriptingBehaviourVersion, version) == 0; 30434 }, 30435 30436 isOn : function (flag) { 30437 switch (flag) { 30438 case this.Flags.RUN_VALUE_COMMMIT_ON_SCRIPT_CHANGE: 30439 if (flagsStatus[flag] == undefined) { 30440 flagsStatus[flag] = this.isAfter(this.AEM_61); 30441 } 30442 return flagsStatus[flag]; 30443 case this.Flags.RUN_VALUE_COMMMIT_ON_PREFILL: 30444 if (flagsStatus[flag] == undefined) { 30445 flagsStatus[flag] = this.isAfter(this.AEM_63); 30446 } 30447 return flagsStatus[flag]; 30448 } 30449 throw "Invalid Flag"; 30450 } 30451 }); 30452 30453 Version.prototype.Flags = {};
30454 Object.defineProperties(Version.prototype.Flags, { 30455 RUN_VALUE_COMMMIT_ON_SCRIPT_CHANGE : { 30456 value : "manageValueCommit", 30457 writable : false 30458 }, 30459 RUN_VALUE_COMMMIT_ON_PREFILL : { 30460 value : "manageValueCommitOnPrefill", 30461 writable : false 30462 } 30463 }); 30464 Version.defineProps({ 30465 AEM_61 : { 30466 value : VERSION_AEM_61, 30467 writable : false 30468 }, 30469 30470 AEM_62 : { 30471 value : VERSION_AEM_62, 30472 writable : false 30473 }, 30474 30475 AEM_63 : { 30476 value : VERSION_AEM_63, 30477 writable : false 30478 }, 30479 30480 AEM_65 : { 30481 value : VERSION_AEM_65, 30482 writable : false 30483 } 30484 }); 30485}(guidelib, $)); 30486(function (_, guidelib) { 30487 guidelib.model.mixin.ValidationsDisabled = { 30488 normalProperties : { 30489 setParentValidationsDisabled : function (bParentValidationsDisabled) { 30490 var oldValidationsDisabled = this.validationsDisabled, 30491 newValidationsDisabled; 30492 this._bParentValidationsDisabled = bParentValidationsDisabled; 30493 newValidationsDisabled = this.validationsDisabled; 30494 this.handleChildValidationsDisabled(newValidationsDisabled, oldValidationsDisabled); 30495 }, 30496 30497 handleChildValidationsDisabled : function (newValidationsDisabled, oldValidationsDisabled) { 30498 if (newValidationsDisabled !== oldValidationsDisabled) { 30499 if (this instanceof guidelib.model.Field) { 30500 if (newValidationsDisabled === true) { 30501 if (this.validationState === false) { 30502 this._errorText = ""; 30503 this.validationState = true; 30504 this._triggerEvent(guidelib.event.GuideModelEvent.ERROR_CHANGED, 30505 "validationStatus", this.validationState, this._errorText); 30506 } 30507 } 30508 } 30509 _.each(this._children, function (child) { 30510 if (child instanceof guidelib.model.Field || child instanceof guidelib.model.GuideItemsContainer) { 30511 child.setParentValidationsDisabled(newValidationsDisabled); 30512 } 30513 }); 30514 } 30515 } 30516 }, 30517 propertyDescriptors : { 30518 validationsDisabled : { 30519 get : function () { 30520 return this._bParentValidationsDisabled || this._validationsDisabled; 30521 }, 30522 set : function (bValidationsDisabled) { 30523 var oldValidationsDisabled = this.validationsDisabled, 30524 newValidationsDisabled; 30525 this._validationsDisabled = bValidationsDisabled; 30526 newValidationsDisabled = this.validationsDisabled; 30527 this.handleChildValidationsDisabled(newValidationsDisabled, oldValidationsDisabled); 30528 } 30529 } 30530 } 30531 }; 30532 30533}(_, guidelib)); 30534(function (_, guidelib) { 30535 30536 30537 var GuideItemsContainer = guidelib.model.GuideItemsContainer = guidelib.model.Scriptable.extend({ 30538 msClassName : "guideItemsContainer", 30539 30540 initialize : function () { 30541 GuideItemsContainer._super.initialize.call(this); 30542 this._children = []; 30543 this._nameArray = {}; 30544 this._private = {}; 30545 this._initChildren(); 30546 this._normalizeChildren(); 30547 this._bParentValidationsDisabled = false; 30548 this._validationsDisabled = false; 30549 }, 30550 30551 _postInitialize : function () { 30552 30553 30554 GuideItemsContainer._super._postInitialize.call(this); 30555 _.each(this._children, function (childNode) { 30556 childNode._postInitialize(); 30557 }, this); 30558 }, 30559 30560 30561 validate : function (errorList) { 30562 var validationStatus = true, 30563 tempValidationStatus; 30564 30565 if (!this.visible) { 30566 return true; 30567 } 30568 if (_.isUndefined(errorList)) { 30569 errorList = []; 30570 } 30571 30572 var subContainerErrorArray = [], 30573 arrLen; 30574 _.each(this.children, function (child) { 30575 tempValidationStatus = child.validate(subContainerErrorArray); 30576 if (tempValidationStatus === false) { 30577 validationStatus = false;
30578 } 30579 }, this); 30580 30581 tempValidationStatus = GuideItemsContainer._super.validate.call(this, subContainerErrorArray); 30582 if (tempValidationStatus === false) { 30583 validationStatus = false; 30584 } 30585 arrLen = subContainerErrorArray.length; 30586 while (arrLen > 0) { 30587 errorList[errorList.length] = subContainerErrorArray[subContainerErrorArray.length - arrLen]; 30588 arrLen--; 30589 } 30590 return validationStatus; 30591 }, 30592 30593 prepare : function () { 30594 _.each(this._children, function (childNode) { 30595 childNode.prepare(); 30596 }, this); 30597 GuideItemsContainer._super.prepare.call(this); 30598 }, 30599 30600 syncXFAProps : function () { 30601 GuideItemsContainer._super.syncXFAProps.apply(this, arguments); 30602 _.each(this._children, function (childNode) { 30603 childNode.syncXFAProps(); 30604 }); 30605 }, 30606 30607 _initChildren : function (bLazyInitialization) { 30608 var panelItems = [], 30609 jsonModelItemsWithoutRepeatJson = {}, 30610 keyLengthForJsonWithoutRepeat = 0, 30611 keyLengthJsonItemsOriginal = 0; 30612 30613 30614 30615 30616 30617 _.each(this.jsonModel.items, function (item) { 30618 30619 30620 30621 if (item.templateId && item.templateId.indexOf("GUID") === -1) { 30622 jsonModelItemsWithoutRepeatJson[item.templateId] = item; 30623 } 30624 }); 30625 keyLengthForJsonWithoutRepeat = _.keys(jsonModelItemsWithoutRepeatJson).length; 30626 30627 keyLengthJsonItemsOriginal = _.keys(this.jsonModel.items || {}).length; 30628 if (keyLengthForJsonWithoutRepeat > 0 && keyLengthForJsonWithoutRepeat !== keyLengthJsonItemsOriginal) { 30629 this.jsonModel.items = jsonModelItemsWithoutRepeatJson; 30630 } 30631 _.each(this.jsonModel.items, 30632 function (item) { 30633 if (_.isObject(item)) { 30634 30635 30636 30637 30638 var options = {}; 30639 if (this.options._guideContainer) { 30640 options = _.extend({}, options, {"_guideContainer" : this.options._guideContainer}); 30641 } 30642 var panelItemModel = guidelib.model.GuideModelRegistry.prototype.createModel(item, options); 30643 panelItemModel._isItem = true; 30644 this._initializeChild(panelItemModel); 30645 panelItems.push(panelItemModel); 30646 } 30647 }, 30648 this); 30649 this._children = panelItems; 30650 }, 30651 30652 _initializeChild : function (childItem) { 30653 childItem.parent = this; 30654 }, 30655 30656 _normalizeChildren : function () { 30657 this._nameArray = {}; 30658 this._private = {}; 30659 _.each(this.children, function (child) { 30660 child._index = this._addProperty(child); 30661 30662 child.getNaked(child._index, guidelib.__runtime__, null); 30663 child.getNaked(child._index, this._guide().runtime, null); 30664 }, this); 30665 }, 30666 30667 nakedChildReferences : function (nIndex, obj) { 30668 var i, oNode; 30669 for (i = 0; i < this._children.length; i++) { 30670 oNode = this._children[i]; 30671 oNode.getNaked(nIndex, obj, this); 30672 } 30673 }, 30674 _getReducedJSON : function (isRepeatable) { 30675 var reducedJSONChildren, 30676 that = this, 30677 index = 0; 30678 30679 reducedJSONChildren = GuideItemsContainer._super._getReducedJSON.call(this); 30680 reducedJSONChildren.items = {}; 30681 30682 30683 30684 30685 _.each(this.jsonModel.items, function (childNode, key) { 30686 reducedJSONChildren.items[key] = that.items[index]._getReducedJSON(isRepeatable); 30687 index += 1; 30688 }); 30689 return reducedJSONChildren; 30690 }, 30691 30692 _addProperty : function (oValueObject) { 30693 var sName = oValueObject.getAttribute("name"), 30694 nIndex = 0; 30695 30696 30697 30698 this._nameArray[sName] = this._nameArray[sName] || nIndex; 30699 nIndex = this._nameArray[sName]++; 30700 if (nIndex === 0) { 30701 30702 30703 30704 30705 guidelib.util.GuideUtil._createGetterSetter(this, sName, oValueObject); 30706 } 30707 return nIndex; 30708 }, 30709 30710 _getTitle : function () { 30711 return this.jsonModel["jcr:title"]; 30712 }, 30713 30714 visit : function (callback, context) { 30715 GuideItemsContainer._super.visit.apply(this, arguments); 30716 _.each(this._children, function (child, index) { 30717 child.visit(callback, context); 30718 }); 30719 }, 30720 30721 playJson : function (pJsonModel) { 30722 if (pJsonModel) { 30723 var pJsonItems = _.filter(pJsonModel.items, function (item) { 30724 if (_.isObject(item)) { 30725 return true; 30726 } 30727 return false;
30728 }, this); 30729 30730 _.each(this.items, function (childNode, index) { 30731 childNode.playJson(pJsonItems[index]); 30732 }, this); 30733 GuideItemsContainer._super.playJson.call(this, pJsonModel); 30734 } 30735 30736 }, 30737 30738 _collectValues : function (keyValue) { 30739 _.each(this._children, function (childNode) { 30740 childNode._collectValues(keyValue); 30741 }, this); 30742 }, 30743 30744 getElement : function (elClassName) { 30745 var element = _.find(this._children, function (childModel) { 30746 return childModel.className === elClassName; 30747 }, this); 30748 return element; 30749 }, 30750 30751 30752 _unloadModel : function () { 30753 _.each(this.children, function (child) { 30754 child._unloadModel(); 30755 }, this); 30756 GuideItemsContainer._super._unloadModel.call(this); 30757 }, 30758 30759 _findChildren : function (oSOM, bMultiple) { 30760 var arr = [], 30761 elemFound = false; 30762 _.find(this._children, function (child) { 30763 if (oSOM === child._escapeQualifiedName()) { 30764 arr.push(child._getNakedThis()); 30765 elemFound = true; 30766 } 30767 if (elemFound && !bMultiple) { 30768 return true; 30769 } 30770 if (elemFound && oSOM.indexOf("[*]") < 0) { 30771 return true; 30772 } 30773 }, this); 30774 return arr; 30775 }, 30776 30777 30778 resetData : function () { 30779 _.each(this._children, function (childNode) { 30780 childNode.resetData(); 30781 }, this); 30782 }, 30783 30784 30785 _changeDescendantsAccess : function (value) { 30786 _.each(this.items, function (child) { 30787 child._setParentAccess(value); 30788 if (child instanceof guidelib.model.GuideItemsContainer) { 30789 child._changeDescendantsAccess(value); 30790 } 30791 }, this); 30792 }, 30793 30794 30795 _changeContainerAccess : function (value) { 30796 this._changeDescendantsAccess(value); 30797 }, 30798 30799 30800 _changeDescendantsProperty : function (value, property, leafNodesOnly) { 30801 _.each(this.items, function (child) { 30802 if (child instanceof guidelib.model.GuideItemsContainer) { 30803 if (!leafNodesOnly) { 30804 child[property] = value; 30805 } 30806 child._changeDescendantsProperty(value, property); 30807 } else { 30808 child[property] = value; 30809 } 30810 }, this); 30811 }, 30812 30813 30814 disableAllFields : function () { 30815 this.enabled = false; 30816 var property = "enabled"; 30817 this._changeDescendantsProperty(false, property, true); 30818 } 30819 30820 }); 30821 30822 GuideItemsContainer.defineProps({ 30823 children : { 30824 get : function () { 30825 return (this._children || []).slice(0); 30826 }, 30827 set : function (value) { 30828 this._children = value; 30829 } 30830 }, 30831 30832 30833 items : { 30834 get : function () { 30835 var itemChildren = _.filter(this._children, function (child) { 30836 if (child._isItem) { 30837 return true; 30838 } 30839 return false; 30840 }, this); 30841 return itemChildren; 30842 } 30843 }, 30844 30845 _selfOrAncestorIsLazyReference : { 30846 get : function () { 30847 if (this._lazyReference) { 30848 return true; 30849 } 30850 return guidelib.util.GuideUtil._checkIfAncestorIsALazyReference(this); 30851 } 30852 }, 30853 _lazyReference : { 30854 get : function () { 30855 return !_.isUndefined(this.jsonModel["fragRef"]) 30856 && !_.isUndefined(this.jsonModel["optimizeRenderPerformance"]); 30857 } 30858 } 30859 }); 30860 30861 GuideItemsContainer.addMixins([ 30862 guidelib.model.mixin.ValidationsDisabled 30863 ]); 30864 30865}(_, guidelib)); 30866 30867(function (_, guidelib) { 30868 30869 30870 var GuideCompositeField = guidelib.model.GuideCompositeField = guidelib.model.GuideItemsContainer.extend({ 30871 msClassName : "guideCompositeField", 30872 initialize : function () { 30873 this._uuid = guideBridge._produceUUID(); 30874 GuideCompositeField._super.initialize.call(this); 30875 }, 30876 30877 _setGuideValue : function (value) { 30878 if (!_.isEmpty(value)) { 30879 _.each(this.items, function (item) { 30880 if (value.hasOwnProperty(item.name) && _.isFunction(item._setGuideValue)) { 30881 item._setGuideValue(value[item.name]); 30882 } 30883 }, this); 30884 } 30885 }, 30886 30887 _collectExpressions : function () { 30888 GuideCompositeField._super._collectExpressions.apply(this); 30889 if (this.valueCommitScript) { 30890 30891 this._compiledScripts.valueCommitScript = this._compileExpression(this.valueCommitScript, null); 30892 } 30893 } 30894 }); 30895 30896 GuideCompositeField.defineProps({ 30897 valueCommitScript : { 30898 get : function () { 30899 return this.getAttribute("valueCommitScript"); 30900 } 30901 }, 30902 uuid : { 30903 get : function () { 30904 return this._uuid; 30905 }, 30906 set : function (newUuid) { 30907 if (this._uuid != newUuid) { 30908 this._uuid = newUuid; 30909 } 30910 } 30911 } 30912 }); 30913 30914})(_, guidelib); 30915 30916(function (_, guidelib) { 30917 30918 30919 var GuideFileUpload = guidelib.model.GuideFileUpload = guidelib.model.GuideCompositeField.extend({ 30920 msClassName : "guideFileUpload", 30921 30922 _getReducedJSON : function () { 30923 this._syncModelToAttachments(); 30924 var reducedJSONChildren = GuideFileUpload._super._getReducedJSON.call(this), 30925 addtionalWhitelistedProperties = ["id", "files"]; 30926 guidelib.model.util.CommonUtils.returnMinimalJSON(addtionalWhitelistedProperties, reducedJSONChildren, this); 30927 var fileAttachmentValue = reducedJSONChildren.files; 30928 reducedJSONChildren.files = this._getFileAttachmentNames(fileAttachmentValue); 30929 return reducedJSONChildren; 30930 }, 30931 30932 _getContentType : function(fileUrl) { 30933 var contentType = null, 30934 self = this; 30935 if (self._fileAttachmentWrapper) { 30936 var element = self._fileAttachmentWrapper.find(function(x) { return x.data === fileUrl}); 30937 if (element) { 30938 contentType = element.contentType; 30939 } 30940 } 30941 return contentType 30942 }, 30943 30944 30945 _getFileAttachmentNames : function (fileAttachmentValue) { 30946 var value = fileAttachmentValue || this.value; 30947 if (value) { 30948 var self = this, 30949 fileNames = _.map(value.split("\n"), function (val) { 30950 if (self._fileAttachmentWrapper) { 30951 var element = self._fileAttachmentWrapper.find(function(x) { return x.data === val}); 30952 if (element) { 30953 return element.name; 30954 } 30955 } 30956 var fName = val; 30957 30958 if (fName.lastIndexOf("/") === fName.length - 1) { 30959 fName = fName.substring(0, fName.length - 1); 30960 } 30961 return fName.substring(fName.lastIndexOf("/") + 1); 30962 }).join("\n"); 30963 return fileNames; 30964 } 30965 }, 30966 30967 _triggerFileListChange : function () { 30968 var currValue = this._fileList; 30969 this.trigger(guidelib.event.GuideModelEvent.MODEL_CHANGED, 30970 guidelib.event.GuideModelEvent.createEvent( 30971 guidelib.event.GuideModelEvent.MODEL_CHANGED, 30972 this, 30973 "fileList", 30974 currValue, 30975 currValue 30976 ) 30977 ); 30978 }, 30979 30980 _getCurrentFileAttachmentWrapper : function(attachments) { 30981 var currentListOfAttachments = null, 30982 effectiveBindRef = this._getEffectiveBindRef(), 30983 self = this; 30984 if (_.isArray(attachments) && attachments.length > 0) { 30985 currentListOfAttachments = attachments.filter(function(x) { 30986 return x.bindRef === effectiveBindRef; 30987 }) 30988 } 30989 return currentListOfAttachments; 30990 }, 30991 30992 _playAttachmentWrappers : function(currentAttachmentWrappers) { 30993 var currValue = this.fileAttachment.value, 30994 _guide = this._guide(); 30995 if (_.isArray(currentAttachmentWrappers) && currentAttachmentWrappers.length > 0) { 30996 this._fileAttachmentWrapper = currentAttachmentWrappers; 30997 30998 if (this.valueCommitScript && _guide.version.isOn(_guide.version.Flags.RUN_VALUE_COMMMIT_ON_PREFILL) && currValue) { 30999 31000 _guide.queueExpressions(this, ["valueCommitScript"]); 31001 } 31002 var data = currentAttachmentWrappers.map(function(x) {return x.data}); 31003 31004 var fieldValue = data.join("\n"); 31005 this.fileAttachment._setGuideValue(fieldValue); 31006 if (!_.isEmpty(fieldValue)) { 31007 this._fileList = fieldValue.split("\n"); 31008 } 31009 } 31010 }, 31011 31012 playJson : function (pJsonModel, attachments) { 31013 if (attachments) { 31014 var currentListOfAttachments = this._getCurrentFileAttachmentWrapper(attachments); 31015 this._playAttachmentWrappers(currentListOfAttachments); 31016 } else { 31017 31018 GuideFileUpload._super.playJson.call(this, pJsonModel); 31019 } 31020 }, 31021 31022 _syncModelToAttachments : function () { 31023 var files = this.fileAttachment.value || "", 31024 filesArray = files.split('\n'), 31025 uniqueNames = guideBridge._makeFileNameUnique(); 31026 var isIOS = guidelib.util.GuideUtil._isIOS(); 31027 var files = this.fileAttachment.value || "", 31028 filesArray = files.split('\n'), 31029 areNamesUnique = (new Set(filesArray)).size === filesArray.length; 31030 this.jsonModel.files = 31031 _.map(files.split('\n'), function (file, index) { 31032 if (!_.isEmpty(file)) { 31033 if ((uniqueNames || (!areNamesUnique && isIOS)) && file[0] !== '/') { 31034 file = this.uuid + "-" + (index + 1) + "__afAttachment__" + file; 31035 } 31036 } 31037 return file; 31038 }, this).join('\n'); 31039 }, 31040 31041 _updateLiveData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar) { 31042 this._syncModelAndData(bound_indexedXpathSoFar, unBound_indexedXpathSoFar, "_updateLiveData"); 31043 }, 31044 31045 _playLiveData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar) { 31046 this._syncModelAndData(bound_indexedXpathSoFar, unBound_indexedXpathSoFar, "_playLiveData"); 31047 }, 31048 31049 _handleFileAttachmentItem : function (fileAttachmentModel, bound_indexedXpathSoFar, unBound_indexedXpathSoFar, recurse) { 31050 31051 var dataUtils = this._guide().internal.liveDataUtils, 31052 dataContext = dataUtils._getDataContext(fileAttachmentModel, bound_indexedXpathSoFar, unBound_indexedXpathSoFar); 31053 if (recurse == "_updateLiveData") { 31054 dataUtils._updateLazyAttachmentMapFromModel(this); 31055 dataUtils.setDataValue(dataContext.indexedXpath, dataContext.xmlSec, 31056 !fileAttachmentModel.isEmpty(), fileAttachmentModel.isEmpty() ? "" : this._getFileAttachmentValue()); 31057 } else { 31058 var data = dataUtils._getAttachmentDataForModel(this); 31059 if (!_.isArray(data) && !_.isEmpty(data)) { 31060 this.fileList = data.fileList; 31061 var fileAttachmentValue = []; 31062 var value = data.value.split("\n"); 31063 _.each(value, function (value, index) { 31064 if (value[0] != '/') { 31065 31066 31067 var name = value.substr(value.lastIndexOf("_") + 1); 31068 fileAttachmentValue.push(name); 31069 } else { 31070 31071 fileAttachmentValue.push(value); 31072 } 31073 }); 31074 fileAttachmentModel.value = fileAttachmentValue.join("\n"); 31075 } 31076 if (_.isArray(data) && data.length > 0) { 31077 this._playAttachmentWrappers(data); 31078 } 31079 this._syncModelToAttachments(); 31080 } 31081 }, 31082 31083 _syncModelAndData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar, recurse) { 31084 if (_.isString(recurse)) { 31085 var liveDataUtils = this._guide().internal.liveDataUtils; 31086 var dataContext = liveDataUtils._getDataContext(this, bound_indexedXpathSoFar, unBound_indexedXpathSoFar); 31087 if (dataContext.xmlSec === liveDataUtils.constants.BOUND_TAG) { 31088 bound_indexedXpathSoFar = dataContext.indexedXpath; 31089 } else { 31090 unBound_indexedXpathSoFar = dataContext.indexedXpath; 31091 } 31092 _.each(this.items, function (item) { 31093 if (_.isFunction(item[recurse])) { 31094 if (item.name == "fileAttachment") { 31095 31096 31097 this._handleFileAttachmentItem(item, bound_indexedXpathSoFar, unBound_indexedXpathSoFar, recurse); 31098 } else { 31099 item[recurse](bound_indexedXpathSoFar, unBound_indexedXpathSoFar); 31100 } 31101 } 31102 }, this); 31103 } 31104 }, 31105 31106 31107 _getIndexedXpath : function (model, bound_indexedXpathSoFar, unBound_indexedXpathSoFar) { 31108 var name = model.getAttribute("name").replace(/\s+/g, ''); 31109 return unBound_indexedXpathSoFar ? unBound_indexedXpathSoFar + '/' + name : bound_indexedXpathSoFar + '/' + name; 31110 }, 31111 31112 31113 _getFileAttachmentValue : function () { 31114 31115 31116 31117 this._syncModelToAttachments(); 31118 return this._getFileAttachmentNames(this.jsonModel.files); 31119 } 31120 31121 }); 31122 31123 GuideFileUpload.defineProps({ 31124 31125 multiSelection : { 31126 get : function () { 31127 return this.getAttribute("multiSelection"); 31128 } 31129 }, 31130 31131 buttonText : { 31132 get : function () { 31133 return this.getAttribute("buttonText"); 31134 } 31135 }, 31136 31137 showComment : { 31138 get : function () { 31139 return this.getAttribute("showComment"); 31140 } 31141 }, 31142 31143 31144 fileSizeLimit : { 31145 get : function () { 31146 return this.getAttribute("fileSizeLimit"); 31147 } 31148 }, 31149 31150 fileList : { 31151 get : function () { 31152 return this._fileList; 31153 }, 31154 31155 set : function (newValue) { 31156 var oldValue = this._fileList; 31157 var newTypedValue = newValue; 31158 if (newTypedValue != oldValue) { 31159 this._fileList = newTypedValue; 31160 } 31161 31162 31163 31164 var isIOS = guidelib.util.GuideUtil._isIOS(), 31165 fileList = this._fileList, 31166 that = this; 31167 if (isIOS && fileList) { 31168 31169 this._fileAttachmentWrapperIOS = []; 31170 31171 for
31171 (var i = 0; i < fileList.length; i++) { 31172 if (!_.isString(fileList[i])) { 31173 31174 var files = fileList[i].get(0).files, 31175 _readFile = function (file) { 31176 31177 that._fileAttachmentWrapperIOS.push( 31178 new Promise(function(resolve, reject){ 31179 var reader = new FileReader(); 31180 reader.onload = function() { 31181 var faWrapper = new guidelib.model.FileAttachmentWrapper({ 31182 name: file.name, 31183 data: this.result, 31184 formElementName : that.name, 31185 contentType: file.type, 31186 bindRef: that._getEffectiveBindRef() 31187 }); 31188 resolve(faWrapper); 31189 }; 31190 reader.onerror = reject; 31191 reader.readAsDataURL(file); 31192 }) 31193 ) 31194 }; 31195 if (files) { 31196 31197 [].forEach.call(files, _readFile); 31198 } 31199 } 31200 } 31201 } 31202 this._triggerFileListChange(); 31203 } 31204 }, 31205 value : { 31206 get : function () { 31207 this._syncModelToAttachments(); 31208 return this.jsonModel.files; 31209 } 31210 } 31211 }); 31212 31213})(_, guidelib); 31214 31215(function (_, guidelib) { 31216 31217 var GuideTermsAndConditions = guidelib.model.GuideTermsAndConditions = guidelib.model.GuideCompositeField.extend({ 31218 msClassName : "guideTermsAndConditions", 31219 31220 playJson : function (pJsonModel) { 31221 this.jsonModel.clickStatus = pJsonModel.clickStatus; 31222 GuideTermsAndConditions._super.playJson.apply(this, arguments); 31223 }, 31224 31225 _updateLiveData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar) { 31226 this._syncModelAndData(bound_indexedXpathSoFar, unBound_indexedXpathSoFar, '_updateLiveData'); 31227 }, 31228 31229 _playLiveData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar) { 31230 this._syncModelAndData(bound_indexedXpathSoFar, unBound_indexedXpathSoFar, '_playLiveData'); 31231 if (this.reviewStatus.value === "true") { 31232 this.clickStatus = "agree"; 31233 } else { 31234 this.clickStatus = "unreviewed"; 31235 } 31236 }, 31237 31238 _syncModelAndData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar, recurse) { 31239 if (_.isString(recurse)) { 31240 var dataContext = this._guide().internal.liveDataUtils._getDataContext(this, bound_indexedXpathSoFar, unBound_indexedXpathSoFar); 31241 if (dataContext.xmlSec === this._guide().internal.liveDataUtils.constants.BOUND_TAG) { 31242 bound_indexedXpathSoFar = dataContext.indexedXpath; 31243 } else { 31244 unBound_indexedXpathSoFar = dataContext.indexedXpath; 31245 } 31246 _.each(this.items, function (item) { 31247 if (_.isFunction(item[recurse])) { 31248 item[recurse](bound_indexedXpathSoFar, unBound_indexedXpathSoFar); 31249 } 31250 }); 31251 } 31252 } 31253 }); 31254 31255 GuideTermsAndConditions.defineProps({ 31256 showLink : { 31257 get : function () { 31258 return this.getAttribute("showLink"); 31259 } 31260 }, 31261 31262 31263 clickStatus : { 31264 get : function () { 31265 return this.getAttribute("clickStatus"); 31266 }, 31267 set : function (status) { 31268 this.setAttribute(status, "clickStatus"); 31269 } 31270 }, 31271 31272 showAsPopUp : { 31273 get : function () { 31274 return this.getAttribute("showAsPopUp"); 31275 } 31276 } 31277 }); 31278 31279})(_, guidelib); 31280(function (_, guidelib) { 31281 var GuideToolbar = guidelib.model.GuideToolbar = guidelib.model.GuideItemsContainer.extend({ 31282 msClassName : "guideToolbar", 31283 31284 initialize : function () { 31285 GuideToolbar._super.initialize.call(this); 31286 }, 31287 31288 execNavigationChangeExpression : function () { 31289 _.each(this.items, function (childModel) { 31290 if (childModel.navigationChangeExp) { 31291 this._guide().queueExpressions(childModel, "navigationChangeExp"); 31292 } 31293 }, this); 31294 } 31295 31296 }); 31297 31298})(_, guidelib); 31299 31300(function (_, guidelib) { 31301 var GuideAdModuleGroup = guidelib.model.GuideAdModuleGroup = guidelib.model.GuideItemsContainer.extend({ 31302 msClassName : "guideAdModuleGroup", 31303 31304 _getTypedValue : function (value) { 31305 31306 if (_.isUndefined(value) || value === null) { 31307 return null; 31308 } 31309 return value + ""; 31310 }, 31311 31312 playJson : function (pJsonModel) { 31313 var typedValue = this._getTypedValue(pJsonModel._value); 31314 31315 if (typedValue || typedValue === "") { 31316 31317 var olval = this.jsonModel._value; 31318 this.jsonModel._value = pJsonModel._value; 31319 this._triggerOnBridge("elementValueChanged", this, "value", olval, this.jsonModel._value); 31320 } else { 31321 31322 GuideAdModuleGroup._super.playJson.call(this, pJsonModel); 31323 } 31324 } 31325 }); 31326 31327 GuideAdModuleGroup.defineProps({ 31328 31329 value : { 31330 get : function () { 31331 return this._getTypedValue(this.jsonModel._value); 31332 }, 31333 set : function (newValue) { 31334 var oldValue = this._getTypedValue(this.jsonModel._value),
31335 newTypedValue = this._getTypedValue(newValue); 31336 31337 if (newTypedValue !== undefined && (newTypedValue !== oldValue)) { 31338 if (this.jsonModel._value !== newValue) { 31339 this.jsonModel._value = newTypedValue || ""; 31340 } 31341 this._triggerOnBridge("elementValueChanged", this, "value", oldValue, newTypedValue); 31342 } 31343 } 31344 } 31345 }); 31346 31347}(_, guidelib)); 31348(function (_, guidelib) { 31349 guidelib.model.mixin.AddDependencyMgmt = { 31350 normalProperties : { 31351 _addDependant : function (oNode, expressionType) { 31352 var dependantConf = this._findDependant(oNode); 31353 if (!dependantConf) { 31354 dependantConf = {dependant : oNode, events : []}; 31355 this.dependants.push(dependantConf); 31356 } 31357 31358 if (dependantConf.events.indexOf(expressionType) < 0) { 31359 dependantConf.events.push(expressionType); 31360 oNode.on(guidelib.event.GuideModelEvent.OBJECT_DESTROYED, this._handleDependentDestroyed, this); 31361 } 31362 }, 31363 31364 _notifyDependants : function () { 31365 _.each(this.dependants, function (dependantConf) { 31366 this._guide().queueExpressions(dependantConf.dependant, dependantConf.events); 31367 }, this); 31368 }, 31369 31370 _removeDependant : function (oNode) { 31371 oNode.off(guidelib.event.GuideModelEvent.OBJECT_DESTROYED, this._handleDependentDestroyed, this); 31372 var dependantConf = this._findDependant(oNode); 31373 this.dependants = _.without(this.dependants, dependantConf); 31374 }, 31375 31376 _findDependant : function (oNode) { 31377 return _.find(this.dependants, function (conf) { return (conf.dependant === oNode); }); 31378 }, 31379 31380 _handleDependentDestroyed : function (event) { 31381 this._removeDependant(event.target); 31382 } 31383 } 31384 }; 31385})(_, guidelib); 31386 31387(function (_, guidelib) { 31388 var GuideChart = guidelib.model.GuideChart = guidelib.model.Scriptable.extend({ 31389 msClassName : "guideChart", 31390 31391 _collectExpressions : function () { 31392 GuideChart._super._collectExpressions.apply(this); 31393 this._compiledExpressions["aggregateExp"] = this._compileExpression('guidelib.chartUtils.gatherAxisData(this);', "data"); 31394 } 31395 }); 31396 31397 GuideChart.defineProps({ 31398 31399 data : { 31400 get : function () { 31401 var context = this._guide()._currentContext; 31402 if (context && context.contextNode && context.expression 31403 && !(context.contextNode === this && context.expression === "aggregateExp")) { 31404 this._addDependant(context.contextNode, context.expression); 31405 } 31406 return this.jsonModel.data; 31407 }, 31408 31409 set : function (newValue) { 31410 var oldValue = this.jsonModel.data; 31411 this.jsonModel.data = newValue; 31412 31413 var valueHasChanged = !_.isEqual(oldValue, newValue); 31414 if (valueHasChanged) { 31415 31416 this._notifyDependants(); 31417 this._triggerEvent(guidelib.event.GuideModelEvent.MODEL_CHANGED, "data", oldValue, newValue); 31418 } 31419 } 31420 }, 31421 31422 31423 dataSourceType : { 31424 get : function () { 31425 return this.getAttribute("dataSourceType"); 31426 }, 31427 set : function (newValue) { 31428 var oldValue = this.jsonModel.dataSourceType; 31429 this.jsonModel.dataSourceType = newValue; 31430 this._triggerEvent(guidelib.event.GuideModelEvent.MODEL_CHANGED, "dataSourceType", oldValue, newValue); 31431 } 31432 }, 31433 31434 31435 width : { 31436 get : function () { 31437 return this.getAttribute("width"); 31438 }, 31439 31440 set : function (newValue) { 31441 this.jsonModel.width = newValue; 31442 } 31443 }, 31444 31445 height : { 31446 get : function () { 31447 return this.getAttribute("height"); 31448 }, 31449 31450 set : function (newValue) { 31451 this.jsonModel.height = newValue; 31452 } 31453 }, 31454 31455 xAxisTitle : { 31456 get : function () { 31457 return this.getAttribute("xAxisTitle"); 31458 }, 31459 set : function (newValue) { 31460 this.jsonModel.chartType = newValue; 31461 } 31462 }, 31463 31464 yAxisTitle : { 31465 get : function () { 31466 return this.getAttribute("yAxisTitle"); 31467 }, 31468 set : function (newValue) { 31469 this.jsonModel.chartType = newValue; 31470 } 31471 }, 31472 31473 chartType : { 31474 get : function () { 31475 return this.getAttribute("chartType"); 31476 }, 31477 set : function (newValue) { 31478 var oldValue = this.jsonModel.chartType; 31479 this.jsonModel.chartType = newValue; 31480 this._triggerEvent(guidelib.event.GuideModelEvent.MODEL_CHANGED, "chartType", oldValue, newValue); 31481 } 31482 }, 31483 31484 repeatableItem : { 31485 get : function () { 31486 return this.getAttribute("repeatableItem"); 31487 }, 31488 set : function (newValue) { 31489 this.jsonModel.repeatableItem = newValue; 31490 } 31491 }, 31492 31493 xExp : { 31494 get : function () { 31495 return this.getAttribute("xExp"); 31496 }, 31497 set : function (newValue) { 31498 this.jsonModel.xExp = newValue; 31499 } 31500 }, 31501 31502 reducerXFunction : { 31503 get : function () { 31504 return this.getAttribute("reducerXFunction"); 31505 }, 31506 set : function (newValue) { 31507 this.jsonModel.reducerXFunction = newValue; 31508 if (newValue !== 'none') {
31509 this.jsonModel.reducerYFunction = 'none'; 31510 } 31511 } 31512 }, 31513 31514 yExp : { 31515 get : function () { 31516 return this.getAttribute("yExp"); 31517 }, 31518 set : function (newValue) { 31519 this.jsonModel.yExp = newValue; 31520 } 31521 }, 31522 31523 reducerYFunction : { 31524 get : function () { 31525 return this.getAttribute("reducerYFunction"); 31526 }, 31527 set : function (newValue) { 31528 this.jsonModel.reducerYFunction = newValue; 31529 if (newValue !== 'none') { 31530 this.jsonModel.reducerXFunction = 'none'; 31531 } 31532 } 31533 }, 31534 31535 innerRadius : { 31536 get : function () { 31537 return this.getAttribute("innerRadius"); 31538 }, 31539 set : function (newValue) { 31540 this.jsonModel.innerRadius = newValue; 31541 } 31542 }, 31543 31544 lineColor : { 31545 get : function () { 31546 return this.getAttribute("lineColor"); 31547 }, 31548 set : function (newValue) { 31549 this.jsonModel.lineColor = newValue; 31550 } 31551 }, 31552 31553 pointColor : { 31554 get : function () { 31555 return this.getAttribute("pointColor"); 31556 }, 31557 set : function (newValue) { 31558 this.jsonModel.pointColor = newValue; 31559 } 31560 }, 31561 31562 areaColor : { 31563 get : function () { 31564 return this.getAttribute("areaColor"); 31565 }, 31566 set : function (newValue) { 31567 this.jsonModel.areaColor = newValue; 31568 } 31569 }, 31570 31571 tooltipHtml : { 31572 get : function () { 31573 return this.getAttribute("tooltipHtml"); 31574 }, 31575 set : function (newValue) { 31576 this.jsonModel.tooltipHtml = newValue; 31577 } 31578 }, 31579 31580 showLegends : { 31581 get : function () { 31582 return this.getAttribute("showLegends"); 31583 }, 31584 set : function (newValue) { 31585 this.jsonModel.showLegends = newValue; 31586 } 31587 }, 31588 31589 legendPosition : { 31590 get : function () { 31591 return this.getAttribute("legendPosition"); 31592 }, 31593 set : function (newValue) { 31594 this.jsonModel.legendPosition = newValue; 31595 } 31596 } 31597 }); 31598 31599 GuideChart.addMixins([ 31600 guidelib.model.mixin.AddDependencyMgmt 31601 ]); 31602}(_, guidelib)); 31603(function (_, guidelib) { 31604 31605 31606 var Field = guidelib.model.Field = guidelib.model.Scriptable.extend({ 31607 msClassName : "field", 31608 31609 _runValidation : true, 31610 initialize : function () { 31611 Field._super.initialize.call(this); 31612 this.jsonModel["{default}"] = this.getOrElse(this.jsonModel, "{default}", this.jsonModel._value); 31613 this.isValid = true; 31614 this.forceErrorShow = false; 31615 31616 this._bParentValidationsDisabled = false; 31617 31618 this._validationsDisabled = false; 31619 31620 this._failedTest = null; 31621 31622 31623 this._errorText = ""; 31624 31625 var effectiveBindRef = this._getEffectiveBindRef(); 31626 31627 if (this.isGlobal || (this._guide() && this._guide().internal.liveModel.isLive(effectiveBindRef))) { 31628 this._guide().internal.liveModel.add(effectiveBindRef, this); 31629 } 31630 }, 31631 _postInitialize: function() { 31632 Field._super._postInitialize.call(this); 31633 if (this.getAttribute("dorExclusion") !== null && this.jsonModel.visible === false) { 31634 if ((this._guide().getAttribute("excludeFromDoRIfHidden") === "true") 31635 || 31636 (this._guide().print && 31637 this._guide().print["excludeFromDoRIfHidden"] === "true")) { 31638 this.dorExclusion = true; 31639 } 31640 } 31641 }, 31642 _unloadModel : function () { 31643 var effectiveBindRef = this.bindRef || this.getAttribute("name"); 31644 if (this.isGlobal || this._guide().internal.liveModel.isLive(effectiveBindRef)) { 31645 this._guide().internal.liveModel.remove(effectiveBindRef, this); 31646 } 31647 Field._super._unloadModel.call(this); 31648 }, 31649 31650 _collectExpressions : function () { 31651 Field._super._collectExpressions.apply(this); 31652 if (this.calcExp) { 31653 this._compiledExpressions.calcExp = this._compileExpression(this.calcExp, "value"); 31654 } 31655 if (this.validateExp) { 31656 31657 this._compiledScripts.validateExp = this._compileExpression(this.validateExp, null); 31658 } 31659 if (this.valueCommitScript) { 31660 31661 31662 this._compiledScripts.valueCommitScript = this._compileExpression(this.valueCommitScript, null); 31663 } 31664 31665 this._compiledScripts.validateAllExp = this._compileExpression("this._runTests()", null); 31666 }, 31667 31668 _handleXfaModelChanged : function (event) { 31669 if (event._property === "rawValue") { 31670 this._triggerEvent(guidelib.event.GuideModelEvent.VALUE_CHANGED, "value", 31671 event.prevText, event.newText); 31672 } else if (event._property == "ClearError" || event._property == "ValidationState") { 31673 31674 this._guide().queueExpressions(this, ["validateAllExp"]); 31675 } else { 31676 Field._super._handleXfaModelChanged.call(this, event); 31677 } 31678 }, 31679 31680 31681 31682 validate : function (errorList) { 31683 31684 if (!this.visible) { 31685 return true; 31686 } 31687 if (_.isUndefined(errorList)) { 31688 errorList = []; 31689 } 31690 var status = true; 31691 this._runTests(true); 31692 if (this._errorText) { 31693 errorList.push({ 31694 som : this.somExpression, 31695 errorText : this._errorText 31696 }); 31697 status = false;
31698 } 31699 return status; 31700 }, 31701 31702 _getTypedValue : function (value) { 31703 if (this.checkIfNull(value)) { 31704 return null; 31705 } 31706 return value + ""; 31707 }, 31708 31709 _getFormattedValue : function (value) { 31710 if (_.isUndefined(value) || value === null || value === "") { 31711 return null; 31712 } 31713 31714 var picture = this.jsonModel.displayPictureClause; 31715 31716 if (picture) { 31717 try { 31718 31719 var formattedValue = xfalib.ut.PictureFmt.format(value + "", picture, null, true); 31720 31721 return formattedValue != null && formattedValue !== "" ? formattedValue : value; 31722 } catch (exception) { 31723 31724 } 31725 } 31726 return value; 31727 }, 31728 31729 _getValue : function () { 31730 if (this.bindNode) { 31731 return this.bindNode.rawValue; 31732 } 31733 return this._getTypedValue(this.jsonModel._value); 31734 }, 31735 31736 _triggerDisplayFormatChange : function () { 31737 var currValue = this._getValue(); 31738 this._triggerEvent(guidelib.event.GuideModelEvent.VALUE_CHANGED, "value", 31739 currValue, this._getFormattedValue(currValue)); 31740 }, 31741 31742 31743 checkIfNull : function (value) { 31744 return value == null || value === ""; 31745 }, 31746 31747 31748 isEmpty : function () { 31749 return this.checkIfNull(this.value); 31750 }, 31751 31752 _setXFAValue : function (value) { 31753 this.bindNode.rawValue = value; 31754 }, 31755 31756 31757 _setXFAMandatory : function (value) { 31758 31759 31760 var convertor = this._guide()._guideSchema.getConvertor("mandatory"); 31761 if (convertor) { 31762 31763 31764 this.bindNode.validate.nullTest = convertor.guideToXfa.apply(this, [!!value]); 31765 } 31766 }, 31767 31768 _setGuideValue : function (value) { 31769 this.jsonModel._value = (value === undefined || value === null) ? null : value; 31770 }, 31771 31772 _runMandatoryTest : function () { 31773 var currValue = this._getValue(), 31774 isNull = this.checkIfNull(currValue); 31775 return !isNull; 31776 }, 31777 31778 _runValidatePictureTest : function () { 31779 var value = this._getValue(), 31780 validateFlag = true, 31781 regex; 31782 if (!this.checkIfNull(value) && this.validatePictureClause) { 31783 31784 try { 31785 value = xfalib.ut.PictureFmt.format(value + "", this.validatePictureClause, null, false); 31786 } catch (exception) { 31787 31788 this.logger().log("AF", exception); 31789 31790 if (exception.indexOf("Invalid picture clause") !== -1) { 31791 value = undefined; 31792 } else { 31793 value = null; 31794 } 31795 } 31796 } 31797 if (_.isUndefined(value)) { 31798 try { 31799 31800 regex = new RegExp(this.validatePictureClause); 31801 if (regex) { 31802 validateFlag = regex.test(this._getValue()); 31803 } 31804 } catch (exception) { 31805 31806 this.logger().error("AF", "Invalid Regular Expression" + exception); 31807 validateFlag = false; 31808 } 31809 } else if (value === null) { 31810 validateFlag = false; 31811 } 31812 31813 return validateFlag; 31814 }, 31815 31816 31817 _runTests : function (forceRun) { 31818 31819 var validFlag = true, 31820 prevErrorText = this._errorText, 31821 prevValidationState = this.validationState, 31822 obj = { 31823 'validFlag' : validFlag, 31824 'forceRun' : forceRun 31825 }; 31826 31827 if (this.validationsDisabled === true) { 31828 31829 31830 return true; 31831 } 31832 31833 this._runValidations(obj); 31834 validFlag = obj.validFlag; 31835 31836 if (validFlag) { 31837 this._errorText = ""; 31838 this.validationState = true; 31839 31840 this._failedTest = null; 31841 } else { 31842 this.validationState = false;
31843 } 31844 31845 if ((prevErrorText !== this._errorText) || (prevValidationState !== this.validationState) || forceRun) { 31846 31847 if (forceRun) { 31848 this.forceErrorShow = true; 31849 } 31850 this._triggerEvent(guidelib.event.GuideModelEvent.ERROR_CHANGED, 31851 "validationStatus", this.validationState, this._errorText); 31852 } 31853 31854 return this.validationState; 31855 }, 31856 31857 playJson : function (pJsonModel) { 31858 var currValue = pJsonModel._value, 31859 _guide = this._guide(); 31860 31861 if (this.valueCommitScript && _guide.version.isOn(_guide.version.Flags.RUN_VALUE_COMMMIT_ON_PREFILL) && currValue) { 31862 31863 _guide.queueExpressions(this, ["valueCommitScript"]); 31864 } 31865 this._setGuideValue(pJsonModel._value); 31866 }, 31867 31868 31869 _runValidations : function (obj) { 31870 var isRegex = false, 31871 INVALID_PICTURE_CLAUSE_LIST = ["date.default{}", "date.short{}", "date.medium{}", 31872 "date.long{}", "date.full{}", "num.percent{}", "num.decimal{}", "num.currency{}"]; 31873 if (this.bindNode) { 31874 if (this.validatePictureClause && (this.value || this.value === 0)) { 31875 31876 31877 try { 31878 xfalib.ut.PictureFmt.format(this.value + "", this.validatePictureClause, null, false); 31879 } catch (exception) { 31880 if (INVALID_PICTURE_CLAUSE_LIST.indexOf(this.validatePictureClause) >= 0) { 31881 isRegex = false; 31882 } else if (exception.indexOf("Invalid picture clause") !== -1) { 31883 isRegex = true; 31884 } 31885 } 31886 } 31887 if (isRegex) { 31888 try { 31889 31890 var regex = new RegExp(this.validatePictureClause); 31891 if (regex) { 31892 obj.validFlag = regex.test(this._getValue()); 31893 } 31894 } catch (exception) { 31895 this.logger().error("AF", "Error in running regular expression" + exception); 31896 obj.validFlag = false; 31897 } 31898 if (!obj.validFlag) { 31899 this.bindNode._setErrorData("formatTest", this.getOrElse(this.bindNode.validate.formatTest, this.bindNode._defaults.validate.formatTest), this.bindNode.formatMessage); 31900 this._errorText = this.bindNode._errorText; 31901 xfalib.ut.XfaUtil.prototype._triggerOnBridge("elementValidationStatusChanged", this.bindNode, "validationStatus", false, true); 31902 this.bindNode.execEvent("validationState"); 31903 } 31904 } else { 31905 if (obj.forceRun) { 31906 this.bindNode.execValidate(); 31907 } 31908 this._errorText = this.bindNode._errorText; 31909 if (this._errorText) { 31910 obj.validFlag = false; 31911 } 31912 } 31913 31914 this._failedTest = this.bindNode._mFailedValTest; 31915 } else { 31916 31917 if (this.mandatory) { 31918 obj.validFlag = this._runMandatoryTest(); 31919 if (!obj.validFlag) { 31920 this._errorText = this.mandatoryMessage; 31921 this._failedTest = this.guideUtil.MANDATORY_TEST; 31922 } 31923 } 31924 if (obj.validFlag && this.validatePictureClause && !this.checkIfNull(this.value)) { 31925 obj.validFlag = this._runValidatePictureTest(); 31926 if (!obj.validFlag) { 31927 this._errorText = this.validatePictureClauseMessage; 31928 this._failedTest = this.guideUtil.FORMAT_TEST; 31929 } 31930 } 31931 } 31932 31933 if (obj.validFlag && this.validateExp) {
31934 obj.validFlag = this.executeExpression("validateExp"); 31935 if (!obj.validFlag) { 31936 this._errorText = this.validateExpMessage; 31937 this._failedTest = this.guideUtil.SCRIPT_TEST; 31938 } 31939 } 31940 }, 31941 31942 _collectValues : function (keyValue) { 31943 31944 keyValue[this.name] = this.value; 31945 }, 31946 31947 31948 resetData : function () { 31949 this._runValidation = false; 31950 this.value = this.jsonModel["{default}"]; 31951 this._runValidation = true; 31952 31953 this._errorText = ""; 31954 this.validationState = true; 31955 this._failedTest = null; 31956 this._triggerEvent(guidelib.event.GuideModelEvent.ERROR_RESET, 31957 "validationStatus", this.validationState, this._errorText); 31958 }, 31959 31960 _preserveLazyValue : function () { 31961 return !(_.contains(['guideButton', 'guideTextDraw', 'guideAdobeSignBlock'], this.className) || this._isXfaNode()); 31962 }, 31963 31964 31965 _updateLiveData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar) { 31966 if (this._preserveLazyValue()) { 31967 var dataUtils = this._guide().internal.liveDataUtils, 31968 dataContext = dataUtils._getDataContext(this, bound_indexedXpathSoFar, 31969 unBound_indexedXpathSoFar), 31970 isRichText = this instanceof guidelib.model.GuideTextBox && this.allowRichText, 31971 setValue = isRichText ? dataUtils.setRichTextValue : dataUtils.setDataValue; 31972 setValue.apply(dataUtils, [dataContext.indexedXpath, dataContext.xmlSec, 31973 !this.isEmpty(), this.isEmpty() ? "" : this.value]); 31974 } 31975 }, 31976 31977 31978 _playLiveData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar) { 31979 if (this._preserveLazyValue()) { 31980 var dataUtils = this._guide().internal.liveDataUtils, 31981 dataContext = dataUtils._getDataContext(this, bound_indexedXpathSoFar, 31982 unBound_indexedXpathSoFar), 31983 isRichText = this instanceof guidelib.model.GuideTextBox && this.allowRichText, 31984 getValue = isRichText ? dataUtils.getRichTextValue : dataUtils.getDataValue; 31985 var value = getValue.apply(dataUtils, [dataContext.indexedXpath, dataContext.xmlSec]); 31986 if (value != undefined) { 31987 this.value = value; 31988 } 31989 } 31990 }, 31991 31992 31993 _allowEmptyValueString : function () { 31994 return false; 31995 }, 31996 31997 markAsInvalid : function (errorText, shouldShowError) { 31998 shouldShowError = (typeof shouldShowError !== 'undefined') ? shouldShowError : false; 31999 this.validationState = false; 32000 if (!errorText) { 32001 errorText = this.validateExpMessage; 32002 } 32003 if(shouldShowError) { 32004 this._errorText = errorText; 32005 this.forceErrorShow = true; 32006 } 32007 this._triggerEvent(guidelib.event.GuideModelEvent.ERROR_CHANGED, 32008 "validationStatus", this.validationState, errorText); 32009 }, 32010 32011 32012 _isStateOverridden : function (property) { 32013 return this.getOrElse(this.jsonModel.stateOverrides, property, null) != null; 32014 } 32015 }); 32016 32017 Field.defineProps({ 32018 calcExp : { 32019 get : function () { 32020 return this.getAttribute("calcExp"); 32021 } 32022 }, 32023 32024 32025 isGlobal : { 32026 get : function () { 32027 return this.getAttribute('isGlobal') === "true"; 32028 } 32029 }, 32030 32031 32032 title : { 32033 get : function () { 32034 return this.getAttribute("jcr:title"); 32035 }, 32036 set : function (title) { 32037 this.setAttribute(title, "jcr:title"); 32038 } 32039 }, 32040 32041 valueCommitScript : { 32042 get : function () { 32043 return this.getAttribute("valueCommitScript"); 32044 } 32045 }, 32046 32047 validateExp : { 32048 get : function () { 32049 return this.getAttribute("validateExp"); 32050 } 32051 }, 32052 32053 32054 placeholderText : { 32055 get : function () { 32056 return this.getAttribute("placeholderText"); 32057 } 32058 }, 32059 32060 32061 value : { 32062 get : function () { 32063 var context = this.getOrElse(this._guide(), "_currentContext", null); 32064 if (context && context.managedExp 32065 32066 && !(context.contextNode === this 32067 && context.expression === "calcExp")) { 32068 32069 this._addDependant(context.contextNode, context.expression); 32070 } 32071 return this._getValue(); 32072 }, 32073 set : function (newValue) { 32074 var oldValue = this._getValue(),
32075 newTypedValue = this._getTypedValue(newValue), 32076 _guide = this._guide(); 32077 32078 if (this._allowEmptyValueString() && newValue === "") { 32079 newTypedValue = ""; 32080 } 32081 32082 32083 if (newTypedValue !== undefined && !(this.checkIfNull(newTypedValue) && this.checkIfNull(oldValue)) 32084 && (newTypedValue !== oldValue)) { 32085 if (this.bindNode) { 32086 this._setXFAValue(newTypedValue); 32087 } else if (this.jsonModel._value !== newValue) { 32088 this._setGuideValue(newTypedValue); 32089 } 32090 if (_guide && _guide.version.isOn(_guide.version.Flags.RUN_VALUE_COMMMIT_ON_SCRIPT_CHANGE)) { 32091 var context = _guide._currentContext, 32092 contextNode = this.getOrElse(context, "contextNode", null), 32093 contextExpression = this.getOrElse(context, "expression", null); 32094 if (!context || contextNode != this || contextExpression != "valueCommitScript") { 32095 32096 _guide.queueExpressions(this, ["valueCommitScript"]); 32097 } 32098 } 32099 32100 this._notifyDependants(); 32101 32102 if (this._runValidation && _guide) { 32103 _guide.queueExpressions(this, ["validateAllExp"]); 32104 } 32105 this._triggerOnBridge("elementValueChanged", this, "value", oldValue, newTypedValue); 32106 32107 32108 if (!this.bindNode || (this.bindNode && this.getAttribute("html5Type") !== undefined)) { 32109 this._triggerDisplayFormatChange(); 32110 } 32111 } 32112 } 32113 }, 32114 32115 32116 formattedValue : { 32117 get : function () { 32118 var value; 32119 if (this.bindNode) { 32120 value = this.bindNode.formattedValue; 32121 } else { 32122 value = this._getFormattedValue(this._getValue()); 32123 } 32124 return value; 32125 } 32126 }, 32127 32128 32129 displayPictureClause : { 32130 get : function () { 32131 return this.getAttribute("displayPictureClause"); 32132 } 32133 }, 32134 32135 32136 validatePictureClause : { 32137 get : function () { 32138 if (this.jsonModel.displayIsSameAsValidate) { 32139 return this.displayPictureClause; 32140 } 32141 return this.getAttribute("validatePictureClause"); 32142 } 32143 }, 32144 32145 32146 editPictureClause : { 32147 get : function () { 32148 if (this.jsonModel.isEditSameAsDisplayPattern) { 32149 return this.displayPictureClause; 32150 } 32151 return this.getAttribute("editPictureClause"); 32152 } 32153 }, 32154 32155 32156 isEditPictureClausePresent : { 32157 get : function () { 32158 return typeof this.editPictureClause !== 'undefined'; 32159 } 32160 }, 32161 32162 32163 mandatory : { 32164 get : function () { 32165 return this.getAttribute("mandatory"); 32166 }, 32167 32168 set : function (newValue) { 32169 var oldValue = this.getAttribute("mandatory"); 32170 if (newValue !== undefined && oldValue !== newValue) { 32171 if (this.bindNode) { 32172 this._setXFAMandatory(newValue); 32173 } else { 32174 32175 this.jsonModel.mandatory = !!newValue; 32176 } 32177 32178 this._triggerEvent(guidelib.event.GuideModelEvent.MODEL_CHANGED, "mandatory", oldValue, newValue); 32179 } 32180 } 32181 }, 32182 32183 32184 mandatoryMessage : { 32185 get : function () { 32186 return this.getAttribute("mandatoryMessage"); 32187 } 32188 }, 32189 32190 32191 validateExpMessage : { 32192 set : function (message) { 32193 32194 if (this.isValid) { 32195 this.jsonModel.validateExpMessage = message; 32196 } else { 32197 this.setAttribute(message, "validateExpMessage"); 32198 } 32199 }, 32200 get : function () { 32201 return this.getAttribute("validateExpMessage"); 32202 } 32203 }, 32204 32205 32206 validatePictureClauseMessage : { 32207 get : function () { 32208 return this.getAttribute("validatePictureClauseMessage"); 32209 } 32210 }, 32211 32212 32213 validationState : { 32214 get : function () { 32215 return this.isValid; 32216 }, 32217 set : function (newValue) { 32218 var oldVal = this.isValid; 32219 if (oldVal != newValue) { 32220 this.isValid = newValue; 32221 this._triggerOnBridge("elementValidationStatusChanged", this, 32222 "validationStatus", oldVal, newValue); 32223 } 32224 } 32225 }, 32226 32227 width : { 32228 get : function () { 32229 return this.getAttribute("width"); 32230 }, 32231 32232 set : function (newValue) { 32233 this.jsonModel.width = newValue; 32234 } 32235 }, 32236 32237 height : { 32238 get : function () { 32239 return this.getAttribute("height"); 32240 }, 32241 32242 set : function (newValue) { 32243 this.jsonModel.height = newValue; 32244 } 32245 } 32246 }); 32247 32248 Field.addMixins([ 32249 guidelib.model.mixin.AddDependencyMgmt, 32250 guidelib.model.mixin.ValidationsDisabled 32251 ]); 32252}(_, guidelib)); 32253 32254(function (_, guidelib) { 32255 32256 var GuideButton = guidelib.model.GuideButton = guidelib.model.Field.extend({ 32257 msClassName : "guideButton", 32258 defaultClickExpressions : { 32259 "moveNext" : "window.guideBridge.setFocus(this.panel.somExpression, 'nextItem', true)", 32260 "movePrev" : "window.guideBridge.setFocus(this.panel.somExpression, 'prevItem', true)" 32261 }, 32262 defaultNavigationExpressions : { 32263 "moveNext" : "this.visible=this.panel.navigationContext.hasNextItem", 32264 "movePrev" : "this.visible=this.panel.navigationContext.hasPrevItem" 32265 }, 32266 32267 _collectExpressions : function () { 32268 GuideButton._super._collectExpressions.apply(this); 32269 if (this.clickExp) { 32270 this._compiledScripts["clickExp"] = this._compileExpression(this.clickExp, null); 32271 } else if (this.targetVersion >= 1.1 && this.defaultClickExpressions[this.type]) { 32272 this.jsonModel.clickExp = this.defaultClickExpressions[this.type]; 32273 this._compiledScripts["clickExp"] = this._compileExpression(this.clickExp, null); 32274 } 32275 if (this.navigationChangeExp) { 32276 this._compiledScripts["navigationChangeExp"] = this._compileExpression(this.navigationChangeExp, null); 32277 } else if (this.targetVersion >= 1.1 && this.defaultNavigationExpressions[this.type]) { 32278 this.jsonModel.navigationChangeExp = this.defaultNavigationExpressions[this.type]; 32279 this._compiledScripts["navigationChangeExp"] = this._compileExpression(this.navigationChangeExp, null); 32280 } 32281 }, 32282 32283 }); 32284 32285 GuideButton.defineProps({ 32286 clickExp : { 32287 get : function () { 32288 return this.jsonModel.clickExp; 32289 } 32290 }, 32291 navigationChangeExp : { 32292 get : function () { 32293 return this.jsonModel.navigationChangeExp; 32294 } 32295 }, 32296 32297 type : { 32298 get : function () { 32299 return this.getAttribute("type"); 32300 } 32301 } 32302 }); 32303})(_, guidelib); 32304 32305(function (_, guidelib) { 32306 var GuideListFileAttachmentButton = guidelib.model.GuideListFileAttachmentButton = guidelib.model.GuideButton.extend({ 32307 msClassName : "guideListFileAttachmentButton", 32308 initialize : function () { 32309 32310 if (_.isUndefined(this.jsonModel.clickExp)) { 32311 this.jsonModel.clickExp = "guideBridge._updateFileListing.call(this,this)"; 32312 32313 } 32314 GuideListFileAttachmentButton._super.initialize.apply(this, arguments); 32315 } 32316 }); 32317 32318})(_, guidelib); 32319(function (_, guidelib) { 32320 var GuideCheckBox = guidelib.model.GuideCheckBox = guidelib.model.Field.extend({ 32321 msClassName : "guideCheckBox", 32322 32323 _collectExpressions : function () { 32324 GuideCheckBox._super._collectExpressions.apply(this); 32325 if (this.optionsExp) { 32326 this._compiledExpressions.optionsExp = this._compileExpression(this.optionsExp, "items"); 32327 } 32328 }, 32329 32330 getOnOffValues : function (index) { 32331 var temp = this.jsonModel.options || [], items = [], on, off; 32332 if (this.bindNode) { 32333 on = this.bindNode.getSaveItem(0); 32334 off = this.bindNode.getSaveItem(1); 32335 } else { 32336 32337 if (temp.length == 0) { 32338 on = "0"; 32339 } else { 32340 on = temp[index].split('=')[0].trim(); 32341 } 32342 off = "-100"; 32343 } 32344 32345 items = [on, off]; 32346 return items; 32347 }, 32348 32349 _setXFAValue : function (value) { 32350 32351 if (value === "" || value === null) { 32352 this.bindNode.rawValue = this.bindNode.getSaveItem(1) || null; 32353 } else { 32354 this.bindNode.rawValue = value; 32355 } 32356 }, 32357 32358 _getCustomAssist : function (index) { 32359 var customAssist, item; 32360 32361 if (index == null) { 32362 32363 if (this.bindNode && this.bindNode.assist && this.bindNode.assist.speak && this.bindNode.assist.speak.value) { 32364 return this.bindNode.assist.speak.value; 32365 } 32366 return null; 32367 } 32368 32369 if (this.bindNode && this.bindNode.members && this.bindNode.members.item) { 32370 item = this.bindNode.members.item(index); 32371 if (item && item.assist && item.assist.speak && item.assist.speak.value) { 32372 customAssist = item.assist.speak.value; 32373 } 32374 } else if (this.jsonModel.custom) { 32375 32376 var custom; 32377 custom = this.jsonModel.custom || []; 32378 if (_.isString(custom) && index <= 0) { 32379 customAssist = custom; 32380 } else if (!custom.length === 0) { 32381 customAssist = custom[index]; 32382 } 32383 } 32384 return customAssist; 32385 }, 32386 _getToolTip : function (index) { 32387 var toolTip, item; 32388 if (this.bindNode && this.bindNode.members && this.bindNode.members.item) { 32389 item = this.bindNode.members.item(index); 32390 32391 if (item && item.assist && item.assist.speak && item.assist.speak.value) { 32392 toolTip = item.assist.toolTip.value; 32393 } 32394 32395 }
32395 else if (this.jsonModel.shortDescription) { 32396 toolTip = this.jsonModel.shortDescription; 32397 } 32398 return toolTip; 32399 }, 32400 _getCaption : function (index) { 32401 var item, caption, option; 32402 if (index == null) { 32403 32404 if (this.bindNode && this.bindNode.caption && this.bindNode.caption.value && this.bindNode.caption.value.oneOfChild && this.bindNode.caption.value.oneOfChild.value) { 32405 return this.bindNode.caption.value.oneOfChild.value; 32406 } 32407 return null; 32408 } 32409 if (this.bindNode && this.bindNode.members && this.bindNode.members.item) { 32410 item = this.bindNode.members.item(index); 32411 if (item.caption && item.caption.value && item.caption.value.oneOfChild && item.caption.value.oneOfChild.value) { 32412 caption = item.caption.value.oneOfChild.value; 32413 } 32414 32415 } else if (this.jsonModel.options) { 32416 var options; 32417 options = this.jsonModel.options || []; 32418 if (index < 0) { 32419 index = 0; 32420 } 32421 if (!options.length == 0) { 32422 option = options[index]; 32423 caption = guidelib.util.GuideUtil.getOptionsKeyValue(option).pop(); 32424 } 32425 32426 } 32427 return caption; 32428 }, 32429 _getName : function (index) { 32430 if (this.bindNode && this.bindNode.members && this.bindNode.members.item && this.bindNode.members.item(index)) { 32431 32432 return this.bindNode.members.item(index).name; 32433 } 32434 return null; 32435 }, 32436 32437 _getScreenReaderText : function (index) { 32438 var screenReaderText, assistPriority = this._getAssistPriority() || "caption"; 32439 32440 if (this.bindNode) { 32441 screenReaderText = GuideCheckBox._super._getScreenReaderText.apply(this, [index]); 32442 } else { 32443 if (assistPriority == "custom") { 32444 screenReaderText = this._getCustomAssist(index) || this._getCaption(index); 32445 } else if (assistPriority == "caption") { 32446 screenReaderText = this._getCaption(index); 32447 } 32448 } 32449 return screenReaderText; 32450 } 32451 }); 32452 32453 GuideCheckBox.defineProps({ 32454 32455 optionsExp : { 32456 get : function () { 32457 return this.getAttribute("optionsExp"); 32458 } 32459 }, 32460 32461 32462 items : { 32463 get : function () { 32464 var items = this.jsonModel.options; 32465 if (items && !_.isArray(items)) { 32466 items = items.split(","); 32467 } else if (items) { 32468 items = items.slice(0); 32469 } 32470 return items; 32471 }, 32472 set : function (newValue) { 32473 if (!this.bindNode) { 32474 var oldValue = this.jsonModel.options; 32475 if (JSON.stringify(newValue) !== JSON.stringify(oldValue)) { 32476 32477 this.jsonModel.options = newValue; 32478 this._resetModelValueForOptionChange(); 32479 this._addStateOverride("options", {"option" : this._getOptionsArray()}); 32480 this._triggerItemsChange(oldValue, newValue); 32481 } 32482 } 32483 } 32484 } 32485 }); 32486 32487 GuideCheckBox.addMixins([ 32488 guidelib.model.mixin.ChoiceGroupOptionHandler 32489 ]); 32490})(_, guidelib); 32491(function (_, guidelib) { 32492 var GuideSwitch = guidelib.model.GuideSwitch = guidelib.model.GuideCheckBox.extend({ 32493 msClassName : "guideSwitch", 32494 32495 initialize : function () { 32496 32497 var uncheckedValue = this.getOnOffValues()[1]; 32498 this.jsonModel["_value"] = this.getOrElse(this.jsonModel, "_value", uncheckedValue); 32499 GuideSwitch._super.initialize.call(this); 32500 }, 32501 32502 getOnOffValues : function (index) { 32503 var options, checkedLabel, uncheckedLabel, items; 32504 if (this.bindNode) { 32505 checkedLabel = this.bindNode.getSaveItem(0); 32506 uncheckedLabel = this.bindNode.getSaveItem(1); 32507 } else { 32508 items = this.jsonModel.options; 32509 32510 if (Array.isArray(items) && items.length > 0) { 32511 checkedLabel = items[0].split('=')[0].trim(); 32512 } else if (!_.isUndefined(items) && items.length > 0) { 32513 checkedLabel = items.split('=')[0].trim(); 32514 } else { 32515 checkedLabel = "1"; 32516 } 32517 if (Array.isArray(items) && items.length > 1) { 32518 uncheckedLabel = items[1].split('=')[0].trim(); 32519 } else { 32520 uncheckedLabel = "0"; 32521 } 32522 } 32523 options = [checkedLabel, uncheckedLabel]; 32524 return options; 32525 }, 32526 32527 resetData : function () { 32528 this.value = this.jsonModel["{default}"]; 32529 } 32530 }); 32531})(_, guidelib); 32532(function (_, guidelib) { 32533 var GuideTextDraw = guidelib.model.GuideTextDraw = guidelib.model.Field.extend({ 32534 msClassName : "guideTextDraw", 32535 32536 _valueEscapeRegex : new RegExp('\\$', 'g'), 32537 32538 32539 _getValue : function () { 32540 if (this.bindNode) { 32541 return this.bindNode._getValue(null, true); 32542 } 32543 return this._getTypedValue(this.jsonModel._value); 32544 }, 32545 32546 32547 playJson : function (pJsonModel) { 32548 32549 this._setGuideValue(this._floatingFieldResolutionFunction(pJsonModel)); 32550 }, 32551 32552 _allowEmptyValueString : function () { 32553 return true; 32554 }, 32555 32556 _isFloatingField : function () { 32557 return this.documentFragmentVariables && this.documentFragmentVariables.length > 0; 32558 }, 32559 32560 _floatingFieldResolutionFunction : function (jsonModel) { 32561 var resolvedValue = this.value, 32562 variableRegexMap = this._variableRegexMap, 32563 valueEscapeRegex = this._valueEscapeRegex, 32564 somExpression = this.somExpression, 32565 self = this, 32566 32567 32568 variablesDefaultValue = [], 32569 documentFragmentVariables = this.documentFragmentVariables; 32570 if (jsonModel.documentFragmentVariables) { 32571 for (var index = 0 ; index < jsonModel.documentFragmentVariables.length ; index++) { 32572 variablesDefaultValue[index] = jsonModel.documentFragmentVariables[index]._value; 32573 } 32574 } 32575 this.jsonModel.defaultValue = variablesDefaultValue; 32576 _.each(variableRegexMap, function (regexPattern, variableId) { 32577 var textVariable, 32578 bindRef, 32579 floatingFieldValue; 32580 textVariable = documentFragmentVariables.filter(function (variable) { 32581 return variable.variableId === variableId; 32582 })[0]; 32583 bindRef = textVariable.bindRef; 32584 if (!bindRef) { 32585 bindRef = textVariable.name; 32586 } 32587 32588 if (jsonModel && jsonModel.documentFragmentVariables && jsonModel.documentFragmentVariables.length > 0) { 32589 var variableFromPlayJson = jsonModel.documentFragmentVariables.filter(function (variable) { 32590 return variable.variableId === variableId; 32591 })[0]; 32592 floatingFieldValue = variableFromPlayJson._value; 32593 } else { 32594 floatingFieldValue = guidelib.util.GuideUtil.getValueForBindRefField(bindRef, somExpression, this._guide()); 32595 } 32596 if (!floatingFieldValue) { 32597 32598 floatingFieldValue = ""; 32599 } else { 32600 32601 32602 floatingFieldValue = floatingFieldValue.replace(valueEscapeRegex, '$$$$'); 32603 } 32604 if (floatingFieldValue) { 32605 var dataType = textVariable.dataType, 32606 displayPattern = textVariable.displayPictureClause; 32607 if (dataType === 'number' || dataType === 'integer') { 32608 displayPattern = displayPattern ? displayPattern : 'num{zzz,zzz,zzz,zzz,zzz,zzz,zzz.zzzzzzzzzzzzzzz}'; 32609 } else if (dataType === 'date-time' || dataType === 'date') { 32610 displayPattern = displayPattern ? displayPattern : 'date{' + guidelib.i18n.datePatterns.med + '}'; 32611 } 32612 32613 if (displayPattern) { 32614 if (floatingFieldValue.indexOf(',') !== -1) { 32615 32616 var valArray = floatingFieldValue.split(','), 32617 tmpValue = ""; 32618 valArray.forEach(function (val) { 32619 tmpValue = tmpValue + guidelib.util.GuideUtil.formatValue(val, displayPattern, dataType) + ", " ; 32620 }); 32621 floatingFieldValue = tmpValue.substr(0, tmpValue.length - 2); 32622 } else { 32623 floatingFieldValue = guidelib.util.GuideUtil.formatValue(floatingFieldValue, displayPattern, dataType); 32624 } 32625 } 32626 } 32627 resolvedValue = resolvedValue.replace(regexPattern, floatingFieldValue); 32628 }); 32629 return resolvedValue; 32630 }, 32631 32632 initialize : function () { 32633 if (this._isFloatingField()) { 32634 var variableRegexMap = this._variableRegexMap = {}; 32635 _.each(this.documentFragmentVariables, function (documentFragmentVariable) { 32636 var variableId = documentFragmentVariable.variableId, 32637 regexPattern; 32638 if (!variableRegexMap[variableId]) { 32639 32640 regexPattern = '(?:<df-variable[^>]*variableid="' + variableId + '"[^>]*>)[^<]*(?:<\/df-variable>)'; 32641 variableRegexMap[variableId] = new RegExp(regexPattern, 'ig'); 32642 } 32643 }); 32644 } 32645 GuideTextDraw._super.initialize.apply(this, [arguments]); 32646 } 32647 }); 32648 32649 GuideTextDraw.defineProps({ 32650 calcExp : { 32651 get : function () { 32652 return this._calcExp; 32653 } 32654 }, 32655 32656 documentFragmentVariables : { 32657 get : function () { 32658 return this.jsonModel.documentFragmentVariables; 32659 } 32660 } 32661 }); 32662}(_, guidelib)); 32663 32664(function (_, guidelib) { 32665 var GuideAdobeSignBlock = guidelib.model.GuideAdobeSignBlock = guidelib.model.GuideTextDraw.extend({ 32666 msClassName : "guideAdobeSignBlock" 32667 }); 32668}(_, guidelib)); 32669(function (_, guidelib) { 32670 32671 var GuideTextBox = guidelib.model.GuideTextBox = guidelib.model.Field.extend({ 32672 msClassName : "guideTextBox", 32673 32674 32675 _runMinimumLengthTest : function () { 32676 return this.value && this.value.length >= this.minLength; 32677 }, 32678 32679 32680 _runTotalLengthTest : function () { 32681 return this.value && this.value.length === this.length; 32682 }, 32683 32684 32685 _runValidations : function (obj) { 32686 GuideTextBox._super._runValidations.call(this, obj); 32687 if (obj.validFlag) { 32688 32689 if (this.length != null) {
32690 obj.validFlag = this._runTotalLengthTest(); 32691 if (!obj.validFlag) { 32692 this._errorText = this.guideUtil.getLocalizedMessage("", guidelib.i18n.strings.totalLengthMessage, [this.length]); 32693 this._failedTest = this.guideUtil.LENGTH_TEST; 32694 } 32695 } else if (this.minLength != null) { 32696 obj.validFlag = this._runMinimumLengthTest(); 32697 if (!obj.validFlag) { 32698 this._errorText = this.guideUtil.getLocalizedMessage("", guidelib.i18n.strings.minimumLengthMessage, [this.minLength]); 32699 this._failedTest = this.guideUtil.MINIMUM_LENGTH_TEST; 32700 } 32701 } 32702 32703 } 32704 }, 32705 32706 32707 _runMandatoryTest : function () { 32708 if (this.allowRichText) { 32709 32710 32711 var getTextContent = function (htmlString) { 32712 var result = htmlString, 32713 regex = null; 32714 if (htmlString != null) { 32715 32716 32717 regex = /(<([^>]+)>)/ig; 32718 result = htmlString.replace(regex, ""); 32719 } 32720 return result; 32721 }, 32722 currValue = getTextContent(this._getValue()), 32723 isNull = this.checkIfNull(currValue); 32724 return !isNull; 32725 } else { 32726 return GuideTextBox._super._runMandatoryTest.apply(this, arguments); 32727 } 32728 }, 32729 32730 _allowEmptyValueString : function () { 32731 return true; 32732 } 32733 32734 }); 32735 32736 GuideTextBox.defineProps({ 32737 32738 "multiLine" : { 32739 get : function () { 32740 return this.getAttribute("multiLine"); 32741 } 32742 }, 32743 32744 32745 "maxChars" : { 32746 get : function () { 32747 return this.getAttribute("maxChars"); 32748 } 32749 }, 32750 32751 32752 "minLength" : { 32753 get : function () { 32754 return this.getAttribute("minLength"); 32755 } 32756 }, 32757 32758 32759 "length" : { 32760 get : function () { 32761 return this.getAttribute("length"); 32762 } 32763 }, 32764 32765 "allowRichText" : { 32766 get : function () { 32767 return this.getAttribute("allowRichText"); 32768 } 32769 } 32770 }); 32771 32772}(_, guidelib)); 32773 32774(function (_, guidelib) { 32775 32776 var countriesDialingCodesMap = { 32777 '441481' : 'Guernsey', 32778 '441624' : 'Isle of Man', 32779 '441534' : 'Jersey', 32780 '1868' : 'Trinidad and Tobago', 32781 '1473' : 'Grenada', 32782 '1670' : 'Northern Mariana Islands', 32783 '1869' : 'Saint Kitts and Nevis', 32784 '1758' : 'Saint Lucia', 32785 '1671' : 'Guam', 32786 "1684" : "American Samoa", 32787 "1268" : "Antigua and Barbuda", 32788 "1264" : "Anguilla", 32789 "1242" : "Bahamas", 32790 "1246" : "Barbados", 32791 '1441' : 'Bermuda', 32792 '1284' : 'British Virgin Islands', 32793 '1345' : 'Cayman Islands', 32794 '1787' : 'Puerto Rico', 32795 '1876' : 'Jamaica', 32796 '1939' : 'Puerto Rico', 32797 '1767' : 'Dominica', 32798 '1809' : 'Dominican Republic', 32799 '1829' : 'Dominican Republic', 32800 '1664' : 'Montserrat', 32801 '1849' : 'Dominican Republic', 32802 '1340' : 'U.S. Virgin Islands', 32803 '1784' : 'Saint Vincent and the Grenadines', 32804 '1649' : 'Turks and Caicos Islands', 32805 '1721' : 'Sint Maarten', 32806 "355" : "Albania", 32807 "213" : "Algeria", 32808 "376" : "Andorra", 32809 "244" : "Angola", 32810 "672" : "Antarctica", 32811 "374" : "Armenia", 32812 "297" : "Aruba", 32813 "994" : "Azerbaijan", 32814 "973" : "Bahrain", 32815 "880" : "Bangladesh", 32816 "375" : "Belarus", 32817 "501" : "Belize", 32818 "229" : "Benin", 32819 '975' : 'Bhutan', 32820 '591' : 'Bolivia', 32821 '387' : 'Bosnia and Herzegovina', 32822 '267' : 'Botswana', 32823 '246' : 'British Indian Ocean Territory', 32824 '673' : 'Brunei', 32825 '359' : 'Bulgaria', 32826 '226' : 'Burkina Faso', 32827 '257' : 'Burundi', 32828 '855' : 'Cambodia', 32829 '237' : 'Cameroon', 32830 '238' : 'Cape Verde', 32831 '236' : 'Central African Republic', 32832 '235' : 'Chad', 32833 '269' : 'Comoros', 32834 '682' : 'Cook Islands', 32835 '506' : 'Costa Rica', 32836 '385' : 'Croatia', 32837 32838 '357' : 'Cyprus', 32839 '420' : 'Czech Republic', 32840 '243' : 'Democratic Republic of the Congo', 32841 '253' : 'Djibouti', 32842 '670' : 'East Timor', 32843 '593' : 'Ecuador', 32844 '503' : 'El Salvador', 32845 '240' : 'Equatorial Guinea', 32846 '291' : 'Eritrea', 32847 '372' : 'Estonia', 32848 '251' : 'Ethiopia', 32849 '500' : 'Falkland Islands', 32850 '298' : 'Faroe Islands', 32851 '679' : 'Fiji', 32852 '358' : 'Finland', 32853 '689' : 'French Polynesia', 32854 '241' : 'Gabon', 32855 '220' : 'Gambia', 32856 '995' : 'Georgia', 32857 '233' : 'Ghana', 32858 '350' : 'Gibraltar', 32859 '299' : 'Greenland', 32860 '502' : 'Guatemala', 32861 '224' : 'Guinea', 32862 '245' : 'Guinea-Bissau', 32863 '592' : 'Guyana', 32864 '509' : 'Haiti', 32865 '504' : 'Honduras', 32866 '852' : 'Hong Kong', 32867 '354' : 'Iceland', 32868 '964' : 'Iraq', 32869 '353' : 'Ireland', 32870 '972' : 'Israel', 32871 '225' : 'Ivory Coast', 32872 '962' : 'Jordan', 32873 '254' : 'Kenya', 32874 '686' : 'Kiribati', 32875 '383' : 'Kosovo', 32876 '965' : 'Kuwait', 32877 '996' : 'Kyrgyzstan', 32878 '856' : 'Laos', 32879 '371' : 'Latvia', 32880 '961' : 'Lebanon', 32881 '266' : 'Lesotho', 32882 '231' : 'Liberia', 32883 '218' : 'Libya', 32884 '423' : 'Liechtenstein', 32885 '370' : 'Lithuania', 32886 '352' : 'Luxembourg', 32887 '853' : 'Macau', 32888 '389' : 'Macedonia', 32889 '261' : 'Madagascar', 32890 '265' : 'Malawi', 32891 '960' : 'Maldives', 32892 '223' : 'Mali', 32893 '356' : 'Malta', 32894 '692' : 'Marshall Islands', 32895 '222' : 'Mauritania', 32896 '230' : 'Mauritius', 32897 32898 '691' : 'Micronesia', 32899 '373' : 'Moldova', 32900 '377' : 'Monaco', 32901 '976' : 'Mongolia', 32902 '382' : 'Montenegro', 32903 32904 '258' : 'Mozambique', 32905 '264' : 'Namibia', 32906 '674' : 'Nauru', 32907 '977' : 'Nepal', 32908 '599' : 'Netherlands Antilles', 32909 '687' : 'New Caledonia', 32910 '505' : 'Nicaragua', 32911 '227' : 'Niger', 32912 '234' : 'Nigeria', 32913 '683' : 'Niue', 32914 '850' : 'North Korea', 32915 '968' : 'Oman', 32916 '680' : 'Palau', 32917 '970' : 'Palestine', 32918 '507' : 'Panama', 32919 '675' : 'Papua New Guinea', 32920 '595' : 'Paraguay', 32921 '351' : 'Portugal', 32922 '974' : 'Qatar', 32923 '242' : 'Republic of the Congo', 32924 '262' : 'Reunion', 32925 '250' : 'Rwanda', 32926 32927 '290' : 'Saint Helena', 32928 '590' : 'Saint Martin', 32929 '508' : 'Saint Pierre and Miquelon', 32930 '685' : 'Samoa', 32931 '378' : 'San Marino', 32932 '239' : 'Sao Tome and Principe', 32933 '966' : 'Saudi Arabia', 32934 '221' : 'Senegal', 32935 '381' : 'Serbia', 32936 '248' : 'Seychelles', 32937 '232' : 'Sierra Leone', 32938 '421' : 'Slovakia', 32939 '386' : 'Slovenia', 32940 '677' : 'Solomon Islands', 32941 '252' : 'Somalia', 32942 '211' : 'South Sudan', 32943 '249' : 'Sudan', 32944 '597' : 'Suriname', 32945 '268' : 'Swaziland', 32946 '963' : 'Syria', 32947 '886' : 'Taiwan', 32948 '992' : 'Tajikistan', 32949 '255' : 'Tanzania', 32950 '228' : 'Togo', 32951 '690' : 'Tokelau', 32952 '676' : 'Tonga', 32953 '216' : 'Tunisia', 32954 '993' : 'Turkmenistan', 32955 '688' : 'Tuvalu', 32956 '256' : 'Uganda', 32957 '380' : 'Ukraine', 32958 '971' : 'United Arab Emirates', 32959 '598' : 'Uruguay', 32960 '998' : 'Uzbekistan', 32961 '678' : 'Vanuatu', 32962 '379' : 'Vatican', 32963 '681' : 'Wallis and Futuna', 32964 '212' : 'Western Sahara', 32965 '967' : 'Yemen', 32966 '260' : 'Zambia', 32967 '263' : 'Zimbabwe', 32968 '60' : 'Malaysia', 32969 '58' : 'Venezuela', 32970 '30' : 'Greece', 32971 '84' : 'Vietnam', 32972 '44' : 'United Kingdom', 32973 '45' : 'Denmark', 32974 '53' : 'Cuba', 32975 '46' : 'Sweden', 32976 '52' : 'Mexico', 32977 '41' : 'Switzerland', 32978 '40' : 'Romania', 32979 32980 '36' : 'Hungary', 32981
32982 "43" : "Austria", 32983 '34' : 'Spain', 32984 '91' : 'India', 32985 '62' : 'Indonesia', 32986 '98' : 'Iran', 32987 '94' : 'Sri Lanka', 32988 '27' : 'South Africa', 32989 '95' : 'Myanmar', 32990 '65' : 'Singapore', 32991 '39' : 'Italy', 32992 '82' : 'South Korea', 32993 "32" : "Belgium", 32994 '81' : 'Japan', 32995 '31' : 'Netherlands', 32996 '20' : 'Egypt', 32997 "54" : "Argentina", 32998 "93" : "Afghanistan", 32999 33000 '56' : 'Chile', 33001 '86' : 'China', 33002 '51' : 'Peru', 33003 '63' : 'Philippines', 33004 '64' : 'Pitcairn', 33005 '48' : 'Poland', 33006 '47' : 'Norway', 33007 '33' : 'France', 33008 33009 '61' : 'Cocos Islands', 33010 '55' : 'Brazil', 33011 '92' : 'Pakistan', 33012 '49' : 'Germany', 33013 '57' : 'Colombia', 33014 '66' : 'Thailand', 33015 '90' : 'Turkey', 33016 33017 '1' : 'Canada', 33018 33019 '7' : 'Russia' 33020 }; 33021 33022 var GuideTelephone = guidelib.model.GuideTelephone = guidelib.model.GuideTextBox.extend({ 33023 msClassName : "guideTelephone", 33024 33025 _extractNumericDigits : function (telephoneNumber) { 33026 var digitArray, 33027 number = ""; 33028 if (telephoneNumber) { 33029 digitArray = telephoneNumber.match(/\d+/g); 33030 if (digitArray) { 33031 number = digitArray.join(""); 33032 } 33033 } 33034 return number; 33035 }, 33036 33037 _extractCountryCode : function (telephoneNumber) { 33038 var number = this._extractNumericDigits(telephoneNumber); 33039 if (!number || (telephoneNumber && number && telephoneNumber.lastIndexOf("+", 0) !== 0)) { 33040 return ""; 33041 } 33042 for (var countryCode in countriesDialingCodesMap) { 33043 if (number && number.lastIndexOf(countryCode, 0) === 0) { 33044 return countryCode; 33045 } 33046 } 33047 return ""; 33048 }, 33049 33050 _extractPhoneNumber : function (telephoneNumber) { 33051 var countryCode = this._extractCountryCode(telephoneNumber), 33052 number = this._extractNumericDigits(telephoneNumber), 33053 phoneNumber = ""; 33054 if (number) { 33055 phoneNumber = number.substr(countryCode.length); 33056 } 33057 return phoneNumber; 33058 } 33059 }); 33060 33061 GuideTelephone.defineProps({ 33062 33063 countryCode : { 33064 get : function () { 33065 var value = this._getValue(); 33066 return this._extractCountryCode(value); 33067 } 33068 }, 33069 33070 33071 phoneNumber : { 33072 get : function () { 33073 var value = this._getValue(); 33074 return this._extractPhoneNumber(value); 33075 } 33076 } 33077 }); 33078 33079}(_, guidelib)); 33080 33081(function (_, guidelib) { 33082 var GuideRadioButton = guidelib.model.GuideRadioButton = guidelib.model.Field.extend({ 33083 msClassName : "guideRadioButton", 33084 prevOnItem : null, 33085 initialize : function () { 33086 33087 GuideRadioButton._super.initialize.call(this); 33088 }, 33089 33090 _postInitialize : function () { 33091 GuideRadioButton._super._postInitialize.call(this); 33092 this.prevOnItem = this.getSelectedIndex(this.value); 33093 if (this.bindNode && this.bindNode.members) { 33094 for (var i = 0; i < this.bindNode.members.length; i++) { 33095 var field = this.bindNode.members.item(i); 33096 field.on(xfalib.script.XfaModelEvent.FORM_MODEL_CHANGED, this); 33097 } 33098 } 33099 }, 33100 33101 _unloadModel : function () { 33102 if (this.bindNode && this.bindNode.members) { 33103 for (var i = 0; i < this.bindNode.members.length; i++) { 33104 var field = this.bindNode.members.item(i); 33105 field.off(xfalib.script.XfaModelEvent.FORM_MODEL_CHANGED, this); 33106 } 33107 } 33108 33109 GuideRadioButton._super._unloadModel.call(this); 33110 }, 33111 33112 33113 _collectExpressions : function () { 33114 GuideRadioButton._super._collectExpressions.apply(this); 33115 if (this.optionsExp) { 33116 this._compiledExpressions.optionsExp = this._compileExpression(this.optionsExp, "items"); 33117 } 33118 }, 33119 33120 33121 getItemIdentifier : function (index) { 33122 if (this.bindNode) { 33123 return this.bindNode.members.item(index).somExpression; 33124 } else { 33125 return index; 33126 } 33127 33128 }, 33129 33130 playJson : function (pJsonModel) { 33131 GuideRadioButton._super.playJson.call(this, pJsonModel);
33132 this.prevOnItem = this.getSelectedIndex(this.jsonModel._value); 33133 }, 33134 33135 getOnOffValues : function (index) { 33136 var temp = this.jsonModel.options || [], 33137 items = [], 33138 on, 33139 off; 33140 if (this.bindNode) { 33141 var item = this.bindNode.members.item(index); 33142 on = item.getSaveItem(0); 33143 off = item.getSaveItem(1) ? item.getSaveItem(1) : null; 33144 } else { 33145 33146 if (temp.length == 0) { 33147 on = "0"; 33148 } else { 33149 on = temp[index].split('=')[0].trim(); 33150 } 33151 off = null; 33152 } 33153 33154 items = [on, off]; 33155 return items; 33156 }, 33157 33158 _handleXfaModelChanged : function (event) { 33159 if (event._property == "rawValue") { 33160 this.trigger(guidelib.event.GuideModelEvent.VALUE_CHANGED, 33161 guidelib.event.GuideModelEvent.createEvent( 33162 guidelib.event.GuideModelEvent.VALUE_CHANGED, 33163 this, 33164 "value", 33165 event.target.somExpression, 33166 event.newText 33167 ) 33168 ); 33169 } else { 33170 GuideRadioButton._super._handleXfaModelChanged.call(this, event); 33171 } 33172 }, 33173 33174 getSelectedIndex : function (value) { 33175 var index = null; 33176 if (!_.isEmpty(this.jsonModel.options) && !_.isArray(this.jsonModel.options)) { 33177 this.jsonModel.options = [this.jsonModel.options]; 33178 } 33179 var currOption = _.find(this.jsonModel.options, function (opt, i) { 33180 var items = this.getOnOffValues(i); 33181 index = i; 33182 return (items[0] == value); 33183 }, this); 33184 33185 if (currOption) { 33186 return index; 33187 } else { 33188 return null; 33189 } 33190 33191 }, 33192 33193 33194 33195 _triggerDisplayFormatChange : function () { 33196 if (!this.bindNode) { 33197 var currValue = this._getValue(); 33198 var currSelected = this.getSelectedIndex(currValue); 33199 33200 if (this.prevOnItem !== null) { 33201 this._triggerEvent(guidelib.event.GuideModelEvent.VALUE_CHANGED, "value", this.prevOnItem, null); 33202 } 33203 if (currSelected !== null) { 33204 this._triggerEvent(guidelib.event.GuideModelEvent.VALUE_CHANGED, "value", currSelected, this._getFormattedValue(currValue)); 33205 } 33206 this.prevOnItem = currSelected; 33207 } 33208 }, 33209 _getCustomAssist : function (index) { 33210 var customAssist, item; 33211 33212 if (index == null) { 33213 33214 if (this.bindNode && this.bindNode.assist && this.bindNode.assist.speak && this.bindNode.assist.speak.value) { 33215 return this.bindNode.assist.speak.value; 33216 } 33217 return null; 33218 } 33219 33220 if (this.bindNode && this.bindNode.members && this.bindNode.members.item) { 33221 item = this.bindNode.members.item(index); 33222 if (item && item.assist && item.assist.speak && item.assist.speak.value) { 33223 customAssist = item.assist.speak.value; 33224 } 33225 } else if (this.jsonModel.custom) { 33226 33227 var custom; 33228 custom = this.jsonModel.custom || []; 33229 if (_.isString(custom) && index <= 0) { 33230 33231 customAssist = custom; 33232 } else { 33233 if (!custom.length == 0) { 33234 customAssist = custom[index]; 33235 } 33236 } 33237 } 33238 return customAssist; 33239 }, 33240 _getToolTip : function (index) { 33241 var toolTip, item; 33242 if (this.bindNode && this.bindNode.members && this.bindNode.members.item) { 33243 item = this.bindNode.members.item(index); 33244 33245 if (item && item.assist && item.assist.speak && item.assist.speak.value) { 33246 toolTip = item.assist.toolTip.value; 33247 } 33248 33249 }
33249 else if (this.jsonModel.shortDescription) { 33250 toolTip = this.jsonModel.shortDescription; 33251 } 33252 return toolTip; 33253 }, 33254 _getCaption : function (index) { 33255 var item, caption, option; 33256 if (index == null) { 33257 33258 if (this.bindNode && this.bindNode.caption && this.bindNode.caption.value && this.bindNode.caption.value.oneOfChild && this.bindNode.caption.value.oneOfChild.value) { 33259 return this.bindNode.caption.value.oneOfChild.value; 33260 } 33261 return null; 33262 } 33263 if (this.bindNode && this.bindNode.members && this.bindNode.members.item) { 33264 item = this.bindNode.members.item(index); 33265 if (item.caption && item.caption.value && item.caption.value.oneOfChild && item.caption.value.oneOfChild.value) { 33266 caption = item.caption.value.oneOfChild.value; 33267 } 33268 33269 } else if (this.jsonModel.options) { 33270 var options; 33271 options = this.jsonModel.options || []; 33272 if (index < 0) { 33273 index = 0; 33274 } 33275 if (!options.length == 0) { 33276 option = options[index]; 33277 caption = guidelib.util.GuideUtil.getOptionsKeyValue(option).pop(); 33278 } 33279 33280 } 33281 return caption; 33282 }, 33283 _getName : function (index) { 33284 if (this.bindNode && this.bindNode.members && this.bindNode.members.item && this.bindNode.members.item(index)) { 33285 33286 return this.bindNode.members.item(index).name; 33287 } 33288 return null; 33289 }, 33290 33291 _getScreenReaderText : function (index) { 33292 var screenReaderText, assistPriority = this._getAssistPriority() || "caption"; 33293 33294 if (this.bindNode) { 33295 screenReaderText = GuideRadioButton._super._getScreenReaderText.apply(this, [index]); 33296 } else { 33297 if (assistPriority == "custom") { 33298 screenReaderText = this._getCustomAssist(index) || this._getCaption(index); 33299 } else if (assistPriority == "caption") { 33300 screenReaderText = this._getCaption(index); 33301 } 33302 } 33303 return screenReaderText; 33304 } 33305 }); 33306 33307 GuideRadioButton.defineProps({ 33308 33309 optionsExp : { 33310 get : function () { 33311 return this.getAttribute("optionsExp"); 33312 } 33313 }, 33314 33315 33316 items : { 33317 get : function () { 33318 var items = this.jsonModel.options; 33319 if (items && !_.isArray(items)) { 33320 items = items.split(","); 33321 } else if (items) { 33322 items = items.slice(0); 33323 } 33324 return items; 33325 }, 33326 set : function (newValue) { 33327 if (!this.bindNode && newValue && newValue.length > 1) { 33328 var oldValue = this.jsonModel.options; 33329 if (JSON.stringify(newValue) !== JSON.stringify(oldValue)) { 33330 33331 this.jsonModel.options = newValue; 33332 this._resetModelValueForOptionChange(); 33333 this._addStateOverride("options", {"option" : this._getOptionsArray()}); 33334 this._triggerItemsChange(oldValue, newValue); 33335 } 33336 } 33337 } 33338 } 33339 }); 33340 33341 GuideRadioButton.addMixins([ 33342 guidelib.model.mixin.ChoiceGroupOptionHandler 33343 ]); 33344})(_, guidelib); 33345 33346(function (_, guidelib) { 33347 var GuidePasswordBox = guidelib.model.GuidePasswordBox = guidelib.model.Field.extend({ 33348 msClassName : "guidePasswordBox", 33349 33350 _getReducedJSON : function () { 33351 33352 33353 if (this.submitPassword) { 33354 return GuidePasswordBox._super._getReducedJSON.call(this); 33355 } 33356 33357 var whitelistedProperties = ["name", "templateId", "guideNodeClass"], 33358 reducedJsonObject = {}; 33359 guidelib.model.util.CommonUtils.returnMinimalJSON(whitelistedProperties, reducedJsonObject, this); 33360 return reducedJsonObject; 33361 }, 33362 33363 _preserveLazyValue : function () { 33364 return !!this.submitPassword && GuidePasswordBox._super._preserveLazyValue.call(this); 33365 }, 33366 33367 _allowEmptyValueString : function () { 33368 return true; 33369 } 33370 }); 33371 GuidePasswordBox.defineProps({ 33372 submitPassword : { 33373 get : function () { 33374 return this.getAttribute("submitPassword"); 33375 } 33376 } 33377 }); 33378 33379})(_, guidelib); 33380 33381(function (_, guidelib) { 33382 var GuideScribble = guidelib.model.GuideScribble = guidelib.model.Field.extend({ 33383 msClassName : "guideScribble" 33384 }); 33385})(_, guidelib); 33386(function (_, guidelib) { 33387 var GuideCompositeFieldItem = guidelib.model.GuideCompositeFieldItem = guidelib.model.Field.extend({ 33388 msClassName : "GuideCompositeFieldItem" 33389 }); 33390 33391 GuideCompositeFieldItem.defineProps({ 33392 33393 bindRef : { 33394 get : function () { 33395 if (this.parent && !this.parent._isXfaNode() && !_.isEmpty(this.parent.bindRef)) { 33396 return this.parent.bindRef + '/' + this.getAttribute("name").replace(/\s+/g, ''); 33397 } else { 33398 return (this.getAttribute("bindRef") || "").replace(/\s+/g, ''); 33399 } 33400 } 33401 } 33402 }); 33403 33404})(_, guidelib); 33405(function (_, guidelib) { 33406 33407 33408 var GuideNumericBox = guidelib.model.GuideNumericBox = guidelib.model.Field.extend({ 33409 msClassName : "guideNumericBox", 33410 33411 _getTypedValue : function (value) { 33412 var dataType = this.dataType, 33413 tmpValue, str, leadD, fracD; 33414 33415 if (this.checkIfNull(value)) { 33416 return null; 33417 } 33418 switch (dataType) { 33419 case "integer": 33420 tmpValue = parseInt(value); 33421 break; 33422 case "float": 33423 tmpValue = parseFloat(value); 33424 break; 33425 case "decimal": 33426 tmpValue = parseFloat(value); 33427 if (!isNaN(tmpValue)) { 33428 str = tmpValue.toString(); 33429 leadD = str.indexOf("."); 33430 leadD = leadD === -1 ? str.length : leadD; 33431 leadD = str.indexOf("-") === 0 ? leadD - 1 : leadD; 33432 fracD = str.length - leadD - 1; 33433 if (fracD > this.fracDigits && this.fracDigits !== -1) { 33434 tmpValue = parseFloat(tmpValue.toFixed(this.fracDigits)); 33435 } 33436 if (leadD > this.leadDigits && this.leadDigits !== -1) { 33437 return undefined; 33438 } 33439 } 33440 break; 33441 } 33442 if (isNaN(tmpValue)) { 33443 return undefined; 33444 } 33445 return tmpValue; 33446 }, 33447 _getFormattedValue : function (value) { 33448 if (_.isUndefined(value) || value === null || value === "") { 33449 return null; 33450 } 33451 33452 var picture = this.jsonModel.displayPictureClause, 33453 defaultPattern = "zzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzz"; 33454 33455 33456 try { 33457 if (picture && this.jsonModel.html5Type !== "number") { 33458 return xfalib.ut.PictureFmt.format(value + "", picture, guideBridge._readRuntimeLocale(), true); 33459 } else { 33460 var pattern = (this.jsonModel.html5Type === "number") ? defaultPattern : guidelib.i18n.numberPatterns.numeric; 33461 return xfalib.ut.PictureFmt.format(value + "", "num{" + pattern + "}", 33462 guideBridge._readRuntimeLocale(), true, true); 33463 } 33464 } catch (exception) { 33465 this.logger().error("Cannot format value " + value + " " + exception); 33466 33467 return value; 33468 } 33469 }, 33470 33471 33472 _totalDigitValidation : function (value, obj) {
33473 if (value && obj.validFlag && this.leadDigits > -1) { 33474 obj.validFlag = true; 33475 if (this.dataType === "integer") { 33476 obj.validFlag = this.value.toString().length <= this.leadDigits; 33477 } 33478 if (!obj.validFlag) { 33479 this._errorText = guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.totalDigitMessage, [this.leadDigits]); 33480 this._failedTest = this.guideUtil.TOTAL_DIGITS_TEST; 33481 } 33482 } 33483 }, 33484 33485 33486 _datatypeValidation : function (obj) { 33487 if (obj.validFlag) { 33488 var value = this.getAttribute("_value"); 33489 obj.validFlag = !isNaN(value); 33490 if (!obj.validFlag) { 33491 this._errorText = guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.datatypeMessage, ["numeric"]); 33492 this._failedTest = this.guideUtil.FORMAT_TEST; 33493 } 33494 } 33495 }, 33496 33497 33498 _runValidations : function (obj) { 33499 var value = this.value; 33500 GuideNumericBox._super._runValidations.call(this, obj); 33501 this._datatypeValidation(obj); 33502 this._minMaxValidation(value, obj); 33503 this._totalDigitValidation(value, obj); 33504 } 33505 }); 33506 GuideNumericBox.defineProps({ 33507 33508 dataType : { 33509 get : function () { 33510 return this.getAttribute("dataType"); 33511 } 33512 }, 33513 33514 33515 leadDigits : { 33516 get : function () { 33517 return this.getAttribute("leadDigits"); 33518 } 33519 }, 33520 33521 33522 fracDigits : { 33523 get : function () { 33524 return this.getAttribute("fracDigits"); 33525 } 33526 } 33527 }); 33528 33529 GuideNumericBox.addMixins([ 33530 guidelib.model.mixin.AddMinMaxValidation 33531 ]); 33532 33533})(_, guidelib); 33534 33535 (function (_, guidelib) { 33536 var GuideFootnotePlaceHolder = guidelib.model.GuideFootnotePlaceHolder = guidelib.model.GuideTextDraw.extend({ 33537 msClassName : "guideFootnotePlaceHolder", 33538 33539 initialize : function () { 33540 GuideFootnotePlaceHolder._super.initialize.apply(this); 33541 } 33542 }); 33543 GuideFootnotePlaceHolder.defineProps({ 33544 footnoteMap : { 33545 get : function () { 33546 if (this.options._guideContainer.jsonModel.textReplacementMap) { 33547 var footnoteMap = {}; 33548 var footnoteArray = Object.entries(this.options._guideContainer.jsonModel.textReplacementMap) 33549 var parentDiv = document.createElement("p"); 33550 parentDiv.setAttribute("class", "footnoteClass"); 33551 for (var i = 0; i < footnoteArray.length; i++) { 33552 var pTag = $("p[id=\"" + footnoteArray[i][0] + "\"]")[0]; 33553 if (pTag != null && pTag.tagName == 'P') { 33554 var childTag = document.createElement("p"); 33555 33556 childTag.setAttribute("role", "footnote"); 33557 childTag.setAttribute("aria-live", "polite"); 33558 childTag.setAttribute("aria-atomic", "true"); 33559 var supTag = document.createElement('sup'); 33560 var anchorTag = document.createElement('a'); 33561 var parentTag = pTag.cloneNode(true); 33562 parentTag.removeAttribute("id"); 33563 anchorTag.setAttribute('id', footnoteArray[i][0]+ "_ftn"); 33564 anchorTag.innerHTML = footnoteArray[i][1]; 33565 supTag.appendChild(anchorTag); 33566 parentTag.insertBefore(supTag, parentTag.children[0]); 33567 parentTag.style.display = "block"; 33568 childTag.appendChild(parentTag); 33569 footnoteMap[footnoteArray[i][0]] = childTag.outerHTML; 33570 } 33571 } 33572 return footnoteMap; 33573 } 33574 return null; 33575 } 33576 } 33577 }); 33578 33579}(_, guidelib)); 33580 33581 33582(function (_, guidelib) { 33583 33584 var GuideDatePicker = guidelib.model.GuideDatePicker = guidelib.model.Field.extend({ 33585 msClassName : "guideDatePicker", 33586 errorList : [], 33587 that : this, 33588 33589 initialize : function () { 33590 GuideDatePicker._super.initialize.call(this); 33591 if (_.isEmpty(this.jsonModel._value) && this.jsonModel.defaultToCurrentDate === "true") { 33592 this._setGuideValue(new Date().toISOString().slice(0, 10)); 33593 } 33594 }, 33595 33596 _setGuideValue : function (value) { 33597 var retVal = guidelib.util.GuideUtil._reformatDate(value, this.isEditPictureClausePresent); 33598 GuideDatePicker._super._setGuideValue.call(this, retVal); 33599 }, 33600 33601 _getTypedValue : function (value) { 33602 if (value) { 33603 return value; 33604 } 33605 return null; 33606 }, 33607 33608 33609 _datatypeValidation : function (obj) { 33610 if (obj.validFlag) { 33611 var value = this.getAttribute("_value");
33612 obj.validFlag = true; 33613 if (value != null && xfalib.ut.DateInfo.Parse(value, undefined, this.isEditPictureClausePresent) == null) { 33614 obj.validFlag = false; 33615 } 33616 if (!obj.validFlag) { 33617 this._errorText = guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.datatypeMessage, ["date"]); 33618 this._failedTest = this.guideUtil.FORMAT_TEST; 33619 } 33620 } 33621 }, 33622 33623 _validateDatePart : function (field, datePart, errorList) { 33624 if (field === "D") { 33625 if (datePart > 31) { 33626 errorList.push(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.genericInvalidDatePart, [guidelib.i18n.calendarSymbols.month, guidelib.i18n.calendarSymbols.more, 31, guidelib.i18n.calendarSymbols.days])); 33627 } 33628 if (datePart < 1) { 33629 errorList.push(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.genericInvalidDatePart, [guidelib.i18n.calendarSymbols.month, guidelib.i18n.calendarSymbols.less, 1, guidelib.i18n.calendarSymbols.days])); 33630 } 33631 } 33632 if (field === "M") { 33633 if (datePart > 12) { 33634 errorList.push(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.genericInvalidDatePart, [guidelib.i18n.calendarSymbols.year, guidelib.i18n.calendarSymbols.more, 12, guidelib.i18n.calendarSymbols.months])); 33635 } 33636 if (datePart < 1) { 33637 errorList.push(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.genericInvalidDatePart, [guidelib.i18n.calendarSymbols.year, guidelib.i18n.calendarSymbols.less, 1, guidelib.i18n.calendarSymbols.months])); 33638 } 33639 } 33640 if (field === "Y") { 33641 if (datePart.length < 4) { 33642 errorList.push(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.genericInvalidYearPart)); 33643 } 33644 33645 } 33646 }, 33647 _getOrderedDateParts : function (value) { 33648 var dateFormat = this.jsonModel.dateDisplayFormat || "date{M/D/YYYY}"; 33649 var separator = dateFormat.match(/^date\{.*([^mdy]).*\}$/i)[1]; 33650 var fieldOrder = ['M', 'D', 'Y'] 33651 .map(function (val) { 33652 return { 33653 value : val, 33654 index : dateFormat.indexOf(val) 33655 }; 33656 }) 33657 .sort(function (a, b) { 33658 return a.index - b.index; 33659 }) 33660 .map(function (obj) { 33661 return obj.value; 33662 }); 33663 var dateParts = value.split(separator); 33664 return [dateParts, fieldOrder]; 33665 }, 33666 _checkIsolatedDateValidity : function (obj, value, errorList) { 33667 var orderedParts = this._getOrderedDateParts(value); 33668 var dateParts = orderedParts[0], fieldOrder = orderedParts[1]; 33669 for (var i = 0; i < fieldOrder.length; i++) { 33670 var field = fieldOrder[i]; 33671 var datePart = dateParts[i]; 33672 if (!_.isEmpty(datePart)) { 33673 this._validateDatePart(field, datePart, errorList); 33674 } 33675 } 33676 }, 33677 _validateDaysOfMonth : function (obj, value, errorList) { 33678 var orderedParts = this._getOrderedDateParts(value); 33679 var dateParts = orderedParts[0], fieldOrder = orderedParts[1]; 33680 month = dateParts[fieldOrder.indexOf('M')], 33681 day = dateParts[fieldOrder.indexOf('D')], 33682 year = dateParts[fieldOrder.indexOf('Y')]; 33683 if (month !== "" && day !== "") { 33684 month = Number(month) || 0; 33685 day = Number(day) || 0; 33686 var currentMonthName = guidelib.i18n.calendarSymbols.monthNames[month - 1]; 33687 if (31 === day && [4,6,9,11].includes(month)) { 33688 errorList.push(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.nonFebruaryMessage, [currentMonthName, day - 1])); 33689 } 33690 } 33691 }, 33692 _validateFieldCompleteness : function (obj, value, errorList) { 33693 var orderedParts = this._getOrderedDateParts(value); 33694 var dateParts = orderedParts[0], fieldOrder = orderedParts[1]; 33695 var localizedFieldMapping = { 33696 M : guidelib.i18n.calendarSymbols.month, 33697 D : guidelib.i18n.calendarSymbols.day, 33698 Y : guidelib.i18n.calendarSymbols.year 33699 }; 33700 var emptyFields = fieldOrder 33701 .map(function (fieldName) { 33702 return localizedFieldMapping[fieldName]; 33703 }) 33704 .filter(function (_, index) { 33705 return dateParts[index] === ""; 33706 }); 33707 if (emptyFields.length !== 3 && emptyFields.length > 0) { 33708 errorList.push("These fields still need to be filled: [" + emptyFields.join(", ") + "]"); 33709 } 33710 }, 33711 _validateFullDate : function (obj, value, errorList) { 33712 var orderedParts = this._getOrderedDateParts(value); 33713 var dateParts = orderedParts[0], fieldOrder = orderedParts[1];
33714 month = dateParts[fieldOrder.indexOf('M')], 33715 day = dateParts[fieldOrder.indexOf('D')], 33716 year = dateParts[fieldOrder.indexOf('Y')]; 33717 if (month !== "" && day !== "" && year !== "") { 33718 month = Number(month) || 0; 33719 day = Number(day) || 0; 33720 year = Number(year) || 0; 33721 var isLeapYear = (year % 400 === 0 || (year % 4 === 0 && year % 100 !== 0)); 33722 if (month === 2) { 33723 var maxFebruary = isLeapYear ? 29 : 28; 33724 if (day === 29 && !isLeapYear) { 33725 errorList.push(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.februaryMessage, [maxFebruary, year])); 33726 } 33727 if (day >= 30) { 33728 errorList.push(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.februaryMessage, [maxFebruary, year])); 33729 } 33730 } 33731 } 33732 }, 33733 _computeErrors : function (obj, errorList) { 33734 var that = this; 33735 obj.validFlag = errorList.length === 0; 33736 if (!obj.validFlag) { 33737 that._errorText = errorList.join(" "); 33738 that._failedTest = that.guideUtil.FORMAT_TEST; 33739 } 33740 }, 33741 33742 33743 _runValidations : function (obj) { 33744 var value = this.value; 33745 if (this.jsonModel.titleDay || this.jsonModel.titleMonth || this.jsonModel.titleYear) { 33746 if (null === value) { 33747 value = "//"; 33748 } 33749 var errorList = []; 33750 33751 this._checkIsolatedDateValidity(obj, value, errorList); 33752 33753 if (errorList.length === 0) { 33754 this._validateDaysOfMonth(obj, value, errorList); 33755 } 33756 33757 if (errorList && errorList.length === 0 && window.FD && window.FD.isToggleEnabled(guidelib.util.FeatureToggleConstants.FT_DATE_PICKER_ERRORMESSAGE) ) { 33758 this._validateFieldCompleteness(obj, value, errorList); 33759 } 33760 33761 if (errorList.length === 0) { 33762 this._validateFullDate(obj, value, errorList); 33763 } 33764 this._computeErrors(obj, errorList); 33765 33766 33767 if (errorList.length === 0) { 33768 this.value = value = this.value === "//" ? "" : this.value; 33769 GuideDatePicker._super._runValidations.call(this, obj); 33770 try { 33771 this.value = value = this.value !== null && this.value !== "" ? xfalib.ut.PictureFmt.parseDate(this.value, (this.jsonModel.dateDisplayFormat || "date{M/D/YYYY}")) : this.value; 33772 } catch (error) {} 33773 this._minMaxValidation(value, obj); 33774 } 33775 } else { 33776 GuideDatePicker._super._runValidations.call(this, obj); 33777 this._datatypeValidation(obj); 33778 this._minMaxValidation(value, obj); 33779 } 33780 } 33781 }); 33782 33783 GuideDatePicker.addMixins([ 33784 guidelib.model.mixin.AddMinMaxValidation 33785 ]); 33786 33787})(_, guidelib); 33788 33789(function (_, guidelib) { 33790 33791 var GuideCaptcha = guidelib.model.GuideCaptcha = guidelib.model.Field.extend({ 33792 msClassName : "guideCaptcha", 33793 33794 initialize : function () { 33795 GuideCaptcha._super.initialize.call(this); 33796 var invisibleMandatoryRecaptchaInitialization = "af.invisibleMandatoryRecaptchaInitialization"; 33797 if ((FD.isToggleEnabled(guidelib.util.FeatureToggleConstants.FT_TURNSTILE_HCAPTCHA) 33798 && (this.isWidgetHcaptcha || this.isWidgetTurnstile) && this.captchaInvisible) 33799 || (this.isWidgetRecaptcha && ((this.captchaEnterprise && !this.checkBoxkey) || (this.captchaInvisible && this.mandatory)))) { 33800 33801 this.captchaValidate = false; 33802 this._triggerOnBridge(invisibleMandatoryRecaptchaInitialization, this, null, null, null); 33803 } 33804 }, 33805 33806 33807 showCaptchaError : function (serverErrorMessage) { 33808 33809 if (this.captchaEnterprise) { 33810 if (this.checkBoxkey) { 33811 serverErrorMessage = this.errorMessage; 33812 } else { 33813 window.alert(this.errorMessage); 33814 return; 33815 } 33816 } 33817 if (this.captchaInvisible) { 33818 if (FD.isToggleEnabled(guidelib.util.FeatureToggleConstants.FT_TURNSTILE_HCAPTCHA)) { 33819 window.alert(this.errorMessage); 33820 } 33821 return; 33822 } 33823 33824 if (FD.isToggleEnabled(guidelib.util.FeatureToggleConstants.FT_TURNSTILE_HCAPTCHA) && !this.isWidgetRecaptcha) { 33825 serverErrorMessage = this.errorMessage; 33826 } else { 33827 if (_.isEmpty(serverErrorMessage)) { 33828 serverErrorMessage = guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.LogMessages["AEM-AF-901-006"]); 33829 } 33830 } 33831 33832 this._triggerEvent(guidelib.event.GuideModelEvent.ERROR_CHANGED, 33833 "validationStatus", false, serverErrorMessage); 33834 }, 33835 33836 validate : function (errorList) { 33837 if (_.isUndefined(errorList)) { 33838 errorList = []; 33839 } 33840 33841 if(!this.captchaValidate) { 33842 return; 33843 } 33844 33845 if (window.guideBridge.hostName !== "server") { 33846 if ((this.visible && !this.value) || (this.mandatory && !this.visible)) { 33847 errorList.push({ 33848 som : this.somExpression, 33849 errorText : this.mandatoryMessage 33850 }); 33851 this._triggerEvent(guidelib.event.GuideModelEvent.ERROR_CHANGED, 33852 "validationStatus", false, this.mandatoryMessage); 33853 return false;
33854 } else { 33855 this._triggerEvent(guidelib.event.GuideModelEvent.ERROR_CHANGED, 33856 "validationStatus", true, null); 33857 } 33858 } 33859 } 33860 }); 33861 33862 GuideCaptcha.defineProps({ 33863 value : { 33864 get : function () { 33865 return this.jsonModel._value; 33866 }, 33867 set : function (value) { 33868 var oldValue = this.jsonModel._value, 33869 newTypedValue; 33870 33871 this.jsonModel._value = (value === undefined) ? oldValue : value; 33872 newTypedValue = this.jsonModel._value; 33873 this.validate(); 33874 this._triggerOnBridge("elementValueChanged", this, "value", oldValue, newTypedValue); 33875 } 33876 }, 33877 33878 captchaWidget : { 33879 get : function () { 33880 return this.getAttribute("captchaService"); 33881 } 33882 }, 33883 captchaValidate : { 33884 get : function () { 33885 return this._captchaValidate == undefined ? true : this._captchaValidate; 33886 }, 33887 set : function (value) { 33888 this._captchaValidate = value; 33889 } 33890 }, 33891 captchaInvisible : { 33892 get : function () { 33893 if (FD.isToggleEnabled(guidelib.util.FeatureToggleConstants.FT_TURNSTILE_HCAPTCHA) && this.captchaWidget === "turnstile") { 33894 return this.getAttribute("widgetType") == "invisible" ? true : false; 33895 } else if (FD.isToggleEnabled(guidelib.util.FeatureToggleConstants.FT_TURNSTILE_HCAPTCHA) && this.captchaWidget === "hcaptcha") { 33896 return this.getAttribute("size") == "invisible" ? true : false; 33897 } else { 33898 return this.getAttribute("rcSize") == "invisible" ? true : false; 33899 } 33900 } 33901 }, 33902 captchaEnterprise : { 33903 get : function () { 33904 return this.getAttribute("rcVersion") === "enterprise" ? true : false; 33905 } 33906 }, 33907 checkBoxkey : { 33908 get : function () { 33909 return this.getAttribute("rcKeyType") === "checkbox" ? true : false; 33910 } 33911 }, 33912 errorMessage : { 33913 get : function () { 33914 return this.getAttribute("errorMessage"); 33915 } 33916 }, 33917 isWidgetRecaptcha : { 33918 get: function () { 33919 return (this.captchaWidget === "recaptcha"); 33920 } 33921 }, 33922 isWidgetHcaptcha : { 33923 get: function () { 33924 return (FD.isToggleEnabled(guidelib.util.FeatureToggleConstants.FT_TURNSTILE_HCAPTCHA) && (this.captchaWidget === "hcaptcha")); 33925 } 33926 }, 33927 isWidgetTurnstile : { 33928 get: function () { 33929 return (FD.isToggleEnabled(guidelib.util.FeatureToggleConstants.FT_TURNSTILE_HCAPTCHA) && (this.captchaWidget === "turnstile")); 33930 } 33931 } 33932 }); 33933 33934}(_, guidelib)); 33935 33936(function (_, guidelib) { 33937 33938 33939 var GuideDropDownList = guidelib.model.GuideDropDownList = guidelib.model.Field.extend({ 33940 msClassName : "guideDropDownList" , 33941 33942 _collectExpressions : function () { 33943 GuideDropDownList._super._collectExpressions.apply(this); 33944 if (this.optionsExp) { 33945 this._compiledExpressions["optionsExp"] = this._compileExpression(this.optionsExp, "items"); 33946 } 33947 }, 33948 33949 _handleXfaModelChanged : function (event) { 33950 if (event._property === "addItem" || event._property === "clearItems" || event._property === "deleteItem") { 33951 this._triggerEvent(guidelib.event.GuideModelEvent.MODEL_CHANGED, event._property, event.prevText, event.newText); 33952 } else { 33953 GuideDropDownList._super._handleXfaModelChanged.call(this, event); 33954 } 33955 }, 33956 33957 _getDisplayValue : function (saveValue) { 33958 var items = this._getOptionsArray(), 33959 displayValue = null; 33960 _.each(items, function (val) { 33961 if (saveValue === val.saveValue) { 33962 displayValue = val.displayValue; 33963 } 33964 }, this);
33965 return displayValue; 33966 }, 33967 33968 _getItems : function () { 33969 return this.jsonModel.options; 33970 }, 33971 33972 _setXFAItems : function (options) { 33973 var optionsStr = this._getXFAOptionStringFromGuideItems(options); 33974 var SET_ITEMS_INSERT_MODE_PAIR = 2; 33975 if (optionsStr) { 33976 this.bindNode.setItems(optionsStr, SET_ITEMS_INSERT_MODE_PAIR); 33977 } else { 33978 this.bindNode.clearItems(); 33979 } 33980 }, 33981 33982 33983 _allowEmptyValueString : function () { 33984 return true; 33985 } 33986 33987 }); 33988 33989 GuideDropDownList.defineProps({ 33990 33991 33992 33993 multiSelect : { 33994 get : function () { 33995 return this.getAttribute("multiSelect"); 33996 }, 33997 set : function () { 33998 this.setAttribute("multiSelect"); 33999 } 34000 }, 34001 34002 optionsExp : { 34003 get : function () { 34004 return this.getAttribute("optionsExp"); 34005 } 34006 }, 34007 34008 34009 displayValue : { 34010 get : function () { 34011 return this._getDisplayValue(this.value); 34012 } 34013 }, 34014 34015 34016 34017 items : { 34018 get : function () { 34019 var items = []; 34020 if (this.bindNode) { 34021 var that = this.bindNode; 34022 for (var index = 0; index < that.length; index++) { 34023 var item = that.getSaveItem(index) + "=" + that.getDisplayItem(index); 34024 items.push(item); 34025 } 34026 return items; 34027 } else { 34028 items = this._getItems(); 34029 if (items && !_.isArray(items)) { 34030 items = items.split(","); 34031 } else if (items) { 34032 items = items.slice(0); 34033 } 34034 return items; 34035 } 34036 }, 34037 set : function (newValue) { 34038 var oldValue = this._getItems(); 34039 if (JSON.stringify(newValue) !== JSON.stringify(oldValue)) { 34040 if (this.bindNode) { 34041 this._setXFAItems(newValue); 34042 } else { 34043 this.jsonModel.options = newValue; 34044 } 34045 if (this.multiSelect) { 34046 this._resetModelValueForOptionChange(); 34047 } 34048 this._addStateOverride("options", {"option" : this._getOptionsArray()}); 34049 this._triggerItemsChange(oldValue, this.items); 34050 } 34051 } 34052 } 34053 }); 34054 GuideDropDownList.addMixins([ 34055 guidelib.model.mixin.ChoiceGroupOptionHandler 34056 ]); 34057})(_, guidelib); 34058 34059(function (_, guidelib) { 34060 34061 var GuideInstanceManager = guidelib.model.GuideInstanceManager = guidelib.model.GuideNode.extend({ 34062 msClassName : "guideInstanceManager", 34063 initialize : function () { 34064 GuideInstanceManager._super.initialize.call(this); 34065 this._instances = []; 34066 this.dependants = []; 34067 this.deafen = false; 34068 this._bindPending = true; 34069 }, 34070 34071 _postInitializeBinding : function () { 34072 34073 34074 34075 if (!this._bindPending) { 34076 return; 34077 } else { 34078 this._bindPending = false; 34079 } 34080 34081 34082 34083 34084 34085 34086 var instance = this._instances[this.instanceCount - 1]; 34087 if (!instance) { 34088 this.logger().log("There was no instance found for InstanceManager at postInitialize:" + this.somExpression); 34089 } 34090 if (instance.bindNode && instance.bindNode.instanceManager) { 34091 this.bindNode = instance.bindNode.instanceManager; 34092 this.bindNode.parent.on(xfalib.script.XfaModelEvent.CHILD_ADDED, this); 34093 this.bindNode.parent.on(xfalib.script.XfaModelEvent.CHILD_REMOVED, this); 34094 } 34095 }, 34096 34097 _unloadModel : function () { 34098 var instance = this._instances[this.instanceCount - 1]; 34099 34100 if (instance.bindNode && instance.bindNode.instanceManager) { 34101 this.bindNode.parent.off(xfalib.script.XfaModelEvent.CHILD_ADDED, this); 34102 this.bindNode.parent.off(xfalib.script.XfaModelEvent.CHILD_REMOVED, this); 34103 } 34104 34105 GuideInstanceManager._super._unloadModel.call(this); 34106 }, 34107 34108 34109 handleEvent : function (event) { 34110 if (!this.deafen && event instanceof xfalib.script.XfaModelEvent) { 34111 switch (event.name) { 34112 case xfalib.script.XfaModelEvent.CHILD_ADDED: 34113 var addedInstance = event.newText; 34114 if (addedInstance.instanceManager == this.bindNode) { 34115 this._insertInstance(addedInstance.instanceIndex, addedInstance); 34116 } 34117 break; 34118 case xfalib.script.XfaModelEvent.CHILD_REMOVED: 34119 var removedInstance = event.prevText; 34120 if (removedInstance.instanceManager == this.bindNode) { 34121 this._removeInstance(removedInstance.instanceIndex, false); 34122 } 34123 break; 34124 case xfalib.script.XfaModelEvent.CHILD_MOVED: 34125 this.logger().log("CHILD_REMOVED should never be dispatched. It's achieved via ad and remove child."); 34126 break; 34127 default: 34128 34129 break; 34130 } 34131 } 34132 }, 34133 34134 _instanceTemplate : function () { 34135 return this._guide()._modelTemplateCacheStore.cloneJsonTemplate(this.jsonModel.instanceTemplateId); 34136 }, 34137 34138 34139 addInstance : function (addedXfaInstance) { 34140 return this._insertInstance(undefined, addedXfaInstance); 34141 }, 34142 34143 34144 addInstances : function (instancesConfig, addedXfaInstances) { 34145 var instanceCount = instancesConfig.instanceCount, 34146 instancesToAdd, availableInstances; 34147 if (this.maxOccur == -1) { 34148 instancesToAdd = instanceCount; 34149 }else { 34150 availableInstances = this.maxOccur - this.instanceCount; 34151 34152 instancesToAdd = instanceCount > availableInstances ? availableInstances : instanceCount; 34153 } 34154 var oChildsAdded = []; 34155 for (var i = 0; i < instancesToAdd ; i++) { 34156 oChildsAdded.push(this._insertInstance(undefined, addedXfaInstances, true)); 34157 } 34158 var oParentContainer = this.parent; 34159 oParentContainer._triggerEvent(guidelib.event.GuideModelEvent.MULTIPLE_CHILD_ADDED, "multipleChildAdded", 34160 null, oChildsAdded); 34161 }, 34162 34163 _manageChild : function (oCreatedChild, nIndex) { 34164 oCreatedChild._instanceManager = this; 34165 if (nIndex === undefined) { 34166 this._instances.push(oCreatedChild); 34167 } else { 34168 this._instances.splice(nIndex, 0, oCreatedChild); 34169 } 34170 }, 34171 34172 34173 _insertInstance : function (nIndex, addedXfaInstance, muteEvent) { 34174 if ((+this.maxOccur >= 0) && (+this.maxOccur == this.instanceCount)) { 34175 return null; 34176 } 34177 34178 if (nIndex !== undefined && nIndex > +this.maxOccur && +this.maxOccur > -1) { 34179 return null; 34180 } 34181 34182 var addedBindNode = addedXfaInstance; 34183 if (addedXfaInstance && this.bindNode == null) { 34184 this.logger().error("AF", "Invalid argument addedXfaInstance."); 34185 } 34186 if (!addedXfaInstance && this.bindNode) { 34187 this.deafen = true; 34188 try { 34189 34190 addedBindNode = this.bindNode.insertInstance(nIndex); 34191 } 34192 finally { 34193 this.deafen = false;
34194 } 34195 } 34196 var template = this._instanceTemplate(); 34197 34198 34199 34200 var clonedJson = {}; 34201 var uniquePrefix = this.guideUtil.generateUID(), 34202 that = this; 34203 this.copyObject(template, clonedJson, 34204 { 34205 transformMaps : { 34206 "id" : function (srcValue, options, parentObj) { 34207 return uniquePrefix + "__" + parentObj.templateId; 34208 }, 34209 34210 34211 34212 "bindRef" : function (originalBindRef, options, src) { 34213 if (addedBindNode != null && that.bindNode != null) { 34214 if (template.bindRef === originalBindRef) { 34215 return addedBindNode.somExpression; 34216 } else if (originalBindRef.substring(0, template.bindRef.length) === template.bindRef) { 34217 return originalBindRef.replace(template.bindRef, addedBindNode.somExpression); 34218 } 34219 } 34220 34221 return originalBindRef; 34222 } 34223 } 34224 } 34225 ); 34226 34227 var options = ((addedBindNode && this.bindNode) ? {bindNode : addedBindNode} : null); 34228 if (this.options._guideContainer) { 34229 options = _.extend({}, options, {"_guideContainer" : this.options._guideContainer}); 34230 } 34231 var oChildAdded = guidelib.model.GuideModelRegistry.prototype.createModel(clonedJson, options); 34232 if (oChildAdded != null) { 34233 34234 34235 34236 this._manageChild(oChildAdded, nIndex); 34237 var oParentContainer = this.parent; 34238 if (oParentContainer != null) { 34239 if (this._instances.length > 0) { 34240 34241 34242 34243 34244 nIndex = nIndex !== undefined ? nIndex : this._instances.length - 1 ; 34245 if(nIndex === 0 ) { 34246 34247 34248 34249 oParentContainer._addChildAt(oChildAdded, oParentContainer._children.indexOf(this) + 1, muteEvent); 34250 } else { 34251 var lastInstanceIndex = oParentContainer._children.indexOf(this._instances[nIndex - 1]); 34252 oParentContainer._addChildAt(oChildAdded, lastInstanceIndex + 1, muteEvent); 34253 } 34254 } else { 34255 34256 34257 34258 34259 oParentContainer._addChildAt(oChildAdded, oParentContainer._children.indexOf(this) + 1, muteEvent); 34260 } 34261 var guideStateConstants = guidelib.model.GuideSchema.prototype.GuideStateConstants; 34262 var dataUtils = this._guide().internal.liveDataUtils; 34263 if (this._isDataNodeUpdateRequired(oChildAdded)) { 34264 var parentNode = dataUtils.getParentDataNode(this._getDataContext(oChildAdded), true, {}); 34265 var index = dataUtils._convertModelIndexToDataIndex(oChildAdded.instanceIndex); 34266 var node = dataUtils._getElement(parentNode, oChildAdded._getDataNodeName(), {index : index}); 34267 34268 34269 if (!node || (node && !(oChildAdded.instanceIndex == this._instances.length - 1))) { 34270 var dataNode = dataUtils.insertNode(parentNode, oChildAdded._getDataNodeName(), oChildAdded.instanceIndex); 34271 if (!dataNode) { 34272 this.logger().warn("AF", "Unable to store the data of the element"); 34273 } 34274 } 34275 } 34276 } 34277 this._execExpressions(nIndex); 34278 return oChildAdded; 34279 } else { 34280 this.logger().log("guide", "insertInstance could not create child" + this.jsonModel.instanceTemplateId); 34281 } 34282 return null; 34283 }, 34284 34285 34286 insertInstance : function (nIndex) { 34287 return this._insertInstance(nIndex); 34288 }, 34289 34290 34291 removeInstance : function (index) { 34292 this._removeInstance(index, true); 34293 }, 34294 34295 34296 _removeInstance : function (index, removeXfaInstance) { 34297 34298 if (this.instanceCount == 0 || this.minOccur >= this.instanceCount) { 34299 return; 34300 } 34301 34302 if (index >= +this.instanceCount) { 34303 return; 34304 } 34305 34306 if (removeXfaInstance && this.bindNode) { 34307 this.deafen = true; 34308 try { 34309 this.bindNode.removeInstance(index); 34310 } 34311 finally { 34312 this.deafen = false;
34313 } 34314 } 34315 34316 34317 34318 var oChild = this._instances[index]; 34319 var dataUtils = this._guide().internal.liveDataUtils; 34320 if (this._isDataNodeUpdateRequired(oChild)) { 34321 var parentNode = dataUtils.getParentDataNode(this._getDataContext(oChild)); 34322 dataUtils.removeChild(parentNode, oChild._getDataNodeName(), oChild.instanceIndex); 34323 } 34324 this._instances.splice(index, 1); 34325 var parent = oChild.parent; 34326 parent._removeChild(oChild); 34327 this._execExpressions(index); 34328 }, 34329 34330 _isDataNodeUpdateRequired : function (child) { 34331 var guideStateConstants = guidelib.model.GuideSchema.prototype.GuideStateConstants, 34332 guide = guideBridge._guide; 34333 return guide && guide.getGuideState() === guideStateConstants.GUIDE_STATE_MODEL_COMPLETE 34334 && child._hasLazyDescendant; 34335 }, 34336 34337 _getDataContext : function (model) { 34338 var dataUtils = this._guide().internal.liveDataUtils, 34339 elementContext = dataUtils._getXpathContext(model), 34340 xmlContext = dataUtils._getDataContext(model, elementContext.bound, 34341 elementContext.unBound), 34342 xpath = xmlContext.indexedXpath; 34343 xpath = dataUtils.addIndexToPath(xpath, model.instanceIndex); 34344 return { 34345 indexedXpath : xpath, 34346 xmlSec : xmlContext.xmlSec 34347 }; 34348 }, 34349 34350 _getInstanceName : function () { 34351 return this.jsonModel.instanceName; 34352 }, 34353 34354 _instanceIsTableRow : function () { 34355 34356 return this._instanceTemplate()["guideNodeClass"] === "guideTableRow"; 34357 }, 34358 34359 34360 _execExpressions : function (modifiedIndex) { 34361 try { 34362 34363 this._notifyDependants(); 34364 34365 34366 for (var i = modifiedIndex; i < this.instances.length; i++) { 34367 this.instances[i]._notifyDependants(); 34368 } 34369 34370 this._guide().runPendingExpressions(); 34371 } catch (ex) { 34372 this.logger().error("guide", ex.message); 34373 } 34374 } 34375 34376 }); 34377 GuideInstanceManager.defineProps({ 34378 34379 minOccur : { 34380 get : function () { 34381 var isTableRow = this._instanceIsTableRow(); 34382 34383 if (isTableRow) { 34384 return ((+this.jsonModel.minOccur) || 1); 34385 } else { 34386 return this.getOrElse(this.jsonModel.minOccur, 1); 34387 } 34388 } 34389 }, 34390 34391 34392 maxOccur : { 34393 get : function () { 34394 return this.getOrElse(this.jsonModel.maxOccur, 1); 34395 } 34396 }, 34397 34398 initialOccur : { 34399 get : function () { 34400 return this.getOrElse(this.jsonModel.initialOccur, 1); 34401 } 34402 }, 34403 34404 34405 instanceTemplateId : { 34406 get : function () { 34407 return this.jsonModel.instanceTemplateId; 34408 } 34409 }, 34410 34411 34412 instanceCount : { 34413 get : function () { 34414 var context = this._guide()._currentContext; 34415 if (context && context.managedExp) { 34416 34417 this._addDependant(context.contextNode, context.expression); 34418 } 34419 return this._instances.length ; 34420 } 34421 }, 34422 34423 34424 repeatable : { 34425 get : function () { 34426 return (this.minOccur != 1 || this.maxOccur != 1); 34427 } 34428 }, 34429 34430 instances : { 34431 34432 get : function () { 34433 var context = this._guide()._currentContext; 34434 if (context && context.managedExp) { 34435 34436 this._addDependant(context.contextNode, context.expression); 34437 } 34438 return (this._instances || []).slice(0); 34439 } 34440 } 34441 }); 34442 34443 GuideInstanceManager.addMixins([ 34444 guidelib.model.mixin.AddDependencyMgmt 34445 ]); 34446})(_, guidelib); 34447 34448 34449(function (_, guidelib) { 34450 var AbstractField = guidelib.model.AbstractField = guidelib.model.GuideNode.extend({ 34451 msClassName : "abstractField", 34452 34453 initialize : function () { 34454 this._name = this.options.name || ""; 34455 this._className = this.options.className || ""; 34456 this._bindRef = this.options.bindRef || ""; 34457 this._afDataSom = this.options.afDataSom || ""; 34458 this._dataSom = this._isXfaNode() ? this.options.dataSom : ""; 34459 this.dependants = []; 34460 34461 this._depdendantIds = []; 34462 }, 34463 34464 _getValue : function () { 34465 return this.jsonModel._value; 34466 }, 34467 34468 _setValue : function (value) { 34469 this.jsonModel._value = value; 34470 }, 34471 34472 resetData : function () { 34473 return guidelib.model.Field.prototype.resetData.call(this); 34474 }, 34475 34476 _isXfaNode : function () { 34477 return this.bindRef.indexOf("xfa[0].form[0].") === 0; 34478 }, 34479 34480 getAttribute : function (attrName) { 34481 var attrValue; 34482 switch (attrName) { 34483 case "name": 34484 attrValue = this.name; 34485 break; 34486 case "bindRef": 34487 attrValue = this.bindRef; 34488 break; 34489 default: 34490 attrValue = null; 34491 break; 34492 } 34493 return attrValue; 34494 } 34495 }); 34496 34497 AbstractField.defineProps({ 34498 somExpression : { 34499 get : function () { 34500 return ""; 34501 } 34502 }, 34503 name : { 34504 get : function () { 34505 return (this._name || "").replace(/\s+/g, ''); 34506 } 34507 }, 34508 className : { 34509 get : function () { 34510 return (this._className || ""); 34511 } 34512 }, 34513 bindRef : { 34514 get : function () { 34515 return (this._bindRef || "").replace(/\s+/g, ''); 34516 } 34517 }, 34518 dataSom : { 34519 get : function () { 34520 return this._dataSom; 34521 } 34522 }, 34523 afDataSom : { 34524 get : function () { 34525 return this._afDataSom.replace(/\s+/g, ''); 34526 } 34527 }, 34528 34529 value : { 34530 get : function () { 34531 var context = this._guide()._currentContext; 34532 if (context && context.managedExp && context.contextNode && context.expression) { 34533 this._addDependant(context.contextNode, context.expression); 34534 34535 this._depdendantIds.push(context.contextNode.id); 34536 } 34537 return this.jsonModel._value; 34538 }, 34539 set : function (newValue) { 34540 if (this.jsonModel._value !== newValue) { 34541 this.jsonModel._value = newValue; 34542 34543 var guideDirtyMarkerAndVisitor = this._guide().internal.GuideDirtyMarkerAndVisitor, 34544 visitMap = guideDirtyMarkerAndVisitor.visitMap, 34545 listOfDependents = this._depdendantIds; 34546 guideDirtyMarkerAndVisitor._findAndMarkDirty(visitMap, listOfDependents); 34547 this._notifyDependants(); 34548 } 34549 } 34550 } 34551 }); 34552 34553 AbstractField.addMixins([ 34554 guidelib.model.mixin.AddDependencyMgmt 34555 ]); 34556}(_, guidelib)); 34557 34558(function ($, guidelib, _) { 34559 var ModelTemplateCacheStore = guidelib.model.util.ModelTemplateCacheStore = xfalib.ut.Class.extend({ 34560 initialize : function () { 34561 ModelTemplateCacheStore._super.initialize.apply(this); 34562 this._modelIdCache = {}; 34563 this._templateIdCache = {}; 34564 34565 34566 34567 34568 this._lazyTemplateIdCache = {}; 34569 var guideJson = JSON.parse(JSON.stringify(this.options.modelTemplateJson)); 34570 this._putTemplate(guideJson); 34571 }, 34572 34573 34574 putModel : function (model) { 34575 if (model.id) { 34576 var modelId = model.id; 34577 this._modelIdCache[modelId] = model; 34578 if (model.children) { 34579 _.each(model.children, function (child) { 34580 this.putModel(child); 34581 }, this); 34582 } 34583 } else { 34584 this.logger().log("no Id found for model" + model.getAttribute("name")); 34585 } 34586 }, 34587 34588 34589 removeModel : function (id) { 34590 if (this._modelIdCache.hasOwnProperty(id)) { 34591 delete this._modelIdCache[id]; 34592 } 34593 }, 34594 34595 getModel : function (id) { 34596 if (this._modelIdCache.hasOwnProperty(id)) { 34597 return this._modelIdCache[id]; 34598 } 34599 }, 34600 34601 34602 _putTemplate : function (jsonTemplate) { 34603 if (jsonTemplate.templateId && jsonTemplate.guideNodeClass) { 34604 this._templateIdCache[jsonTemplate.templateId] = jsonTemplate; 34605 } 34606 _.each(jsonTemplate, function (childTemplate, key) { 34607 if (_.isObject(childTemplate)) { 34608 this._putTemplate(childTemplate); 34609 } 34610 }, this); 34611 }, 34612 34613 34614 _putLazyTemplate : function (lazyTemplateJson) { 34615 if (lazyTemplateJson.templateId && lazyTemplateJson.guideNodeClass) { 34616 this._lazyTemplateIdCache[lazyTemplateJson.templateId] = lazyTemplateJson; 34617 } 34618 }, 34619 34620 cloneJsonTemplate : function (templateId) { 34621 if (this._templateIdCache[templateId]) { 34622 var template = this._templateIdCache[templateId]; 34623 return JSON.parse(JSON.stringify(template)); 34624 } 34625 }, 34626 34627 _getTemplate : function (templateId, lookupLazyStore) { 34628 var template = this._templateIdCache[templateId]; 34629 34630 34631 34632 if (lookupLazyStore && guidelib.util.GuideUtil.isLazyJson(template)) { 34633 template = this._lazyTemplateIdCache[templateId]; 34634 } 34635 34636 if (!_.isUndefined(template)) { 34637 return JSON.parse(JSON.stringify(template)); 34638 34639 } 34640 } 34641 }); 34642 34643 ModelTemplateCacheStore.defineProps({ 34644 }); 34645}($, guidelib, window._)); 34646(function (guidelib, $, _) { 34647 var ErrorConstants = guidelib.util.ErrorConstants = { 34648 DATA_ATTRIBUTE_ERROR_ITEM : "data-af-global-error-item", 34649 DATA_ATTRIBUTE_DISPLAY_ON : "data-af-global-errors-display-on", 34650 DATA_ATTRIBUTE_ERROR_TEXT_CONTAINER : "data-af-global-error-text", 34651 DATA_ATTRIBUTE_ERROR_CONTAINER : "data-af-global-errors", 34652 DATA_ATTRIBUTE_SOM : "data-af-som",
34653 CONTEXT_SUBMISSION : "form", 34654 CONTEXT_NAVIGATION : "panel", 34655 CONTEXT_FIELD : "field" 34656 34657 }; 34658 ErrorConstants[ErrorConstants.CONTEXT_SUBMISSION] = 4; 34659 ErrorConstants[ErrorConstants.CONTEXT_NAVIGATION] = 2; 34660 ErrorConstants[ErrorConstants.CONTEXT_FIELD] = 1; 34661 34662 var GlobalErrorContainer = function ($el, options) { 34663 this.$container = $el; 34664 var $items = $el.find("[" + ErrorConstants.DATA_ATTRIBUTE_ERROR_ITEM + "]").first(), 34665 displayOnAttribute = $el.attr(ErrorConstants.DATA_ATTRIBUTE_DISPLAY_ON) || ""; 34666 this.displayOn = 0; 34667 this.errorCount = 0; 34668 this.$container.addClass("no-validation-errors"); 34669 _.each(displayOnAttribute.split(","), function (displayOn) { 34670 var val = ErrorConstants[displayOn] || 0; 34671 this.displayOn += val; 34672 }, this); 34673 this.$item = $items.eq(0).clone(); 34674 $items.remove(); 34675 }; 34676 _.extend(GlobalErrorContainer.prototype, { 34677 34678 showError : function (msg, context, fieldSom) { 34679 var nContext, 34680 $el = this.$container.find('[' + ErrorConstants.DATA_ATTRIBUTE_SOM + '="' + fieldSom + '"]');; 34681 if ($el.length > 0) { 34682 $el.find("[" + ErrorConstants.DATA_ATTRIBUTE_ERROR_TEXT_CONTAINER + "]") 34683 .addBack("[" + ErrorConstants.DATA_ATTRIBUTE_ERROR_TEXT_CONTAINER + "]") 34684 .text(msg); 34685 } else { 34686 if (typeof ErrorConstants[context] !== "number") { 34687 return; 34688 } 34689 nContext = ErrorConstants[context]; 34690 if ((nContext & this.displayOn) === nContext) { 34691 if (this.errorCount === 0) { 34692 this.$container.removeClass("no-validation-errors"); 34693 } 34694 this.errorCount++; 34695 this.$item.clone() 34696 .find("[" + ErrorConstants.DATA_ATTRIBUTE_ERROR_TEXT_CONTAINER + "]") 34697 .addBack("[" + ErrorConstants.DATA_ATTRIBUTE_ERROR_TEXT_CONTAINER + "]") 34698 .text(msg) 34699 .click(function (evnt) { 34700 guideBridge.setFocus(fieldSom); 34701 }) 34702 .end() 34703 .end() 34704 .attr(ErrorConstants.DATA_ATTRIBUTE_SOM, fieldSom) 34705 .appendTo(this.$container); 34706 } 34707 } 34708 }, 34709 hideError : function (fieldSom) { 34710 var $err = this.$container.find('[' + ErrorConstants.DATA_ATTRIBUTE_SOM + '="' + fieldSom + '"]'); 34711 if ($err.length > 0) { 34712 $err.remove(); 34713 this.errorCount--; 34714 } 34715 if (this.errorCount === 0) { 34716 this.$container.addClass("no-validation-errors"); 34717 } 34718 } 34719 }); 34720 34721 $.fn.globalErrorContainer = function (options) { 34722 var args = arguments; 34723 return this.each(function () { 34724 var $this = $(this), 34725 obj = $this.data("global-error-container"); 34726 if (obj === undefined) { 34727 obj = new GlobalErrorContainer($this, $.extend({}, typeof options === "object" && options)); 34728 $this.data("global-error-container", obj); 34729 } 34730 if (typeof options === "string" && typeof obj[options] === "function") { 34731 obj[options].apply(obj, [].splice.apply(args, [1])); 34732 } 34733 }); 34734 }; 34735}(guidelib, $, _)); 34736 34737(function (guidelib, $, _) { 34738 34739 var ErrorConstants = guidelib.util.ErrorConstants, 34740 $GlobalErrorContainer; 34741 var GuideErrorManager = guidelib.util.GuideErrorManager = xfalib.ut.Class.extend({ 34742 34743 _defaultErrorMessage : "There is an error in this field !", 34744 34745 initialize : function () { 34746 GuideErrorManager._super.initialize.apply(arguments); 34747 $GlobalErrorContainer = $("[" + ErrorConstants.DATA_ATTRIBUTE_ERROR_CONTAINER + "]").globalErrorContainer(); 34748 }, 34749 34750 34751 34752 markError : function (msg, wrapper, fieldSom, context, type) { 34753 var errorDiv; 34754 34755 if (_.isUndefined(msg)) { 34756 msg = this._defaultErrorMessage; 34757 } 34758 34759 msg = msg.trim(); 34760 34761 $GlobalErrorContainer.globalErrorContainer("showError", msg, context, fieldSom); 34762 34763 34764 if (wrapper) { 34765 if (wrapper.length >= 1) { 34766 errorDiv = wrapper.find(".guideFieldError"); 34767 if (errorDiv.length < 1) { 34768 $("<div class='guideFieldError'></div>").appendTo(wrapper).text(msg); 34769 } else { 34770 errorDiv.text(msg); 34771 var roleAttr = errorDiv.attr('role'); 34772 if (roleAttr != undefined || roleAttr !== false) { 34773 errorDiv.attr('role', 'alert'); 34774 } 34775 errorDiv.show(); 34776 } 34777 34778 } 34779 } 34780 }, 34781 34782 unMarkError : function (wrapper, fieldSom) { 34783 34784 wrapper.find(".guideFieldError").hide(); 34785 wrapper.find(".guideFieldError").text(""); 34786 $GlobalErrorContainer.globalErrorContainer("hideError", fieldSom); 34787 } 34788 }); 34789})(guidelib, $, _); 34790 34791(function (guidelib, $, _) { 34792
34793 var GuideLazyUtil = guidelib.util.GuideLazyUtil = xfalib.ut.Class.extend({ 34794 34795 34796 putDirtyToTemplateCacheIfMissing : function (guide) { 34797 var guideDirtyMarker = guide.internal.GuideDirtyMarkerAndVisitor || this._guide().internal.GuideDirtyMarkerAndVisitor, 34798 listOfDirtyChildren = guideDirtyMarker._flattenDirtyPanelToList(); 34799 this._getAllDirtyJsonTemplateInCache(listOfDirtyChildren); 34800 }, 34801 34802 34803 _getAllDirtyJsonTemplateInCache : function (listOfTemplateIds) { 34804 var modelTemplateCache = window.guideBridge._guide._modelTemplateCacheStore, 34805 toGetFromServer = this._generateListOfCacheMissFromTemplateJson(listOfTemplateIds); 34806 if (toGetFromServer.length > 0 && window.guideBridge.panelProvider) { 34807 var options = { 34808 path : window.guideBridge._getGuidePathUrl(".jsonhtmlemitter"), 34809 listOfTemplateIds : toGetFromServer, 34810 success : addToTemplateCache 34811 }; 34812 window.guideBridge.panelProvider.getMultipleTemplateJson(options); 34813 } 34814 34815 function addToTemplateCache(toInsertToTemplateCache) { 34816 _.each(toInsertToTemplateCache, function (jsonModelString) { 34817 var template = JSON.parse(jsonModelString); 34818 modelTemplateCache._putLazyTemplate(template); 34819 }); 34820 } 34821 }, 34822 34823 34824 _generateListOfCacheMissFromTemplateJson : function (listOfTemplateIds) { 34825 var templateCache = window.guideBridge._guide._modelTemplateCacheStore, 34826 cacheMiss = []; 34827 _.each(listOfTemplateIds, function (templateID) { 34828 var templateJson = templateCache._getTemplate(templateID, true); 34829 if (guidelib.util.GuideUtil.isLazyJson(templateJson)) { 34830 cacheMiss.push(templateID); 34831 } 34832 }); 34833 return cacheMiss; 34834 }, 34835 34836 _guide : function () { 34837 return this.options._guideContainer; 34838 } 34839 34840 }); 34841})(guidelib, $, _); 34842(function (_, guidelib) { 34843 var guideSchema = {}, 34844 convertor = { 34845 "visible" : { 34846 "xfaToGuide" : function (xfaValue) { 34847 return xfaValue === "visible"; 34848 }, 34849 "guideToXfa" : function (guideValue) { 34850 return guideValue === true ? "visible" : "hidden"; 34851 } 34852 }, 34853 "enabled" : { 34854 "xfaToGuide" : function (xfaValue) { 34855 return xfaValue === "open"; 34856 }, 34857 "guideToXfa" : function (guideValue) { 34858 return guideValue === true ? "open" : "readOnly"; 34859 } 34860 }, 34861 "assistPriority" : { 34862 "xfaToGuide" : function (xfaValue) { 34863 return { 34864 "custom" : "custom", 34865 "toolTip" : "shortDescription", 34866 "caption" : "label", 34867 "name" : "name" 34868 }[xfaValue]; 34869 }, 34870 "guideToXfa" : function (guideValue) { 34871 return { 34872 "custom" : "custom", 34873 "shortDescription" : "toolTip", 34874 "title" : "caption", 34875 "name" : "name" 34876 }[guideValue]; 34877 } 34878 }, 34879 "mandatory" : { 34880 "xfaToGuide" : function (xfaValue) { 34881 return xfaValue === "error"; 34882 }, 34883 "guideToXfa" : function (guideValue) { 34884 return guideValue === true ? "error" : "disabled"; 34885 } 34886 }, 34887 "multiLine" : { 34888 "xfaToGuide" : function (xfaValue) { 34889 return xfaValue == 1; 34890 }, 34891 "guideToXfa" : function (guideValue) { 34892 return guideValue === true ? 1 : 0; 34893 } 34894 }, 34895 34896 34897 "options" : { 34898 "xfaToGuide" : function (xfaValue) { 34899 var items = []; 34900 if (xfaValue) { 34901 var bndNode = this.bindNode; 34902 _.each(xfaValue, function (item, index, list) { 34903 items.push(bndNode.getSaveItem(index) + "=" + bndNode.getDisplayItem(index)); 34904 }); 34905 } 34906 return items; 34907 }, 34908 "guideToXfa" : function (guideValue) { 34909 return guideValue; 34910 } 34911 }, 34912 "multiSelect" : { 34913 "xfaToGuide" : function (xfaValue) { 34914 return xfaValue === "multiSelect"; 34915 }, 34916 "guideToXfa" : function (guideValue) { 34917 return guideValue === true ? "multiSelect" : "userControl"; 34918 } 34919 }, 34920 "calcExp" : { 34921 "xfaToGuide" : function (xfaValue) { 34922 return xfaValue !== null && xfaValue !== "" ? null : undefined; 34923 }, 34924 "guideToXfa" : function (guideValue) { 34925 return guideValue !== null && guideValue !== "" ? null : undefined; 34926 } 34927 }, 34928 "dataType" : { 34929 "xfaToGuide" : function (xfaValue) { 34930 return xfaValue; 34931 }, 34932 "guideToXfa" : function (guideValue) { 34933 return undefined; 34934 } 34935 } 34936 }; 34937 convertor.validateExp = convertor.visibleExp = 34938 convertor.enabledExp = 34939 convertor.clickExp = 34940 convertor.calcExp; 34941 34942 guidelib.model.GuideSchema = xfalib.ut.Class.extend({ 34943 34944 GuideStateConstants : { 34945 34946 GUIDE_STATE_MODEL_CREATION : 0, 34947 34948 GUIDE_STATE_MODEL_CREATED : 1, 34949 34950 GUIDE_STATE_MERGE_PROGRESS : 2, 34951 34952 GUIDE_STATE_MERGE_COMPLETE : 3, 34953 34954 GUIDE_STATE_MODEL_COMPLETE : 4 34955 }, 34956 34957 initialize : function () { 34958
34959 this.addSchema('guideNode', 34960 [ 34961 ["name", "string", null], 34962 ["id", "string", null], 34963 ["jcr:title", "string", null], 34964 ["jcr:description", "string", null], 34965 ["css", "string", ""], 34966 ["fd:targetVersion", "float", 1.0] 34967 ]); 34968 34969 this.addSchema("scriptable", 34970 [ 34971 ["visibleExp", "string", null], 34972 ["enabledExp", "string", null], 34973 ["visible", "boolean", true, "presence"], 34974 ["enabled", "boolean", true, "access"], 34975 ["assistPriority", "string", null, "assist.speak.priority"], 34976 ["custom", "string", null, "assist.speak.value"], 34977 ["shortDescription", "string", null, "assist.toolTip.value"], 34978 ["longDescription", "string", null] 34979 ], 34980 'guideNode'); 34981 34982 this.addSchema("guideInstanceManager", [], "guideNode"); 34983 34984 this.addSchema("esign", [], "guideNode"); 34985 34986 this.addSchema("verify", [], "guideNode"); 34987 34988 this.addSchema("guideItemsContainer", [], "scriptable"); 34989 34990 this.addSchema("guideImage", [], "scriptable"); 34991 34992 this.addSchema("guideContainerNode", 34993 [ 34994 ["disableSwipeGesture", "boolean", false] 34995 ], 34996 "guideItemsContainer"); 34997 34998 this.addSchema("guidePanel", 34999 [ 35000 ["validateOnStepCompletion","boolean",false] 35001 ], 35002 "guideItemsContainer"); 35003 35004 this.addSchema("rootPanelNode", [], "guidePanel"); 35005 35006 this.addSchema("guideTable", [], "guidePanel"); 35007 35008 this.addSchema("guideTableRow", [], "guidePanel"); 35009 35010 this.addSchema("guideToolbar", [], "guideItemsContainer"); 35011 35012 this.addSchema("guideCompositeField", [], "guideItemsContainer"); 35013 35014 this.addSchema("guideFileUpload", 35015 [ 35016 ["multiSelection", "boolean", false], 35017 ["buttonText", "string", null], 35018 ["fileSizeLimit", "integer", 2], 35019 ["showComment", "boolean", false] 35020 ], 35021 "guideCompositeField"); 35022 35023 35024 35025 this.addSchema("guideField", 35026 [ 35027 ["jcr:title", "string", null, "caption.value.oneOfChild.value","Guide"], 35028 ["calcExp", "string", null, "calculate.script.value", "Guide"], 35029 ["validateExp", "string", null, "validate.script.value", "Guide"], 35030 ["_value", "string", null, "rawValue"], 35031 ["displayPictureClause", "string", null, "format.picture.value"], 35032 ["validatePictureClause", "string", null, "validate.picture.value"], 35033 ["mandatory", "boolean", false, "validate.nullTest"], 35034 ["mandatoryMessage", "string", guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.LogMessages["AEM-AF-901-005"]), 35035 "mandatoryMessage"], 35036 ["validateExpMessage", "string", guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.LogMessages["AEM-AF-901-006"]), 35037 "validationMessage","Guide"], 35038 ["validatePictureClauseMessage", "string", guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.LogMessages["AEM-AF-901-007"]), 35039 "formatMessage"], 35040 ["validationState", "boolean", false], 35041 ["width", "string", null], 35042 ["height", "string", null] 35043 ], 35044 "scriptable"); 35045 35046 this.addSchema("guideTextBox", 35047 [ 35048 ["multiLine", "boolean", false, "ui.textEdit.multiLine"], 35049 ["maxChars", "integer", 0, "value.text.maxChars"], 35050 ["minLength", "integer", null], 35051 ["length", "integer", null] 35052 ], 35053 "guideField"); 35054 35055 this.addSchema("guideCaptcha", [], "guideField"); 35056 35057 this.addSchema("guideTelephone", [], "guideField"); 35058 35059 this.addSchema("guideNumericBox", 35060 [ 35061 ["dataType", "string", "decimal", "value.oneOfChild.className"], 35062 ["leadDigits", "integer", -1, "value.decimal.leadDigits"], 35063 ["fracDigits", "integer", 2, "value.decimal.fracDigits"], 35064 ["maximum", "integer", null], 35065 ["minimum", "integer", null], 35066 ["exclusiveMaximum", "boolean", null], 35067 ["exclusiveMinimum", "boolean", null] 35068 ], 35069 "guideField"); 35070 35071 this.addSchema("guidePasswordBox", [], "guideField"); 35072 35073 this.addSchema("guideRadioButton", [ 35074 ["optionsExp", "string", null], 35075 ["options", "object", null, "items"] 35076 ], "guideField"); 35077 35078 this.addSchema("guideCheckBox", [ 35079 ["optionsExp", "string", null], 35080 ["options", "object", null, "items"] 35081 ], "guideField"); 35082 35083 this.addSchema("guideSwitch", [], "guideCheckBox"); 35084 35085 this.addSchema("guideScribble", [], "guideField"); 35086 35087 this.addSchema("guideDatePicker", 35088 [ 35089 ["maximum", "string", null], 35090 ["minimum", "string", null], 35091 ["exclusiveMaximum", "boolean", null], 35092 ["exclusiveMinimum", "boolean", null] 35093 ], "guideField"); 35094 35095 this.addSchema("guideButton", [], "guideField"); 35096 35097 this.addSchema("guideListFileAttachmentButton", [], "guideButton"); 35098 35099 this.addSchema("guideTextDraw", 35100 [ 35101 ["documentFragmentVariables", "string", null] 35102 ], 35103 "guideField"); 35104 35105 this.addSchema("guideFootnotePlaceHolder",[], "guideTextDraw"); 35106 35107 this.addSchema("guideAdobeSignBlock", 35108 [ 35109 ["documentFragmentVariables", "string", null] 35110 ], 35111 "guideField"); 35112 35113 this.addSchema("guideCompositeFieldItem", [], "guideField"); 35114 35115 this.addSchema("guideDropDownList", 35116 [ 35117 ["title", "string", "DropDown"], 35118 ["multiSelect", "boolean", false, "ui.oneOfChild.open"], 35119 ["optionsExp", "string", null], 35120 ["options", "object", null, "items"] 35121 ], 35122 "guideField"); 35123 35124 this.addSchema("guideTermsAndConditions", 35125 [ 35126 ["showLink", "boolean", false], 35127 ["showAsPopUp", "boolean", false], 35128 ["clickStatus", "string", null] 35129 ], 35130 "guideCompositeField"); 35131 35132 this.addSchema("guideChart", [ 35133 ["height", "integer", 300], 35134 ["width", "integer", 100], 35135 ["data", "object", null], 35136 ["xAxisTitle", "string", null], 35137 ["yAxisTitle", "string", null], 35138 ["chartType", "string", "linepoint"], 35139 ["repeatableItem", "string", null], 35140 ["xExp", "string", null], 35141 ["reducerXFunction", "string", "none"], 35142 ["yExp", "string", null], 35143 ["reducerYFunction", "string", "none"], 35144 ["innerRadius", "integer", 0], 35145 ["lineColor", "string", "#000000"], 35146 ["pointColor", "string", "#000000"], 35147 ["areaColor", "string", "#000000"], 35148 ["tooltipHtml", "string", "<p>${x}(${y})</p>"], 35149 ["showLegends", "boolean", false], 35150 ["legendPosition", "string", "right"] 35151 ], "scriptable"); 35152 35153 this.addSchema("guideAdModule", [["_value", "string", null]], "scriptable"); 35154 this.addSchema("guideAdModuleGroup", [["_value", "string", null]], "scriptable"); 35155 }, 35156 35157 addSchema : function (elementName, attrArray, superElement) { 35158 var el = {}; 35159 if (typeof superElement === "object") { 35160 _.extend(el, superElement); 35161 } else if (typeof superElement === "string" && guideSchema[superElement]) { 35162 _.extend(el, guideSchema[superElement]); 35163 } 35164 this.addAttributes(el, attrArray); 35165 guideSchema[elementName] = el; 35166 }, 35167 35168 addAttributes : function (element, attrArray) { 35169 _.each(attrArray, function (elem) { 35170 element[elem[0]] = { 35171 "type" : elem[1], 35172 "default" : elem[2], 35173 "xfaProp" : elem[3], 35174 "priority" : elem[4] 35175 }; 35176 }); 35177 }, 35178 35179 getAttributeProps : function (element, attribute) { 35180 try { 35181 return guideSchema[element][attribute] || {}; 35182 } catch (e) { 35183 this.logger().error("AF", "schema has no element " + element); 35184 } 35185 }, 35186 getAttributes : function (element) { 35187 return guideSchema[element]; 35188 }, 35189 35190 getTypedValue : function (type, value) { 35191 if (value === null || value === undefined) { 35192 return value; 35193 } 35194 if (type instanceof Array) { 35195 return value; 35196 } 35197 switch (type) { 35198 case "string": 35199 return value + ""; 35200 case "integer": 35201 return parseInt(value); 35202 case "boolean": 35203 return value === true || value === "true" ? true : false;
35204 case "float": 35205 return parseFloat(value); 35206 default : 35207 return value; 35208 } 35209 }, 35210 35211 getConvertor : function (attr) { 35212 return convertor[attr]; 35213 } 35214 }); 35215 35216}(_, guidelib)); 35217 35218(function (_, guidelib) { 35219 35220 35221 35222 var GuideContainerNode = guidelib.model.GuideContainerNode = guidelib.model.GuideItemsContainer.extend({ 35223 msClassName : "guideContainerNode", 35224 35225 setGuideState : function (guideState) { 35226 var isStateValid = _.some(guidelib.model.GuideSchema.prototype.GuideStateConstants, function (val) { 35227 return val === guideState; 35228 }); 35229 if (isStateValid === true) { 35230 this._guideState = guideState; 35231 } 35232 }, 35233 35234 getGuideState : function () { 35235 return this._guideState; 35236 }, 35237 35238 initialize : function () { 35239 var configString = ""; 35240 35241 guidelib.__runtime__.guide = this; 35242 35243 35244 35245 this._guideState = guidelib.model.GuideSchema.prototype.GuideStateConstants.GUIDE_STATE_MODEL_CREATION; 35246 35247 35248 this.internal = this.internal || {}; 35249 35250 35251 this.internal.liveDataUtils = this.options.liveDataUtils || new guidelib.model.LiveXmlUtils(); 35252 this.internal.liveModel = this.options.liveModel || new guidelib.model.LiveModel(); 35253 this.internal.GuideDirtyMarkerAndVisitor = new guidelib.model.GuideDirtyMarkerAndVisitor(); 35254 35255 35256 this.runtime = { 35257 guideContext : {}, 35258 _private : {}, 35259 errorManager : {} 35260 }; 35261 35262 35263 this.runtime.errorManager = new guidelib.util.GuideErrorManager(); 35264 35265 this._modelTemplateCacheStore = 35266 new guidelib.model.util.ModelTemplateCacheStore({modelTemplateJson : this.jsonModel}); 35267 this._guideSchema = new guidelib.model.GuideSchema(); 35268 this.guideLazyUtil = new guidelib.util.GuideLazyUtil({"_guideContainer" : this}); 35269 this._pendingQueues = { 35270 calcExp : [], 35271 valueCommitScript : [], 35272 enabledExp : [], 35273 visibleExp : [], 35274 validateAllExp : [], 35275 optionsExp : [], 35276 navigationChangeExp : [], 35277 summaryExp : [], 35278 autoSaveStartExp : [], 35279 aggregateExp : [], 35280 submitSuccess : [], 35281 submitError : [] 35282 }; 35283 this._resetExpressionCounters(); 35284 this._currentContext = null; 35285 GuideContainerNode._super.initialize.call(this); 35286 this.autoSaveStart = false;
35287 35288 35289 this._modelTemplateCacheStore.putModel(this); 35290 this._postInitialize(); 35291 var xfaHost = this.getOrElse(xfalib, "runtime.xfa.host", null); 35292 if (xfaHost !== null) { 35293 xfaHost.on(xfalib.script.XfaModelEvent.FORM_MODEL_REFRESH, 35294 function (evnt) { 35295 switch (evnt.name) { 35296 case xfalib.script.XfaModelEvent.FORM_MODEL_REFRESH: 35297 this._triggerEvent(guidelib.event.GuideModelEvent.MODEL_REFRESH, "jsonModel", null, null); 35298 break; 35299 default: 35300 35301 } 35302 }, 35303 this); 35304 } 35305 }, 35306 35307 _resetExpressionCounters : function () { 35308 this._runningExpressionCount = { 35309 calcExp : {}, 35310 valueCommitScript : {}, 35311 enabledExp : {}, 35312 visibleExp : {}, 35313 validateAllExp : {}, 35314 optionsExp : {}, 35315 navigationChangeExp : {}, 35316 summaryExp : {}, 35317 autoSaveStartExp : {}, 35318 aggregateExp : {}, 35319 submitSuccess : {}, 35320 submitError : {} 35321 }; 35322 }, 35323 35324 _getReducedJSON : function () { 35325 35326 35327 var reducedJSONChildren = guidelib.model.GuideNode.prototype._getReducedJSON.call(this), 35328 addtionalWhitelistedProperties = ["xdpRef", "xsdRef", "id", "dorTemplateRef", "dorType", "excludeFromDoRIfHidden", "schemaRef", "schemaType"]; 35329 guidelib.model.util.CommonUtils.returnMinimalJSON(addtionalWhitelistedProperties, reducedJSONChildren, this); 35330 reducedJSONChildren["rootPanel"] = this["rootPanel"]._getReducedJSON(); 35331 if (this.jsonModel.toolbar) { 35332 reducedJSONChildren["toolbar"] = this["toolbar"]._getReducedJSON(); 35333 } 35334 return reducedJSONChildren; 35335 }, 35336 35337 _initChildren : function () { 35338 35339 var options = {"_guideContainer" : this}; 35340 this.rootPanel = guidelib.model.GuideModelRegistry.prototype.createModel(this.jsonModel.rootPanel, options); 35341 this._initializeChild(this.rootPanel); 35342 this._children.push(this.rootPanel); 35343 35344 var instanceManager = guidelib.model.GuideModelRegistry.prototype.createInstanceManager(this.rootPanel); 35345 this._initializeChild(instanceManager); 35346 this._children.splice(this._children.indexOf(this.rootPanel), 0, instanceManager); 35347 instanceManager._manageChild(this.rootPanel); 35348 35349 if (this.jsonModel.toolbar) { 35350 var options = {}; 35351 if (this._guide()) { 35352 options = _.extend({}, options, {"_guideContainer" : this._guide()}); 35353 } 35354 this.toolbar = guidelib.model.GuideModelRegistry.prototype.createModel(this.jsonModel.toolbar, options); 35355 this._initializeChild(this.toolbar); 35356 this._children.push(this.toolbar); 35357 } 35358 }, 35359 35360 35361 _addToExcludeFromDorMap : function (fieldTemplateId, bExcludeFromDor) { 35362 this._excludeFromDorMap = this._excludeFromDorMap || {}; 35363 this._excludeFromDorMap[fieldTemplateId] = bExcludeFromDor; 35364 }, 35365 35366 35367 _getExcludeFromDorMap : function () { 35368 var that = this; 35369 if (!_.isUndefined(that._excludeFromDorMap)) { 35370 return _.keys(that._excludeFromDorMap).map(function (key) { 35371 35372 return key + "=" + that._excludeFromDorMap[key]; 35373 }); 35374 } 35375 }, 35376 35377 35378 _addToStateOverrideMap : function (fieldName, fieldsOverrid
35378denMap) { 35379 this._stateOverrideMap = this._stateOverrideMap || {}; 35380 this._stateOverrideMap[fieldName] = fieldsOverriddenMap; 35381 }, 35382 35383 35384 _getStateOverrideMap : function () { 35385 var that = this; 35386 var retval = {}; 35387 if (!_.isUndefined(that._stateOverrideMap)) { 35388 var elementsArray = _.keys(that._stateOverrideMap).map(function (key) { 35389 return that._stateOverrideMap[key]; 35390 }); 35391 retval = {"element" : elementsArray}; 35392 } 35393 return retval; 35394 35395 }, 35396 35397 35398 _resolveAfDataSom : function (afDataSom) { 35399 var resolvedField = null; 35400 35401 35402 _.each(this.internal.liveModel.getCrossFragmentFields(), function (fields) { 35403 35404 var globalFieldModels = this.internal.liveModel.getAllAbstractFieldModels(_.keys(fields)); 35405 _.each(globalFieldModels, function (globalField) { 35406 if (globalField.afDataSom === afDataSom) { 35407 resolvedField = globalField; 35408 return false; 35409 } 35410 }); 35411 if (resolvedField) { 35412 return false; 35413 } 35414 }); 35415 return resolvedField; 35416 }, 35417 35418 35419 _getSigners : function () { 35420 var signers = {}; 35421 35422 if (this.enableAdobeSign && (_.isString(this.xdpRef) || _.isString(this.xsdRef) || (!_.isString(this.jsonModel.schemaRef)))) { 35423 var signer, 35424 that = this, 35425 email, 35426 number, 35427 countryCode, 35428 evalExp = function (fldSom, fldAfDataSom, type) { 35429 var val = null, 35430 resolvedField; 35431 try { 35432 resolvedField = guideBridge._guide.resolveNode(fldSom); 35433 if (!resolvedField) { 35434 resolvedField = guideBridge._guide._resolveAfDataSom(fldAfDataSom); 35435 } 35436 val = resolvedField.value; 35437 if (resolvedField.className === 'guideTelephone') { 35438 if (type === 'countryCode') { 35439 val = guidelib.model.GuideTelephone.prototype._extractCountryCode(val); 35440 } else if (type === 'phone') { 35441 val = guidelib.model.GuideTelephone.prototype._extractPhoneNumber(val); 35442 } 35443 } 35444 } catch (e) { 35445 35446 } 35447 35448 35449 return val ? val.toString() : val; 35450 }; 35451 if (this.signerInfo) { 35452 _.each(_.keys(this.signerInfo), function (name) { 35453 signer = that.signerInfo[name]; 35454 if (signer && typeof signer === "object") { 35455 email = null; 35456 number = null; 35457 countryCode = null; 35458 if (signer.emailSource === 'form' && signer.email) { 35459 email = evalExp(signer.email, signer.emailAfDataSom, 'email'); 35460 } 35461 signers[name] = {}; 35462 signers[name].email = email ? email : ""; 35463 if (signer.securityOption === 'PHONE') { 35464 if (signer.phoneSource === 'form' && signer.phone) { 35465 number = evalExp(signer.phone, signer.phoneAfDataSom, 'phone'); 35466 } 35467 if (signer.countryCodeSource === 'form' && signer.countryCode) { 35468 countryCode = evalExp(signer.countryCode, signer.countryCodeAfDataSom, 'countryCode'); 35469 } 35470 signers[name].phone = {}; 35471 signers[name].phone.countryCode = countryCode ? countryCode : ""; 35472 signers[name].phone.number = number ? number : ""; 35473 } 35474 } 35475 }); 35476 } 35477 } 35478 35479 return signers; 35480 }, 35481 35482 35483 defaultSubmitSuccess : "window.guideBridge._defaultSubmitSuccessHandler($event.data)", 35484 35485 35486 defaultSubmitError : "window.guideBridge._handleServerValidationError($event.data)", 35487 35488 35489 _collectExpressions : function () { 35490 if (this.autoSaveStartExpression) { 35491 this._compiledExpressions["autoSaveStartExp"] = this._compileExpression(this.autoSaveStartExpression, "autoSaveStart"); 35492 } 35493 35494 35495 if (!this.submitSuccess) { 35496 this.jsonModel.submitSuccess = this.defaultSubmitSuccess; 35497 } 35498 this._compiledScripts.submitSuccess = this._compileExpression(this.submitSuccess, null); 35499 35500 if (!this.submitError) { 35501 this.jsonModel.submitError = this.defaultSubmitError; 35502 } 35503 this._compiledScripts.submitError = this._compileExpression(this.submitError, null); 35504 }, 35505 35506 prepare : function () { 35507 35508 35509 if ((this.getGuideState() !== guidelib.model.GuideSchema.prototype.GuideStateConstants.GUIDE_STATE_MERGE_PROGRESS) && (this.getGuideState() !== guidelib.model.GuideSchema.prototype.GuideStateConstants.GUIDE_STATE_MODEL_CREATION)) { 35510 _.each(this._children, function (childNode) { 35511 childNode.prepare(); 35512 }, this); 35513 this.queueExpressions(this, ["autoSaveStartExp"]); 35514 this.runPendingExpressions(); 35515 } 35516 }, 35517 35518 runPendingExpressions : function () { 35519 35520 this._runExpressionQueue("calcExp"); 35521 this._runExpressionQueue("enabledExp"); 35522 this._runExpressionQueue("visibleExp"); 35523 this._runExpressionQueue("valueCommitScript"); 35524 this._runExpressionQueue("validateAllExp"); 35525 this._runExpressionQueue("optionsExp"); 35526 this._runExpressionQueue("navigationChangeExp"); 35527 this._runExpressionQueue("summaryExp"); 35528 this._runExpressionQueue("aggregateExp"); 35529 this._runExpressionQueue("submitSuccess"); 35530 this._runExpressionQueue("submitError"); 35531 if (window.guideBridge.hostName !== "server") { 35532 this._runExpressionQueue("autoSaveStartExp"); 35533 } 35534 this._resetExpressionCounters(); 35535 }, 35536 35537 _runExpressionQueue : function (expName) { 35538 var expQueue = this._pendingQueues[expName], node; 35539 if (expQueue) { 35540 while (expQueue.length > 0) { 35541 node = this._pendingQueues[expName].shift(); 35542 if (node) { 35543 node.executeExpression(expName); 35544 } 35545 } 35546 } 35547 }, 35548 35549 queueExpressions : function (node, expressionArray) { 35550 if (!node || !expressionArray) { 35551 return; 35552 } 35553 if (_.isString(expressionArray)) { 35554 expressionArray = [expressionArray]; 35555 } 35556 _.each(expressionArray, function (expression) { 35557 var expQueue = this._pendingQueues[expression], 35558 som = node.somExpression, 35559 counters = this._runningExpressionCount[expression]; 35560 counters[som] = counters[som] || 0; 35561 if (expQueue && expQueue.indexOf(node) < 0 && counters[som] < 10) { 35562 expQueue.push(node); 35563 counters[som] += 1; 35564 } 35565 }, this); 35566 }, 35567 35568 playJson : function (pJsonModel, attachments) { 35569 this.rootPanel.playJson(pJsonModel.rootPanel, attachments); 35570 if (this.toolbar) { 35571 this.toolbar.playJson(pJsonModel.toolbar, attachments); 35572 } 35573 }, 35574 35575 _guide : function () { 35576 return this; 35577 }, 35578 35579 _collectValues : function (keyValue) { 35580 _.each(this._children, function (childNode) { 35581 childNode._collectValues(keyValue); 35582 }, this); 35583 }, 35584 35585 35586 resolveNode : function (somExpression) { 35587 if (!somExpression || somExpression === "") { 35588 return; 35589 } 35590 var hierarchy = somExpression.split("."), 35591 componentInModel = null; 35592 if (hierarchy[0] === "guide[0]") { 35593 hierarchy.shift(); 35594 componentInModel = this; 35595 } 35596 if (hierarchy[0] === this._escapeQualifiedName()) { 35597 componentInModel = this; 35598 hierarchy.shift(); 35599 } else if (this.hasOwnProperty(hierarchy[0])) { 35600 componentInModel = this[hierarchy[0]]; 35601 hierarchy.shift(); 35602 } else if (!componentInModel) { 35603 componentInModel = this.rootPanel; 35604 } 35605 _.each(hierarchy, function (element) { 35606 if (componentInModel && componentInModel._findChildren) { 35607 componentInModel = componentInModel._findChildren(element, false)[0]; 35608 } else { 35609 componentInModel = null; 35610 } 35611 }, this); 35612 if (componentInModel == null) { 35613 35614 var relativeName = somExpression; 35615 componentInModel = this.getOrElse(this._guide().runtime, relativeName, null); 35616 } 35617 return componentInModel; 35618 } 35619 }); 35620 35621 GuideContainerNode.defineProps({ 35622 35623 submitSuccess : { 35624 get : function () { 35625 return this.jsonModel.submitSuccess; 35626 } 35627 }, 35628 35629 submitError : { 35630 get : function () { 35631 return this.jsonModel.submitError; 35632 } 35633 }, 35634 35635 35636 "autoSaveStart" : { 35637 get : function () { 35638 return this.jsonModel.autoSaveStart; 35639 }, 35640 35641 set : function (newValue) { 35642 this.jsonModel.autoSaveStart = newValue; 35643 if (newValue === true) { 35644 delete this._compiledExpressions.autoSaveStartExp; 35645 this._triggerOnBridge(window.guideBridge.GUIDE_AUTO_SAVE_START, this); 35646 } 35647 } 35648 }, 35649 35650 35651 "enableAutoSave" : { 35652 set : function (newValue) { 35653 this.jsonModel.enableAutoSave = newValue; 35654 }, 35655 35656 get : function () { 35657 return this.jsonModel.enableAutoSave || false; 35658 } 35659 }, 35660 35661 35662 "autoSaveStartExpression" : { 35663 get : function () { 35664 return this.jsonModel.autoSaveStartExpression; 35665 } 35666 }, 35667 35668 35669 "autoSaveInfo" : { 35670 get : function () { 35671 return this.jsonModel.autoSaveInfo; 35672 } 35673 }, 35674 35675 35676 "globalMetaInfo" : { 35677 get : function () { 35678 return this.jsonModel.globalMetaInfo; 35679 } 35680 }, 35681 35682 35683 "submissionMetaInfo" : { 35684 get : function () { 35685 return this.jsonModel.submissionMetaInfo; 35686 } 35687 }, 35688 35689 35690 "signerInfo" : { 35691 get : function () { 35692 return this.jsonModel.signerInfo; 35693 } 35694 }, 35695 35696 "xdpRef" : { 35697 get : function () { 35698 return this.jsonModel.xdpRef; 35699 } 35700 }, 35701 35702 "dorTemplateRef" : { 35703 get : function () { 35704 return this.jsonModel.dorTemplateRef; 35705 } 35706 }, 35707 35708 "dorType" : { 35709 get : function () { 35710 return this.jsonModel.dorType; 35711 } 35712 }, 35713 35714 "actionType" : { 35715 get : function () { 35716 return this.jsonModel.actionType; 35717 } 35718 }, 35719 35720 "xsdRef" : { 35721 get : function () { 35722 return this.jsonModel.xsdRef; 35723 } 35724 }, 35725 35726 35727 panel : { 35728 get : function () { 35729 return this.rootPanel; 35730 } 35731 }, 35732 35733 35734 print : { 35735 get : function () { 35736 if (this.dorType === "generate" && this.jsonModel.view) { 35737 return this.jsonModel.view.print; 35738 } 35739 35740 return null; 35741 } 35742 }, 35743 35744 35745 "allLazyChildren" : { 35746 get : function () { 35747 return this.jsonModel.allLazyChildren; 35748 } 35749 }, 35750 35751 35752 "enableAsyncSubmission" : { 35753 set : function (newValue) { 35754 this.jsonModel.enableAsyncSubmission = newValue; 35755 }, 35756 35757 get : function () { 35758 if (this.jsonModel.enableAsyncSubmission && (this.jsonModel.enableAsyncSubmission === "true" || this.jsonModel.enableAsyncSubmission === true)) { 35759 return true; 35760 } else { 35761 return false;
35762 } 35763 } 35764 }, 35765 35766 35767 "enableAdobeSign" : { 35768 get : function () { 35769 return this.jsonModel._useSignedPdf; 35770 } 35771 }, 35772 35773 35774 "enableFocusOnFirstField" : { 35775 set : function (newValue) { 35776 this.jsonModel.enableFocusOnFirstField = newValue; 35777 }, 35778 35779 get : function () { 35780 if (this.jsonModel.enableFocusOnFirstField === undefined) { 35781 return true; 35782 } 35783 return this.jsonModel.enableFocusOnFirstField; 35784 } 35785 } 35786 }); 35787}(_, guidelib)); 35788 35789(function (_, guidelib) { 35790 guidelib.model.mixin.AddNavigationContext = { 35791 propertyDescriptors : { 35792 "navigationContext" : { 35793 get : function () { 35794 if (!this._navigationContext) { 35795 this._navigationContext = new guidelib.model.util.GuideNavigationContext({ 35796 currentItem : null, 35797 parentPanel : this.panel 35798 }); 35799 } 35800 return this._navigationContext; 35801 } 35802 } 35803 } 35804 }; 35805})(_, guidelib); 35806 35807(function (_, guidelib) { 35808 35809 35810 var GuidePanel = guidelib.model.GuidePanel = guidelib.model.GuideItemsContainer.extend({ 35811 msClassName : "guidePanel", 35812 defaultExpressions : { 35813 "summary" : "this.title + (this.instanceIndex > 0 ? ' ' + this.instanceIndex : '')" 35814 }, 35815 35816 initialize : function () { 35817 GuidePanel._super.initialize.call(this); 35818 this._currentItem = null; 35819 35820 this._navigationContext = null; 35821 }, 35822 35823 _collectExpressions : function () { 35824 GuidePanel._super._collectExpressions.call(this); 35825 if (this.completionExp) { 35826 this._compiledScripts.completionExp = this._compileExpression(this.completionExp, null); 35827 } 35828 if (this.jsonModel.summaryExp) { 35829 this._compiledExpressions.summaryExp = this._compileExpression(this.jsonModel.summaryExp, "summary"); 35830 } else { 35831 this._compiledExpressions.summaryExp = this._compileExpression(this.defaultExpressions["summary"], "summary"); 35832 } 35833 }, 35834 35835 _initializeInstanceManager : function (child, index, insertOffset) { 35836 var instanceManager = guidelib.model.GuideModelRegistry.prototype.createInstanceManager(child); 35837 this._initializeChild(instanceManager); 35838 35839 this._children.splice(index + insertOffset++, 0, instanceManager); 35840 instanceManager._manageChild(child); 35841 35842 var bindNode = child._getBindNode(), 35843 bindNodeInstCount = this.getOrElse(bindNode, "instanceManager.count", 0), 35844 35845 panelInstancesToAdd = Math.max(child.minOccur, bindNodeInstCount) - 1, 35846 bindNodeOffset = 1, 35847 addedXfaInstance; 35848 while (panelInstancesToAdd > 0) { 35849 35850 addedXfaInstance = null; 35851 if (bindNodeInstCount > 1) { 35852 35853 addedXfaInstance = bindNode.instanceManager.instances[bindNodeOffset++]; 35854 } 35855 instanceManager.addInstance(addedXfaInstance); 35856 panelInstancesToAdd -= 1; 35857 insertOffset += 1; 35858 } 35859 return insertOffset; 35860 }, 35861 35862 35863 _initChildren : function (bLazyInitialization) { 35864 GuidePanel._super._initChildren.call(this); 35865 if (!bLazyInitialization) { 35866 this._instanceManager = null; 35867 } 35868 this._childInitializeGoingOn = true; 35869 var currentChildren = this.children, 35870 insertOffset = 0; 35871 _.each(currentChildren, function (child, index) { 35872 if (child instanceof guidelib.model.GuidePanel) { 35873 insertOffset = this._initializeInstanceManager(child, index, insertOffset); 35874 } 35875 }, this); 35876 if (this.jsonModel.toolbar) { 35877 var options = {}; 35878 if (this.options._guideContainer) { 35879 options = _.extend({}, options, {"_guideContainer" : this.options._guideContainer}); 35880 } 35881 var toolbar = guidelib.model.GuideModelRegistry.prototype.createModel(this.jsonModel.toolbar, options); 35882 this._initializeChild(toolbar); 35883 this._children.push(toolbar); 35884 } 35885 this._summary = null; 35886 this._childInitializeGoingOn = false;
35887 }, 35888 35889 _postInitialize : function () { 35890 GuidePanel._super._postInitialize.call(this); 35891 35892 this.instanceManager._postInitializeBinding(); 35893 }, 35894 35895 _addChildAt : function (child, childIndex, muteEvent) { 35896 if (child) { 35897 this._initializeChild(child); 35898 this._guide()._modelTemplateCacheStore.putModel(child); 35899 var newItemIndex = this._getItemsInsertIndex(childIndex - 1); 35900 var newItems = {}; 35901 var newItemKey = child.id; 35902 var lastItemIndex = -1; 35903 _.each(this.jsonModel.items, function (value, key) { 35904 if (lastItemIndex == newItemIndex - 1) { 35905 newItems[newItemKey] = child.jsonModel; 35906 } 35907 newItems[key] = value; 35908 lastItemIndex++; 35909 }, this); 35910 if (lastItemIndex == newItemIndex - 1) { 35911 newItems[newItemKey] = child.jsonModel; 35912 } 35913 this.jsonModel.items = newItems; 35914 child._isItem = true; 35915 this._children.splice(childIndex, 0, child); 35916 this._normalizeChildren(); 35917 child._postInitialize(); 35918 if (this._guide().getGuideState() >= guidelib.model.GuideSchema.prototype.GuideStateConstants.GUIDE_STATE_MERGE_COMPLETE) { 35919 child.prepare(); 35920 } 35921 35922 35923 35924 if (!(this._lazyReference && this._childInitializeGoingOn)) { 35925 if (!muteEvent) { 35926 this._triggerEvent(guidelib.event.GuideModelEvent.CHILD_CHANGED, "childAdded", null, child); 35927 } 35928 } 35929 } 35930 }, 35931 35932 35933 validate : function (errorList) { 35934 var markInvalid = false; 35935 35936 35937 if (!this.visible) { 35938 return true; 35939 } 35940 var lazyModelUnloadPending = false; 35941 35942 if (this._lazyReference && this.guideUtil.isLazyJson(this.jsonModel)) { 35943 var guideDirtyMarker = this._guide().internal.GuideDirtyMarkerAndVisitor, 35944 visitMap = guideDirtyMarker.visitMap, 35945 modelTemplateCacheStore = this._guide()._modelTemplateCacheStore, 35946 guideUtil = guidelib.util.GuideUtil, 35947 templateJson, 35948 templateId = this.templateId, 35949 uniquePrefix; 35950 35951 if (visitMap[templateId] === 0) { 35952 if (this._ancestorRepeatable) { 35953 uniquePrefix = guideUtil.generateUID(); 35954 } 35955 35956 templateJson = modelTemplateCacheStore._getTemplate(templateId, true); 35957 35958 35959 if (!_.isEmpty(templateJson)) { 35960 this._embedJson(templateJson.items, uniquePrefix); 35961 this._guide().internal.liveDataUtils.playLiveData(this); 35962 35963 this.prepare(); 35964 this._guide().runPendingExpressions(); 35965 this._guide().internal.liveDataUtils.updateLiveData(); 35966 lazyModelUnloadPending = true; 35967 } else { 35968 35969 markInvalid = true; 35970 } 35971 35972 } 35973 35974 } 35975 var validationResult = GuidePanel._super.validate.call(this, errorList); 35976 if (lazyModelUnloadPending) { 35977 35978 35979 this._unloadLazyReferenceModel(true); 35980 } 35981 if (markInvalid === true) { 35982 validationResult = false;
35983 } 35984 return validationResult; 35985 }, 35986 35987 _loadLazyFragment : function (options) { 35988 options = options || {}; 35989 if (_.isUndefined(this._itemsLoaded)) { 35990 35991 var path = this.jsonModel["jcr:path"], 35992 externalizedPath; 35993 35994 externalizedPath = guideBridge._getGuidePathUrl(".jsonhtmlemitter"); 35995 this._fetchFromAjaxCall(externalizedPath, options); 35996 } else { 35997 if (_.isFunction(options.success)) { 35998 options.success.call(this); 35999 } 36000 } 36001 36002 36003 }, 36004 36005 _fetchFromAjaxCall : function (externalizedPath, options) { 36006 if (options && _.isFunction(options.preFetch)) { 36007 options.preFetch.call(this); 36008 } 36009 var that = this, 36010 lazyOptions = { 36011 path : externalizedPath, 36012 templateId : that.templateId, 36013 fetchJSON : true, 36014 fetchHTML : true, 36015 success : fetchCallback, 36016 error : (options && _.isFunction(options.error)) ? options.error : errorCallback, 36017 complete : completeCallback 36018 }; 36019 36020 window.guideBridge.panelProvider.getHtmlJson(lazyOptions); 36021 36022 function fetchCallback(jsonHtml) { 36023 var uniquePrefix; 36024 36025 36026 36027 if (that.repeatable || that._ancestorRepeatable) { 36028 uniquePrefix = that.guideUtil.generateUID(); 36029 } 36030 if (guidelib.util.GuideUtil._embedHtml(that, jsonHtml["html"], uniquePrefix)) { 36031 that._ajaxCallDone = true; 36032 36033 36034 36035 36036 var referredJson = JSON.parse(jsonHtml["json"])["items"]; 36037 that._embedJson(referredJson, uniquePrefix); 36038 36039 var guideDirtyMarkerAndVisitor = that._guide().internal.GuideDirtyMarkerAndVisitor; 36040 36041 if (!that.repeatable) { 36042 guideDirtyMarkerAndVisitor._updateCountOrInsert(guideDirtyMarkerAndVisitor.visitMap, that.templateId); 36043 } 36044 36045 that._guide().internal.liveDataUtils.playLiveData(that); 36046 36047 that.prepare(); 36048 that._itemsLoaded = true; 36049 that._guide().trigger(guidelib.event.GuideModelEvent.LAZY_LOADED); 36050 36051 that._triggerOnBridge("elementLazyLoaded", that); 36052 36053 36054 if (options && _.isFunction(options.success)) { 36055 options.success.call(this); 36056 } 36057 36058 36059 36060 } 36061 } 36062 36063 function errorCallback() { 36064 that.logger().error("AF", "Failed to fetch HTML and JSON for :" + externalizedPath); 36065 } 36066 36067 function completeCallback() { 36068 if (options && _.isFunction(options.postFetch)) { 36069 options.postFetch.call(this); 36070 } 36071 } 36072 36073 }, 36074 36075 36076 _unloadLazyReferenceModel : function (muteValidation) { 36077 try { 36078 if (this._lazyReference) { 36079 window.guideBridge._populateBindRefToSomMap(this); 36080 if (!muteValidation) { 36081 var validationStatus = this.validate(), 36082 visitMap = this._guide().internal.GuideDirtyMarkerAndVisitor.visitMap; 36083 if (validationStatus === false && visitMap[this.id] > 0) { 36084 visitMap[this.id] = 0; 36085 } 36086 } 36087 36088 36089 _.each(this.children, function (child) { 36090 child._unloadModel(muteValidation); 36091 var nIndex = this._children.indexOf(child); 36092 36093 this._children.splice(nIndex, 1); 36094 var childKey = null; 36095 36096 _.each(this.jsonModel.items, function (value, key) { 36097 if (value === child.jsonModel) { 36098 childKey = key; 36099 } 36100 }, this); 36101 if (childKey) { 36102 delete this.jsonModel.items[childKey]; 36103 } 36104 36105 this._normalizeChildren(); 36106 }, this); 36107 36108 this._navigationContext = null; 36109 this._currentItem = null; 36110 } 36111 } catch (exception) { 36112 this.logger().error(exception); 36113 } 36114 36115 }, 36116 36117 _unloadModel : function (muteValidation) { 36118 var visitMap = this._guide().internal.GuideDirtyMarkerAndVisitor.visitMap; 36119 _.each(this.children, function (child) { 36120 if (this._lazyReference && !muteValidation) {
36121 var validationStatus = child.validate(); 36122 if (validationStatus === false) { 36123 if (!_.isUndefined(visitMap[this.templateId])) { 36124 visitMap[this.templateId] = 0; 36125 } 36126 } 36127 } 36128 child._unloadModel(muteValidation); 36129 }, this); 36130 guidelib.model.Scriptable.prototype._unloadModel.call(this); 36131 }, 36132 36133 _removeChild : function (oChild) { 36134 oChild._unloadModel(); 36135 var nIndex = this._children.indexOf(oChild); 36136 this._children.splice(nIndex, 1); 36137 var childKey = null; 36138 _.each(this.jsonModel.items, function (value, key) { 36139 if (value === oChild.jsonModel) { 36140 childKey = key; 36141 } 36142 }, this); 36143 if (childKey) { 36144 delete this.jsonModel.items[childKey]; 36145 } 36146 this._normalizeChildren(); 36147 this._triggerEvent(guidelib.event.GuideModelEvent.CHILD_CHANGED, "childRemoved", oChild, null); 36148 }, 36149 36150 36151 _embedJson : function (referredJson, uniquePrefix) { 36152 36153 var bIsSuccess = false; 36154 var clonedJson = JSON.parse(JSON.stringify(referredJson)), 36155 currentPanelId = this.id, 36156 referredPanelRoot = null, 36157 referredPanelRootName = null, 36158 bindRefPrefix = this.jsonModel.bindRef; 36159 36160 currentPanelId = currentPanelId.slice(0, -2); 36161 if (referredJson) { 36162 36163 if (this.repeatable || this._ancestorRepeatable) { 36164 this.copyObject(referredJson, clonedJson, 36165 { 36166 transformMaps : { 36167 "id" : function (srcValue, options, parentObj) { 36168 return uniquePrefix + "__" + parentObj.templateId; 36169 } 36170 } 36171 } 36172 ); 36173 } 36174 36175 36176 _.each(clonedJson, function (panelJson, panelName) { 36177 if (_.isObject(panelJson)) { 36178 bIsSuccess = true; 36179 36180 this.jsonModel.items = this.jsonModel.items || {}; 36181 this.jsonModel.items[panelName] = panelJson; 36182 36183 this._guide()._modelTemplateCacheStore._putTemplate(JSON.parse(JSON.stringify(panelJson))); 36184 } 36185 }, this); 36186 36187 this._embedModel(); 36188 36189 } 36190 if (bIsSuccess === true) { 36191 36192 } 36193 return bIsSuccess; 36194 }, 36195 36196 36197 _embedModel : function () { 36198 36199 this._initChildren(true); 36200 36201 36202 this._guide()._modelTemplateCacheStore.putModel(this); 36203 36204 this._postInitialize(); 36205 36206 this._normalizeChildren(); 36207 }, 36208 36209 _getItemsInsertIndex : function (childIndex) { 36210 var itemIndex = 0; 36211 _.find(this._children, function (child, index) { 36212 if (child._isItem) { 36213 itemIndex++; 36214 } 36215 if (index >= childIndex) { 36216 return true; 36217 } 36218 }, this); 36219 return itemIndex; 36220 }, 36221 36222 playJson : function (pJsonModel, attachments) { 36223 var playNonPanelItems = {}; 36224 var playPanelItems = {}; 36225 _.each(pJsonModel.items, function (item) { 36226 if (_.isObject(item)) { 36227 36228 if (item.guideNodeClass === "guidePanel" || item.guideNodeClass === "guideTable" || item.guideNodeClass === "guideTableRow") { 36229 if (playPanelItems[item.name]) { 36230 playPanelItems[item.name].push(item); 36231 } else { 36232 playPanelItems[item.name] = [item]; 36233 } 36234 } else { 36235 if (playNonPanelItems[item.name]) { 36236 playNonPanelItems[item.name].push(item); 36237 } else { 36238 playNonPanelItems[item.name] = [item]; 36239 } 36240 } 36241 } 36242 }, this); 36243 36244 36245 var panelIMs = _.filter(this._children, function (child) { 36246 return child instanceof guidelib.model.GuideInstanceManager; 36247 }, this); 36248 36249 _.each(panelIMs, function (instanceManager) { 36250 var panelName = instanceManager._getInstanceName(); 36251 var newPanelItems = playPanelItems[panelName] || []; 36252 var panelInstances = instanceManager._instances.slice(0); 36253 _.each(panelInstances, function (panelInstance, index) { 36254 if (newPanelItems.length > 0) { 36255 var panelJson = newPanelItems.shift(); 36256 panelInstance.playJson(panelJson, attachments); 36257 } else { 36258 instanceManager.removeInstance(index); 36259 } 36260 }, this); 36261 if (newPanelItems.length > 0) { 36262 _.each(newPanelItems, function (paneljson) { 36263 var addedInstance = instanceManager.addInstance(); 36264 if (addedInstance) { 36265 addedInstance.playJson(paneljson, attachments); 36266 } 36267 }, this); 36268 } 36269 }, this); 36270 36271 36272 _.each(this.items, function (child) { 36273 if (!(child instanceof guidelib.model.GuidePanel)) { 36274 var nonPanelItemName = child.name; 36275 var nonPanelItem = playNonPanelItems[nonPanelItemName]; 36276 if (nonPanelItem && nonPanelItem.length > 0) { 36277 child.playJson(nonPanelItem.shift(), attachments); 36278 } 36279 } 36280 }, this); 36281 36282 36283 if (this.toolbar) { 36284 this.toolbar.playJson(pJsonModel.toolbar, attachments); 36285 } 36286 }, 36287 36288 _getReducedJSON : function (isParentRepeatable) { 36289 var reducedJSONChildren, 36290 isRepeatable; 36291 isRepeatable = isParentRepeatable || this.canBeRepeatable; 36292 reducedJSONChildren = GuidePanel._super._getReducedJSON.call(this, isRepeatable); 36293 36294 36295 if (this.jsonModel.toolbar) { 36296 reducedJSONChildren["toolbar"] = this.toolbar._getReducedJSON(); 36297 } 36298 return reducedJSONChildren; 36299 }, 36300 36301 _getRole : function () { 36302 var guideRole, xfaRole, roleMap; 36303 36304 roleMap = { 36305 "Table" : "grid", 36306 "Header Row" : "rowHeader", 36307 "Body Row" : "rowGroup", 36308 "Footer Row" : "rowGroup", 36309 "List" : "list" 36310 }; 36311 if (this.bindNode) { 36312 xfaRole = this.getOrElse(this.bindNode.assist && this.bindNode.assist.role, null); 36313 if (xfaRole) { 36314 guideRole = roleMap[xfaRole]; 36315 } 36316 } 36317 return guideRole; 36318 }, 36319 _getAssistPriority : function () { 36320 return (this.getAttribute("assistPriority") || "description"); 36321 }, 36322 36323 _getScreenReaderText : function () { 36324 var screenReaderText, assistPriority = this._getAssistPriority(); 36325 if (assistPriority !== "description") { 36326 screenReaderText = GuidePanel._super._getScreenReaderText.apply(this); 36327 } 36328 return screenReaderText; 36329 }, 36330 36331 execCompletion : function () { 36332 var complete = true; 36333 _.find(this.children, function (childModel) { 36334 36335 if (childModel instanceof guidelib.model.GuidePanel && !childModel.execCompletion()) { 36336 complete = false;
36337 return true; 36338 } 36339 }, this); 36340 if (complete && this.completionExp) { 36341 complete = this.executeExpression("completionExp"); 36342 } 36343 return complete; 36344 }, 36345 36346 _preserveLazyValue : function () { 36347 return !this._isXfaNode() && !(this instanceof guidelib.model.RootPanelNode) 36348 && (this.canBeRepeatable || this._guide().internal.liveDataUtils.isIndexedPath(this.bindRef)); 36349 }, 36350 36351 36352 _syncModelAndData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar, updateInstances, recurse) { 36353 var dataUtils = this._guide().internal.liveDataUtils; 36354 if (this._preserveLazyValue()) { 36355 36356 var dataContext = dataUtils._getDataContext(this, bound_indexedXpathSoFar, unBound_indexedXpathSoFar), 36357 indexedXpath = dataContext.indexedXpath; 36358 36359 if (this.canBeRepeatable) { 36360 36361 if (_.isFunction(updateInstances) && this.instanceIndex === 0) { 36362 updateInstances(dataUtils.getDataInstances(dataContext, this._getDataNodeName()), 36363 dataUtils.getParentDataNode(dataContext)); 36364 } 36365 indexedXpath = dataUtils.addIndexToPath(indexedXpath, this.instanceIndex); 36366 } 36367 36368 36369 if (dataContext.xmlSec === dataUtils.constants.UNBOUND_TAG) { 36370 unBound_indexedXpathSoFar = indexedXpath; 36371 } else if (dataContext.xmlSec === dataUtils.constants.BOUND_TAG) { 36372 bound_indexedXpathSoFar = indexedXpath; 36373 } 36374 } 36375 36376 if (_.isString(recurse)) { 36377 36378 _.each(this.items, function (item) { 36379 if (_.isFunction(item[recurse])) { 36380 item[recurse](bound_indexedXpathSoFar, unBound_indexedXpathSoFar); 36381 } 36382 }); 36383 } 36384 36385 return { 36386 'bound' : bound_indexedXpathSoFar, 36387 'unBound' : unBound_indexedXpathSoFar 36388 }; 36389 }, 36390 36391 _getDataNodeName : function () { 36392 var bindRef = this.bindRef, 36393 dataNodeName; 36394 if (bindRef) { 36395 dataNodeName = bindRef.substring(bindRef.lastIndexOf("/") + 1); 36396 } else { 36397 36398 dataNodeName = this.getAttribute("name"); 36399 } 36400 return dataNodeName; 36401 }, 36402 36403 _updateLiveData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar) { 36404 var dataUtils = this._guide().internal.liveDataUtils, 36405 that = this; 36406 36407 function updateDataInstances(dataNodes, parentNode) { 36408 var count = that.instanceManager.instanceCount; 36409 if (dataNodes && (dataNodes.length > count)) { 36410 36411 36412 for (var i = dataNodes.length -1; i >= count; --i) { 36413 dataUtils.removeChild(parentNode, that._getDataNodeName(), i); 36414 } 36415 } 36416 } 36417 36418 var contextSoFar = this._syncModelAndData(bound_indexedXpathSoFar, unBound_indexedXpathSoFar, updateDataInstances, '_updateLiveData'); 36419 }, 36420 36421 _playLiveData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar) { 36422 var parentArgs = arguments, 36423 that = this; 36424 36425 function updateModelInstances(dataNodes, parentNode) { 36426 var _dataNodes = dataNodes; 36427 if (_dataNodes == null) { 36428 _dataNodes = []; 36429 } 36430 36431 var i; 36432 if (_dataNodes && (_dataNodes.length < that.instanceManager.instanceCount)) { 36433 36434 for (i = Math.max(_dataNodes.length, Math.abs(that.minOccur)); i < that.instanceManager.instanceCount; ++i) { 36435 that.instanceManager.removeInstance(i); 36436 } 36437 } else if (_dataNodes && (_dataNodes.length > that.instanceManager.instanceCount)) { 36438 36439 var totalInstances = that.maxOccur < 0 ? _dataNodes.length : Math.min(_dataNodes.length, that.maxOccur); 36440 for (i = that.instanceManager.instanceCount; i < totalInstances; ++i) { 36441 var addedInstance = that.instanceManager.addInstance(); 36442 if (addedInstance) { 36443 that._playLiveData.apply(addedInstance, parentArgs); 36444 } 36445 } 36446 } 36447 } 36448 36449 this._syncModelAndData(bound_indexedXpathSoFar, unBound_indexedXpathSoFar, updateModelInstances, '_playLiveData'); 36450 } 36451 }); 36452 36453 GuidePanel.defineProps({ 36454 36455 completionExp : { 36456 get : function () { 36457 return this.getAttribute("completionExp"); 36458 } 36459 }, 36460 36461 completionExpReq : { 36462 get : function () { 36463 return this.getAttribute("completionExpReq"); 36464 } 36465 }, 36466 36467 36468 minOccur : { 36469 get : function () { 36470 return this.getOrElse(this.jsonModel.minOccur, 1); 36471 } 36472 }, 36473 36474 36475 maxOccur : { 36476 get : function () { 36477 return this.getOrElse(this.jsonModel.maxOccur, 1); 36478 } 36479 }, 36480 initialOccur : { 36481 get : function () { 36482 return this.getOrElse(this.jsonModel.initialOccur, 1); 36483 } 36484 }, 36485 36486 repeatable : { 36487 get : function () { 36488 return (this.minOccur != 1 || this.maxOccur != 1); 36489 } 36490 }, 36491 36492 36493 canBeRepeatable : { 36494 get : function () { 36495 return (this.maxOccur < 0 || this.maxOccur > 1); 36496 } 36497 }, 36498 36499 panel : { 36500 get : function () { 36501 return this; 36502 } 36503 }, 36504 toolbar : { 36505 get : function () { 36506 this.getElement("guideToolbar"); 36507 } 36508 }, 36509 36510 instanceManager : { 36511 get : function () { 36512 return this._instanceManager; 36513 } 36514 }, 36515 36516 36517 instanceIndex : { 36518 get : function () { 36519 var context = this._guide()._currentContext; 36520 if (context && context.managedExp) { 36521 this._addDependant(context.contextNode, context.expression); 36522 } 36523 return this.instanceManager._instances.indexOf(this); 36524 } 36525 }, 36526 36527 title : { 36528 get : function () { 36529 return this.jsonModel["jcr:title"]; 36530 }, 36531 set : function (value) { 36532 var oldTitle = this.title; 36533 if (oldTitle !== value) { 36534 this.jsonModel["jcr:title"] = value; 36535 this.trigger(guidelib.event.GuideModelEvent.MODEL_CHANGED, 36536 guidelib.event.GuideModelEvent.createEvent( 36537 guidelib.event.GuideModelEvent.MODEL_CHANGED, 36538 this, 36539 "title", 36540 oldTitle, 36541 value 36542 ) 36543 ); 36544 } 36545 } 36546 }, 36547 36548 summary : { 36549 get : function () { 36550 return this._summary; 36551 }, 36552 set : function (value) { 36553 var oldSummary = this._summary; 36554 if (oldSummary !== value) { 36555 this._summary = value; 36556 this.trigger(guidelib.event.GuideModelEvent.MODEL_CHANGED, 36557 guidelib.event.GuideModelEvent.createEvent( 36558 guidelib.event.GuideModelEvent.MODEL_CHANGED, 36559 this, 36560 "summary", 36561 oldSummary, 36562 this._summary 36563 ) 36564 ); 36565 } 36566 } 36567 }, 36568 enableLayoutOptimization : { 36569 get : function () { 36570 return this.getOrElse(this.jsonModel, "layout.enableLayoutOptimization", false); 36571 } 36572 }, 36573 36574 36575 isNavigable : { 36576 get : function () { 36577 var isNonNavigable = this.getOrElse(this.jsonModel, "layout.nonNavigable", false); 36578 36579 36580 if (typeof isNonNavigable === 'string') { 36581 return !(isNonNavigable === "true"); 36582 } else { 36583 return !isNonNavigable; 36584 } 36585 } 36586 }, 36587 36588 _hopsToRootPanel : { 36589 get : function () { 36590 return guidelib.util.GuideUtil._countHopsToRootPanel(this); 36591 } 36592 36593 }, 36594 36595 _ancestorRepeatable : { 36596 get : function () { 36597 var parentOrAncestor = this.parent; 36598 while (parentOrAncestor) { 36599 if (parentOrAncestor && parentOrAncestor.repeatable) { 36600 return true; 36601 } 36602 parentOrAncestor = parentOrAncestor.parent; 36603 } 36604 36605 return false;
36606 } 36607 }, 36608 36609 36610 enabled : { 36611 get : function () { 36612 return guidelib.model.Scriptable.prototype._getEnabled.call(this); 36613 }, 36614 36615 set : function (value) { 36616 var oldValue = this.enabled; 36617 guidelib.model.Scriptable.prototype._setEnabled.call(this, value); 36618 if (this._parentAccess && value != oldValue) { 36619 this._changeContainerAccess(value); 36620 } 36621 } 36622 }, 36623 36624 36625 _hasLazyDescendant : { 36626 get : function () { 36627 if (!_.isEmpty(guideBridge._guide.allLazyChildren)) { 36628 return true; 36629 } 36630 return false; 36631 } 36632 } 36633 }); 36634 36635 36636 GuidePanel.addMixins([ 36637 guidelib.model.mixin.AddNavigationContext, 36638 guidelib.model.mixin.AddDependencyMgmt 36639 ]); 36640 36641})(_, guidelib); 36642 36643(function (_, guidelib) { 36644 var GuideTableRow = guidelib.model.GuideTableRow = guidelib.model.GuidePanel.extend({ 36645 msClassName : "guideTableRow" 36646 }); 36647}(_, guidelib)); 36648(function (_, guidelib) { 36649 36650 36651 var GuideTable = guidelib.model.GuideTable = guidelib.model.GuidePanel.extend({ 36652 msClassName : "guideTable" 36653 }); 36654 36655 GuideTable.defineProps({ 36656 36657 mobileLayout : { 36658 get : function () { 36659 return this.jsonModel.layout.mobileLayout; 36660 } 36661 }, 36662 36663 columnWidth : { 36664 get : function () { 36665 return this.jsonModel.columnWidth; 36666 } 36667 } 36668 }); 36669})(_, guidelib); 36670 36671(function (_, guidelib) { 36672 var RootPanelNode = guidelib.model.RootPanelNode = guidelib.model.GuidePanel.extend({ 36673 msClassName : "rootPanelNode", 36674 36675 _clearInactiveLazyViews : function (panelView) { 36676 _.each(this.childViews, function (item) { 36677 item._clearInactiveLazyViews(panelView); 36678 }); 36679 } 36680 36681 }); 36682 RootPanelNode.defineProps({ 36683 toolbar : { 36684 get : function () { 36685 36686 return this.getElement("guideToolbar") || this.parent.toolbar; 36687 } 36688 } 36689 }); 36690})(_, guidelib); 36691(function ($, guidelib, _) { 36692 function negate(predicateFunc) { 36693 return function () { 36694 return !predicateFunc.apply(this, arguments); 36695 }; 36696 } 36697 36698 function getPredicate(condition) { 36699 return condition instanceof Array 36700 ? Array.prototype.includes.bind(condition) 36701 : condition; 36702 } 36703 36704 var CommonUtils = { 36705 36706 36707 returnMinimalJSON : function (whitelistedProperties, reducedJsonObject, that) { 36708 if (!_.isObject(reducedJsonObject)) { 36709 reducedJsonObject = {}; 36710 } 36711 _.each(whitelistedProperties, function (whitelistedProperty) { 36712 if (!_.isUndefined(that.jsonModel[whitelistedProperty])) { 36713 reducedJsonObject[whitelistedProperty] = that.jsonModel[whitelistedProperty] ; 36714 36715 } else if (!_.isUndefined(that[whitelistedProperty])) { 36716 reducedJsonObject[whitelistedProperty] = that[whitelistedProperty]; 36717 } 36718 }); 36719 }, 36720 36721 createMap : function (list, value) { 36722 return _.mapObject(_.object(list, []), function () { 36723 return value; 36724 }); 36725 }, 36726 36727 updatedMapIfNot : function (map, condition, value) { 36728 return this._updateMap(map, negate(getPredicate(condition)), value); 36729 }, 36730 36731 updateMap : function (map, condition, value) { 36732 return this._updateMap(map, getPredicate(condition), value); 36733 }, 36734 36735 _updateMap : function (map, condition, value) { 36736 var newMap = {}, 36737 prop; 36738 for (prop in map) { 36739 if (map.hasOwnProperty(prop)) { 36740 newMap[prop] = condition(prop) ? value : map[prop]; 36741 } 36742 } 36743 return newMap; 36744 }, 36745 36746 _getScope : function (context) { 36747 var mergedScope = Object.assign(guidelib.runtime, context._guide().runtime); 36748 return mergedScope; 36749 } 36750 }; 36751 36752 guidelib.model.util.CommonUtils = CommonUtils; 36753}($, guidelib, _)); 36754(function (_, $, guidelib) { 36755 var getOrElse = xfalib.ut.XfaUtil.prototype.getOrElse, 36756 commonUtils = guidelib.model.util.CommonUtils, 36757 logger, 36758 constants = guidelib.model.GuideSchema.prototype.GuideStateConstants; 36759 36760 var initializeLogger = function () {
36761 var configString = window.AF_log_config === undefined ? "0-a9" 36762 : "1-" + window.AF_log_config; 36763 36764 xfalib.ut.XfaUtil.prototype.registerLocaleProperties(guidelib.i18n); 36765 if (window.formBridge) { 36766 window.formBridge.registerConfig("contextPath", window.guideBridge.userConfig["contextPath"]); 36767 window.formBridge.registerConfig("LoggerConfig", { 36768 "logConfigString" : configString, 36769 "categoryAcronyms" : {"d" : "AF"} 36770 }); 36771 } else { 36772 xfalib.ut.XfaUtil.prototype.logger = new xfalib.ut.Logger({ 36773 "jsonModel" : { 36774 "logConfigString" : configString, 36775 "categoryAcronyms" : {"d" : "AF"} 36776 } 36777 }); 36778 logger = xfalib.ut.XfaUtil.prototype.logger; 36779 } 36780 }; 36781 36782 var utils = { 36783 triggerEventOnWindow : function (eventPayload) { 36784 $(window).trigger(eventPayload); 36785 }, 36786 36787 postExternalMessage : function (name) { 36788 window.guideBridge._postExternalMessage({name : name}); 36789 } 36790 }; 36791 36792 var viewOnlyUtils = { 36793 createView : function (guide, $element) { 36794 utils.postExternalMessage("_layoutstart"); 36795 36796 var guideContainerView = new guidelib.view.GuideContainerView({ 36797 element : $element, 36798 model : guide 36799 }); 36800 36801 36802 window.guideBridge._setGuideView(guideContainerView); 36803 guidelib.util.GuideUtil.initializeHelp(); 36804 36805 36806 guidelib.util.AdUtil.applyDescriptionPlugin(); 36807 36808 utils.postExternalMessage("_layoutend"); 36809 36810 $(window).on("mousedown.guidebridge", function () { 36811 window.guideBridge.clickedOnWindow = true; 36812 }); 36813 }, 36814 36815 getLastFocusItem : function (guide) { 36816 var lastFocusItem; 36817 if (guide.runtime.guideContext) { 36818 lastFocusItem = guidelib.util.GuideUtil.fetchXMLNodeValue(guide.runtime.guideContext.guidePrefillXml, "lastFocusItem"); 36819 } 36820 36821 if (_.isUndefined(lastFocusItem)) { 36822 lastFocusItem = guidelib.util.GuideUtil._fetchJSONNodeValue(guide.runtime.guideContext.guidePrefillJson, "afSubmissionInfo.lastFocusItem"); 36823 } 36824 36825 if (_.isUndefined(lastFocusItem)) { 36826 lastFocusItem = window.guideBridge.customContextProperty("lastFocusItem"); 36827 } 36828 return lastFocusItem; 36829 }, 36830 36831 setFocus : function (item) { 36832 if (item) { 36833 window.guideBridge.setFocus(item); 36834 } else { 36835 window.guideBridge.setFocus(); 36836 } 36837 }, 36838 36839 preventCheckBoxMovementOnClick : function () { 36840 36841 36842 36843 36844 if (xfalib.ut.XfaUtil.prototype.isSafari() && !xfalib.ut.TouchUtil.TOUCH_ENABLED) { 36845 $('#guideContainerForm').addClass('macSafariForm'); 36846 } 36847 }, 36848 36849 disableDefaultSubmit : function () { 36850 36851 36852 $("#guideContainerForm").submit(function (evnt) { 36853 evnt.preventDefault(); 36854 }); 36855 }, 36856 36857 preventFormSubmitOnEnter : function () { 36858 36859 36860 $("#guideContainerForm input").keypress(function (evnt) { 36861 if (evnt.keyCode == 13 || evnt.charCode == 13 || evnt.which == 13) { 36862 evnt.preventDefault(); 36863 } 36864 }); 36865 }, 36866 36867 renderView : function (guide, $guideElement) { 36868 viewOnlyUtils.createView(guide, $guideElement); 36869 36870 var lastFocusItem = viewOnlyUtils.getLastFocusItem(guide); 36871 viewOnlyUtils.setFocus(lastFocusItem); 36872 utils.triggerEventOnWindow({type : "guideInitialized", guide : guide}); 36873 36874 viewOnlyUtils.preventCheckBoxMovementOnClick(); 36875 viewOnlyUtils.disableDefaultSubmit(); 36876 viewOnlyUtils.preventFormSubmitOnEnter(); 36877 } 36878 36879 }; 36880 36881 36882 guidelib.model._createXfaAndGuideModel = function (guideJson, xfaJson, options) { 36883 if (xfaJson) { 36884 xfalib.script.XfaModelRegistry.prototype.createModel(xfaJson); 36885 36886 new xfalib.acrobat.Acrobat(); 36887 } 36888 var guide = {}; 36889 guide = guidelib.model.GuideModelRegistry.prototype.createModel(guideJson, options); 36890 36891 guide._bindRefMap = {}; 36892 return guide; 36893 36894 }; 36895 36896 36897 guidelib.model._getGuideJsonWithSyncXfaProps = function (guideJson, xfaJson) { 36898 36899 var guide = guidelib.model._createXfaAndGuideModel(guideJson, xfaJson); 36900 36901 guide.syncXFAProps(); 36902 36903 36904 return { 36905 "guidejson" : JSON.stringify(guideJson), 36906 "xfajson" : JSON.stringify(xfaJson) 36907 }; 36908 }; 36909 36910 guidelib.model._prepareGuide = function (prefillData, guide) { 36911 var liveDataUtils = guide.internal.liveDataUtils, 36912 liveModel = guide.internal.liveModel, 36913 _getFileAttachmentWrappers = function(prefillDataAttachments) { 36914 var fileAttachmentWrappers = []; 36915 try { 36916 var atts = JSON.parse(prefillDataAttachments); 36917 fileAttachmentWrappers = atts.map(function (x) { 36918 return new guidelib.model.FileAttachmentWrapper(JSON.parse(x)) 36919 }); 36920 } catch (e) { 36921 if (e.stack) { 36922 guide.logger().error(e.stack); 36923 } 36924 } 36925 return fileAttachmentWrappers; 36926 }; 36927 36928 if (prefillData.isMergedJson && prefillData.data) { 36929 36930 if (prefillData.data.guideState && prefillData.data.guideState.attachments) { 36931 prefillData.data["attachments"] = _getFileAttachmentWrappers(prefillData.data.guideState.attachments); 36932 } 36933 window.guideBridge.restoreGuideState(prefillData.data); 36934 } else if (prefillData.data) { 36935 guide.setGuideState(constants.GUIDE_STATE_MERGE_PROGRESS); 36936 liveDataUtils.initLiveData(prefillData.data, 36937 null, 36938 _.isString(guide.xdpRef), 36939 _.isString(guide.xsdRef), 36940 guide.getAttribute("xsdRootElement"), 36941 _getFileAttachmentWrappers(prefillData.attachments)); 36942 liveDataUtils.playLiveData(guide.rootPanel); 36943 liveModel.prefillCrossFragFields(guide); 36944 guide.setGuideState(constants.GUIDE_STATE_MERGE_COMPLETE); 36945 guide.prepare(); 36946 } else { 36947 guide.prepare(); 36948 liveDataUtils.initLiveData(null, null, 36949 _.isString(guide.xdpRef), _.isString(guide.xsdRef), 36950 guide.getAttribute("xsdRootElement")); 36951 } 36952 36953 var fileAttachmentMap, 36954 obj = guideBridge.customContextProperty("fileAttachmentMap"); 36955 if (!_.isUndefined(obj) && typeof(obj) === "string") { 36956 try { 36957 obj = JSON.parse(obj); 36958 } catch (e) { 36959 if (e.stack) { 36960 guide.logger().error(e.stack); 36961 } 36962 obj = undefined; 36963 } 36964 } 36965 fileAttachmentMap = obj; 36966 36967 var i, node, fieldValue, 36968 fileAttachmentsList = window.guideBridge._getFileAttachmentsList(); 36969 36970 36971 if (!_.isUndefined(fileAttachmentMap)) { 36972 for (i = 0; i < fileAttachmentsList.length; i++) { 36973 node = fileAttachmentsList[i]; 36974 fieldValue = fileAttachmentMap[node.somExpression]; 36975 node.fileAttachment.value = fieldValue; 36976 if (!_.isEmpty(fieldValue)) { 36977 node._fileList = fieldValue.split("\n"); 36978 } 36979 } 36980 } 36981 guide.setGuideState(constants.GUIDE_STATE_MODEL_COMPLETE); 36982 }; 36983 36984 guidelib.model.markDirtyPanels = function (lazyChildren, dataString, dirtyPanels, guide) {
36985 var lazyChildrenMap = commonUtils.createMap(lazyChildren, 0); 36986 36987 if (!_.isEmpty(dataString)) { 36988 if (dirtyPanels === null || dirtyPanels.length === 0) { 36989 dirtyPanels = guide.internal.liveDataUtils.getListOfDirtyPanels(dataString); 36990 } 36991 if (dirtyPanels && dirtyPanels.length > 0) { 36992 lazyChildrenMap = commonUtils.updatedMapIfNot(lazyChildrenMap, dirtyPanels, 1); 36993 guide.internal.GuideDirtyMarkerAndVisitor.visitMap = lazyChildrenMap; 36994 } 36995 } else { 36996 guide.internal.GuideDirtyMarkerAndVisitor.visitMap = lazyChildrenMap; 36997 } 36998 }; 36999 37000 guidelib.model.initializeLiveDataUtils = function (schemaType) { 37001 var liveDataUtils = null; 37002 if (schemaType === "formdatamodel" || schemaType === "jsonschema") { 37003 liveDataUtils = new guidelib.model.LiveJsonUtils(); 37004 } else { 37005 liveDataUtils = new guidelib.model.LiveXmlUtils(); 37006 } 37007 return liveDataUtils; 37008 }; 37009 37010 guidelib.model.prepareInput = function (guideJsonData) { 37011 return { 37012 guideJson : JSON.parse(guideJsonData.guidejson || "null"), 37013 guideContext : JSON.parse(guideJsonData.guidecontext || "null"), 37014 guidemergedjson : JSON.parse(guideJsonData.guidemergedjson || "null"), 37015 xfaJson : JSON.parse(guideJsonData.xfajson || "null"), 37016 xfaRenderContext : JSON.parse(guideJsonData.xfarendercontext || "null") 37017 }; 37018 }; 37019 37020 guidelib.model.mergeData = function (prefillData, guide, guideContext) { 37021 var rawData = prefillData.data, 37022 liveDataUtils = guide.internal.liveDataUtils, 37023 dirtyPanels = [], 37024 customPropertyMap = {}, 37025 mergedXfaRenderContext = null; 37026 37027 guide.runtime.guideContext = guide.runtime.guideContext || {}; 37028 37029 if (prefillData.isMergedJson) { 37030 if (typeof prefillData.data === "string") { 37031 try { 37032 prefillData.data = JSON.parse(prefillData.data); 37033 } catch (e) { 37034 prefillData.data = ""; 37035 } 37036 } 37037 rawData = getOrElse(prefillData.data, 37038 "guideState.guideLiveData", 37039 getOrElse(rawData, 37040 "guideState.guidePrefillXml", 37041 getOrElse(prefillData.data, 37042 "guideState.guidePrefillJson", undefined))); 37043 37044 var dirtyPanelsStr = getOrElse(prefillData.data, 37045 "guideState.guideContext.afSubmissionInfo.afDraft", "") 37046 .replace(/\"/g, ""); 37047 37048 if (dirtyPanelsStr) { 37049 dirtyPanels = dirtyPanelsStr.split(","); 37050 } 37051 customPropertyMap = getOrElse(prefillData.data, 37052 "guideState.guideContext.customPropertyMap", 37053 {}); 37054 37055 var ccpMapViaNewPrefillService = getOrElse(prefillData.data, "guideState.customContext", null); 37056 var ccpMapViaOldImplementation = getOrElse(guidelib, "__runtime__.guideContext.customPropertyMap", {}); 37057 var ccpMapViaOldAndNewImplementation = _.extend({}, ccpMapViaOldImplementation, getOrElse(guide, "runtime.guideContext.customPropertyMap", {})); 37058 if (!_.isEmpty(ccpMapViaNewPrefillService) && _.isEmpty(ccpMapViaOldAndNewImplementation)) { 37059 guideBridge.customContextProperty(ccpMapViaOldAndNewImplementation); 37060 } 37061 37062 var fileMapViaNewPrefillService = getOrElse(prefillData.data, "guideState.fileAttachmentMap", null); 37063 var fileMapViaOldImplementation = guideBridge.customContextProperty("fileAttachmentMap"); 37064 if (!_.isEmpty(fileMapViaNewPrefillService) && _.isEmpty(fileMapViaOldImplementation)) { 37065 guideBridge.customContextProperty("fileAttachmentMap", fileMapViaNewPrefillService); 37066 } 37067 } else { 37068 guideBridge.customContextProperty("fileAttachmentMap", prefillData.fileAttachmentMap); 37069 guideBridge.customContextProperty("fileAttachmentWrappers", prefillData.fileAttachmentWrappers); 37070 } 37071 37072 if (guide.xdpRef) { 37073 mergedXfaRenderContext = getOrElse(prefillData.data, "guideState.xfaState.xfaRenderContext", null); 37074 37075 if (mergedXfaRenderContext != null) { 37076 37077 xfalib.runtime.renderContext = JSON.parse(mergedXfaRenderContext); 37078 } 37079 37080 xfalib.runtime.xfa.form._initialize(true);
37081 $(window).trigger("XfaInitialized"); 37082 } 37083 37084 if (rawData !== "") { 37085 if (guideContext.schemaType === "formdatamodel" || guideContext.schemaType === "jsonschema") { 37086 guideContext.guidePrefillJson = rawData; 37087 } else { 37088 guideContext.guidePrefillXml = rawData; 37089 } 37090 } 37091 37092 guideContext.customPropertyMap = $.extend({}, guideContext.customPropertyMap, customPropertyMap); 37093 37094 37095 $.extend(true, guide.runtime.guideContext, guideContext); 37096 37097 guidelib.model.markDirtyPanels(guide.allLazyChildren, rawData, dirtyPanels, guide); 37098 37099 guidelib.model._prepareGuide(prefillData, guide); 37100 37101 37102 37103 if (guide.allLazyChildren.length > 0 && guideBridge.customContextProperty("fileAttachmentMap")) { 37104 var fileAttachmentMap = guideBridge.customContextProperty("fileAttachmentMap"); 37105 if (typeof fileAttachmentMap === "string") { 37106 fileAttachmentMap = JSON.parse(fileAttachmentMap); 37107 } 37108 guide.internal.liveDataUtils._updateLazyAttachmentMap(fileAttachmentMap); 37109 } 37110 }; 37111 37112 guidelib.model.fireOnContainerDomElementReady = function (guideJsonData, fetchData, $htmlElement, localContextCustomPropertyMap) { 37113 initializeLogger(); 37114 var inputData = this.prepareInput(guideJsonData), 37115 guideJson = inputData.guideJson, 37116 guideContext = inputData.guideContext, 37117 guidemergedjson = inputData.guidemergedjson, 37118 xfaJson = inputData.xfaJson, 37119 xfaRenderContext = inputData.xfaRenderContext, 37120 localStorage, 37121 guide, 37122 dataPromise; 37123 37124 if (guideJson === null || guideContext == null) { 37125 console.error("Unable to load Form. Adaptive Form Json is invalid."); 37126 return; 37127 } 37128 37129 if (window.guideBridge !== undefined) { 37130 localStorage = window.guideBridge._getStorage(); 37131 } 37132 try { 37133 37134 localContextCustomPropertyMap = _.isObject(localContextCustomPropertyMap) ? 37135 JSON.stringify(localContextCustomPropertyMap) : localContextCustomPropertyMap; 37136 localContextCustomPropertyMap = JSON.parse(localContextCustomPropertyMap); 37137 } catch(e) { 37138 localContextCustomPropertyMap = {}; 37139 } 37140 37141 if (fetchData && (guidemergedjson === null || guidemergedjson === "" || getOrElse(localStorage, "guideState", null) !== null)) { 37142 if (fetchData instanceof Function) { 37143 var result = fetchData(); 37144 if (result.then instanceof Function) { 37145 dataPromise = result; 37146 } else { 37147 dataPromise = _.extend({}, {isMergedJson : false}, fetchData()); 37148 } 37149 } else if ((!(window.FD && window.FD.isToggleEnabled("FT_FORMS-14840"))) || 37150 ((guideJson.prefillService !== undefined && guideJson.prefillService !== "none") || (new URLSearchParams(window.location.search)).get("dataRef") !== null)) { 37151 var formContainerPath = getOrElse(window.guideBridge, "userConfig.submitConfig.aemFormComponentPath", guideContext.guidePath); 37152 var guideUrl = window.guideBridge._getGuidePathUrl(".af.prefilldata.json", formContainerPath); 37153 dataPromise = this.fetchData(guideUrl + window.location.search); 37154 } else { 37155 dataPromise = {data: "", isMergedJson: false}; 37156 } 37157 } else { 37158 var _mergeData = guidemergedjson; 37159 if (getOrElse(localStorage, "guideState", null) !== null) { 37160 _mergeData = localStorage; 37161 } 37162 37163 37164 dataPromise = { 37165 data : _mergeData, 37166 isMergedJson : true 37167 }; 37168 } 37169 37170 37171 var liveDataUtils = this.initializeLiveDataUtils(guideContext.schemaType), 37172 liveModel = new guidelib.model.LiveModel(); 37173 37174 if (window.guideBridge.hostName == "server") { 37175 37176 if (!FD.isToggleEnabled(guidelib.util.FeatureToggleConstants.FT_BROWSERLESS_SUBMISSION)) { 37177 liveModel._disableFunctions(); 37178 liveDataUtils._disableFunctions(); 37179 } 37180 37181 _.each(_.functions(viewOnlyUtils), function (funcName) { 37182 viewOnlyUtils[funcName] = function () {}; 37183 }); 37184 37185 if (window.formBridge) { 37186 37187 37188 37189 window.formBridge.ajaxCallMode = "server"; 37190 } 37191 } 37192 37193 liveModel.createDataNodes(guideJson.repeatBindRef); 37194 var allLazyChildren = getOrElse(guideJson, "allLazyChildren", []); 37195 37196 var options = {}; 37197 options = _.extend({}, options, {"liveModel" : liveModel, "liveDataUtils" : liveDataUtils}); 37198 37199 utils.postExternalMessage("_formdomstart"); 37200 try { 37201 guide = guidelib.model._createXfaAndGuideModel(guideJson, xfaJson, options); 37202 37203 guide.runtime.guideContext.customPropertyMap = _.extend({}, guide.runtime.guideContext.customPropertyMap, localContextCustomPropertyMap); 37204 if (allLazyChildren.length > 0) { 37205 liveModel.createCrossFragFields(guideJson.guideGlobalLazyField, guide); 37206 } 37207 guide.version = new guidelib.util.Version({ 37208 scriptingBehaviourVersion: guideContext.scriptingBehaviourVersion 37209 }); 37210 guide.setGuideState(constants.GUIDE_STATE_MODEL_CREATED); 37211 if (xfaJson && xfaRenderContext) { 37212 xfalib.runtime.renderContext = xfaRenderContext; 37213 } 37214 utils.triggerEventOnWindow({type: "guideModelInitialized", guide: guide}); 37215 } catch (e) { 37216 37217 if (e.stack) { 37218 console.error(e.stack); 37219 } 37220 } 37221 37222 var $guideElement = $htmlElement || $("div.guideContainerWrapperNode"); 37223 37224 if (dataPromise.then instanceof Function) { 37225 return dataPromise.then(function (result) { 37226 guidelib.model.mergeData(result, guide, guideContext); 37227 viewOnlyUtils.renderView(guide, $guideElement); 37228 }); 37229 } else { 37230 37231 guidelib.model.mergeData(dataPromise, guide, guideContext); 37232 viewOnlyUtils.renderView(guide, $guideElement); 37233 return guide; 37234 } 37235 }; 37236 37237 guidelib.model.fetchData = function (path) { 37238 var deferred = $.Deferred(); 37239 if (window.guideBridge.hostName === "server") { 37240 deferred.resolve({ 37241 data : "", 37242 isMergedJson : false 37243 }); 37244 } else { 37245 $.ajax({ 37246 url : path, 37247 type : 'POST', 37248 dataType : 'json' 37249 }).done(function (data) { 37250 var obj = _.extend({}, data, {isMergedJson : false}); 37251 deferred.resolve(obj); 37252 }).fail(function (obj, textStatus, errorThrown) { 37253 console.error(textStatus + " " + errorThrown); 37254 deferred.resolve({ 37255 data : "", 37256 isMergedJson : false 37257 }); 37258 }); 37259 } 37260 return deferred.promise(); 37261 }; 37262})(_, $, window.guidelib); 37263 37264/************************************************************************* 37265 * 37266 * ADOBE CONFIDENTIAL 37267 * __________________ 37268 * 37269 * Copyright 2014 Adobe Systems Incorporated 37270 * All Rights Reserved. 37271 *
37272 * NOTICE: All information contained herein is, and remains 37273 * the property of Adobe Systems Incorporated and its suppliers, 37274 * if any. The intellectual and technical concepts contained 37275 * herein are proprietary to Adobe Systems Incorporated and its 37276 * suppliers and may be covered by U.S. and Foreign Patents, 37277 * patents in process, and are protected by trade secret or copyright law. 37278 * Dissemination of this information or reproduction of this material 37279 * is strictly forbidden unless prior written permission is obtained 37280 * from Adobe Systems Incorporated. 37281 **************************************************************************/ 37282 37283/** 37284 * Created with IntelliJ IDEA. 37285 * User: rismehta 37286 * Date: 1/15/14 37287 * Time: 5:49 PM 37288 * To change this template use File | Settings | File Templates. 37289 */ 37290 37291/*anonymous function to handle show of file list view */ 37292(function ($, guidelib) { 37293 37294 // Was causing problem in IE9 37295 // hence have added timeout to ensure that once button is rendered, event handler is registered 37296 // todo: may have to think of better namespace ? 37297 guidelib.intervals = guidelib.intervals || {}; 37298 guidelib.intervals.intId = setInterval(function () { 37299 var fileAttachmentListingBtn = $("div.fileattachmentlisting button[data-guide-fileListing]"); 37300 if (fileAttachmentListingBtn.length > 0) { 37301 clearInterval(guidelib.intervals.intId); 37302 var self; 37303 fileAttachmentListingBtn.click(function () { 37304 self = $(this); 37305 // added because in mobile devices it was causing problem of backdrop 37306 $("#fileAttachment").addClass("fileAttachmentDialog"); 37307 $("#fileAttachment").appendTo('body'); 37308 $("#fileAttachment").modal("show"); 37309 }); 37310 37311 // bring focus back to file attachment listing button on dialog hide 37312 $(".fileAttachmentDialog").on('hidden.bs.modal', function (e) { 37313 $(this).removeClass("fileAttachmentDialog"); 37314 self.focus(); 37315 }); 37316 } 37317 }, 1000); 37318}($, guidelib)); 37319 37320/************************************************************************* 37321 * 37322 * ADOBE CONFIDENTIAL 37323 * __________________ 37324 * 37325 * Copyright 2014 Adobe Systems Incorporated 37326 * All Rights Reserved. 37327 *
37328 * NOTICE: All information contained herein is, and remains 37329 * the property of Adobe Systems Incorporated and its suppliers, 37330 * if any. The intellectual and technical concepts contained 37331 * herein are proprietary to Adobe Systems Incorporated and its 37332 * suppliers and may be covered by U.S. and Foreign Patents, 37333 * patents in process, and are protected by trade secret or copyright law. 37334 * Dissemination of this information or reproduction of this material 37335 * is strictly forbidden unless prior written permission is obtained 37336 * from Adobe Systems Incorporated. 37337 **************************************************************************/ 37338 37339(function ($) { 37340 37341 // GUIDE ADD REMOVE CLASS DEFINITION 37342 // ==================== 37343 37344 var GuideAddRemove = function (element) { 37345 this.element = $(element); 37346 }; 37347 37348 GuideAddRemove.prototype.add = function () { 37349 $this = this.element; 37350 var id = $this.attr("data-guide-id"), 37351 nextPanel; 37352 37353 if (id) { 37354 if (window.guideBridge) { 37355 var guidePanel = window.guideBridge._resolveId(id); 37356 if (guidePanel) { 37357 nextPanel = guidePanel.instanceManager.insertInstance(guidePanel.instanceIndex + 1); 37358 if (nextPanel) { 37359 window.guideBridge.setFocus(nextPanel.somExpression, "firstItem"); 37360 } 37361 } 37362 } else { 37363 console.log("could not add new instance" + id); 37364 } 37365 } 37366 }; 37367 37368 GuideAddRemove.prototype.remove = function () { 37369 $this = this.element; 37370 var id = $this.attr("data-guide-id"); 37371 37372 if (id) { 37373 if (window.guideBridge) { 37374 var guidePanel = window.guideBridge._resolveId(id); 37375 if (guidePanel) { 37376 guidePanel.instanceManager.removeInstance(guidePanel.instanceIndex); 37377 } 37378 } else { 37379 console.log("could not remove instance"); 37380 } 37381 } 37382 }; 37383 37384 // GUIDE ADD REMOVE PLUGIN DEFINITION 37385 // ===================== 37386 37387 var old = $.fn.guideAddRemove; 37388 37389 $.fn.guideAddRemove = function (option) { 37390 return this.each(function () { 37391 var $this = $(this); 37392 var data = $this.data('guideAddRemove'); 37393 37394 if (!data) { 37395 $this.data('guideAddRemove', (data = new GuideAddRemove(this))); 37396 } 37397 if (typeof option == 'string') { 37398 data[option](); 37399 } 37400 }); 37401 }; 37402 37403 $.fn.guideAddRemove.Constructor = GuideAddRemove(); 37404 37405 // ADD REMOVE NO CONFLICT 37406 // =============== 37407 37408 $.fn.guideAddRemove.noConflict = function () { 37409 $.fn.guideAddRemove = old; 37410 return this; 37411 }; 37412 37413 // ADD REMOVE DATA-API 37414 // ============ 37415 37416 $(document).on('click.guideAddRemove.data-api keypress.guideAddRemove.data-api', '[data-guide-addremove="add"]', function (e) { 37417 if (e.type == "keypress" && !guidelib.util.GuideUtil.isEnterKeyPressed(e)) { 37418 return; 37419 } 37420 e.preventDefault(); 37421 //This is required for setting the focus on the new panel. Otherwise the focus remains on the previous panel. 37422 e.stopImmediatePropagation(); 37423 $(this).guideAddRemove('add'); 37424 }).on('click.guideAddRemove.data-api keypress.guideAddRemove.data-api', '[data-guide-addremove="remove"]', function (e) { 37425 if (e.type == "keypress" && !guidelib.util.GuideUtil.isEnterKeyPressed(e)) { 37426 return; 37427 } 37428 e.preventDefault(); 37429 $(this).guideAddRemove('remove'); 37430 }); 37431 37432}($)); 37433 37434/************************************************************************* 37435 * 37436 * ADOBE CONFIDENTIAL 37437 * __________________ 37438 * 37439 * Copyright <year> Adobe Systems Incorporated 37440 * All Rights Reserved. 37441 *
37442 * NOTICE: All information contained herein is, and remains 37443 * the property of Adobe Systems Incorporated and its suppliers, 37444 * if any. The intellectual and technical concepts contained 37445 * herein are proprietary to Adobe Systems Incorporated and its 37446 * suppliers and may be covered by U.S. and Foreign Patents, 37447 * patents in process, and are protected by trade secret or copyright law. 37448 * Dissemination of this information or reproduction of this material 37449 * is strictly forbidden unless prior written permission is obtained 37450 * from Adobe Systems Incorporated. 37451 **************************************************************************/ 37452 37453(function ($) { 37454 37455 // TABLE LAYOUT PLUGIN 37456 // ============ 37457 37458 $(document).on('panelRemoved.af', '.guideTableNode', function (e, $childRemoved, index) { 37459 // this plugin is specific to a layout 37460 // one can also check the layout based on CSS class set and perform things accordingly 37461 // prevent the bubbling up of the event 37462 e.stopPropagation(); 37463 // this would work only in runtime 37464 var $bodyRows = $(e.target).find("tr.guideTableRowNode:not(.guideTableHeader)"); 37465 // Set focus to first child 37466 if (index > 1) { 37467 // set focus on prev row since index is greater than 1 37468 var $prevRow = $bodyRows.eq(index - 1); 37469 guidelib.util.GuideUtil.setFocusOnFirstItemOfTableRow($prevRow); 37470 } else if (index == 1) { 37471 var $nextRow = $bodyRows.eq(1); 37472 // may there is only one row which has got deleted, hence check if next row actually exists 37473 if ($nextRow.length > 0) { 37474 guidelib.util.GuideUtil.setFocusOnFirstItemOfTableRow($nextRow); 37475 } 37476 } 37477 }); 37478 37479}($)); 37480 37481/************************************************************************* 37482 * 37483 * ADOBE CONFIDENTIAL 37484 * __________________ 37485 * 37486 * Copyright 2014 Adobe Systems Incorporated 37487 * All Rights Reserved. 37488 *
37489 * NOTICE: All information contained herein is, and remains 37490 * the property of Adobe Systems Incorporated and its suppliers, 37491 * if any. The intellectual and technical concepts contained 37492 * herein are proprietary to Adobe Systems Incorporated and its 37493 * suppliers and may be covered by U.S. and Foreign Patents, 37494 * patents in process, and are protected by trade secret or copyright law. 37495 * Dissemination of this information or reproduction of this material 37496 * is strictly forbidden unless prior written permission is obtained 37497 * from Adobe Systems Incorporated. 37498 **************************************************************************/ 37499 37500/*handle click of default next and previous navigator*/ 37501$(function ($) { 37502 var getPanelSom = function (panelId) { 37503 var panel = window.guideBridge._resolveId(panelId); 37504 if (panel === undefined || panel === null) { 37505 return ""; 37506 } 37507 return panel.somExpression; 37508 }, 37509 pointerup_evnt = xfalib.ut.TouchUtil.POINTER_UP; 37510 37511 if (pointerup_evnt === "touchend") { 37512 // touchend happens before blur, hence the value of the current 37513 // focused field is not committed and setFocus API receives the old 37514 // value. So as a hack we are using mouseup instead of touchend to 37515 // make sure that the value gets committed 37516 pointerup_evnt = "mouseup"; 37517 } 37518 $('body').on(pointerup_evnt + " keydown", '[data-guide-wizard-nav]', function (e) { 37519 var triggerKeyEvent = false; 37520 // check for event type and key press space/enter 37521 if (e.type === "keydown" && (e.keyCode === 32 || e.keyCode === 13)) { 37522 e.preventDefault(); 37523 triggerKeyEvent = true; // set to trigger key event 37524 } 37525 37526 // when event is pointerup(click) or space/enter key is pressed, trigger navigation 37527 if (e.type === "pointerup" || triggerKeyEvent) { 37528 var $this = $(this), 37529 options = $this.data("guide-wizard-nav"); 37530 if (_.isObject(options)) { //case of all the options, get som expression out of id 37531 options.somExpression = getPanelSom(options.panelId); 37532 } else { //case where its value of somId 37533 var somExpr = getPanelSom(options), 37534 navType = $(this).data("guide-wizard-nav-type"); 37535 options = { 37536 somExpression: somExpr, 37537 focusOption: navType, 37538 runCompletionScript: true 37539 }; 37540 } 37541 window.guideBridge.setFocus(options); 37542 } 37543 }); 37544 37545 window.guideBridge.on("elementNavigationChanged", 37546 function (evntName, evnt) { 37547 var activePanelSom = evnt.newText, 37548 activePanel = window.guideBridge._guideView.getView(activePanelSom), 37549 scrollDirection, 37550 scrollStep, 37551 scrollPos, 37552 list, 37553 $listElements; 37554 if (activePanel instanceof guidelib.view.GuidePanelView) { 37555 $listElements = activePanel.parentView.$element.find('[id*="' + guidelib.util.GuideUtil.GUIDE_ITEM_NAV_CONTAINER_SUFFIX + '"]'); 37556 if (!_.isUndefined($listElements) && !_.isNull($listElements) && $listElements.length > 0) { 37557 list = $listElements.eq(0); 37558 if (_.isUndefined(list.attr("data-guide-nav-scroll-pos"))) { 37559 list.attr("data-guide-nav-scroll-pos", 0); 37560 } 37561 scrollPos = parseInt(list.attr("data-guide-nav-scroll-pos"), 10); 37562 //Find index among the visible panels 37563 var parentChildViews = activePanel.parentView.childViews, 37564 iterator, 37565 navPos = 0; 37566 for (iterator = 0; iterator < parentChildViews.length; iterator++) { 37567 if (activePanel === parentChildViews[iterator]) { 37568 break; 37569 } 37570 if (parentChildViews[iterator]._model.visible) { 37571 navPos = navPos + 1; 37572 } 37573 } 37574 if (navPos > scrollPos) { 37575 scrollDirection = "right"; 37576 } else { 37577 scrollDirection = "left"; 37578 } 37579 scrollStep = Math.abs(navPos - scrollPos); 37580 guidelib.util.GuideUtil.navScroll(list, scrollDirection, scrollStep, '[id*="' + guidelib.util.GuideUtil.GUIDE_ITEM_
37580NAV_SUFFIX + '"]:not(.hidden)'); 37581 } 37582 } 37583 }); 37584}); 37585 37586/************************************************************************* 37587 * 37588 * ADOBE CONFIDENTIAL 37589 * __________________ 37590 * 37591 * Copyright 2014 Adobe Systems Incorporated 37592 * All Rights Reserved. 37593 * 37594 * NOTICE: All information contained herein is, and remains 37595 * the property of Adobe Systems Incorporated and its suppliers, 37596 * if any. The intellectual and technical concepts contained 37597 * herein are proprietary to Adobe Systems Incorporated and its 37598 * suppliers and may be covered by U.S. and Foreign Patents, 37599 * patents in process, and are protected by trade secret or copyright law. 37600 * Dissemination of this information or reproduction of this material 37601 * is strictly forbidden unless prior written permission is obtained 37602 * from Adobe Systems Incorporated. 37603 **************************************************************************/ 37604 37605$(function ($) { 37606 37607 /* handle swipe*/ 37608 var setSwipeGestureState = function () { 37609 var swipeEnabled = !window.guideBridge._guide.getAttribute("disableSwipeGesture"); 37610 window.guideBridge.enableSwipeGesture(swipeEnabled, swipeEnabled); 37611 }; 37612 window.guideBridge.connect(setSwipeGestureState, this); 37613 37614 /*show scroll indication on mobile devices*/ 37615 var scrollIndicator = function () { 37616 if ($(window).scrollTop() == $(document).height() - $(window).height()) { 37617 $('[data-guide-scroll-indicator]').removeClass('mobileScrollIndicator'); 37618 } else if ($(window).scrollTop() < $(document).height() - $(window).height()) { 37619 $('[data-guide-scroll-indicator]').addClass('mobileScrollIndicator'); 37620 } 37621 }; 37622 37623 //this should be changed back to $(document).ready(scrollIndicator) instead of windows onload, 37624 //once jquery version is bumped 37625 $(window).on('load scroll resize', scrollIndicator); 37626 window.guideBridge.on('elementNavigationChanged', scrollIndicator); 37627}); 37628 37629/************************************************************************* 37630 * 37631 * ADOBE CONFIDENTIAL 37632 * __________________ 37633 * 37634 * Copyright 2014 Adobe Systems Incorporated 37635 * All Rights Reserved. 37636 *
37637 * NOTICE: All information contained herein is, and remains 37638 * the property of Adobe Systems Incorporated and its suppliers, 37639 * if any. The intellectual and technical concepts contained 37640 * herein are proprietary to Adobe Systems Incorporated and its 37641 * suppliers and may be covered by U.S. and Foreign Patents, 37642 * patents in process, and are protected by trade secret or copyright law. 37643 * Dissemination of this information or reproduction of this material 37644 * is strictly forbidden unless prior written permission is obtained 37645 * from Adobe Systems Incorporated. 37646 **************************************************************************/ 37647/*anonymous function to handle click of default next and previous navigator*/ 37648(function ($) { 37649 window.guideBridge.on("elementNavigationChanged", 37650 function (evntName, evnt) { 37651 var activePanelSom = evnt.newText, 37652 activePanel = window.guideBridge.resolveNode(activePanelSom); 37653 if (activePanel) { 37654 var dynamicContentSelector = "[data-target-guide-content]", 37655 text = $(dynamicContentSelector).text(); 37656 // if there is an active panel already set and active panel is not an instance of root panel node 37657 // only then set the active panel title to the content 37658 if (text != null && text.length > 0 && (!(activePanel instanceof guidelib.model.RootPanelNode))) { 37659 $(dynamicContentSelector).text(activePanel.title ? activePanel.title : ""); 37660 } 37661 } 37662 }); 37663}($)); 37664 37665/************************************************************************* 37666 * 37667 * ADOBE CONFIDENTIAL 37668 * __________________ 37669 * 37670 * Copyright 2015 Adobe Systems Incorporated 37671 * All Rights Reserved. 37672 *
37673 * NOTICE: All information contained herein is, and remains 37674 * the property of Adobe Systems Incorporated and its suppliers, 37675 * if any. The intellectual and technical concepts contained 37676 * herein are proprietary to Adobe Systems Incorporated and its 37677 * suppliers and may be covered by U.S. and Foreign Patents, 37678 * patents in process, and are protected by trade secret or copyright law. 37679 * Dissemination of this information or reproduction of this material 37680 * is strictly forbidden unless prior written permission is obtained 37681 * from Adobe Systems Incorporated. 37682 **************************************************************************/ 37683 37684/*handle click of default next and previous navigator for PDC*/ 37685$(function ($) { 37686 window.guideBridge.connect(function () { 37687 //this function will be called after adaptive form is initialized 37688 var progressive = window.guideBridge.progressive; 37689 if (progressive) { 37690 /** 37691 * Add listener to navigate across section for custom layout 37692 */ 37693 $(document).on('click', 'button[data-guide-progressive-nav]', $.proxy(progressive.navigateSection, progressive)); 37694 } 37695 }); 37696 37697}); 37698 37699// jscs:disable requireDotNotation 37700/* 37701 * *********************************************************************** 37702 * ADOBE CONFIDENTIAL 37703 * __________________ 37704 * 37705 * Copyright 2015 Adobe Systems Incorporated 37706 * All Rights Reserved. 37707 *
37708 * NOTICE: All information contained herein is, and remains 37709 * the property of Adobe Systems Incorporated and its suppliers, 37710 * if any. The intellectual and technical concepts contained 37711 * herein are proprietary to Adobe Systems Incorporated and its 37712 * suppliers and may be covered by U.S. and Foreign Patents, 37713 * patents in process, and are protected by trade secret or copyright law. 37714 * Dissemination of this information or reproduction of this material 37715 * is strictly forbidden unless prior written permission is obtained 37716 * from Adobe Systems Incorporated. 37717 * *********************************************************************** 37718 */ 37719 37720(function ($, guidelib, _) { 37721 var GuideUtil = guidelib.util.GuideUtil, 37722 CHART_TYPE = GuideUtil.chartType, 37723 37724 ChartUtils = guidelib.chartUtils = { 37725 37726 reducerOptions : window.chartReducer.reducerOptions, 37727 37728 /** 37729 * Returns the display format of axis data 37730 * @param dataType {string} representing data type of axis 37731 * @returns {string} 37732 */ 37733 getDisplayFormat : function (dataType) { 37734 var displayFormat = ""; 37735 if (dataType === 'date' || dataType === 'date-time') { 37736 displayFormat = 'date{' + guidelib.i18n.datePatterns.med + '}'; 37737 } 37738 return displayFormat; 37739 }, 37740 37741 /** 37742 * Reads chart model for chart configuration and computes the data for chart 37743 * @param chartModel 37744 * @returns {{}} 37745 */ 37746 gatherAxisData : function (chartModel) { 37747 var categoryExp, 37748 valueExp, 37749 reducerFunction, 37750 repeatableInstances, 37751 repeatableItem, 37752 seriesRepeatableItem, 37753 series, 37754 relativeSeriesNameExp, 37755 currentSeries, 37756 repeatablePath, 37757 seriesLength = 0, 37758 seriesRepeatableInstances, 37759 relativeSeriesRefExp, 37760 data = new Map(), 37761 chartBuildOptions = {}, 37762 isWebChannelChart = chartModel.jsonModel["sling:resourceType"] === 'fd/ccm/web-channel/components/chart/v1/chart', 37763 dataToFill = {}; 37764 chartBuildOptions.isFDMDataSource = chartModel.dataSourceType === "fdm" ? true : false; 37765 chartBuildOptions.chartModel = chartModel; 37766 dataToFill.valueDisplayFormat = ""; 37767 dataToFill.labelDisplayFormat = ""; 37768 dataToFill.categoryDataType = ""; 37769 dataToFill.valueDataType = ""; 37770 37771 repeatableItem = chartModel.getOrElse(chartModel._guide().runtime, chartModel.repeatableItem, undefined); 37772 37773 //Do not support reducer functions on x-axis for Web channel charts 37774 if (chartModel.reducerXFunction && chartModel.reducerXFunction !== 'none' && !isWebChannelChart) { 37775 chartBuildOptions.categoryExp = chartModel.yExp; 37776 chartBuildOptions.valueExp = chartModel.xExp; 37777 chartBuildOptions.reducerFunction = chartModel.reducerXFunction; 37778 dataToFill = ChartUtils._setProp(dataToFill, "categoryDataType", chartModel.jsonModel.yDataType); 37779 dataToFill = ChartUtils._setProp(dataToFill, "valueDataType", chartModel.jsonModel.xDataType); 37780 } else { 37781 chartBuildOptions.categoryExp = chartModel.xExp; 37782 chartBuildOptions.valueExp = chartModel.yExp; 37783 dataToFill = ChartUtils._setProp(dataToFill, "categoryDataType", chartModel.jsonModel.yDataType); 37784 dataToFill = ChartUtils._setProp(dataToFill, "valueDataType", chartModel.jsonModel.xDataType); 37785 if (chartModel.reducerYFunction && chartModel.reducerYFunction !== 'none') { 37786 chartBuildOptions.reducerFunction = chartModel.reducerYFunction; 37787 } 37788 } 37789 37790 if (chartBuildOptions.isFDMDataSource) { 37791 dataToFill.valueDisplayFormat = ChartUtils.getDisplayFormat(dataToFill.valueDataType); 37792 dataToFill.labelDisplayFormat = ChartUtils.getDisplayFormat(dataToFill.categoryDataType); 37793 repeatableItem = chartModel.repeatableItem; 37794 chartBuildOptions.categoryExp = chartBuildOptions.categoryExp.substring(repeatableItem.length + 1, chartBuildOptions.categoryExp.length).split("/"); 37795 chartBuildOptions.valueExp = chartBuildOptions.valueExp.substring(repeatableItem.length + 1, chartBuildOptions.valueExp.length).split("/"); 37796 if (isWebChannelChart) { 37797 dataToFill.series = series = []; 37798 if (chartModel.jsonModel.chartType === 'quadrant') { 37799 chartBuildOptions.isXYReferencePointSet = false;
37800 if (chartModel.jsonModel.referencePointType === 'staticReferencePoint') { 37801 if (chartModel.jsonModel.xDataType === 'date' || chartModel.jsonModel.xDataType === 'date-time') { 37802 //Whenx-axis is of Date type we need to compute reference value in milliseconds. 37803 chartModel.jsonModel.xAxisReferencePoint = new Date(chartModel.jsonModel.xAxisReferencePoint).getTime(); 37804 } 37805 chartBuildOptions.isXYReferencePointSet = true; 37806 } 37807 } 37808 } 37809 if ("true" == chartModel.jsonModel.multiSeries) { 37810 seriesRepeatableItem = chartModel.jsonModel.seriesRepeatableItem; 37811 relativeSeriesNameExp = chartModel.jsonModel.seriesName.substring(seriesRepeatableItem.length + 1, chartModel.jsonModel.seriesName.length); 37812 seriesRepeatableInstances = this._getRepeatableInstances(seriesRepeatableItem, null, chartModel); 37813 seriesLength = seriesRepeatableInstances ? seriesRepeatableInstances.length : seriesLength; 37814 repeatablePath = repeatableItem.substring(seriesRepeatableItem.length, repeatableItem.length); 37815 if (chartModel.jsonModel.chartType === 'quadrant' && chartModel.jsonModel.referencePointType === 'fdmReferencePoint') { 37816 relativeSeriesRefExp = chartModel.jsonModel.seriesReferenceExp.substring(seriesRepeatableItem.length + 1, chartModel.jsonModel.seriesReferenceExp.length); 37817 } 37818 for (var i = 0; i < seriesLength; i++) { 37819 chartBuildOptions.repeatableInstances = this._getRepeatableInstances(repeatablePath, seriesRepeatableInstances[i], chartModel); 37820 chartBuildOptions.repeatableItemForReferencePoint; 37821 if (relativeSeriesRefExp && !chartBuildOptions.isXYReferencePointSet) { 37822 chartBuildOptions.repeatableItemForReferencePoint = undefined; 37823 if (this.matchUserInputWithFDM(chartModel.jsonModel.seriesReferenceDataType, seriesRepeatableInstances[i][relativeSeriesRefExp], chartModel.jsonModel.seriesReferenceValue)) { 37824 chartBuildOptions.repeatableItemForReferencePoint = repeatableItem; 37825 } 37826 } 37827 currentSeries = this.buildChartData(chartBuildOptions); 37828 currentSeries.name = seriesRepeatableInstances[i][relativeSeriesNameExp]; 37829 series.push(currentSeries); 37830 } 37831 } else { 37832 chartBuildOptions.repeatableInstances = this._getRepeatableInstances(repeatableItem, null, chartModel); 37833 chartBuildOptions.repeatableItemForReferencePoint = repeatableItem; 37834 currentSeries = this.buildChartData(chartBuildOptions); 37835 series.push(currentSeries); 37836 } 37837 if (isWebChannelChart && chartModel.jsonModel.chartType === 'quadrant' && chartModel.jsonModel.referencePointType === 'fdmReferencePoint' && !chartBuildOptions.isXYReferencePointSet) { 37838 chartModel.jsonModel.xAxisReferencePoint = undefined; 37839 chartModel.jsonModel.yAxisReferencePoint = undefined; 37840 } 37841 chartBuildOptions.repeatableInstances = null; 37842 } else if (repeatableItem) { 37843 chartBuildOptions.repeatableInstances = repeatableItem.instanceManager.instances; 37844 } 37845 if (chartBuildOptions.repeatableInstances) { 37846 var chartData = this.buildChartData(chartBuildOptions); 37847 dataToFill.label = chartData.label; 37848 dataToFill.value = chartData.value; 37849 } 37850 return dataToFill; 37851 }, 37852 37853 buildChartData : function (chartBuildOptions) { 37854 var dataToFill = {}, 37855 data = new Map(), 37856 referencePointExp, 37857 isFDMReferencePointSet = false;
37858 dataToFill.value = []; 37859 dataToFill.label = []; 37860 37861 if (chartBuildOptions.chartModel.jsonModel.chartType === 'quadrant' && chartBuildOptions.chartModel.jsonModel.referencePointType === 'fdmReferencePoint' && chartBuildOptions.repeatableItemForReferencePoint) { 37862 referencePointExp = chartBuildOptions.chartModel.jsonModel.xyReferencePointExp.substring(chartBuildOptions.repeatableItemForReferencePoint.length + 1, chartBuildOptions.chartModel.jsonModel.xyReferencePointExp.length).split("/"); 37863 } 37864 var that = this; 37865 _.each(chartBuildOptions.repeatableInstances, function (repeatableInstance, index) { 37866 var categoryPropVal, 37867 valuePropVal, 37868 xyReferenceVal; 37869 if (chartBuildOptions.isFDMDataSource) { 37870 if (_.isArray(chartBuildOptions.categoryExp) && _.isArray(chartBuildOptions.valueExp)) { 37871 //Handling composite key case. 37872 var temp = repeatableInstance; 37873 _.each(chartBuildOptions.categoryExp, function (obj) { 37874 temp = temp[obj]; 37875 }); 37876 categoryPropVal = temp; 37877 37878 temp = repeatableInstance; 37879 _.each(chartBuildOptions.valueExp, function (obj) { 37880 temp = temp[obj]; 37881 }); 37882 valuePropVal = temp; 37883 37884 if (chartBuildOptions.chartModel.jsonModel.chartType === 'quadrant' && !chartBuildOptions.isXYReferencePointSet) { 37885 if (chartBuildOptions.repeatableItemForReferencePoint && chartBuildOptions.chartModel.jsonModel.referencePointType === 'fdmReferencePoint') { 37886 temp = repeatableInstance; 37887 _.each(referencePointExp, function (obj) { 37888 temp = temp[obj]; 37889 }); 37890 xyReferenceVal = temp; 37891 if (that.matchUserInputWithFDM(chartBuildOptions.chartModel.jsonModel.xyReferencePointDataType, xyReferenceVal, chartBuildOptions.chartModel.jsonModel.xyReferencePointValue)) { 37892 //For date type x-axis FDM value we need to get time in milliseconds to send to Highcharts 37893 chartBuildOptions.chartModel.jsonModel.xAxisReferencePoint = (chartBuildOptions.chartModel.jsonModel.xDataType === 'date' || chartBuildOptions.chartModel.jsonModel.xDataType === 'date-time') ? new Date(categoryPropVal).getTime() : categoryPropVal; 37894 chartBuildOptions.chartModel.jsonModel.yAxisReferencePoint = valuePropVal; 37895 chartBuildOptions.isXYReferencePointSet = true; 37896 } 37897 } 37898 } 37899 } 37900 } else { 37901 categoryPropVal = repeatableInstance[chartBuildOptions.categoryExp].value; 37902 valuePropVal = repeatableInstance[chartBuildOptions.valueExp].value; 37903 } 37904 37905 categoryPropVal = _.isUndefined(categoryPropVal) ? '' : categoryPropVal; 37906 valuePropVal = _.isUndefined(valuePropVal) ? '' : valuePropVal; 37907 if (chartBuildOptions.reducerFunction) { 37908 if (!data.has(categoryPropVal)) { 37909 data.set(categoryPropVal, []); 37910 } 37911 data.get(categoryPropVal).push(valuePropVal); 37912 } else { 37913 dataToFill.label.push(categoryPropVal); 37914 dataToFill.value.push(valuePropVal); 37915 } 37916 }); 37917 37918 if (chartBuildOptions.reducerFunction) { 37919 var reducer = ChartUtils.reducerOptions[chartBuildOptions.reducerFunction] || window[chartBuildOptions.reducerFunction]; 37920 data.forEach(function (value, key) { 37921 dataToFill.label.push(key); 37922 dataToFill.value.push(reducer(data.get(key))); 37923 }); 37924 } 37925 return dataToFill; 37926 }, 37927 37928 matchUserInputWithFDM : function (fdmObjectDataType, fdmObjectValue, userInputValue) { 37929 return (((fdmObjectDataType == 'date-time' || fdmObjectDataType == 'date') && new Date(userInputValue).getTime() == new Date(fdmObjectValue).getTime()) 37930 || (fdmObjectDataType == 'boolean' && JSON.parse(userInputValue) == fdmObjectValue) 37931 || (userInputValue == fdmObjectValue)); 37932 }, 37933 37934 /** 37935 * Returns dv.chart object created from chart model. 37936 * @param chartModel 37937 * @param $chartElement 37938 * @returns {dv.chart} 37939 */ 37940 constructChart : function (chartModel, $chartElement) { 37941 var chartType = chartModel.chartType, 37942 showLegends = chartModel.showLegends, 37943 legendPosition = chartModel.legendPosition, 37944 tooltipHtml = chartModel.tooltipHtml, 37945 innerRadius = chartModel.innerRadius, 37946 lineColor = chartModel.lineColor, 37947 pointColor = chartModel.pointColor, 37948 areaColor = chartModel.areaColor, 37949 dataToFill = chartModel.data, 37950 chartBehavior = [], 37951 axisMap = {}, 37952 axisScale = {}, 37953 chartLayers, 37954 chart, 37955 categoryAxis, 37956 valueAxis; 37957 if (chartModel.reducerXFunction && chartModel.reducerXFunction !== 'none') { 37958 categoryAxis = 'y'; 37959 valueAxis = 'x'; 37960 } else { 37961 categoryAxis = 'x'; 37962 valueAxis = 'y'; 37963 } 37964 37965 if (dataToFill.labelDisplayFormat) { 37966 dataToFill.label = dataToFill.label.map(function (value) { 37967 return guidelib.util.GuideUtil.formatValue(value, 37968 dataToFill.labelDisplayFormat, 37969 dataToFill.categoryDataType); 37970 }); 37971 } 37972 37973 if (dataToFill.valueDisplayFormat) { 37974 dataToFill.value = dataToFill.value.map(function (value) { 37975 return guidelib.util.GuideUtil.formatValue(value, 37976 dataToFill.valueDisplayFormat, 37977 dataToFill.valueDataType); 37978 }); 37979 } 37980 37981 axisMap[categoryAxis] = 'label'; 37982 axisMap[valueAxis] = 'value'; 37983 axisScale[valueAxis] = dv.scale.linear().lowerLimit(0); 37984 37985 try { 37986 if (GuideUtil.isChartTooltipApplicable(chartType)) { 37987 if (tooltipHtml && tooltipHtml !== '') { 37988 var xValMap = axisMap['x'], 37989 yValMap = axisMap['y']; 37990 chartBehavior = [dv.behavior.rollover().content(function (d) { 37991 var tooltip = tooltipHtml.replace(/\${x}/g, d.data[xValMap]); 37992 tooltip = tooltip.replace(/\${y}/g, d.data[yValMap]); 37993 return tooltip; 37994 })]; 37995 } 37996 } 37997 axisScale[categoryAxis] = dv.scale.ordinal(); 37998 chart = dv.chart(); 37999 chart.map('fill', 'label') 38000 .map('x', axisMap['x'], axisScale['x']) 38001 .map('y', axisMap['y'], axisScale['y']); 38002 38003 var chartPoint = dv.geom.point().set('fill', pointColor).behaviors(chartBehavior), 38004 chartLine = dv.geom.line().set('fill', lineColor), 38005 chartArea = dv.geom.area().set('alpha', 0.1).set('fill', areaColor), 38006 flippedCaretesianCoord = dv.coord.cartesian().flip(true),
38007 lineCommon = function () { 38008 chart.set('stroke', lineColor); 38009 chartLayers = [dv.geom.line()]; 38010 }, 38011 barTypeCommon = function () { 38012 chartLayers = [dv.geom.bar().behaviors(chartBehavior)]; 38013 chart.map('x', 'label', axisScale[categoryAxis]) 38014 .map('y', 'value'); 38015 }, 38016 barCommon = function () { 38017 barTypeCommon(); 38018 if (categoryAxis === 'x') { 38019 chart.coord(flippedCaretesianCoord); 38020 } 38021 }, 38022 columnCommon = function () { 38023 barTypeCommon(); 38024 if (categoryAxis === 'y') { 38025 chart.coord(flippedCaretesianCoord); 38026 } 38027 }, 38028 pieCommon = function (radius) { 38029 columnCommon(); 38030 dataToFill[categoryAxis] = Array.apply(null, Array(dataToFill["label"].length)).map(function () { 38031 return 1; 38032 }); 38033 axisMap[categoryAxis] = categoryAxis; 38034 if (radius > 0) { 38035 axisScale[categoryAxis] = axisScale[categoryAxis].padding(.3); 38036 } 38037 38038 chart.map('x', axisMap[categoryAxis], axisScale[categoryAxis]); 38039 38040 chart.coord(dv.coord.polar().flip(true).innerRadius(radius)) 38041 .guide(['x', 'y'], 'none') 38042 .position('fill'); 38043 }; 38044 38045 switch (chartType) { 38046 case CHART_TYPE.LINE: 38047 lineCommon(); 38048 chartLayers.push(chartLine); 38049 break; 38050 case CHART_TYPE.POINT: 38051 lineCommon(); 38052 chartLayers.push(chartPoint); 38053 break; 38054 case CHART_TYPE.AREA: 38055 lineCommon(); 38056 chartLayers.push(chartLine); 38057 chartLayers.push(chartArea); 38058 break; 38059 case CHART_TYPE.LINE_POINT: 38060 lineCommon(); 38061 chartLayers.push(chartPoint); 38062 chartLayers.push(chartLine); 38063 break; 38064 case CHART_TYPE.BAR: 38065 barCommon(); 38066 break; 38067 case CHART_TYPE.COLUMN: 38068 columnCommon(); 38069 break; 38070 case CHART_TYPE.PIE: 38071 pieCommon(0); 38072 break; 38073 case CHART_TYPE.DONUT: 38074 pieCommon(innerRadius); 38075 break; 38076 } 38077 38078 chart.layers(chartLayers); 38079 chart.data(dataToFill) 38080 .width(chartModel.width + '%') 38081 .height(chartModel.height) 38082 .parent("#" + $chartElement.attr('id')) 38083 .padding({"left" : 10, "top" : 10, "right" : 10, "bottom" : 10}); 38084 38085 if (GuideUtil.isChartAxisTitleApplicable(chartType)) { 38086 chart.guide('x', dv.guide.axis().title(chartModel.xAxisTitle)) 38087 .guide('y', dv.guide.axis().title(chartModel.yAxisTitle)); 38088 } 38089 38090 if (GuideUtil.isChartLegendApplicable(chartType) && showLegends) { 38091 chart.guide('fill', dv.guide.legend().orientation(legendPosition)); 38092 } 38093 } catch (exception) { 38094 window.guideBridge._guide.logger().log("Error while constructing chart " + exception); 38095 } 38096 return chart; 38097 }, 38098 38099 _setProp : function (object, prop, value) { 38100 if (object.constructor == {}.constructor && !_.isEmpty(value)) { 38101 object[prop] = value; 38102 } 38103 return object; 38104 }, 38105 38106 /** 38107 * Retrieves Repeatable Instances using liveDataUtils API for the given 38108 * repeatablePath. This API internally handles naked/non-naked case. 38109 * 38110 * @param repeatablePath 38111 * @param data 38112 * @return Repeatable Instances for the given repeatablePath using liveDataUtils. 38113 * 38114 * TODO Move this API to data utils. 38115 */ 38116 _getRepeatableInstances : function (repeatablePath, data, chartModel) { 38117 var liveDataUtils = chartModel._guide().internal.liveDataUtils, 38118 liveData = data ? data : liveDataUtils._liveDataDoc, 38119 xpath = ""; 38120 38121 if (_.isEmpty(liveData) || _.isEmpty(repeatablePath)) { 38122 return; 38123 } 38124 38125 if (!_.isEmpty(liveData.afData)) {//Non-Naked data case 38126 liveData = liveData.afData; 38127 xpath = liveDataUtils.constants.BOUND_DATA_XPATH; 38128 } else {//Naked data case or multiple series case 38129 repeatablePath = repeatablePath.substring(1, repeatablePath.length); 38130 } 38131 38132 //Find the repeatable instances. 38133 repeatableInstances = liveDataUtils._getElement(liveData, xpath + repeatablePath); 38134 38135 return repeatableInstances; 38136 } 38137 }; 38138}($, guidelib, _)); 38139 38140//Poly-filling request animation frame function for IE 9 38141(function () { 38142 var lastFramePaintTime = 0; 38143 if (!window.requestAnimationFrame) { 38144 window.requestAnimationFrame = function (callback, element) { 38145 var currTime = new Date().getTime(), 38146 timeToCall = Math.max(0, 16 - (currTime - lastFramePaintTime)), //16-16 frames per second 38147 id = window.setTimeout(function () { 38148 callback(currTime + timeToCall); 38149 }, timeToCall); 38150 lastFramePaintTime = currTime + timeToCall; 38151 return id; 38152 }; 38153 } 38154 38155 if (!window.cancelAnimationFrame) { 38156 window.cancelAnimationFrame = function (id) { 38157 clearTimeout(id); 38158 }; 38159 } 38160}()); 38161 38162/* 38163 * *********************************************************************** 38164 * ADOBE CONFIDENTIAL 38165 * __________________ 38166 * 38167 * Copyright 2015 Adobe Systems Incorporated 38168 * All Rights Reserved. 38169 *
38170 * NOTICE: All information contained herein is, and remains 38171 * the property of Adobe Systems Incorporated and its suppliers, 38172 * if any. The intellectual and technical concepts contained 38173 * herein are proprietary to Adobe Systems Incorporated and its 38174 * suppliers and may be covered by U.S. and Foreign Patents, 38175 * patents in process, and are protected by trade secret or copyright law. 38176 * Dissemination of this information or reproduction of this material 38177 * is strictly forbidden unless prior written permission is obtained 38178 * from Adobe Systems Incorporated. 38179 * *********************************************************************** 38180 */ 38181 38182(function ($, guidelib, xfalib, _) { 38183 var errorHandler = function (jqXHR) { 38184 var errorPayload; 38185 38186 // Actually we need clean-up old data but its not even happening in case of success with empty data 38187 // Running output mapping with empty result set to ensure old data is cleared 38188 38189 if (jqXHR.responseText) { 38190 var inputMapping = this.inputMapping; 38191 try { 38192 errorPayload = JSON.parse(jqXHR.responseText); 38193 } catch (error) { 38194 // result should be json if its not wel formed json or empty then ignoring it 38195 } 38196 if(errorPayload && errorPayload.errors) { 38197 38198 // Iterating over violations received and set it at field level using input mapping provided. 38199 var violations = errorPayload.errors; 38200 $.each(violations, function (key, violation) { 38201 if(violation && violation.bindRef && violation.errorMessages) { 38202 var key = violation.bindRef.slice(1).split("/").join("."); 38203 var field = inputMapping[key]; 38204 if (field) { 38205 field.markAsInvalid(violation.errorMessages.join("\n")); 38206 } 38207 } 38208 }) 38209 } 38210 } 38211 // Invoke author register error handler (if any) 38212 if(this.customErrorHandler) { 38213 this.customErrorHandler.call(this, jqXHR, errorPayload); 38214 } 38215 }; 38216 38217 var defaultErrorHandler = function (responseJson, headerMap) { 38218 if (responseJson) { 38219 if (responseJson && responseJson.validationErrors) { 38220 var violations = responseJson.validationErrors; 38221 $.each(violations, function (key, violation) { 38222 if (violation && violation.details && (violation.fieldName || violation.dataRef)) { 38223 if (!window.guideBridge._guide._bindRefMap || Object.keys(window.guideBridge._guide._bindRefMap).length === 0) { 38224 window.guideBridge._populateBindRefToSomMap(); 38225 } 38226 var som = (violation.fieldName) ? violation.fieldName : window.guideBridge._guide._bindRefMap[violation.dataRef]; 38227 var field = window.guideBridge.resolveNode(som); 38228 if (field) { 38229 field.markAsInvalid(violation.details.join("\n")); 38230 } 38231 } 38232 }); 38233 } 38234 } 38235 }; 38236 38237 var defaultErrorHandlerWrapper = function(jqXHR) { 38238 if (jqXHR.responseText) { 38239 try { 38240 responseJson = JSON.parse(jqXHR.responseText); 38241 } catch (error) { 38242 // result should be json if its not well formed json or empty then ignoring it 38243 } 38244 } 38245 38246 var headers = jqXHR.getAllResponseHeaders(); 38247 38248 // Convert the header string into an array 38249 // of individual headers 38250 var arr = headers.trim().split(/[\r\n]+/); 38251 38252 // Create a map of header names to values 38253 var headerMap = {}; 38254 arr.forEach(function (line) { 38255 var parts = line.split(': '); 38256 var header = parts.shift(); 38257 var value = parts.join(': '); 38258 headerMap[header] = value; 38259 }); 38260 38261 if(this.customErrorHandler) { 38262 this.customErrorHandler.call(this, responseJson, headerMap); 38263 } 38264 } 38265 38266 // Counts the number of Array(repeatable) in the output JSON of the WSDL. 38267 var outputJsonRepeatCount = function (wsdlOutputId, outputJSONObj) { 38268 var count = 0, 38269 wsdlOutputHierarchy = wsdlOutputId.split("."); 38270 if (Array.isArray(outputJSONObj)) { 38271 count++; 38272 outputJSONObj = outputJSONObj[0]; 38273 } 38274 $.each(wsdlOutputHierarchy, function (depth) { 38275 if (outputJSONObj) { 38276 outputJSONObj = outputJSONObj[wsdlOutputHierarchy[depth]]; 38277 if (Array.isArray(outputJSONObj)) { 38278 count++; 38279 outputJSONObj = outputJSONObj[0]; 38280 } 38281 } 38282 }); 38283 return count; 38284 }; 38285 38286 //Traversing to the highest repeatable field in hierarchy as a starting point. 38287 var outputRepeatAncestor = function (targetNode, repeatCount, targetNameHierarchy) { 38288 while (repeatCount > 0) { 38289 if (_.isNull(targetNode.parent)) { 38290 return targetNode;
38291 } 38292 targetNameHierarchy.push(targetNode.name); 38293 targetNode = targetNode.parent; 38294 if (targetNode.repeatable) { 38295 repeatCount--; 38296 } 38297 } 38298 return targetNode; 38299 }; 38300 38301 /** 38302 * Extract value of a hierarchy of properties 38303 * from a nested javascript object. 38304 * @param {Object} obj Nested javascript object 38305 * @param {Array|String} props list of properties 38306 * or dot separated string from root to leaf object 38307 * @return {Array} return list of values found 38308 */ 38309 function extractValues(obj, props) { 38310 // handle easy cases 38311 if (obj === null || typeof(obj) === "undefined") { 38312 return []; 38313 } 38314 if (typeof(props) == "string") { 38315 props = props.split("."); 38316 } 38317 if (props.length == 0) { 38318 return [obj]; 38319 } 38320 var ret = []; 38321 if (obj instanceof Array) { 38322 for (var i = 0; i < obj.length; i++) { 38323 ret = ret.concat(extractValues(obj[i], props)); 38324 } 38325 return ret; 38326 } 38327 if (!obj.hasOwnProperty(props[0])) { 38328 return []; 38329 } 38330 // handle actual case now 38331 38332 var key = props[0]; 38333 var remainingKeys = props.slice(1); 38334 var values = obj[key]; 38335 if (!(values instanceof Array)) { 38336 values = [values]; 38337 } 38338 for (var x = 0; x < values.length; x++) { 38339 ret = ret.concat(extractValues(values[x], remainingKeys)); 38340 } 38341 return ret; 38342 } 38343 //Maps the output JSON(outputJSONObj) to the Model(targetNode) 38344 var outputJsonMapping = function (wsdlOutputId, targetNode, targetNameHierarchy, outputJSONObj) { 38345 if (targetNameHierarchy.length === 0) { 38346 targetNode.value = xfalib.ut.XfaUtil.prototype.getOrElse(outputJSONObj, wsdlOutputId, ""); 38347 return; 38348 } 38349 var targetName = targetNameHierarchy.pop(); 38350 if (targetNode.repeatable) { 38351 //Gets respective array for this repeatable field. 38352 while (typeof outputJSONObj === "object" && !Array.isArray(outputJSONObj)) { 38353 var argsIndex = wsdlOutputId.indexOf('.'); 38354 outputJSONObj = outputJSONObj[wsdlOutputId.substring(0, argsIndex)] || ""; 38355 wsdlOutputId = wsdlOutputId.substring(argsIndex + 1); 38356 } 38357 //Adjust the number of instances to the number of array elements. 38358 var jsonLength = outputJSONObj.length, 38359 instanceCount = targetNode.instanceManager.instanceCount; 38360 if (instanceCount < jsonLength) { 38361 targetNode.instanceManager.addInstances({ 38362 instanceCount : jsonLength 38363 }); 38364 } 38365 //Check as "" might occur too for incorrect mappings. 38366 if (Array.isArray(outputJSONObj)) { 38367 //Recursive call for every instance with corresponding value. 38368 $.each(outputJSONObj, function (index) { 38369 // if the output from external API call contains more records, than the number 38370 // of instances present, return 38371 if (index >= targetNode.instanceManager.instanceCount) { 38372 return false; 38373 } 38374 targetNode = targetNode.instanceManager.instances[index]; 38375 outputJsonMapping(wsdlOutputId, targetNode[targetName], targetNameHierarchy, outputJSONObj[index]); 38376 }); 38377 } 38378 } else { 38379 //Recursive call down the hierarchy. 38380 outputJsonMapping(wsdlOutputId, targetNode[targetName], targetNameHierarchy, outputJSONObj); 38381 } 38382 //Pushing back the hierarchy for next instance if any. 38383 targetNameHierarchy.push(targetName); 38384 }; 38385 38386 var populateWsdlOutput = function (wsdlOutput, textStatus, jqXHR) { 38387 if (wsdlOutput == null || wsdlOutput.length == 0) { 38388 return; 38389 } 38390 38391 var origOutputJSONObj, 38392 outputMappingObj = this.callbackData; 38393 try { 38394 origOutputJSONObj = JSON.parse(wsdlOutput); 38395 } catch (e) { 38396 //Handling primitive output 38397 origOutputJSONObj = {"response" : wsdlOutput}; 38398 } 38399 38400 /* For each entry in outputMappingObj, we need to find the corresponding value in responseObj. 38401 * wsdlOutputId - wsdlOutput hierarchy, targetNode - field in the form whose value is to be set. 38402 * e.g. {ipinfo.ip, txtfield} */ 38403 $.each(outputMappingObj, function (wsdlOutputId, targetNode) { 38404 /* Gets value in outputJSONObj corresponding to targetNode. 38405 * First, It counts the number of Array in hierarchy as repeatCount. 38406 * Next, targetNode is taken to the starting point for traversal. 38407 * It's the topmost repeatable node in hierarchy. 38408 * Lastly, The outputJson is mapped to the TargetNode.*/ 38409 var repeatCount = outputJsonRepeatCount(wsdlOutputId, origOutputJSONObj), 38410 targetNameHierarchy = [], 38411 targetNode = outputRepeatAncestor(targetNode, repeatCount, targetNameHierarchy); 38412 outputJsonMapping(wsdlOutputId, targetNode, targetNameHierarchy, origOutputJSONObj); 38413 }); 38414 window.guideBridge._guide.runPendingExpressions(); 38415 }; 38416 38417 /** 38418 * Create and set items to dropdown field from wsdl response. 38419 * @this {Object} is of form {callbackData:data} 38420 */ 38421 function setOptionsCallback(wsdlOutput) { 38422 var cbData = this.callbackData; 38423 var options = []; 38424 if (!_.isEmpty(wsdlOutput)) { 38425 var wsdlOutputObj = JSON.parse(wsdlOutput); 38426 var savedValues = extractValues(wsdlOutputObj, cbData.savedValue); 38427 var displayedValues = extractValues(wsdlOutputObj, cbData.displayedValue); 38428 for (var i = 0; i < savedValues.length; i++) {
38429 options.push(savedValues[i] + "=" + displayedValues[i]); 38430 } 38431 } 38432 cbData.field.items = options; 38433 } 38434 38435 function setValueCallback(wsdlOutput) { 38436 var cbData = this.callbackData; 38437 var wsdlOutputObj = JSON.parse(wsdlOutput); 38438 cbData.field.value = extractValues(wsdlOutputObj, cbData.value); 38439 } 38440 38441 function appendLoadingIcon() { 38442 $("#loadingPage").addClass("guideServiceLoading"); 38443 } 38444 38445 function removeLoadingIcon() { 38446 $("#loadingPage").removeClass("guideServiceLoading"); 38447 } 38448 38449 function executeOperationInternal (wsdlInfoObj, jsonInputMappingObj, jsonOutputMappingObj, processOutputCallback, customErrorHandler, model, defaultErrorHandler, apiVersion) { 38450 // populate operationDetails object 38451 var successHandler = processOutputCallback || populateWsdlOutput; 38452 var wsdlInputObj = {}; 38453 38454 /* Iterate through the jsonInputMapping and create the input object. 38455 * wsdlInputId - wsdlInput hierarchy, targetNode - field in the form whose value is to be retrieved.*/ 38456 $.each(jsonInputMappingObj, function (wsdlInputId, targetNode) { 38457 var argsHierarchy = wsdlInputId.split("."), 38458 wsdlArgObj = wsdlInputObj, 38459 argDepth, 38460 valueToBeAssigned; 38461 38462 for (argDepth = 0; argDepth < argsHierarchy.length - 1; argDepth++) { 38463 wsdlArgObj[argsHierarchy[argDepth]] = wsdlArgObj[argsHierarchy[argDepth]] || {}; 38464 wsdlArgObj = wsdlArgObj[argsHierarchy[argDepth]]; 38465 } 38466 // assign the value of targetNode 38467 if (typeof targetNode === "object") { 38468 valueToBeAssigned = targetNode.value; 38469 } else { 38470 valueToBeAssigned = targetNode; 38471 } 38472 wsdlArgObj[argsHierarchy[argDepth]] = valueToBeAssigned; 38473 }); 38474 38475 var wsdlEndPoint = wsdlInfoObj.wsdlEndPoint, 38476 operationDetails = {}; 38477 operationDetails.operationName = wsdlInfoObj.operationName; 38478 operationDetails.input = JSON.stringify(wsdlInputObj); 38479 operationDetails.port = wsdlInfoObj.port; 38480 operationDetails.soapActionURI = wsdlInfoObj.soapActionURI; 38481 operationDetails.namespace = wsdlInfoObj.namespace; 38482 operationDetails.inputRoot = wsdlInfoObj.inputRoot; 38483 operationDetails.inputAttr = JSON.stringify(wsdlInfoObj.inputAttr); 38484 operationDetails.serviceEndPoint = wsdlInfoObj.serviceEndPoint; 38485 if (!model) { 38486 console.log("No model parameter passed to this API, this may fail during server side re-validation. Please correct your scripts.") 38487 } 38488 // TODO: this needs to be fixed, this API does not have access to guideContext but would execute in context of AF always 38489 var guide = model && model._guide && model._guide(); 38490 var wsdlServletURL = ((guide ? guide.jcrPath : guidelib.__runtime__.guide.jcrPath) + ".af.dermis"); 38491 var externalizedWSDLServletURL; 38492 if (guideBridge != null) { 38493 externalizedWSDLServletURL = guideBridge._getUrl(wsdlServletURL); 38494 } else { 38495 externalizedWSDLServletURL = Granite.HTTP.externalize(wsdlServletURL); 38496 } 38497 38498 var invokeData = {}; 38499 if (wsdlInfoObj.wsdlEndPoint) { 38500 invokeData.functionToExecute = 'invokeWsdlOperation'; 38501 invokeData.wsdlEndPoint = wsdlEndPoint; 38502 invokeData.operationName = operationDetails.operationName; 38503 invokeData.input = operationDetails.input; 38504 38505 if (operationDetails.port) { 38506 invokeData.port = operationDetails.port; 38507 } 38508 if (operationDetails.soapActionURI) { 38509 invokeData.soapActionURI = operationDetails.soapActionURI; 38510 } 38511 if (operationDetails.namespace) { 38512 invokeData.namespace = operationDetails.namespace; 38513 } 38514 if (operationDetails.inputRoot) { 38515 invokeData.inputRoot = operationDetails.inputRoot; 38516 } 38517 if (operationDetails.inputAttr) {
38518 invokeData.inputAttr = operationDetails.inputAttr; 38519 } 38520 if (operationDetails.serviceEndPoint) { 38521 invokeData.serviceEndPoint = operationDetails.serviceEndPoint; 38522 } 38523 } else if (wsdlInfoObj.formDataModelId) { 38524 invokeData.functionToExecute = 'invokeFDMOperation'; 38525 invokeData.formDataModelId = wsdlInfoObj.formDataModelId; 38526 invokeData.input = JSON.stringify(wsdlInputObj); 38527 invokeData.operationName = wsdlInfoObj.operationName; 38528 invokeData.runValidation = wsdlInfoObj.runValidation; 38529 invokeData.apiVersion = apiVersion; 38530 } 38531 invokeData.guideNodePath = guide ? guide._currentContext.contextNode.jcrPath : guidelib.__runtime__.guide._currentContext.contextNode.jcrPath; 38532 38533 $.ajax({ 38534 type : 'POST', 38535 url : externalizedWSDLServletURL, 38536 data : invokeData, 38537 beforeSend : appendLoadingIcon, 38538 complete : removeLoadingIcon, 38539 dataType : 'text', 38540 success : successHandler, 38541 error : defaultErrorHandler, 38542 context : {callbackData : jsonOutputMappingObj, inputMapping: jsonInputMappingObj, customErrorHandler: customErrorHandler} 38543 }); 38544 } 38545 38546 var DataIntegrationUtils = guidelib.dataIntegrationUtils = { 38547 38548 setOptionsFromService : function (wsdlInfoObj, jsonInputMapping, jsonOutputMapping) { 38549 this.executeOperation(wsdlInfoObj, jsonInputMapping, jsonOutputMapping, setOptionsCallback); 38550 return jsonOutputMapping.field.items; 38551 }, 38552 38553 setValueFromService : function (wsdlInfoObj, jsonInputMapping, jsonOutputMapping) { 38554 this.executeOperation(wsdlInfoObj, jsonInputMapping, jsonOutputMapping, setValueCallback); 38555 return jsonOutputMapping.field.items; 38556 }, 38557 38558 /** 38559 * @deprecated 38560 */ 38561 executeOperation : function (wsdlInfoObj, jsonInputMappingObj, jsonOutputMappingObj, processOutputCallback, customErrorHandler, model) { 38562 var defaultErrorHandler = errorHandler; 38563 executeOperationInternal(wsdlInfoObj, jsonInputMappingObj, jsonOutputMappingObj, processOutputCallback, customErrorHandler, model, defaultErrorHandler); 38564 }, 38565 38566 executeOperationV2 : function (wsdlInfoObj, jsonInputMappingObj, jsonOutputMappingObj, processOutputCallback, customErrorHandler, model) { 38567 var defaultErrorHandler = defaultErrorHandlerWrapper; 38568 var apiVersion = "2"; 38569 executeOperationInternal(wsdlInfoObj, jsonInputMappingObj, jsonOutputMappingObj, processOutputCallback, customErrorHandler, model, defaultErrorHandler, apiVersion); 38570 }, 38571 38572 defaultErrorHandler : defaultErrorHandler 38573 }; 38574 38575 var WsdlUtils = guidelib.wsdlUtils = { 38576 /** 38577 * Internal API, called for invoking webservice and setting items in a drop down 38578 */ 38579 setOptionsFromWSDL : function (wsdlInfoObj, jsonInputMapping, jsonOutputMapping) { 38580 DataIntegrationUtils.executeOperation(wsdlInfoObj, jsonInputMapping, jsonOutputMapping, setOptionsCallback); 38581 return jsonOutputMapping.field.items; 38582 }, 38583 38584 setValueFromWSDL : function (wsdlInfoObj, jsonInputMapping, jsonOutputMapping) { 38585 DataIntegrationUtils.executeOperation(wsdlInfoObj, jsonInputMapping, jsonOutputMapping, setValueCallback); 38586 return jsonOutputMapping.field.items; 38587 }, 38588 38589 executeWSDLFunction : function (wsdlInfoObj, jsonInputMappingObj, jsonOutputMappingObj) { 38590 // populate operationDetails object 38591 DataIntegrationUtils.executeOperation(wsdlInfoObj, jsonInputMappingObj, jsonOutputMappingObj); 38592 } 38593 }; 38594}($, guidelib, xfalib, _)); 38595 38596/* 38597 * *********************************************************************** 38598 * ADOBE CONFIDENTIAL 38599 * __________________ 38600 * 38601 * Copyright 2015 Adobe Systems Incorporated 38602 * All Rights Reserved. 38603 *
38604 * NOTICE: All information contained herein is, and remains 38605 * the property of Adobe Systems Incorporated and its suppliers, 38606 * if any. The intellectual and technical concepts contained 38607 * herein are proprietary to Adobe Systems Incorporated and its 38608 * suppliers and may be covered by U.S. and Foreign Patents, 38609 * patents in process, and are protected by trade secret or copyright law. 38610 * Dissemination of this information or reproduction of this material 38611 * is strictly forbidden unless prior written permission is obtained 38612 * from Adobe Systems Incorporated. 38613 * *********************************************************************** 38614 */ 38615 38616/** 38617 * @package guidelib.model.GuideDirtyMarkerAndVisitor 38618 * @version 0.0.1 38619 */ 38620 38621(function ($, _, guidelib) { 38622 var GuideDirtyMarkerAndVisitor = guidelib.model.GuideDirtyMarkerAndVisitor = xfalib.ut.EventClass.extend({ 38623 38624 initialize : function() { 38625 // need to save the map while save and restore - will do it in getGuideState 38626 this.visitMap = {}; 38627 }, 38628 /** 38629 * Return a list of dirty children 38630 * @returns {Array} 38631 * @private 38632 */ 38633 _flattenDirtyPanelToList : function () { 38634 var csv = this.flattenDirtyPanelMapToCSV(); 38635 if (csv.length > 0) { 38636 return csv.split(","); 38637 } 38638 }, 38639 /** 38640 * If any dirty element then save it to CSV 38641 */ 38642 flattenDirtyPanelMapToCSV : function () { 38643 var listOfDirtyPanels = ""; 38644 _.each(_.keys(this.visitMap), function (key, index) { 38645 if (this.visitMap[key] === 0) { 38646 listOfDirtyPanels += key + ","; 38647 } 38648 }, this); 38649 if (listOfDirtyPanels.length > 0) { 38650 // strip last , 38651 listOfDirtyPanels = listOfDirtyPanels.substring(0, listOfDirtyPanels.length - 1); 38652 } 38653 return listOfDirtyPanels; 38654 }, 38655 /** 38656 * This method finds and marks dirty all the lazy children that were dependant of global field's value 38657 * @param mapOfLazyChildren 38658 * @param listOfIdsOfDependents 38659 * @private 38660 */ 38661 _findAndMarkDirty : function (mapOfLazyChildren, listOfIdsOfDependents) { 38662 var listOfLazyChildren = _.keys(mapOfLazyChildren); 38663 38664 _.each(listOfIdsOfDependents, function (depenId, index) { 38665 var longestPrefixLenSoFar = 0, 38666 currentPrefixLen = 0, 38667 nearestLazyId = null, 38668 i; 38669 // find hierarchically closest field by matching longest som prefix 38670 for (i = 0; i < listOfLazyChildren.length; ++i) { 38671 currentPrefixLen = guidelib.util.GuideUtil.commonPrefixLen(depenId, listOfLazyChildren[i]); 38672 if (longestPrefixLenSoFar < currentPrefixLen) { 38673 longestPrefixLenSoFar = currentPrefixLen; 38674 nearestLazyId = listOfLazyChildren[i]; 38675 } 38676 } 38677 // Mark dirty 38678 if (longestPrefixLenSoFar > 0) { 38679 mapOfLazyChildren[nearestLazyId] = 0; 38680 } 38681 }); 38682 }, 38683 /** 38684 * Iterates a map and finds the first occurrence of value found in any key 38685 * @param map 38686 * @param value 38687 */ 38688 _iterateMapAndReturnKeyOnValueFound : function (map, value) { 38689 var keyToReturn; 38690 _.each(_.keys(map), function (key, index) { 38691 if (map[key] === value) { 38692 keyToReturn = key; 38693 } 38694 }); 38695 return keyToReturn; 38696 }, 38697 /** 38698 * Updates the value of the key in map by one if present otherwise puts the key with value zero 38699 * @param map 38700 * @param key 38701 * @returns {*} 38702 */ 38703 _updateCountOrInsert : function (map, key) { 38704 if (_.isUndefined(map[key])) { 38705 map[key] = 0; 38706 } else { 38707 map[key]++; 38708 } 38709 38710 return map; 38711 } 38712 }); 38713 38714}($, _, window.guidelib)); 38715 38716/* 38717 * *********************************************************************** 38718 * ADOBE CONFIDENTIAL 38719 * __________________ 38720 * 38721 * Copyright 2016 Adobe Systems Incorporated 38722 * All Rights Reserved. 38723 *
38724 * NOTICE: All information contained herein is, and remains 38725 * the property of Adobe Systems Incorporated and its suppliers, 38726 * if any. The intellectual and technical concepts contained 38727 * herein are proprietary to Adobe Systems Incorporated and its 38728 * suppliers and may be covered by U.S. and Foreign Patents, 38729 * patents in process, and are protected by trade secret or copyright law. 38730 * Dissemination of this information or reproduction of this material 38731 * is strictly forbidden unless prior written permission is obtained 38732 * from Adobe Systems Incorporated. 38733 * *********************************************************************** 38734 */ 38735 38736(function ($) { 38737 //Firing resize as, CSS is loaded after table mobile layout, cell width is adjusted for repeatable row, to accommodate +, - controls 38738 $(function () { 38739 $(window).trigger('resize'); 38740 }); 38741}($)); 38742 38743/* 38744 * ADOBE CONFIDENTIAL 38745 * ___________________ 38746 * 38747 * Copyright 2014 Adobe Systems Incorporated 38748 * All Rights Reserved. 38749 * 38750 * NOTICE: All information contained herein
38750is, and remains 38751 * the property of Adobe Systems Incorporated and its suppliers, 38752 * if any. The intellectual and technical concepts contained 38753 * herein are proprietary to Adobe Systems Incorporated and its 38754 * suppliers and may be covered by U.S. and Foreign Patents, 38755 * patents in process, and are protected by trade secret or copyright law. 38756 * Dissemination of this information or reproduction of this material 38757 * is strictly forbidden unless prior written permission is obtained 38758 * from Adobe Systems Incorporated. 38759 * 38760 */ 38761(function ($, _) { 38762 window.FD = window.FD || {}; 38763 FD.FP = FD.FP || {}; 38764 38765 FD.FP.AF = { 38766 /*** 38767 * Saves the draft of adaptive forms 38768 @param options: {object} options can consist of following 38769 * <ul> 38770 * <li> isAutoSaveTriggered: {boolean} Indicates if the auto save is triggered or not </li> 38771 * <li> metadataToSave: {object} The meta data to save with draft </li> 38772 * <li> enableAnonymous: {boolean} indicating whether you want to have anonymous save or not.</li> 38773 * <li> success: {function} Handler executed in case when the draft is successfully saved</li> 38774 * <li> error: {function} Handler executed in case of draft failure</li> 38775 * <li> context {object} The context with which the success or error handler needs to be executed</li> 38776 * </ul> 38777 * @private 38778 */ 38779 _handleDraftSave: function (options) { 38780 var isAutoSaveTriggered = options.isAutoSaveTriggered, 38781 metadataToSave = options.metadataToSave, 38782 enableAnonymous = options.enableAnonymous, 38783 guidePath = window.guideBridge.getGuideContext().data[window.guideBridge.GUIDE_PATH], 38784 draftID = window.guideBridge.customContextProperty("draftID"), 38785 customContextProperty = xfalib.ut.Class.prototype.getOrElse(window.guidelib.runtime.guideContext.customPropertyMap,{}), 38786 errorObj, 38787 dataXML, 38788 node, 38789 fileAttachmentsList = [], 38790 fileAttachmentMap = {}; 38791 38792 $("#draftID").attr("value", draftID); 38793 var currentNodePath = $("#saveButtonPath").data("savebuttonpath") || guidePath, 38794 contextPath = window.guideBridge._getUrl(currentNodePath); 38795 var fileUploadPath = contextPath + ".fp.attach.jsp/" + draftID; 38796 // If custom uploader plugin is configured, then portal should not send fileUploadPath 38797 if (window.guideBridge && window.guideBridge.userConfig && window.guideBridge.userConfig.uploaderPluginName && window.guideBridge.userConfig.uploaderPluginName !== 'adobeFileUploader') { 38798 fileUploadPath = ''; 38799 } 38800 if(customContextProperty == null) { 38801 customContextProperty = {}; 38802 }; 38803 38804 var paramObj = { 38805 "success": function (result) { 38806 window.guideBridge.trigger( 38807 "saveStarted", 38808 window.guidelib.event.GuideModelEvent.createEvent("saveStarted") 38809 ); 38810 dataXML = result.data; 38811 //it can be json, fdm, xsd, xdp or nothing. 38812 var guide = guideBridge.resolveNode("guide[0].guide1[0]"); 38813 var schemaType = guide.getAttribute("schemaType"); 38814 //keep it default as xml 38815 var dataType = "XML"; 38816 if(!_.isUndefined(schemaType)) { 38817 if(schemaType == "jsonschema" || schemaType == "formdatamodel") { 38818 dataType = "JSON"; 38819 } else { 38820 dataType = "XML"; 38821 } 38822 } 38823 /* 38824 * file attachment map will be used for restoring the attachment for xml based adaptive forms 38825 * as this information is not available in dataXML,sending it seperately 38826 */ 38827 fileAttachmentMap = window.guideBridge.getFileAttachmentMap(); 38828 var urlForDraft = contextPath + ".fp.draft.json?func=saveDraft"; 38829 var data = { 38830 'formPath': guidePath, 38831 'formData': dataXML, 38832 'draftID': draftID, 38833 'formType': "af", 38834 '_charset_': "UTF-8", 38835 'enableAnonymousSave': enableAnonymous, 38836 'dataType': dataType, //dataType for defining the type of formdata for backward compatibility 38837 'fileAttachmentMap': JSON.stringify(fileAttachmentMap), 38838 'customContextProperty' : JSON.stringify(customContextProperty) 38839 }; 38840 if (metadataToSave) { 38841 for (var key in metadataToSave) { 38842 if (metadataToSave.hasOwnProperty(key)) { 38843 data[key] = metadataToSave[key]; 38844 } 38845 } 38846 } 38847 var allowedMetadata = []; 38848 for (key in data) { 38849 if (key !== 'formData') { 38850 allowedMetadata.push(key); 38851 } 38852 } 38853 data["fpAllowedMetadata"] = allowedMetadata.toString(); 38854 38855 $.ajax({ 38856 type: "POST", 38857 url: urlForDraft, 38858 async: true, 38859 cache: false, 38860 mimeType: "multipart/form-data", 38861 data: data, 38862 success: function (result) { 38863 if (!isAutoSaveTriggered) { 38864 alert(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings["draftSavedSuccessMessage"])); 38865 } 38866 window.guideBridge.trigger( 38867 "saveCompleted", 38868 window.guidelib.event.GuideModelEvent.createEvent("saveCompleted") 38869 ); 38870 if (!_.isUndefined(options.success)) { 38871 options.success.call(options.context || this); 38872 } 38873 }, 38874 error: function (result) { 38875 if (!isAutoSaveTriggered) { 38876 if (result.status == "503") { 38877 alert(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.LogMessages["AEM-AF-901-008"])); 38878 } else { 38879 alert(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.LogMessages["AEM-AF-901-009"])); 38880 } 38881 } 38882 if (!_.isUndefined(options.error)) { 38883 options.error.call(options.context || this); 38884 } 38885 } 38886 }); 38887 }, 38888 "error": function (result) { 38889 errorObj = result; 38890 if (errorObj != null) { 38891 console.log(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.LogMessages["AEM-AF-901-009"])); 38892 return 0; 38893 } 38894 }, 38895 "fileUploadPath": fileUploadPath 38896 }; 38897 window.guideBridge.getData(paramObj); 38898 }, 38899 38900 _handleDraftSaveWrapper: function (options) { 38901 var draftAndSubmissionRenderPath = $("#saveButtonPath").data("draftandsubmissionp
38901ortalnode") || '/content/forms/portal/draftandsubmission'; 38902 if (typeof window.guideBridge.customContextProperty("draftID") === "undefined" || window.guideBridge.customContextProperty("draftID") == null) { 38903 $.ajax({ 38904 method: "GET", 38905 url: Granite.HTTP.externalize(draftAndSubmissionRenderPath + ".fp.draft.json?func=getUid"), 38906 cache: false, 38907 dataType: "json" 38908 }).done(function (response) { 38909 var draftID = response.id; 38910 window.guideBridge.customContextProperty("draftID", draftID + "_af"); 38911 FD.FP.AF._handleDraftSave(options); 38912 }).fail(function (errorObj) { 38913 alert(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.LogMessages["AEM-AF-901-009"])); 38914 return 0; 38915 }); 38916 } else { 38917 FD.FP.AF._handleDraftSave(options); 38918 } 38919 } 38920 }; 38921 38922 /** 38923 * Save draft of the current adaptive form loaded 38924 * @param saveBtnConfig {object} Optional parameter for providing 38925 * @param options {object} Optional parameter options can consist of following - 38926 * <ul> 38927 * <li> success: {function} Handler executed in case when the draft is successfully saved</li> 38928 * <li> error: {function} Handler executed in case of draft failure</li> 38929 * <li> context {object} The context with which the success or error handler needs to be executed</li> 38930 * </ul> 38931 * 38932 */ 38933 // To maintain backward compatibility, keeping this function on window 38934 // This method will be used for click expression of save button 38935 // saveBtnConfig kept as it is for backward compatiablity metadata to the save button 38936 handleDraftSave = function (saveBtnConfig, options) { 38937 var metadataToSave = {}, enableAnonymous = false, fpMetadata = null, metadata = null; 38938 if (saveBtnConfig) { 38939 var metadataselector = saveBtnConfig.getAttribute('metadataselector'); 38940 if (metadataselector && metadataselector === 'local') { 38941 fpMetadata = saveBtnConfig.getAttribute("fpmetadata"); 38942 } else { 38943 var metaInfo = window.guideBridge.getGlobalMetaInfo(); 38944 fpMetadata = metaInfo && metaInfo.hasOwnProperty("metadata") ? metaInfo['metadata'] : null; 38945 } 38946 if (fpMetadata) { 38947 if (typeof fpMetadata === 'object') { 38948 for (var index in fpMetadata) { 38949 var currentMetadata = JSON.parse(fpMetadata[index]); 38950 metadataToSave[currentMetadata["key"]] = window.guideBridge._guide._compileExpression(currentMetadata["value"]).call(window.guideBridge._guide); 38951 } 38952 } else if (typeof fpMetadata === 'string') { 38953 var currentMetadata = JSON.parse(fpMetadata); 38954 metadataToSave[currentMetadata["key"]] = window.guideBridge._guide._compileExpression(currentMetadata["value"]).call(window.guideBridge._guide); 38955 } 38956 } 38957 if (saveBtnConfig.getAttribute("enableAnonymous")) { 38958 enableAnonymous = saveBtnConfig.getAttribute("enableAnonymous"); 38959 } 38960 } 38961 if (_.isUndefined(options)) { 38962 options = {} 38963 } 38964 options.metadataToSave = metadataToSave; 38965 options.enableAnonymous = enableAnonymous; 38966 options.isAutoSaveTriggered = false; 38967 window.FD.FP.AF._handleDraftSaveWrapper(options); 38968 } 38969})(jQuery, _); 38970 38971/************************************************************************* 38972 * 38973 * ADOBE CONFIDENTIAL 38974 * __________________ 38975 * 38976 * Copyright 2015 Adobe Systems Incorporated 38977 * All Rights Reserved. 38978 *
38979 * NOTICE: All information contained herein is, and remains 38980 * the property of Adobe Systems Incorporated and its suppliers, 38981 * if any. The intellectual and technical concepts contained 38982 * herein are proprietary to Adobe Systems Incorporated and its 38983 * suppliers and may be covered by U.S. and Foreign Patents, 38984 * patents in process, and are protected by trade secret or copyright law. 38985 * Dissemination of this information or reproduction of this material 38986 * is strictly forbidden unless prior written permission is obtained 38987 * from Adobe Systems Incorporated. 38988 **************************************************************************/ 38989 38990(function(){ 38991 window.FD = window.FD || {}; 38992 FD.FP = FD.FP || {}; 38993 FD.FP.SaveConfigChangeListener = function(field){ 38994 var dialog, hasClickExpChanged, clickExp; 38995 dialog = field instanceof CQ.Dialog ? field : field.findParentByType('dialog'); 38996 clickExp = dialog.getField('./clickExp'); 38997 hasClickExpChanged = dialog.getField('./hasClickExpChanged'); 38998 if(hasClickExpChanged){ 38999 var value = hasClickExpChanged.getValue(); 39000 var clickExpVal = clickExp.getValue(); 39001 if((!value || value != 'true') && (clickExpVal === "handleDraftSave()")){ 39002 clickExp.setValue('handleDraftSave(this)'); 39003 hasClickExpChanged.setValue('true'); 39004 } 39005 } 39006 } 39007})(); 39008
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.