PageSourceSearch

https://www.shannons.com.au/etc.clientlibs/fd/af/runtime/clientlib…-ac77e18c240595fcab0f12c717c41af6-lc.min.js

js shannons.com.au collected 2026-09-24 18:12:11 UTC 1,562,795 bytes, 38,655 lines download raw bytes

1/*
2 * ADOBE CONFIDENTIAL
3 *
4 * Copyright 2024 Adobe Systems Incorporated
5 * All Rights Reserved.
6 *
7 * NOTICE:  All information contained herein is, and remains
8 * the property of Adobe Systems Incorporated and its suppliers,
9 * if any.  The intellectual and technical concepts contained
10 * herein are proprietary to Adobe Systems Incorporated and its
11 * suppliers and may be covered by U.S. and Foreign Patents,
12 * patents in process, and are protected by trade secret or copyright law.
13 * Dissemination of this information or reproduction of this material
14 * is strictly forbidden unless prior written permission is obtained
15 * from Adobe Systems Incorporated.
16 *
17 */
18(function() {
19    "use strict";
20    window.af = window.af || {};
21
22    function waitForRumInitialization() {
23        return new Promise(function(resolve, reject){
24            var timeout = 10000; // 10 seconds
25            var startTime = Date.now();
26            function checkSampleRUM() {
27                // only execute forms runtime FT check if sampleRUM is defined via SITES FT
28                // adding check for forms specific feature toggle for RUM
29                if (window.hlx && window.hlx.sampleRUM) {
30                    resolve(window.hlx.sampleRUM);
31                } else if (Date.now() - startTime >= timeout) {
32                    // Reject the promise if the sampleRUM is not available within the timeout
33                    reject();
34                } else {
35                    // If the rum is not set, wait and check again
36                    setTimeout(checkSampleRUM, 50);
37                }
38            }
39            checkSampleRUM();
40        });
41    }
42    function initializeBridgeEvents(callback) {
43        var bridge;
44        var startTime = (new Date()).getTime();
45        // this is for AF v1
46        if (window.guideBridge !== undefined) {
47            bridge = window.guideBridge;
48            if ('_guide' in bridge && bridge._guide != null) {
49                callback(bridge, null, bridge._guide.jcrPath, startTime);
50            }
51        } else {
52            window.addEventListener("bridgeInitializeStart", function(event) {
53                bridge = event.detail.guideBridge;
54                // this is only for AF v1, since in v2 we wont know all AF's, instead we rely on "AF_FormContainerInitialized" event
55                if ('_guide' in bridge) {
56                    callback(bridge, null, null, startTime);
57                }
58            });
59        }
60        // this is for AF v2
61        document.addEventListener("AF_FormContainerInitialised", function(event) {
62            callback(bridge, event, null, startTime);
63        });
64    }
65
66    initializeBridgeEvents(function(bridge, e, _formContainerPath, startTime){
67        var containerState = {};
68        var CheckPoints = {
69            RENDER: "viewblock"
70        };
71
72        var formContainerPath = e ? e.detail.getPath() : _formContainerPath;
73        if (formContainerPath != null) {
74            containerState[formContainerPath] = {
75                submitted: false,
76                formPath: formContainerPath
77            };
78        }
79        bridge.connect(function() {
80            // special case for af v1
81            if (formContainerPath == null) {
82                formContainerPath = bridge._guide.jcrPath;
83                containerState[formContainerPath] = {
84                    submitted: false,
85                    formPath: formContainerPath
86                };
87            }
88
89             waitForRumInitialization().then(function(sampleRUM) {
90                 // form specific FT
91                if (window.FD && window.FD.isToggleEnabled("FT_FORMS-8965")) {
92                    var timeToFormInteractivity = ((new Date()).getTime() - startTime) / 1000;
93                    sampleRUM(CheckPoints.RENDER,
94                        {
95                            source: ".form",
96                            target: bridge._guide != null ? "foundation" : "core",
97                        }
98                    );
99                }
100            })
101            .catch(function() {
102                // Handle the rejection without logging any error
103            });
104        }, null, formContainerPath);
105    });
106
107
108    // Attach functions to the window namespace
109    window.af.waitForRumInitialization = waitForRumInitialization;
110
111})();
112
113/*
114 * ***********************************************************************
115 * ADOBE CONFIDENTIAL
116 * __________________
117 *
118 * Copyright 2015 Adobe Systems Incorporated
119 * All Rights Reserved.
120 *
121 * NOTICE:  All information contained herein is, and remains
122 * the property of Adobe Systems Incorporated and its suppliers,
123 * if any.  The intellectual and technical concepts contained
124 * herein are proprietary to Adobe Systems Incorporated and its
125 * suppliers and may be covered by U.S. and Foreign Patents,
126 * patents in process, and are protected by trade secret or copyright law.
127 * Dissemination of this information or reproduction of this material
128 * is strictly forbidden unless prior written permission is obtained
129 * from Adobe Systems Incorporated.
130 * ***********************************************************************
131 */
132
133(function ($) {
134    $.uaMatch = function( ua ) {
135        ua = ua.toLowerCase();
136        var match = /(chrome)[ \/]([\w.]+)/.exec( ua ) ||
137            /(webkit)[ \/]([\w.]+)/.exec( ua ) ||
138            /(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) ||
139            /(msie) ([\w.]+)/.exec( ua ) ||
140            ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) || [];
141        return {
142            browser: match[ 1 ] || "",
143            version: match[ 2 ] || "0"
144        };
145    };
146    // Not clobbering any existing $.browser
147    if ( !$.browser ) {
148        var
149            matched = $.uaMatch( navigator.userAgent ),
150            browser = {};
151        if ( matched.browser ) {
152            browser[ matched.browser ] = true;
153            browser.version = matched.version;
154        }
155        // Chrome is Webkit, but Webkit is also Safari.
156        if ( browser.chrome ) {
157            browser.webkit = true;
158        } else if ( browser.webkit ) {
159            browser.safari = true;
160        }
161        $.browser = browser;
162    }
163})($);
164/*************************************************************************
165 * ADOBE CONFIDENTIAL
166 * ___________________
167 *
168 *  Copyright 2013 Adobe Systems Incorporated
169 *  All Rights Reserved.
170 *
171 * NOTICE:  All information contained herein is, and remains
172 * the property of Adobe Systems Incorporated and its suppliers,
173 * if any.  The intellectual and technical concepts contained
174 * herein are proprietary to Adobe Systems Incorporated and its
175 * suppliers and are protected by all applicable intellectual property
176 * laws, including trade secret and copyright laws.
177 * Dissemination of this information or reproduction of this material
178 * is strictly forbidden unless prior written permission is obtained
179 * from Adobe Systems Incorporated.
180 **************************************************************************/
181
182
183/**
184 * @package xfalib.ut.Class
185 */
186(function(_, xfalib){
187
188    xfalib.ns = xfalib.ns || function (namespaceString) {
189        var parts = namespaceString.split('.'),
190            parent = window,
191            currentPart = '';
192
193        for(var i = 0, length = parts.length; i < length; i++) {
194            currentPart = parts[i];
195            parent[currentPart] = parent[currentPart] || {};
196            parent = parent[currentPart];
197        }
198
199        return parent;
200    };
201
202    var Class = xfalib.ut.Class = function(options) {
203        this.options = _.extend({}, this.options, options);
204        if(!this.options.jsonModel)
205            this.options.jsonModel = {};
206        //For perf reason, we are setting jsonModel as direct property instead of using property descriptor
207        this.jsonModel = this.options.jsonModel;
208        this.initialize.apply(this, arguments);
209    };
210
211    _.extend(Class.prototype, {
212        initialize : function(){
213        },
214
215        xfaUtil :function(){
216          return xfalib.ut.XfaUtil.prototype;
217        },
218
219        copyArray : function(src,dst,options) {
220            var keepReference = this.getOrElse(options, "keepReference", true);
221            if(src instanceof Array)
222            {
223                for (var i = 0;i<src.length;i++)
224                {
225                    var obj;
226                    if(src[i] instanceof Array)
227                    {
228                        obj = this._createDestination(dst, i, keepReference, []);
229                        this.copyArray(src[i],obj,options);
230                    }
231                    else if(typeof src[i] == "object")
232                    {
233                        obj = this._createDestination(dst, i, keepReference, {});
234                        this.copyObject(src[i],obj,options);
235                    } else {
236                        obj = src[i];
237                    }
238                    dst[i] = obj;
239                }
240                if(dst.length > src.length){
241                    dst.splice(src.length, (dst.length - src.length));  //Remove ths rest of the extra destination items
242                }
243            }
244        },
245
246        /**
247         *
248         * @param src
249         * @param dst
250         * @param options e.g. {keepReference: true, exceptions:["htmlId"], transformMaps: {"dataId", function(src, options){ return src "33"+src; }}}
251         */
252        copyObject : function(src,dst,options) {
253            var keepReference = this.getOrElse(options, "keepReference", true);
254            var exceptions = this.getOrElse(options, "exceptions", []);
255            var transformMaps = this.getOrElse(options, "transformMaps", {});
256            if(typeof src == "object") {
257                for (var child in src) {
258                    if(exceptions.indexOf(child) == -1) {
259                        if(src[child] instanceof Array) {
260                            dst[child] = this._createDestination(dst, child, keepReference, []);
261                            this.copyArray(src[child],dst[child],options);
262                        }
263                        else if(typeof src[child] == "object" && src[child] != null) {
264                            dst[child] = this._createDestination(dst, child, keepReference, {});
265                            this.copyObject(src[child],dst[child],options);
266                        }
267                        else{
268                            if(!_.isUndefined(transformMaps[child])){
269                                dst[child] = transformMaps[child](src[child], options, src);
270                            }
271                            else
272                                dst[child] = src[child];
273                        }
274                    }
275                }
276            }
277        },
278
279        _createDestination : function(obj, property, keepReference, defaultValue) {
280            if(!keepReference)
281                return defaultValue;
282            else if(_.isObject(obj) && !obj.hasOwnProperty(property))
283                return defaultValue;
284            else
285                return obj[property] || defaultValue ;  //Would handle both, Array and objects
286        },
287
288        /**
289         * will replace functions in the object with noop function based on a predicate function's result.
290         * If no predicate is passed all functions will be disabled.
291         * Warning once disabled object cant be re-enabled.
292         *
293         * sample predicate to disable all 'public' functions : function (funcName) { return funcName[0] != '_'}
294         *
295         * @param predicate
296         * @private
297         */
298        _disableFunctions: function (predicate) {
299            var noop = function () {},
300                disableAll = !_.isFunction(predicate);
301
302            _.each(_.functions(this), function (funcName) {
303                if (disableAll || predicate(funcName)) {
304                    this[funcName] = noop;
305                }
306            }, this);
307        },
308
309        /**
310         * getOrElse can take multiple arguments.
311         * arg1(obj): base Object
312         * arg2: string representing property chain where properties are concatenated via dot
313         * arg3: default value
314         **/
315
316        getOrElse : function(obj){
317            var currObject = obj;
318            if(arguments.length < 2)
319                return currObject;
320            else if(arguments.length == 2) {
321                if(!_.isUndefined(currObject)){
322                    return currObject;
323                } else {
324                    return _.clone(arguments[1]);
325                }
326            }
327            else {
328                var propChain = (arguments[1] || "").split(".");
329                var defaultValue = arguments[2];
330                _.each(propChain, function(prop){
331                    if(_.isObject(currObject))
332                        currObject = currObject[prop];
333                    else
334                        currObject = undefined;
335                }, this);
336
337                if(!_.isUndefined(currObject))
338                    return currObject;
339                else {
340                    return _.clone(defaultValue) ; //May have to do deep clone in future. TODO: support for conditional clone
341                }
342            }
343        },
344
345        jqId: function (id) {
346            return xfalib.ut.XfaUtil.prototype.jqId(id);
347        },
348
349        logger : function(){
350            return this.xfaUtil().getLogger();
351        },
352
353        validateInput : function(param, dataType,fallback){
354        	if(typeof param !== "undefined" && param !== null) {
355        		switch(dataType) {
356        		case "string":
357        			param = param+"";
358        			break;
359        		case "object":
360        			if(typeof param !== "object")
361        				param = fallback;
362        			break;
363        	    case "integer":
364                    param = parseInt(param);
365                    if(isNaN(param))
366                        param = fallback;
367                    break;
368               case "measurement":
369                     break;
370        		default:
371        			if(dataType instanceof Array) {
372                        if(!~dataType.indexOf(param))
373                            param = fallback
374                    }
375        		}
376        	}
377        	return param;
378        }
379
380    });
381
382    _.extend(Class, {
383        defineProps : function(propsMap){
384            _.each(propsMap, function(propDesc, propName){
385                //Check property can be resolved using resolveNode
386                if(propDesc.resolve) {
387                    //Check whether prototype owns the object resolveProperties
388                    if(!this.prototype.hasOwnProperty("resolveProperties")) {
389                        //check whether prototype inherits the object resolveProperties
390                        if(this.prototype.resolveProperties) {
391                            //clone the object since we do not want to modify parent's prototype
392                            this.prototype.resolveProperties = _.clone(this.prototype.resolveProperties);
393                        }
394                        else
395                            this.prototype.resolveProperties = [];
396                    }
397                    this.prototype.resolveProperties.push(propName)
398                }
399                Object.defineProperty(this.prototype, propName, propDesc);
400
401            }, this);
402        },
403        extend : function(props){
404            var child = inherits(this, props);
405            child.extend = this.extend;
406            return child;
407        },
408        addMixins : function(mixinBakers){
409            if(!_.isArray(mixinBakers)){
410                mixinBakers = [mixinBakers];
411            }
412            _.each(mixinBakers, function(mixinBaker){
413                if(mixinBaker.normalProperties){
414                    _.extend(this.prototype, mixinBaker.normalProperties);
415                }
416                if(mixinBaker.propertyDescriptors){
417                    this.defineProps(mixinBaker.propertyDescriptors);
418                }
419            }, this);
420        }
421    });
422
423    // Shared empty constructor function to aid in prototype-chain creation.
424    var ctor = function(){};
425
426    // Helper function to correctly set up the prototype chain, for subclasses.
427    // Similar to `goog.inherits`, but uses a hash of prototype properties and
428    // class properties to be extended.
429    function inherits(parent, protoProps, staticProps) {
430        var child;
431        var _super = parent.prototype;
432        // The constructor function for the new subclass is either defined by you
433        // (the "constructor" property in your `extend` definition), or defaulted
434        // by us to simply call the parent's constructor.
435        if (protoProps && protoProps.hasOwnProperty('constructor')) {
436            child = protoProps.constructor;
437        } else {
438            child = function(){ parent.apply(this, arguments); };
439        }
440
441        // Inherit class (static) properties from parent.
442        _.extend(child, parent);
443
444        // Set the prototype chain to inherit from `parent`, without calling
445        // `parent`'s constructor function.
446        ctor.prototype = parent.prototype;
447        child.prototype = new ctor();
448        child._super = parent.prototype;
449        child._superClass = parent;
450
451        // Add prototype properties (instance properties) to the subclass,
452        // if supplied.
453        if (protoProps) { //_.extend(child.prototype, protoProps);
454            // Copy the properties over onto the new prototype
455            for (var name in protoProps) {
456                if(name == "_defaults"){
457                    protoProps[name] = _.extend({}, _super[name], protoProps[name]);
458                }
459                child.prototype[name] = protoProps[name];
460            }
461        }
462
463
464        // Add static properties to the constructor function, if supplied.
465        if (staticProps) _.extend(child, staticProps);
466
467        // Correctly set child's `prototype.constructor`.
468        child.prototype.constructor = child;
469
470        // Set a convenience property in case the parent's prototype is needed later.
471        child.__super__ = parent.prototype;
472
473        return child;
474    };
475})(_, window.xfalib);
476/**
477 * Created by vdua on 2/18/2015.
478 */
479(function (_, xfalib) {
480    var XMLUtils = {
481        dataSom2xpath: function (dataSom) {
482            var xpath = "";
483
484            if (!_.isEmpty(dataSom)) {
485                // any dot preceded by ], takes care of dot-s in name,
486                // and remove constant prefix "xfa[0].datasets[0].data[0]" and form root name, then join using '/'
487                _.each(dataSom.split(/\]\./).slice(4),
488                    function (part) {
489                        var openBracketPos = part.lastIndexOf('[');
490                        xpath += part.substring(0, openBracketPos + 1) +
491                            (parseInt(part.substring(openBracketPos + 1)) + 1) + // increment index by 1 for xpath query
492                            "]/";
493                    });
494
495                if (_.isEmpty(xpath)) {
496                    xpath = dataSom;
497                } else if (xpath[xpath.length - 1] === '/') {
498                    xpath = xpath.slice(0, -1);
499                }
500            }
501
502            return xpath;
503        },
504
505        /**
506         * Converts an xPathResult of type iterator to an array
507         * @param xPathResult
508         * @returns {Array}
509         */
510        iteratorToArray: function (xPathResult) {
511            var result = [];
512            // in some browsers, if xpath is invalid xPath result is null whereas some browsers return XpathResult with empty iterator
513            var node = xPathResult ? xPathResult.iterateNext() : null;
514            while (node != null) {
515                result.push(node);
516                node = xPathResult.iterateNext();
517            }
518            return result;
519        },
520        /**
521         * Wrapper API for document.evaluate to provide cross-browser support.
522         * @param xpath
523         * @param node
524         * @param nsResolver
525         * @param resultType
526         * @param result
527         * @returns {Object|*}
528         */
529        evaluateXPath: function (xpath, node, nsResolver, resultType, result) {
530            try {
531                if(_.isEmpty(xpath) || !_.isString(xpath) || !(node instanceof Node)) {
532                    return null;
533                }
534
535                // Determine the appropriate document context for searching.
536                var searchContext = node instanceof Document ? node : node.ownerDocument;
537                // Check if the document.evaluate function is undefined or if we're in a server-side context.
538                var isEvaluateUndefined = typeof searchContext.evaluate === 'undefined';
539                var isServerSide = window.guideBridge && window.guideBridge.hostName === "server";
540                var needsXPathPolyfill = isEvaluateUndefined || isServerSide;
541                if (needsXPathPolyfill) {
542                    // Install the wgxpath polyfill to provide evaluate functionality.
543                    wgxpath.install(window, true);
544                    // Assign the newly installed evaluate function to the search context.
545                    searchContext.evaluate = window.document.evaluate;
546                }
547
548                var documentToEval = searchContext.evaluate ? searchContext : document;
549                xpath = this.sanitizeXPath(xpath);
550
551                return documentToEval.evaluate(xpath, node, nsResolver, resultType, result);
552
553            } catch (exception) {
554                xfalib.ut.XfaUtil.prototype.getLogger().error("Could not evaluate xpath: " + xpath  + exception);
555
556            }
557
558        },
559         /**
560         *Removes all [*] other than ['numeric'] from xpath
561         *@param xpath
562         *@returns xpath after removing "[*]"
563         */
564         sanitizeXPath: function(xpath) {
565             var xpathArray=xpath.split("/"),
566                 resultXpath = _.map(xpathArray, function (path) {
567                 return path.replace(/\[(.*\D+.*)\]|\[\]/g,"");
568             }).join("/");
569             return resultXpath;
570         },
571
572        /**
573         * Creates all the Elements (if they don't exist) in the xpath leading to the node being searched for in the
574         * xpath relative to the element. Optionally creates the node as well if bParentsOnly is false
575         * @param xpath
576         * @param element
577         * @param bParentsOnly whether to create only the parents or the node as well
578         * @returns node that is being represented by the xpath relative to the element.
579         */
580        createElementsFromXPath: function (xpath, element, bParentsOnly) {
581            if (xpath != null || element != null) {
582                var parts = xpath.split("/"),
583                    actualParts = bParentsOnly ? _.initial(parts) : parts,
584                    el = element;
585                _.each(actualParts, function (part, index) {
586                    var som = part.match(/^([^[]+)(\[(\d+)\])?/),
587                        childEl;
588                    if (som == null) {
589                        xfalib.ut.XfaUtil.prototype.getLogger().error("Unsupported expression in Bindref " + part);
590                        return null;
591                    }
592                    //only the last element can be attribute
593                    childEl = this.findOrCreateElement(part, el, index === actualParts.length - 1);
594                    el = childEl;
595                }, this);
596                return el;
597            }
598            return null;
599        },
600
601        /**
602         * Form an xpath part returns the index as well as the tagName. Index can be * as well
603         * @param xpathName
604         * @returns {*}
605         * @private
606         */
607        _getElementNameAndIndexFromXPathPart: function (xpathName) {
608            var som  =  xpathName.match(/^([^[]+)(?:\[(\d+|\*)\])?/);
609            if (som !== null) {
610                return {
611                    name: som[1],
612                    index: som[2] || 0
613                };
614            }
615            return null;
616        },
617
618        /**
619         * create an element with the tagName elementName for the ownerDocument of element.
620         * @param elementName
621         * @param element
622         * @returns {HTMLElement}
623         */
624        createElement: function (elementName, element) {
625            var el = element.ownerDocument.createElement(elementName);
626            return el;
627        },
628
629        /**
630         * Searches for the nodeXpath relative to element. If it doesn't exists creates it and returns the node
631         * @param element
632         * @param nodeXpath
633         * @param bAttribute if true then check for attribute otherwise not.
634         * @returns {Node|*}
635         */
636        findOrCreateElement: function (nodeXpath, element, bAttribute) {
637            try {
638                if (element == null) {
639                    return null;
640                }
641                var result = this.evaluateXPath(nodeXpath, element, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null),
642                    el = result.iterateNext(),
643                    res;
644                if (el == null) {
645                    res = this._getElementNameAndIndexFromXPathPart(nodeXpath);
646                    if (res != null) {
647                        if (bAttribute && res.name.match(/^@/)) {
648                            var attrName = res.name.replace(/^@/, "");
649                            el = element.ownerDocument.createAttribute(attrName);
650                            element.setAttributeNode(el);
651                        } else {
652                            el = element.ownerDocument.createElement(res.name);
653                            element.appendChild(el);
654                        }
655                    }
656                }
657                return el;
658
659            } catch (exception) {
660                xfalib.ut.XfaUtil.prototype.getLogger().error("Following exception "
661                    +  "occurred while executing findOrCreateElement " + exception);
662            }
663
664        },
665
666        /**
667         * Returns the Root Form Elment from the xmlDocumentElement
668         * @param xmlDocumentElement It can be a document or Element. If the root element is xdp element, it returns
669         *        the grand grand child of that element. otherwise the root element is returned. The root
670         *        Element can be either the element itself or documentElement of the element.
671         */
672        getXFARootFormElementFromXML: function (xmlDocumentElement) {
673            if(_.isUndefined(document.evaluate)) {
674                wgxpath.install();
675            }
676            var isElement = xmlDocumentElement instanceof Element,
677                docElemName = isElement ? xmlDocumentElement.nodeName : xmlDocumentElement.documentElement.nodeName,
678                rootElement = isElement ? xmlDocumentElement : xmlDocumentElement.documentElement,
679                nodeList;
680
681            if ("xdp:xdp" === docElemName || "xdp" === docElemName) {
682                if (xfalib.ut.XfaUtil.prototype.isIE()) {
683                    //IE doesn't support evaluating namespace elements
684                    var datasets = rootElement.firstElementChild,
685                        data = datasets.firstElementChild;
686                    rootElement = data.firstElementChild;
687                } else {
688                    // assumption is that the xml will be of format <xdp><datasets><data><form1>
689                    // TODO: change first * to xfa:datasets
690                    nodeList = this.evaluateXPath("*/xfa:data/*", rootElement, formBridge.nsResolver,
691                                            XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
692                    rootElement = nodeList.iterateNext();
693                }
694            }
695            return rootElement;
696        },
697
698        /**
699         * Returns an object containing the prefix and namespaces present in the rootElement. For default namespace the
700         * prefix is "_default"
701         * @param rootElement {Element} xml element which has to be looked for namespaces
702         * @returns {object} object whose keys are the prefix and values are the namespace
703         */
704        getNamespaces: function (rootElement) {
705            var namespaces = {
706                "_default" : null
707            };
708            _.each(rootElement.attributes, function (attr) {
709                var name = attr.name,
710                    parsedAttrName = name.match(/^xmlns(?:\:(.*))?/),
711                    isNamespace = parsedAttrName != null,
712                    namespaceName = isNamespace ? parsedAttrName[1] || "_default" : null;
713                if (namespaceName) {
714                    namespaces[namespaceName] = attr.value;
715                }
716            });
717            return namespaces;
718        },
719
720        /**
721         * Returns a namespace resolver given a element. The nsResolver returns the namespace given a prefix by
722         * using the namespaces mentioned in the element.
723         * @param rootElement element from which to create the nsResolver
724         * @returns {function} the function returns the namespace given a prefix.
725         */
726        getNsResolver: function (rootElement) {
727            var namespaces = this.getNamespaces(rootElement),
728                nsResolver = (function (namespaces) {
729                    return function (nsPrefix) {
730                        var namespace = formBridge.nsResolver(nsPrefix) || namespaces[nsPrefix];
731                        return namespace;
732                    };
733                }(namespaces));
734            return nsResolver;
735        },
736
737        /**
738         * Removes default namespaces from xml, basically the namespace defined as xmlns="some namespace". The
739         * side-effect of the API is it removes the string "xmlns='some namespace'" from any attribute value as well.
740         * @param xml {string}
741         * @returns {string}
742         */
743        removeDefaultNamespace: function (xml) {
744            var stringRegex = "(\\s+)" + // any number of spaces
745                             "(xmlns=" + // then xmlns=
746                            "('[^']*'|\"[^\"]*\"))" + // then value in single quotes ('[^']') or
747                                                    //                 double quotes ("[^"]")
748                            "(?=[^<>]*>)",  // followed by closing tag (implies attribute) and before another
749                                           // opening tag(implies text)
750                regex = new RegExp(stringRegex, "g");
751            return xml.replace(regex, "$1");
752        }
753    };
754    xfalib.ut.XMLUtils = XMLUtils;
755}(_, xfalib));
756/**
757 * @package xfalib.ut.Logger
758 * @import xfalib.ut.Class
759 */
760
761(function(_, xfalib, $){
762    var categoryAcronyms = {
763                            "a": "xfa",
764                            "b": "xfaView",
765                            "c": "xfaPerf"
766        },
767        loggerTypes = ["off", "console", "server", "consoleServer"];
768    var Logger = xfalib.ut.Logger = xfalib.ut.Class.extend({
769
770//      Count of log messages so far.
771        LOG_COUNT : {
772            level : {
773                "FATAL" : 0,
774                "ERROR" : 0,
775                "WARN" : 0,
776                "INFO" : 0,
777                "DEBUG" : 0,
778                "TRACE" : 0,
779                "ALL" : 0
780            },
781            category : {
782                "xfa" : 0,
783                "xfaView" : 0,
784                "xfaPerf" : 0,
785                "Unknown" : 0
786           }
787        },
788
789        /**
790         * Log level to turn logging off (default).
791         * @static
792         * @final
793         * @type Number
794         */
795        OFF : 0,
796
797        /**
798         * Log level for fatal error messages.
799         * @static
800         * @final
801         * @type Number
802         */
803        FATAL : 1,
804
805        /**
806         * Log level for error messages.
807         * @static
808         * @type Number
809         * @final
810         */
811        ERROR : 2,
812
813        /**
814         * Log level for warning messages.
815         * @static
816         * @type Number
817         * @final
818         */
819        WARN : 3,
820
821        /**
822         * Log level for info messages.
823         * @static
824         * @type Number
825         * @final
826         */
827        INFO : 4,
828
829        /**
830         * Log level for debug messages.
831         * @static
832         * @type Number
833         * @final
834         */
835        DEBUG : 5,
836
837        /**
838         * Log level for trace messages.
839         * @static
840         * @type Number
841         * @final
842         */
843        TRACE : 6,
844
845        /**
846         * Log level for all messages.
847         * @static
848         * @type Number
849         * @final
850         */
851        ALL : 7,
852
853
854        logLevelNames : ["OFF", "FATAL", "ERROR", "WARN", "INFO", "DEBUG", "TRACE", "ALL"],
855
856        initialize : function(){
857            var str = "",
858                that =this;
859            Logger._super.initialize.call(this);
860            this.logs = {};
861            this.logMessages = "";
862            this.logServiceProxy = this.options.logServiceProxy;
863            this.contextPath = this.options.contextPath;
864            this.renderContext =  this.options.renderContext;
865            if(this.jsonModel.logConfigString) {
866                _.extend(this.jsonModel, this.parse(this.jsonModel.logConfigString));
867            }
868            _.each(this.jsonModel.category, function(category) {
869                that.LOG_COUNT.category[category] = 0;
870            })
871        },
872
873        /**
874         * parses a log config string of the form <0,1,2,3>-<category string><level integer>-<category string><level integer>..
875         * and returns an a config object that logger uses. The function is a private and not to be called outside
876         * this function
877         *
878         * category can not contain numbers and only valid characters are a-zA-Z
879         * level can be any integer.
880         *
881         * category string is converted into actual category for the logger by using default categoryAcronyms
882         * [a : xfa, b: xfaView, c: xfaPerf} and the categoryAcronyms passed to the options while instantiating the
883         * object. If not found in both the acronyms then the value category string is used as actual category
884         *
885         * For example for the input string 1-a9-b9-c9 return object is
886         * {on: true, category: [xfa,xfaView, xfaPerf], level: [9, 9, 9], type: console}
887         *
888         * For the input string 1-a9-b9-c9-d9-e11 with options.categoryAcronyms {a:a, d:AF} return object is
889         * {on: true, category: [xfa,xfaView, xfaPerf, AF, e], level: [9, 9, 9, 9, 11], type: console}
890         */
891        parse : function(configString) {
892            var arr = configString.split("-"),
893                logType = _.first(arr),
894                logConfig = _.rest(arr),
895                res = {
896                    on: logType === "0" ? "false": "true",
897                    category: [],
898                    level:[],
899                    type:loggerTypes[parseInt(logType)]
900                };
901           _.each(logConfig, function(item, index) {
902                var config = item.match(/^([A-Za-z]+)(\d+)$/),
903                    category;
904                if (config && config.length === 3) {
905                    category = this.getOrElse(categoryAcronyms, config[1],
906                                    this.getOrElse(this.jsonModel, "categoryAcronyms." + config[1], config[1]));
907                    res.category.push(category);
908                    res.level.push(parseInt(config[2]));
909                } else {
910                    //calling this because logger is not initialized as of now
911                    this.consoleHandler(this.resolveMessage(xfalib.locale.LogMessages["ALC-FRM-901-020"],
912                                                    [item, configString]))
913                }
914            }, this);
915            return res;
916        },
917
918        /*
919         *
920         */
921        resolveMessage : function(message, snippets) {
922            snippets = snippets || [];
923            return message.replace(/{(\d+)}/g, function(match, number) {
924                return typeof snippets[number] != 'undefined'
925                    ? snippets[number]
926                    : match
927                    ;
928            });
929        },
930
931        /**
932         * Writes a message to the console.
933         * @private
934         * @param {Number} level The log level
935         * @param {String} message The log message
936         * @param {String/String[]} snippets (optional) The texts replacing
937         *        <code>{n}</code>
938         * @return The log message
939         * @type String
940         */
941        log : function(category, level, message, snippets) {
942            var d= new Date();
943            var day = d.getDate();
944            var month = d.getMonth() + 1;
945            var year = d.getFullYear();
946            var mili = d.getMilliseconds();
947            var sec = d.getSeconds();
948            var min = d.getMinutes();
949            var hour = d.getHours();
950            var date = day + "." + month + "." + year +" " + hour + ":" + min + ":" + sec + ":" + mili;
951            if(this.jsonModel && this.jsonModel.category) {
952                for(var i = 0; i<this.jsonModel.category.length; i++) {
953                    if (level != 0 && this.jsonModel.level[i] >= level && this.jsonModel.category[i] == category && this.jsonModel.on == "true") {
954
955                        var resolvedMessage = message;
956                        if(snippets){
957                            //resolve message with snippet
958                            resolvedMessage = this.resolveMessage(message, snippets);
959                        }
960
961                        var text = "";
962                        text += date ;
963                        text += " *" + this.logLevelNames[level] + "*";
964                        text += " [" +  category + "]" ;
965                        text += "  " + resolvedMessage + "\r\n" ;
966                        this.logMessages += text ;
967                        if(this.jsonModel.type == "console" || this.jsonModel.type == "consoleServer" ) {
968                            ++this.LOG_COUNT.category[category || 'Unknown'];
969                            ++this.LOG_COUNT.level[this.logLevelNames[parseInt(level) < 8? level:7]];
970                            this.consoleHandler(text, level);
971                        }
972                    }
973                }
974            }
975        },
976
977        consoleHandler : function(text, level){
978            if(typeof console != "undefined") {
979                var levelName = typeof this.logLevelNames[level] === "string"
980                    ? this.logLevelNames[level].toLowerCase()
981                    : "log",
982                    logFunction = console.log;
983                if (typeof console[levelName] === "function") {
984                    logFunction = console[levelName]
985                }
986                logFunction.call(console, "\n\n\n" + text);
987                //Error log already shows the call stack for debugging.
988                if(levelName !== "error") {
989                    try {
990                        n.test
991                    } catch (exception) {
992                        if (exception.stack) {
993                            logFunction.call(console, exception.stack.replace("ReferenceError: n is not defined", ""));
994                        }
995                    }
996                }
997            }
998
999        },
1000
1001        /*
1002         *  Helper function to ger submit service proxy url
1003         */
1004        _getLogServiceProxyUrl: function() {
1005            var logServiceProxyUrl = "";
1006            if(this.logServiceProxy)
1007                logServiceProxyUrl += this.logServiceProxy;
1008            else //finally hard code it
1009                logServiceProxyUrl += ((this.contextPath && this.contextPath != "/") ? this.contextPath : "") + "/libs/xfaforms/profiles/default.log.html";
1010            return logServiceProxyUrl;
1011        },
1012
1013        _invokeAtServer: function(options) {
1014            var localSubmitUrl =  this._getLogServiceProxyUrl();
1015            var params = {
1016                    async: true,
1017                    url: localSubmitUrl,
1018                    type: 'POST',
1019                    contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
1020                    data: options
1021                };
1022            $.ajax(params);
1023        },
1024
1025        isServerLoggingEnabled : function(){
1026            if((this.jsonModel.on == "true") && (this.jsonModel.type == "server" || this.jsonModel.type == "consoleServer"))
1027                return true;
1028            else
1029                return false;
1030        },
1031
1032        serverHandler :function() {
1033            var options = {'logMessages' : this.logMessages, 'renderContext' : this.renderContext};
1034            this._invokeAtServer(options);
1035            this.logMessages = "" ;
1036        },
1037
1038        /**
1039         * Writes a message to the console if log level is set to
1040         * {@link #FATAL} or higher.
1041         * @static
1042         * @param {String} message The log message
1043         * @param {String/String[]} snippets (optional) The texts replacing
1044         *        <code>{n}</code>
1045         */
1046        fatal : function(category, message, snippets) {
1047            this.log(category, this.FATAL, message, snippets);
1048        },
1049
1050        /**
1051         * Writes a message to the console if log level is set to
1052         * {@link #ERROR} or higher.
1053         * @static
1054         * @param {String} message The log message
1055         * @param {String/String[]} snippets (optional) The texts replacing
1056         *        <code>{n}</code>
1057         */
1058        error : function(category, message, snippets) {
1059            this.log(category, this.ERROR, message, snippets);
1060        },
1061
1062        /**
1063         * Writes a message to the console if log level is set to
1064         * {@link #WARN} or higher.
1065         * @static
1066         * @param {String} message The log message
1067         * @param {String/String[]} snippets (optional) The texts replacing
1068         *        <code>{n}</code>
1069         */
1070        warn : function(category, message, snippets) {
1071            this.log(category, this.WARN, message, snippets);
1072        },
1073
1074        /**
1075         * Writes a message to the console if log level is set to
1076         * {@link #INFO} or higher.
1077         * @static
1078         * @param {String} message The log message
1079         * @param {String/String[]} snippets (optional) The texts replacing
1080         *        <code>{n}</code>
1081         */
1082        info : function(category, message, snippets) {
1083            this.log(category, this.INFO, message, snippets);
1084        },
1085
1086        /**
1087         * Writes a message to the console if log level is set to
1088         * {@link #DEBUG} or higher.
1089         * @static
1090         * @param {String} message The log message
1091         * @param {String/String[]} snippets (optional) The texts replacing
1092         *        <code>{n}</code>
1093         */
1094        debug : function(category, message, snippets) {
1095            this.log(category, this.DEBUG, message, snippets);
1096        },
1097
1098        /**
1099         * Writes a message to the console if log level is set to
1100         * {@link #TRACE} or higher.
1101         * @static
1102         * @param {String} message The log message
1103         * @param {String/String[]} snippets (optional) The texts replacing
1104         *        <code>{n}</code>
1105         */
1106        trace :  function(category, message, snippets) {
1107            this.log(category, this.TRACE, message, snippets);
1108        },
1109
1110        isLogEnabled : function(category, level) {
1111            if(this.jsonModel.on == "true") {
1112                var pos = this.jsonModel.category.indexOf(category) ;
1113                if(this.jsonModel.level[pos] >= level)
1114                    return true;
1115            }
1116            return false;
1117        }
1118
1119    });
1120})(_, xfalib, $);
1121/**
1122 * @package xfalib.ut.EventClass
1123 * @import xfalib.ut.Class
1124 */
1125(function(_, xfalib){
1126    // Regular expression used to split event strings
1127    // Regular expression used to split event strings
1128    var eventSplitter = /\s+/;
1129
1130    // A module that can be mixed in to *any object* in order to provide it with
1131    // custom events. You may bind with `on` or remove with `off` callback functions
1132    // to an event; trigger`-ing an event fires all callbacks in succession.
1133    //
1134    var EventClass = xfalib.ut.EventClass =  xfalib.ut.Class.extend({
1135
1136        // Bind one or more space separated events, `events`, to a `listener`
1137        // object. The object should implement `handleEvent` function which will be
1138        // called on event dispatch
1139        on: function(event, listener, context) {
1140
1141            var calls, list,retVal = true;
1142            var fnCallback = _.isFunction(listener) ? listener : null;
1143            if (!listener || (!listener["handleEvent"] && !fnCallback)) return false;
1144
1145            calls = this._callbacks || (this._callbacks = {});
1146
1147            list = calls[event] || (calls[event] = []);
1148            if(fnCallback){
1149                context = context || this;
1150                var found = _.find(list, function(callback){
1151                    return (callback.fn == fnCallback && callback.context == context);
1152                }, this);
1153                if(found)
1154                    return false;
1155                else {
1156                    list.push({"fn" : fnCallback, "context": context});
1157                }
1158            }
1159            else{
1160                if(~list.indexOf(listener))
1161                    return false;
1162                else
1163                    list.push(listener);
1164            }
1165
1166            return  true;
1167        },
1168
1169        // Remove one or many callbacks. If `listener` is null, removes all listener for the
1170        // event. If `events` is null, removes all bound callbacks for all events.
1171        off: function(events, listener, context) {
1172            var event, calls, node;
1173
1174            // No events, or removing *all* events.
1175            if (!(calls = this._callbacks)) return;
1176            if (!(events || listener)) {
1177                delete this._callbacks;
1178                return this;
1179            }
1180
1181            var fnCallback = _.isFunction(listener) ? listener : null;
1182            // Loop through the listed events and contexts and remove the required ones.
1183            events = events ? events.split(eventSplitter) : _.keys(calls);
1184            while (event = events.shift()) {
1185                node = calls[event];
1186                calls[event] = _.filter(calls[event],function(elem) {
1187                    if(typeof(listener) !== "undefined"){
1188                        if(fnCallback && elem.fn == fnCallback && elem.context == context)
1189                            return false;
1190                        else if(!fnCallback && listener === elem)
1191                            return false;
1192                    }
1193                    else{
1194                        return false;
1195                    }
1196                    return true;
1197                });
1198                if(!calls[event].length)
1199                    delete calls[event];
1200            }
1201
1202            return this;
1203        },
1204
1205        // Trigger one or many events, firing all bound callbacks. Callbacks are
1206        // passed the same arguments as `trigger` except the first
1207        trigger: function(events) {
1208            var event, calls, rest;
1209            if (!(calls = this._callbacks)) return this;
1210            events = events.split(eventSplitter);
1211            var payLoad = _.rest(arguments);
1212            while (event = events.shift()) {
1213                _.each(calls[event],function(callback) {
1214                    if(callback.fn && callback.context){
1215                        callback.fn.apply(callback.context, payLoad);
1216                    }
1217                    else if (_.isFunction(callback.handleEvent)){
1218                        callback.handleEvent.apply(callback, payLoad);
1219                    }
1220                });
1221            }
1222
1223            return this;
1224        }
1225
1226    });
1227
1228
1229})(_, xfalib);
1230
1231
1232(function (_, $, xfalib) {
1233    var XfaUtil = xfalib.ut.XfaUtil = function () {
1234        },
1235        registeredLocaleProperties = null,
1236        timeoutListenerAttached = false,
1237        timeouts = [],
1238        attachClearTimeoutListener = function (timeout) {
1239            timeouts.push(timeout);
1240            if (timeoutListenerAttached === false) {
1241                $(window).one("destroy.xfa", function () {
1242                    _.each(timeouts, function (_timeout) {
1243                        clearTimeout(_timeout);
1244                    });
1245                    timeouts = [];
1246                    timeoutListenerAttached = false;
1247                });
1248                timeoutListenerAttached = true;
1249            }
1250        };
1251    _.extend(XfaUtil.prototype, {
1252        _globalUniqueId: (new Date()).getTime(),
1253        logger: null,
1254
1255        formScaleFactor: 1,      // used to appropriately scale the form when contained inside an iframe
1256
1257        getOrElse: xfalib.ut.Class.prototype.getOrElse,
1258        //map of event names between XTG and Mobile Form
1259        //Mobile Form uses different names for some the event and let's fix those names before sending them to XTG.
1260        _xtgEventName: {
1261            "$formready": "ready",
1262            "$layoutready": "ready"
1263        },
1264
1265        generateUID: function () {
1266            return "UID" + (++XfaUtil.prototype._globalUniqueId);
1267        },
1268
1269        matchJsonType: function (jsonModel, _class) {   //TODO: handle getOrElse
1270            return (jsonModel && _class && XfaUtil.prototype.getOrElse(jsonModel._class, "").toLowerCase() == ("" + _class).toLowerCase());
1271        },
1272
1273        $data: function (elem, name, data) {
1274            if (!$.data(elem, "_xfaInitialized")) {
1275                //Initialized data- attributes parse for once using this call.
1276                // Next onward don't use this. Instead use $.data which is cheap/
1277                $(elem).data();
1278                $.data(elem, "_xfaInitialized", true); //Mark the element to say that data has been initialized.
1279            }
1280            return $.data(elem, name, data);
1281        },
1282
1283        /*
1284         * alternative to jQuery.css which sets style properties directly through element.style. This is much faster then
1285         * corresponding jQuery.css alternative.
1286         *
1287         * Warning: this only supports standard css property names and does not do any pre-processing of name and value.
1288         * So calling this, make sure the style names are compatible.
1289         */
1290        $css: function (elem, stylesObj) {
1291            // Exclude the following css properties to add px. copied from jquery.cssNumber to add hyphenated style names
1292            var cssNumber = {
1293                "fillOpacity": true,
1294                "fill-opacity": true,
1295                "fontWeight": true,
1296                "font-weight": true,
1297                "lineHeight": true,
1298                "line-height": true,
1299                "zIndex": true,
1300                "z-index": true,
1301                "opacity": true,
1302                "orphans": true,
1303                "widows": true,
1304                "zoom": true
1305            };
1306
1307            for (var prop in stylesObj) {
1308                var value = stylesObj[prop];
1309                // If a number was passed in, add 'px' to the (except for certain CSS properties)
1310                if (_.isNumber(value) && !cssNumber[ prop ]) {
1311                    value += "px";
1312                }
1313                elem.style[prop] = value;
1314            }
1315        },
1316
1317        isTableHF: function (iChildNode) {
1318            //model can be a Node object or simply a json
1319            var assistJson = _.find(iChildNode.children, function (jChild) {
1320                return jChild._class == "assist";
1321            }, this);
1322            var childRole = (assistJson || {}).role;
1323            if (childRole == "TH" || childRole == "TF")
1324                return true;
1325            else
1326                return false;
1327        },
1328
1329        getUiOneOfChildTag: function (uiParent) {
1330            var uiEl = _.find(uiParent.children, function (child) {
1331                return child._class == "ui";
1332            });
1333            if (!uiEl)
1334                return undefined;
1335            var uiOneOfChildMap = xfalib.runtime.xfa._templateSchema._getOneOfChild("ui");
1336            var uiOneOfChild = _.find(uiEl.children, function (child) {
1337                return uiOneOfChildMap[child._class] == true;
1338            });
1339            if (!uiOneOfChild)
1340                return undefined;
1341            return uiOneOfChild._class;
1342        },
1343
1344        //TODO: this should be removed. One of the worst function.
1345        dIndexOf: function (searchArray, item2Find) {
1346            var ind = -1;
1347            _.find(searchArray, function (item, index) {
1348                return item == item2Find && (ind = index)
1349            });
1350            return ind;
1351        },
1352
1353        splitStringByWidth: function (value, width, refEl) {
1354            var i = value.length , expectedWidth;
1355            do {
1356                expectedWidth = xfalib.view.util.TextMetrics.measureExtent(value.slice(0, i), {"refEl": refEl, maxWidth: -1}).width;
1357                i--;
1358            } while (expectedWidth > width)
1359            if (i != value.length - 1)
1360                return value.slice(0, i + 1);
1361            return value;
1362        },
1363
1364        isRepeatabeEl: function (elTag) {
1365            if (elTag == "subform" || elTag == "subformSet")
1366                return true;
1367            else
1368                return false;
1369        },
1370
1371        /**
1372         * @function
1373         * stripOrCall(toStrip, diffFunc, fArgs)
1374         * @description
1375         * common utility function to handle final submission payload stripping
1376         * @param {bool} toStrip : flag to signify whether to optimize jsonModelDiff size, by stripping off unnecessary properties
1377         * @param {function} diffFunc : callback func. call in case submit is not on
1378         * @param {Array} fArgs : arguments to be passed to the diff func.
1379         * @returns {object} object containing the jsonDiff
1380         */
1381        // should ALWAYS be called with a flag signifying if a submission is in progress,
1382        // and a callback function to compute the json to be sent back during submission, usually an apt '_computeJsonDiff'
1383        stripOrCall: function (toStrip, diffFunc, fArgs) {
1384            if (toStrip) {
1385                return {
1386                    "changed": false,
1387                    "jsonDifference": {}
1388                };
1389            }
1390            else if (_.isFunction(diffFunc)) {
1391                return diffFunc.apply(this, fArgs);
1392            }
1393        },
1394
1395        /**
1396         * @function
1397         * partialStripOrCall(stripLvl, diffFunc, fArgs)
1398         * @description
1399         * common utility function to handle final submission payload stripping or for output of getFormState.
1400         * @param {int} diff_level : flag to signify whether to optimize jsonModelDiff size, by stripping off unnecessary properties
1401         *                        must be 0,1, or 2, as with "diff_level" param of _computeJsonDiff.
1402         * @param {function} diffFunc : callback func. call in case submit is not on
1403         * @returns {object}
1403 object containing the jsonDiff
1404         */
1405        partialStripOrCall: function (diff_level, diffFunc) {
1406            var diffObj = diffFunc.call(this, diff_level);
1407
1408            if (!diffObj.changed) {
1409                if(diff_level === 1) {
1410                    diffObj = {
1411                        "changed": true,
1412                        "jsonDifference": {
1413                            "_class": this.jsonModel._class,
1414                            "name": this.jsonModel.name
1415                        }
1416                    };
1417                } else {
1418                    diffObj.jsonDifference = {};  // don't need stuff for other cases
1419                }
1420            }
1421
1422            return diffObj;
1423        },
1424
1425        /**
1426         * @function
1427         * stripObject(obj, exceptionNames)
1428         * @description
1429         * Utility function to strip unnecessary properties from an object
1430         * @param {object} obj : the object to strip
1431         * @param {Array} exceptionNames : array holding names of important properties to preserve
1432         * @returns {boolean} : true if this obj, or any of it's descendant is returned un-stripped
1433         */
1434        stripObject: function (obj, exceptionNames) {
1435            if (_.isEmpty(obj) || !_.isObject(obj)) {
1436                return true;
1437            } else {
1438                var dontStrip = false;
1439                _.each(_.keys(obj), function (propName) {
1440                    var keepProp = false;
1441                    if (!_.contains(exceptionNames, propName)) {
1442                        if (_.isArray(obj[propName])) {
1443                            _.each(obj[propName], function (arrElem) {
1444                                var isUnStripped = XfaUtil.prototype.stripObject(arrElem, exceptionNames);
1445                                keepProp = keepProp || isUnStripped;
1446                            });
1447                        } else if (_.isObject(obj[propName])) {
1448                            keepProp = XfaUtil.prototype.stripObject(obj[propName], exceptionNames);
1449                        }
1450
1451                        if (!keepProp) {
1452                            delete obj[propName];
1453                        } else {
1454                            dontStrip = true;
1455                        }
1456                    } else {
1457                        dontStrip = true;
1458                    }
1459                });
1460                return dontStrip;
1461            }
1462        },
1463
1464        computeDomJsonDiff: function (domNode, diff_level) {
1465            var changed = true;
1466            if (domNode.hasOwnProperty("_modelChanged")) {
1467                changed = domNode._modelChanged;
1468            }
1469            var jsonDiff = {};
1470            if (changed) {
1471                this.copyObject(domNode.jsonModel, jsonDiff, {"exceptions": ["children", "{default}", "extras"]});
1472            } else {
1473                jsonDiff = {_class: domNode.className};
1474            }
1475            if (!changed && domNode.jsonModel.hasOwnProperty("name")) {
1476                jsonDiff.name = domNode.jsonModel.name;
1477            }
1478            if (domNode.name === "FS_EXTRAS" && diff_level === 3) {
1479                domNode._childModified = true;
1480            }
1481            return {
1482                "changed": changed,
1483                jsonDifference: jsonDiff
1484            };
1485        },
1486
1487        getLogger: function () {
1488            return XfaUtil.prototype.logger || XfaUtil.prototype.getOrElse(xfalib, "runtime.xfa.Logger", null);
1489        },
1490
1491        getErrorManager: function () {
1492            return XfaUtil.prototype.getOrElse(xfalib, "runtime.xfa.ErrorManager", null);
1493        },
1494
1495        XFA_CLICK_EVENT: "xfaclick",
1496        XFA_EXIT_EVENT: "xfaexit",
1497        XFA_ENTER_EVENT: "xfaenter",
1498        XFA_CHANGE_EVENT: "xfachange",
1499        XFA_PREOPEN_EVENT: "xfapreopen",
1500
1501        btwn: function (val, a, b) {
1502            return val > a && val < b;
1503        },
1504
1505        // function to detect if Browser is chrome / safari (webkit)
1506        isWebkit: function () {
1507            return  !!$.browser.webkit || /webkit/.test(navigator.userAgent.toLowerCase()) || !!window.chrome || !!$.browser.chrome || /chrom(e|ium)/.test(navigator.userAgent.toLowerCase()) || !!$.browser.safari || !!window.webkitURL ||
1508                ( /safari/.test(navigator.userAgent.toLowerCase()) &&
1509                    /apple computer/.test(navigator.vendor.toLowerCase()) );
1510
1511            // TODO : find a better way to do this as $.browser is deprecated and
1512            // userAgent may be spoofed
1513        },
1514
1515        clearTimeoutOnDestroy: function (timeout) {
1516            attachClearTimeoutListener(timeout);
1517        },
1518
1519        // function to detect if Browser is  safari
1520        isSafari: function () {
1521            return ( /safari/.test(navigator.userAgent.toLowerCase()) &&
1522                    /apple computer/.test(navigator.vendor.toLowerCase()) );
1523        },
1524
1525        getLocaleStrings: function () {
1526            return xfalib.locale.Strings;
1527        },
1528
1529        getLogMessages: function () {
1530            return xfalib.locale.LogMessages;
1531        },
1532
1533        /*
1534         * This function should not be added in the prototype of any Object
1535         * as in the case of other functions
1536         */
1537        registerLocaleProperties: function (props) {
1538            registeredLocaleProperties = props;
1539        },
1540
1541        /*
1542         * This function should not be added in the prototype of any Object
1543         * as in the case of other functions
1544         */
1545        getDefaultLocaleProperty: function (property) {
1546            var localeProps = registeredLocaleProperties || this.getOrElse(xfalib, "script.Xfa._defaultLocale", null);
1547            return this.getOrElse(localeProps, property, null);
1548        },
1549
1550        /**
1551         * Encodes <script> and </script> with &lt;script&gt; and &lt;/script&gt;
1552         * Does same with img, video and audio tags also.
1553         * These tags are being removed since scripts can be run through
1554         * <img onerror="script" /> (same for audio and video).
1555         */
1556        encodeScriptableTags: function (str) {
1557            var index;
1558            if (_.isString(str)) {
1559                return str.replace(/<(\/?)(script[^<>]*)>/gi, '&lt;$1$2&gt;')
1560                    .replace(/<(\/?)(img[^<>]*)>/gi, '&lt;$1$2&gt;')
1561                    .replace(/<(\/?)(video[^<>]*)>/gi, '&lt;$1$2&gt;')
1562                    .replace(/<(\/?)(audio[^<>]*)>/gi, '&lt;$1$2&gt;')
1563            }
1564        },
1565
1566        /**
1567         *
1568         * @param id : a string representing an HTML element id.
1569         *
1570         * return after applying an escaping '\' before each # . : [ ]
1571         */
1572        jqId: function(id) {
1573            return "#" + id.replace(/(#|:|\.|\[|\])/g, "\\$1");
1574        },
1575
1576        _triggerOnBridge: function (eventName, target, property, oldVal, newVal) {
1577            var evnt = xfalib.script.XfaModelEvent.createEvent(eventName, target,
1578                property, oldVal, newVal);
1579            if(formBridge){
1580                window.formBridge.trigger(eventName, evnt);
1581            }
1582        },
1583
1584        /*
1585         * pads the passed in String str by pre-pending padChars to convert it to a string of given width.
1586         * If string length is already greater that equal to given width, original string is returned.
1587         */
1588        padString : function (str, width, padChar) {
1589            padChar = padChar || '0';
1590            str = str + '';
1591            return str.length >= width ? str : new Array(width - str.length + 1).join(padChar) + str;
1592        },
1593
1594        /**
1595         * returns true if the browser is IE otherwise false
1596         * @returns {boolean}
1597         */
1598        isIE: function () {
1599            return $.browser.msie || (navigator.appName === "Netscape" && navigator.userAgent.match(/Trident\//))
1600        },
1601
1602        /**
1603         * returns false if other browser
1604         * if ie tries to return browser version (non falsy)
1605         * @returns {*}
1606         */
1607
1608        detectIE: function () {
1609            // 1st try jq
1610            if($.browser.msie) {
1611                if($.browser.version && parseInt($.browser.version, 10)) {
1612                    return parseInt($.browser.version, 10);
1613                }
1614            }
1615
1616            var ua = window.navigator.userAgent;
1617
1618            // IE 10
1619            // ua = 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)';
1620
1621            // IE 11
1622            // ua = 'Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko';
1623
1624            // IE 12 / Spartan
1625            // ua = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36 Edge/12.0';
1626
1627            // Edge (IE 12+)
1628            // ua = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Safari/537.36 Edge/13.10586';
1629
1630            var msie = ua.indexOf('MSIE ');
1631            if (msie > 0) {
1632                // IE 10 or older => return version number
1633                return parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10);
1634            }
1635
1636            var trident = ua.indexOf('Trident/');
1637            if (trident > 0) {
1638                // IE 11 => return version number
1639                var rv = ua.indexOf('rv:');
1640                return parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10);
1641            }
1642
1643            var edge = ua.indexOf('Edge/');
1644            if (edge > 0) {
1645                // Edge (IE 12+) => return version number
1646                return parseInt(ua.substring(edge + 5, ua.indexOf('.', edge)), 10);
1647            }
1648
1649            // other browser
1650            return false;
1651        },
1652        /**
1653         * returns true if the browser is chrome otherwise false
1654         * @returns {boolean}
1655         */
1656        detectChrome : function () {
1657            return (!!window.chrome || !!$.browser.chrome || /chrom(e|ium)/.test(navigator.userAgent.toLowerCase()));
1658        },
1659
1660        /**
1661        * @param {String} val: value to be verified
1662        * @returns {boolean}
1663        * returns true if the provided string contains DOM element
1664        */
1665        isHTML: function(val) {
1666            //check whether string contains tags, so that $val does not contain result of the val used as selector
1667            // eg: val = "a" will return result for $(val) which is not required
1668            if(val && /<[a-z][\s\S]*>/.test(val)) {
1669                try {
1670                    var $val = $(val);
1671                    return $val.length > 0;
1672                } catch (exception) {
1673                    // if jquery throws exception that means string is not a proper HTML
1674                    return false;
1675                }
1676            } else {
1677                return false;
1678            }
1679        },
1680
1681        /**
1682         * returns true if passed key is non printable, false otherwise.
1683         * @param {String} key event.key property of a Keyboard event
1684         */
1685        isNonPrintableKey : function (key) {
1686            return (key   // In IE, event.key returns words instead of actual characters for some keys.
1687               && !_.contains(['MozPrintableKey','Divide','Multiply','Subtract','Add','Enter','Decimal','Spacebar','Del'],key)
1688               && key.length != 1 )
1689        },
1690
1691        /**
1692        * returns true for ipad
1693        * @returns {boolean}
1694        */
1695        _isIpad : function () {
1696            return navigator.userAgent.match(/iPad/i) != null;
1697        },
1698
1699        /**
1700        * returns true if the subform is table or having role table else false
1701        * @param {Object} view
1702        */
1703        _tableCheckForAccessibility : function (view) {
1704            var assist = view.model.getElement("assist", 0, true);
1705            return this.getOrElse(view, "layoutModel.layout", null) == xfalib.view.LayoutConst.LAYOUT_TABLE
1706                || this.getOrElse(assist, "role", null) == "Table";
1707        },
1708
1709        /**
1710        * returns value of tooltip to be assigned as title based on values provided in accessibility
1711        * @param {Object} model
1712        * @returns toolTipText
1713        */
1714        _getToolTipText : function (model) {
1715            var assist = model.getElement("assist", 0, true),
1716                toolTipText = "";
1717            // going against xfa spec, on hover show tooltip or speak text or element name, don't show caption as it's already visible
1718            // assist priority doesn't matter, but selecting none will disable tooltip on hover
1719            if (this.getOrElse(assist, "speak.disable", 0) != 1) { // loose compare str
1719ing value
1720                toolTipText = this.getOrElse(assist, "toolTip.value", "") ||
1721                    this.getOrElse(assist, "speak.value", "")   ||
1722                    this.getOrElse(model, "jsonModel.name", "");
1723            }
1724            return toolTipText;
1725        },
1726
1727        /**
1728        * returns value of mandatory message
1729        * @param {Object} model
1730        * @returns mandatoryMessage
1731        */
1732        _getMandatoryMessage : function (model) {
1733            var defaultMessage = model._defaults.validate.message.defaultMessage,
1734                msg = this.getOrElse(model, "validate.message.nullTest", defaultMessage);
1735            return (msg && msg.value) ? msg.value : defaultMessage.value;
1736        },
1737        /**
1738        * returns boolean based on val1, val2, checkEqual
1739        * For comparing date, use date object
1740        */
1741        _compareVal : function (val1, val2, checkEqual) {
1742            if(!val1 || !val2) {
1743                return false;
1744            }
1745
1746            if(checkEqual) {
1747                return val1 >= val2;
1748            } else {
1749                return val1 > val2;
1750            }
1751        }
1752    });
1753
1754    //Special handling for IE.
1755    if ($.browser.msie || $.browser.mozilla) {
1756        XfaUtil.prototype.$css = function (elem, stylesObj) {
1757            $(elem).css(stylesObj);
1758        }
1759    }
1760})(_, $, xfalib);
1761/*************************************************************************
1762 *
1763 * ADOBE CONFIDENTIAL
1764 * ___________________
1765 *
1766 *  Copyright 2013 Adobe Systems Incorporated
1767 *  All Rights Reserved.
1768 *
1769 * NOTICE:  All information contained herein is, and remains
1770 * the property of Adobe Systems Incorporated and its suppliers,
1771 * if any.  The intellectual and technical concepts contained
1772 * herein are proprietary to Adobe Systems Incorporated and its
1773 * suppliers and are protected by trade secret or copyright law.
1774 * Dissemination of this information or reproduction of this material
1775 * is strictly forbidden unless prior written permission is obtained
1776 * from Adobe Systems Incorporated.
1777 **************************************************************************/
1778
1779
1780
1781(function (_, $, xfalib) {
1782    xfalib.ut.Utilities = {
1783
1784        isIE11: function () {
1785            return !!navigator.userAgent.match(/Trident.*rv\:11\./);
1786        },
1787
1788        checkMinMozillaVersion: function (version) {
1789            return (!this.isIE11() && $.browser.mozilla && parseInt($.browser.version) >= version);
1790        },
1791
1792        getObjectFromKeyValueStringList: function (list) {
1793            var key, value, object = {}, tempArray;
1794            _.each(list, function (keyValuePair, index) {
1795                tempArray = keyValuePair.split("=");
1796                if (tempArray && tempArray.length > 1) {
1797                    object[tempArray[0]] = tempArray[1];
1798                }
1799            });
1800            return object;
1801        },
1802
1803        _getNameWithoutMarker: function (fileName) {
1804            var markerIndex = fileName.indexOf("__afAttachment__");
1805            if (markerIndex !== -1) {
1806                fileName = fileName.substring(markerIndex + "__afAttachment__".length, fileName.length);
1807            }
1808            return fileName;
1809        },
1810
1811        /*
1812         * This is to check support of multiple files selection in one add new dialog
1813         */
1814        _isDataContainerSupported : function () {
1815            try {
1816                var dataContainer = new DataTransfer() || (new ClipboardEvent("")).clipboardData;
1817                if (dataContainer && dataContainer.items) {
1818                    return true;
1819                }
1820            } catch(err) {
1821                // if err comes then dataContainer is not supported
1822            }
1823            return false;
1824        }
1825    };
1826})(_, $, xfalib);
1827/**
1828 * @package xfalib.ut.Scanner
1829 * @fileOverview helper class to scan over a string.
1830 * @version 0.0.1
1831 */
1832
1833/**
1834 * @constructor
1835 * @param Object {jsonModel:{_str: String}}
1836 */
1837
1838(function(_,xfalib){
1839    var Scanner = xfalib.ut.Scanner = xfalib.ut.Class.extend({
1840
1841        initialize: function() {
1842            this._pos = 0;
1843        },
1844
1845        isEOF : function(){
1846            return (this.jsonModel._str.length <= this._pos);
1847        },
1848
1849        peek : function(){
1850            return (this.isEOF()) ? null : this.jsonModel._str.charAt(this._pos);
1851        },
1852
1853        optionalConsumeChar : function(aChar){
1854            if(this.jsonModel._str.charAt(this._pos) == aChar){
1855                this._pos++;
1856                return aChar;
1857            }else{
1858                return null;
1859            }
1860        },
1861
1862        /**
1863         * Gets next char ignore quoted string.
1864         *    |
1865         *   abc returns c.
1866         *     |
1867         *   abc'de'f returns f.
1868         * @param aChar
1869         */
1870        getNCharIQS : function(){
1871            this._pos++;
1872            if(this.jsonModel._str.length <= this._pos){
1873                var current = this.jsonModel._str.charAt(this._pos);
1874                if(current != '\''){
1875                    return current;
1876                }else{
1877                    if(moveNextExpectedChar('\'')){
1878                        return this.jsonModel._str.charAt(this._pos);
1879                    }
1880                }
1881            }
1882            return null;
1883        },
1884
1885        moveNextExpectedChar : function(aChar){
1886            this._pos++;// currently point to '
1887            while(this._pos< this.jsonModel._str.length && this.jsonModel._str.charAt(this._pos) != aChar){
1888                this._pos++;
1889            }
1890            return this._pos < this.jsonModel._str.length;
1891        },
1892
1893        readInteger : function(len){
1894            if(this.pos+len >this.jsonModel._str.length){
1895                return null;
1896            }
1897            var integer = xfalib.ut.PictureUtils.parseIntExact(this.jsonModel._str,this._pos,len);
1898            this._pos+=len;
1899            return integer;
1900        }
1901    });
1902
1903    Scanner.lookupNext = function(pat, patPos, filter){
1904        var patLen = pat.length;
1905        if(patPos >= patLen){
1906            return null;
1907        }
1908
1909        var token = {};
1910        token.startPos = patPos;
1911
1912        var firstChar = pat.charAt(patPos);
1913        var patValid = false;
1914        //
1915        if (firstChar == '\''){
1916            for (var i = patPos+1; i < patLen;i++ ){
1917                var chr = pat.charAt(i);
1918                if(chr =='\''){
1919                    token.type=1;
1920                    token.len = i - patPos + 1;
1921                    patValid = true;
1922                    break;
1923                }
1924            }
1925
1926        }else if( ('a' <= firstChar && firstChar <= 'z' || 'A' <= firstChar && firstChar <= 'Z') || filter.call(null, firstChar)){
1927            var endPos = patLen;//end is exclusive
1928            for (var i = 1; patPos+i < patLen;i++ ){
1929                if(pat.charAt(patPos+i)!=firstChar){
1930                    endPos = patPos+i;
1931                    break;
1932                }
1933            }
1934            token.type=2;
1935            token.len = endPos - patPos;
1936            token.patChar = firstChar;
1937            token.patPos = patPos;
1938            patValid = true;
1939        }else{
1940            if (firstChar == '?' || firstChar == '+' || firstChar == '*') {
1941                token.type=3;
1942                token.len = 1;
1943            }else{
1944                token.type=4;
1945                token.len = 1;
1946            }
1947            patValid = true;
1948        }
1949        if(patValid){
1950            return token;
1951        }else{
1952            throw "Picture is invalid.";
1953        }
1954    }
1955})(_,xfalib);
1956
1957
1958/**
1959 * @package xfalib.ut.PictureFmt
1960 * @fileOverview The file defines methods to parse and format data
1961 * according to XFA picture patterns.
1962 * @version 0.0.1
1963 */
1964(function(_,xfalib) {
1965
1966    var PictureFmt = xfalib.ut.PictureFmt = function() {};
1967    PictureFmt.DatePicturePattern =  /^date(?:\([a-zA-Z]*_[a-zA-Z]*\))?\{([\w\W]*?)\}$/;
1968    PictureFmt.TimePicturePattern =  /^time(?:\([a-zA-Z]*_[a-zA-Z]*\))?\{([\w\W]*?)\}$/;
1969    PictureFmt.TextPicturePattern =  /^text\{([\w\W]*?)\}$/;
1970    PictureFmt.NumPicturePattern =  /^num\{([\w\W]*?)\}$/;
1971
1972    /**
1973     * Parses a given data source according to the given picture.
1974     * @param sSource {string}
1975     * @param sPicture {string}
1976     * @param sLocale {string}
1977     * @returns {object}
1978     */
1979    PictureFmt.parse  = function(sSource, sPicture,sLocale){
1980        var PictureEngine = new xfalib.ut.PictureEngine({jsonModel:{locale:sLocale}});
1981
1982        var match = PictureFmt.DatePicturePattern.exec(sPicture);
1983        if(match && match[1]){
1984            return PictureEngine.parseDate(sSource, match[1]);
1985        }
1986        match = PictureFmt.TimePicturePattern.exec(sPicture);
1987        if(match && match[1]){
1988            return PictureEngine.parseTime(sSource, match[1]);
1989        }
1990        match = PictureFmt.TextPicturePattern.exec(sPicture);
1991        if(match && match[1]){
1992            return PictureEngine.parseText(sSource, match[1]);
1993        }
1994        match = PictureFmt.NumPicturePattern.exec(sPicture);
1995        if(match && match[1]){
1996            return PictureEngine.parseNumeric(sSource, match[1]);
1997        }
1998        throw "Invalid picture clause "+sPicture;
1999    };
2000
2001    /**
2002     * Formats a given data source according to the given picture.
2003     * @param date {object}
2004     * @param sPicture {string}
2005     * @param sLocale {string}
2006     * @returns {string}
2007     */
2008    PictureFmt.format  = function(sSource, sPicture, sLocale,bRelaxed,bFormatNumberFromasDefaultPC){
2009        var PictureEngine = new xfalib.ut.PictureEngine({jsonModel:{locale:sLocale}});
2010
2011        var match = PictureFmt.DatePicturePattern.exec(sPicture);
2012        if(match && match[1]){
2013            return PictureEngine.formatDate(sSource, match[1]);
2014        }
2015        match = PictureFmt.TimePicturePattern.exec(sPicture);
2016        if(match && match[1]){
2017            return PictureEngine.formatTime(sSource, match[1]);
2018        }
2019        match = PictureFmt.TextPicturePattern.exec(sPicture);
2020        if(match && match[1]){
2021            return PictureEngine.formatText(sSource, match[1],bRelaxed);
2022        }
2023        match = PictureFmt.NumPicturePattern.exec(sPicture);
2024        if(match && match[1]){
2025            return PictureEngine.formatNumeric(sSource, match[1],sLocale,bRelaxed,bFormatNumberFromasDefaultPC);
2026        }
2027            throw "Invalid picture clause "+sPicture;
2028    };
2029
2030    /**
2031     * Checks if a given data source is formatted according to the given picture.
2032     * @param date {object}
2033     * @param sPicture {string}
2034     * @param sLocale {string}
2035     * @returns {boolean}
2036     */
2037    PictureFmt.formatTest = function (sSource, sPicture, sLocale, bRelaxed, bFormatNumberFromasDefaultPC) {
2038        var formattedData;
2039        try {
2040            formattedData = PictureFmt.format(sSource, sPicture, sLocale, bRelaxed, bFormatNumberFromasDefaultPC);
2041        }catch(e) {
2042            return false;
2043        }
2044
2045        if(!_.isString(formattedData)) {
2046            return false;
2047        } else {
2048            var parsedData;
2049            try {
2050                parsedData = PictureFmt.parse(formattedData, sPicture, sLocale);
2051            } catch (e) {
2052                return false;
2053            }
2054            if(!_.isString(parsedData) && parsedData !== formattedData) {
2055                return false;
2056            }
2057        }
2058        return true;
2059    };
2060
2061    /**
2062     * Parses a given data source according to the given date picture
2063     * under the given sLocale.
2064     * @param sSource {string}
2065     * @param sPicture {string}
2066     * @param sLocale {string}
2067     * @returns {string}
2068     */
2069    PictureFmt.parseDate  = function(sSource, sPicture,sLocale){
2070        var picRegexp = PictureFmt.DatePicturePattern;
2071        var match = picRegexp.exec(sPicture);
2072        var PictureEngine = new xfalib.ut.PictureEngine({jsonModel:{locale:sLocale}});
2073        if(match && match[1]){
2074            return PictureEngine.parseDate(sSource, match[1]);
2075        }else{
2076            return PictureEngine.parseDate(sSource, sPicture);
2077        }
2078    };
2079
2080
2081    /**
2082     * Formats a given data source according to the given date picture
2083     * * under the given sLocale.
2084     * @param date {string}
2085     * @param sPicture {string}
2086     * @param sLocale {string}
2087     * @returns {string}
2088     */
2089    PictureFmt.formatDate  = function(date, sPicture, sLocale){
2090        var picRegexp =  PictureFmt.DatePicturePattern;
2091        var match = picRegexp.exec(sPicture);
2092        var PictureEngine = new xfalib.ut.PictureEngine({jsonModel:{locale:sLocale}});
2093        if(match && match[1]){
2094            return PictureEngine.formatDate(date, match[1]);
2095        }else{
2096            return PictureEngine.formatDate(date, sPicture);
2097        }
2098    };
2099
2100    /**
2101     * Parses a given data source according to the given date picture
2102     * under the given sLocale.
2103     * @param sSource {string}
2104     * @param sPicture {string}
2105     * @param sLocale {string}
2106     * @returns {date}
2107     */
2108    PictureFmt.parseTime  = function(sSource, sPicture,sLocale){
2109        var picRegexp = PictureFmt.TimePicturePattern;
2110        var match = picRegexp.exec(sPicture);
2111        var PictureEngine = new xfalib.ut.PictureEngine({jsonModel:{locale:sLocale}});
2112        if(match && match[1]){
2113            return PictureEngine.parseTime(sSource, match[1]);
2114        }else{
2115            return PictureEngine.parseTime(sSource, sPicture);
2116        }
2117        return null;
2118    };
2119
2120
2121    /**
2122     * Formats a given data source according to the given date picture
2123     * * under the given sLocale.
2124     * @param date {string}
2125     * @param sPicture {string}
2126     * @param sLocale {string}
2127     * @returns {string}
2128     */
2129    PictureFmt.formatTime  = function(date, sPicture, sLocale){
2130        var picRegexp =  PictureFmt.TimePicturePattern;
2131        var match = picRegexp.exec(sPicture);
2132        var PictureEngine = new xfalib.ut.PictureEngine({jsonModel:{locale:sLocale}});
2133        if(match && match[1]){
2134            return PictureEngine.formatTime(date, match[1]);
2135        }else{
2136            return PictureEngine.formatTime(date, sPicture);
2137        }
2138    };
2139
2140    /**
2141     * Parses a given data source according to the given text picture
2142     * under the given sLocale.
2143     * @param sSource {string}
2144     * @param sPicture {string}
2145     * @param sLocale {string}
2146     * @returns {string}
2147     */
2148    PictureFmt.parseText  = function(sSource, sPicture,sLocale){
2149        var picRegexp = PictureFmt.TextPicturePattern;
2150        var match = picRegexp.exec(sPicture);
2151        var PictureEngine = new xfalib.ut.PictureEngine({jsonModel:{locale:sLocale}});
2152        if(match && match[1]){
2153            return PictureEngine.parseText(sSource, match[1]);
2154        }else{
2155            return PictureEngine.parseText(sSource, sPicture);
2156        }
2157    };
2158
2159    /**
2160     * Formats a given data source according to the given text picture
2161     *  under the given sLocale.
2162     * @param sSource {string}
2163     * @param sPicture {string}
2164     * @param sLocale {string}
2165     * @returns {string}
2166     */
2167    PictureFmt.formatText  = function(sSource, sPicture, sLocale,bRelaxed){
2168        var picRegexp =  PictureFmt.TextPicturePattern;
2169        var match = picRegexp.exec(sPicture);
2170        var PictureEngine = new xfalib.ut.PictureEngine({jsonModel:{locale:sLocale}});
2171        if(match && match[1]){
2172            return PictureEngine.formatText(sSource, match[1],bRelaxed);
2173        }else{
2174            return PictureEngine.formatText(sSource, sPicture,bRelaxed);
2175        }
2176        return null;
2177    };
2178
2179    /**
2180     * Parses a given data source according to the given numeric picture
2181     * under the given sLocale.
2182     * @param sSource {string}
2183     * @param sPicture {string}
2184     * @param sLocale {string}
2185     * @returns {string}
2186     */
2187    PictureFmt.parseNumeric  = function(sSource, sPicture,sLocale){
2188        var picRegexp = PictureFmt.NumPicturePattern;
2189        var match = picRegexp.exec(sPicture);
2190        var PictureEngine = new xfalib.ut.PictureEngine({jsonModel:{locale:sLocale}});
2191        if(match && match[1]){
2192            return PictureEngine.parseNumeric(sSource, match[1]);
2193        }else{
2194            return PictureEngine.parseNumeric(sSource, sPicture);
2195        }
2196        return null;
2197    };
2198
2199    /**
2200     * Formats a given data source according to the given numeric picture
2201     *  under the given sLocale.
2202     * @param sSource {string}
2203     * @param sPicture {string}
2204     * @param sLocale {string}
2205     * @returns {string}
2206     */
2207    PictureFmt.formatNumeric  = function(sSource, sPicture, sLocale){
2208        var picRegexp =  PictureFmt.NumPicturePattern;
2209        var match = picRegexp.exec(sPicture);
2210        var PictureEngine = new xfalib.ut.PictureEngine({jsonModel:{locale:sLocale}});
2211        if(match && match[1]){
2212            return PictureEngine.formatNumeric(sSource, match[1]);
2213        }else{
2214            return PictureEngine.formatNumeric(sSource, sPicture);
2215        }
2216    };
2217
2218
2219
2220
2221    /**
2222     * Parses a given data source according to the given datetime picture
2223     * under the given sLocale.
2224     * @param sSource {string}
2225     *            the source data.
2226     * @param sPicture {string}
2227     *            the datetime picture.
2228     * @param sDateMask {string}
2229     *            the date sub-picture.
2230     * @param sTimeMask {string}
2231     *            the time sub-picture.
2232     * @param sLocale
2233     *            the locale name.
2234     *
2235     */
2236    PictureFmt.parseDateTime  = function(sSource, sPicture, sDateMask, sTimeMask, sLocale){
2237
2238    };
2239    /**
2240     * Formats a given data source according to the given datetime picture
2241     * under the given locale.
2242     *
2243     * @param sSource {string}
2244     *            the source data.
2245     * @param sPicture {string}
2246     *            the datetime picture.
2247     * @param sDateMask {string}
2248     *            the date sub-picture.
2249     * @param sTimeMask {string}
2250     *            the time sub-picture.
2251     * @param sLocale {string}
2252     *            the locale name.
2253     */
2254    PictureFmt.formatDateTime  = function(sSource, sPicture, sDateMask, sTimeMask, sLocale){
2255
2256    };
2257
2258})(_,xfalib);
2259/**
2260 * @package xfalib.ut.PictureUtils
2261 * @fileOverview The file defines static utilities methods.
2262 * @version 0.0.1
2263 */
2264
2265(function(_,xfalib){
2266    var PictureUtils = xfalib.ut.PictureUtils = function() {}
2267
2268    PictureUtils.padding = function(number, digits, isFw, zero){
2269        var leading = ["0","00","000","0000"];
2270        var numStr = leading[digits-1] + number;
2271        return numStr.slice(- digits);
2272    };
2273
2274    PictureUtils.parseIntAggressive = function(dateString, startPos,len){
2275        var result = new Object();
2276        var parsedNum = 0; //The number value parsed from dateString
2277        var parsedLen = -1; //How many chars parsed according to this pattern;
2278        for(var idx=0; idx<len && (startPos + idx) < dateString.length; idx++){
2279            var chr = dateString.charAt(startPos + idx);
2280            if(chr >='0' && chr <='9'){
2281                parsedNum = parsedNum *10 + (chr- '0');
2282            }else{
2283                parsedLen = idx;
2284                break;
2285            }
2286        }
2287        if(parsedLen == -1) {
2288            parsedLen = len;
2289        }
2290        result.value = parsedNum;
2291        result.len = parsedLen;
2292        return result;
2293    };
2294
2295    PictureUtils.parseIntExact = function(dateString, startPos,len){
2296        var result = 0;
2297        PictureUtils.assert(startPos+ len <= dateString.length, "mismatch");
2298        for(var idx=0; idx<len ; idx++){
2299            var chr = dateString.charAt(startPos + idx);
2300            if(chr >='0' && chr <='9'){
2301                result = result *10 + (chr- '0');
2302            }else{
2303                throw "unexpected currentChar in PictureUtils.parseInt";
2304            }
2305        }
2306        return result;
2307    };
2308
2309    PictureUtils.isDigit = function(chr){
2310        return /[0-9]/.test(chr) ;
2311    };
2312
2313    PictureUtils.inString = function(chr,aString){
2314        return (aString.indexOf(chr) >=0) ;
2315    };
2316
2317
2318    var regExpIsLetter = /[\u0041-\u005a\u0061-\u007a\u00aa-\u00aa\u00b5-\u00b5\u00ba-\u00ba\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u0236\u0250-\u02
2318c1\u02c6-\u02d1\u02e0-\u02e4\u02ee-\u02ee\u037a-\u037a\u0386-\u0386\u0388-\u038a\u038c-\u038c\u038e-\u03a1\u03a3-\u03ce\u03d0-\u03f5\u03f7-\u03fb\u0400-\u0481\u048a-\u04ce\u04d0-\u04f5\u04f8-\u04f9\u0500-\u050f\u0531-\u0556\u0559-\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0621-\u063a\u0640-\u064a\u066e-\u066f\u0671-\u06d3\u06d5-\u06d5\u06e5-\u06e6\u06ee-\u06ef\u06fa-\u06fc\u06ff-\u06ff\u0710-\u0710\u0712-\u072f\u074d-\u074f\u0780-\u07a5\u07b1-\u07b1\u0904-\u0939\u093d-\u093d\u0950-\u0950\u0958-\u0961\u0985-\u098c\u098f-\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2-\u09b2\u09b6-\u09b9\u09bd-\u09bd\u09dc-\u09dd\u09df-\u09e1\u09f0-\u09f1\u0a05-\u0a0a\u0a0f-\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32-\u0a33\u0a35-\u0a36\u0a38-\u0a39\u0a59-\u0a5c\u0a5e-\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2-\u0ab3\u0ab5-\u0ab9\u0abd-\u0abd\u0ad0-\u0ad0\u0ae0-\u0ae1\u0b05-\u0b0c\u0b0f-\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32-\u0b33\u0b35-\u0b39\u0b3d-\u0b3d\u0b5c-\u0b5d\u0b5f-\u0b61\u0b71-\u0b71\u0b83-\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99-\u0b9a\u0b9c-\u0b9c\u0b9e-\u0b9f\u0ba3-\u0ba4\u0ba8-\u0baa\u0bae-\u0bb5\u0bb7-\u0bb9\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c60-\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd-\u0cbd\u0cde-\u0cde\u0ce0-\u0ce1\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d28\u0d2a-\u0d39\u0d60-\u0d61\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd-\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32-\u0e33\u0e40-\u0e46\u0e81-\u0e82\u0e84-\u0e84\u0e87-\u0e88\u0e8a-\u0e8a\u0e8d-\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5-\u0ea5\u0ea7-\u0ea7\u0eaa-\u0eab\u0ead-\u0eb0\u0eb2-\u0eb3\u0ebd-\u0ebd\u0ec0-\u0ec4\u0ec6-\u0ec6\u0edc-\u0edd\u0f00-\u0f00\u0f40-\u0f47\u0f49-\u0f6a\u0f88-\u0f8b\u1000-\u1021\u1023-\u1027\u1029-\u102a\u1050-\u1055\u10a0-\u10c5\u10d0-\u10f8\u1100-\u1159\u115f-\u11a2\u11a8-\u11f9\u1200-\u1206\u1208-\u1246\u1248-\u1248\u124a-\u124d\u1250-\u1256\u1258-\u1258\u125a-\u125d\u1260-\u1286\u1288-\u1288\u128a-\u128d\u1290-\u12ae\u12b0-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0-\u12c0\u12c2-\u12c5\u12c8-\u12ce\u12d0-\u12d6\u12d8-\u12ee\u12f0-\u130e\u1310-\u1310\u1312-\u1315\u1318-\u131e\u1320-\u1346\u1348-\u135a\u13a0-\u13f4\u1401-\u166c\u166f-\u1676\u1681-\u169a\u16a0-\u16ea\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7-\u17d7\u17dc-\u17dc\u1820-\u1877\u1880-\u18a8\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1d00-\u1d6b\u1e00-\u1e9b\u1ea0-\u1ef9\u1f00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59-\u1f59\u1f5b-\u1f5b\u1f5d-\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe-\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071-\u2071\u207f-\u207f\u2102-\u2102\u2107-\u2107\u210a-\u2113\u2115-\u2115\u2119-\u211d\u2124-\u2124\u2126-\u2126\u2128-\u2128\u212a-\u212d\u212f-\u2131\u2133-\u2139\u213d-\u213f\u2145-\u2149\u3005-\u3006\u3031-\u3035\u303b-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312c\u3131-\u318e\u31a0-\u31b7\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fa5\ua000-\ua48c\uac00-\ud7a3\uf900-\ufa2d\ufa30-\ufa6a\ufb00-\ufb06\ufb13-\ufb17\ufb1d-\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e-\ufb3e\ufb40-\ufb41\ufb43-\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]/
2319
2320    /**
2321     * TODO Implement method equivalent to Character.isLetter.
2322     */
2323    PictureUtils.isLetter = function(chr){
2324        return regExpIsLetter.test(chr);
2325    };
2326
2327    PictureUtils.isLetterOrDigit = function(chr){
2328        return this.isLetter(chr) || this.isDigit(chr);
2329    };
2330
2331    /**
2332     * Scan this string for the first character in the given set. Similar to
2333     * strcspn().
2334     *
2335     * @param src{String}
2336     *            the string to scan
2337     * @param sSkip{String}
2338     *            the characters to scan for
2339     * @param nOffset{number}
2340     *            the position where to start the scan. Default = 0.
2341     * @return The position, relative to nOffset, for the first character found
2342     *         in the given set
2343     */
2344    PictureUtils.skipUntil = function(srcStr, sSkip, nOffset) {
2345        var nCharsSkipped = nOffset;
2346
2347        // starting at the offset position, scan the characters in this string
2348        // until it matches one of the characters in the given set.
2349        while (nCharsSkipped < srcStr.length) {
2350            var i = nCharsSkipped;
2351            if (sSkip.indexOf(srcStr.charAt(i++)) >= 0)
2352                break;
2353            nCharsSkipped = i;
2354        }
2355
2356        return nCharsSkipped - nOffset;
2357    };
2358
2359    PictureUtils.matchString = function(str, startPos, target){
2360        if(startPos + target.length > str.length){
2361            return false;
2362        }else{
2363            for(var idx = 0; idx<target.length; idx++){
2364                if(target.charAt(idx) != str.charAt(startPos + idx)) return false;
2365            }
2366            return true;
2367        }
2368    };
2369
2370    PictureUtils.assert = function(condition, message){
2371        if(!condition){
2372            throw message;
2373        }
2374    };
2375
2376    PictureUtils.getLocaleObject = function(locale,property) {
2377        if(locale !== null && xfalib.runtime.xfa) {
2378            return xfalib.runtime.xfa._getLocaleSymbols(locale, property);
2379        } else {
2380            return xfalib.ut.XfaUtil.prototype.getDefaultLocaleProperty(property)
2381        }
2382    }
2383
2384    PictureUtils.getHashOfLocaleObject = function(locale,property) {
2385          if(!PictureUtils.getHashOfLocaleObject[locale+"_"+property]) {
2386              var hashObj = {};
2387              _.each(PictureUtils.getLocaleObject(locale,property), function(val) {
2388                  var sVal = (val+"").toLowerCase();
2389                  var hash = 0;
2390                  for(var i =0;i<sVal.length;i++) {
2391                      hash+=(i+1)*sVal.charCodeAt(i)
2392                  }
2393                  hashObj[hash] = hashObj[hash] || [];
2394                  hashObj[hash].push(sVal);
2395              })
2396              PictureUtils.getHashOfLocaleObject[locale+"_"+property] = hashObj;
2397          }
2398          return PictureUtils.getHashOfLocaleObject[locale+"_"+property]
2399    }
2400
2401    PictureUtils.convertNumberToLocale = function(locale,number) {
2402        var zero = PictureUtils.getLocaleObject(locale,"numberSymbols.zero");
2403        var zeroCode = zero.charCodeAt(0);
2404        number += "";
2405        var newNumber = [];
2406        for(var i = 0;i < number.length;i++) {
2407            newNumber.push(String.fromCharCode(zeroCode + parseInt(number.charAt(i))));
2408        }
2409        return newNumber.join("");
2410    }
2411
2412    PictureUtils.parsePictureClause = function (clause){
2413        if(clause === null || clause === undefined) {
2414            return [];
2415        }
2416        var insidePattern = false,
2417            insideQuote=false,
2418            insideLocale = false,
2419            locale = "",
2420            type = "",
2421            pattern = "",
2422            flag = false,
2423            currentChar = "",
2424            result = [],
2425            matchType = /^num$|^text$|^date$/,
2426            matchLocale = /^[a-zA-Z]*_[a-zA-Z]*$/,
2427            i = 0,
2428            bracketOpenCount = 0;
2429        for(;i<clause.length;i++) {
2430            currentChar = clause.charAt(i);
2431            if(insideQuote && currentChar !== "'") {
2432                pattern += currentChar;
2433                continue;
2434            }
2435            switch(currentChar) {
2436               case "'":
2437                   if(!insidePattern) {
2438                       // ' is not allowed except insidePattern
2439                       return null;
2440                   }
2441                   insideQuote = !insideQuote;
2442                   pattern += currentChar;
2443                   break;
2444               case "{":
2445                    if(insidePattern || insideLocale || type === "") {
2446                        // { is not allowed insidePattern or insideLocale
2447                        return null;
2448                    }
2449                   insidePattern = true;
2450                    break;
2451                case "}":
2452                    if(!insidePattern || (insideLocale && pattern === "") || type === "") {
2453                        // { is allowed only insidePattern and not insideLocale
2454                        return null;
2455                    } else {
2456                        bracketOpenCount = 0;
2457                        insidePattern = false;
2458                        if(matchType.exec(type) === null) {
2459                            return null;
2460                        }
2461                        if(locale !== "" && matchLocale.exec(locale) === null) {
2462                            return null;
2463                        }
2464                        result.push({
2465                            category: type,
2466                            mask: pattern,
2467                            locale: locale
2468                        })
2469                    }
2470                    break;
2471                case "|":
2472                    if(type === "" || insidePattern || insideLocale) {
2473                        return null;
2474                    } else {
2475                        type = pattern = locale = "";
2476                        insidePattern = insideLocale = false;
2477                    }
2478                    break;
2479                case "(" :
2480                    if(type === "" || bracketOpenCount === 1) {
2481                        // ( is not allowed inside Locale
2482                        return null;
2483                    } else {
2484                        if(!insidePattern) {
2485                            insideLocale = true;
2486                        } else {
2487                            pattern += currentChar;
2488                        }
2489                        bracketOpenCount++;
2490                    }
2491                    break;
2492                case ")" :
2493                    if((!insideLocale && !insidePattern) || bracketOpenCount === 0) {
2494                        return null;
2495                    } else {
2496                        if(insidePattern) {
2497                            pattern += currentChar;
2498                        }
2499                        insideLocale = false;
2500                        bracketOpenCount--;
2501                    }
2502                    break;
2503                default:
2504                    if(insidePattern) {
2505                        pattern += currentChar;
2506                    } else if(insideLocale) {
2507                        locale += currentChar;
2508                    } else if(type !== "" && (pattern !== "" || locale !== "")){
2509                        return null;
2510                    } else {
2511                        type += currentChar;
2512                    }
2513                    break;
2514           }
2515       }
2516       if(insidePattern || insideLocale || insideQuote || bracketOpenCount !== 0) {
2517           return null;
2518       }
2519       return result;
2520    }
2521
2522})(_,xfalib);
2523
2524/**
2525 * @package xfalib.ut.VisitorBase
2526 * @import xfalib.ut.Class
2527 * @fileOverview Base class for visitor
2528 * @version 0.0.1
2529 */
2530
2531/**
2532 * @constructor
2533 * @param Object {jsonModel: {_sPicture: String}}
2534 */
2535
2536(function(_,xfalib) {
2537    var VisitorBase = xfalib.ut.VisitorBase = xfalib.ut.Class.extend({
2538        consume : function(token){
2539            switch (token.type)
2540            {
2541                case 1:
2542                    this.consumeStringLiteral(token);
2543                    break;
2544                case 2:
2545                    this.consumeSubPattern(token);
2546                    break;
2547                case 3:
2548                    this.consumeStringWildCard(token);
2549                    break;
2550                case 4:
2551                    this.consumeCharLiteral(token);
2552                    break;
2553            }
2554        },
2555        acceptPatternChar : function(chr){
2556            return false;
2557        },
2558        getPicture : function(){
2559            return this.jsonModel._sPicture;
2560        },
2561        abstractMethod : function(){
2562            throw "Not implemented";
2563        },
2564        consumeStringWildCard : this.abstractMethod,
2565        consumeStringLiteral: this.abstractMethod,
2566        consumeCharLiteral: this.abstractMethod,
2567        consumeSubPattern: this.abstractMethod,
2568        getResult: this.abstractMethod
2569    });
2570})(_,xfalib);
2571
2572/**
2573 * @package xfalib.ut.NumPictureDesc
2574 * @import xfalib.ut.Class
2575 * @fileOverview Pre-process Numeric Picture.
2576 * @version 0.0.1
2577 */
2578
2579/**
2580 * @constructor
2581 * @param Object {jsonModel: {_sPicture: String}}
2582 */
2583
2584(function(_,xfalib){
2585    var NumPictureDesc = xfalib.ut.NumPictureDesc = xfalib.ut.Class.extend({
2586
2587        initialize: function() {
2588            this.hasRadix = false;
2589            this.hasExpon = false;
2590            this.hasSign = false;
2591            this.hasPercent = false;
2592            this.fracDigit = 0;
2593            this.intDigit = 0;
2594
2595            this._mbLeftParenSeen = false;
2596            this._mbRightParenSeen = false;
2597            this._compactPattern();
2598            this._xlatePattern();
2599            NumPictureDesc._super.initialize.call(this);
2600        },
2601        
2602        getPicture : function(){
2603            return this.jsonModel._sPicture;
2604        },
2605
2606        _match2Char : function (char1, char2, idx){
2607            if(idx+1 < this.jsonModel._sPicture.length){
2608                return (this.jsonModel._sPicture.charAt(idx) ==char1 && this.jsonModel._sPicture.charAt(idx+1) ==char2);
2609            }else{
2610                return false;
2611            }
2612        },
2613
2614        _xlatePattern : function(){
2615            var patPos = 0;
2616            for(var token = xfalib.ut.Scanner.lookupNext(this.jsonModel._sPicture, patPos, this._acceptPatternChar); token != null;  ){
2617                this._consume(token);
2618                patPos = patPos + token.len;
2619                token = xfalib.ut.Scanner.lookupNext(this.jsonModel._sPicture, patPos, this._acceptPatternChar);
2620            }
2621        },
2622        
2623        _compactPattern : function(){
2624            var buf = new Array();
2625            for(var index =0, len = this.jsonModel._sPicture.length; index <len; index++){
2626                if(this._match2Char('D','B',index)){
2627                    buf.push('D');
2628                    index++;
2629                }else if(this._match2Char('d','b',index)){
2630                    buf.push('d');
2631                    index++;
2632                }else if(this._match2Char('C','R',index)){
2633                    buf.push('C');
2634                    index++;
2635                }else if(this._match2Char('c','r',index)){
2636                    buf.push('c');
2637                    index++;
2638                }else{
2639                    buf.push(this.jsonModel._sPicture.charAt(index));
2640                }
2641            }
2642            this.jsonModel._sPicture = buf.join("");
2643        },
2644
2645        _acceptPatternChar : function(chr){
2646            return xfalib.ut.PictureUtils.inString(chr, "(%$,.)89BCDERSVZbcdrsvzt");
2647        },
2648
2649        _consume : function(token){
2650            if(token.type == 2){
2651                this._subConsume(token.patChar, token.len);
2652            }// else not a pattern
2653        },
2654
2655        _subConsume : function(chr, chrCnt){
2656            switch (chr) {
2657                case'E' :
2658                    if (chrCnt > 1 || this.hasExpon || (this.fracDigit + this.intDigit)==0)
2659                        throw "Illegal Numeric Picture: more than one Expon";
2660                    this.hasExpon = true;
2661                    break;
2662                case '(':
2663                    if (chrCnt > 1 || this._mbLeftParenSeen	|| this.fracDigit + this.intDigit >0 )
2664                        throw "Illegal Numeric Picture:  ()";
2665                    this._mbLeftParenSeen = true;
2666                    break;
2667
2668                case ')':
2669                    if (chrCnt > 1 || ! this._mbLeftParenSeen || this._mbRightParenSeen)
2670                        throw "Illegal Numeric Picture:  ()";
2671                    this._mbRightParenSeen = true;
2672                    if(this.fracDigit + this.intDigit >0) this.hasSign = true;
2673                    break;
2674                case 'S':
2675                case 's':
2676                case 'C': //CR
2677                case 'c': //cr
2678                case 'D': //DB
2679                case 'd': //db
2680                    this.hasSign = true;
2681                    break;
2682                case '%' :
2683                    this.hasPercent = true;
2684                    break;
2685                case '.':
2686                case 'V':
2687                case 'v':
2688                    if (chrCnt > 1 || this.hasRadix)
2689                        throw "Illegal Numeric Picture: too many vV.";
2690                    this.hasRadix = true;
2691                    this._mbFracStartSeen = true;
2692                    break;
2693                case '8' :
2694                case '9' :
2695                case 'Z':
2696                case 'z':
2697                    if (this.hasRadix){
2698                        this.fracDigit += chrCnt;
2699                    } else{
2700                        this.intDigit += chrCnt;
2701                    }
2702                    break;
2703            }
2704        },
2705
2706        parseNumberInfo : function(msText){
2707            var text=msText,
2708                num = Number(text),
2709                negative = false
2710            if(num < 0){
2711                negative = true;
2712                num = -num;
2713                text = text.replace("-","");
2714            }
2715            if(this.hasPercent){
2716                num *= 100;
2717                text = ""+num;
2718            }
2719            var shift = 0;
2720            if(this.hasExpon){
2721                var threshold = Math.pow(10,this.intDigit);
2722                if(num < threshold){
2723                    while(num*10 < threshold) {
2724                        num *= 10;
2725                        shift--;
2726                    }
2727                }else{
2728                    while(num > threshold){
2729                        num /= 10;
2730                        shift++;
2731                    }
2732                }
2733                text = num+"";
2734            }
2735            var radixPos = text.indexOf(".", 0),
2736                fractionDigit = radixPos<0 ? 0 : text.length - radixPos - 1
2737
2738            if(this.fracDigit < fractionDigit) {
2739                num = num.toFixed(this.fracDigit);
2740                text = num +""
2741            }
2742
2743            if(text.indexOf("0") == 0 && msText.indexOf("0") != 0) {
2744                text = text.substring(1);
2745            }
2746
2747            radixPos = text.indexOf(".", 0)
2748            var integerDigit = radixPos < 0 ? text.length : radixPos,
2749                offset = this.intDigit - integerDigit
2750
2751            if(offset <0 ){
2752                throw "Exit: most significant " + offset +" digit lost";
2753            }
2754            return {
2755                "integerDigit" : integerDigit,
2756                "radixPos" : radixPos ,
2757                "fractionDigit" :  radixPos<0 ? 0 : text.length - radixPos - 1,
2758                "msText" : text,
2759                "shift" : shift,
2760                "isNegative" : negative,
2761                "padding" :offset
2762            };
2763        }
2764    });
2765
2766    NumPictureDesc.gsDB = "DB";
2767    NumPictureDesc.gsCR = "CR";
2768    NumPictureDesc.gsE = "E";
2769    NumPictureDesc.gsDSP = "  ";
2770    NumPictureDesc.gsSSP = " ";
2771
2772})(_,xfalib);
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784    /**
2785 * @package xfalib.ut.TimeInfo
2786 * @import xfalib.ut.Class
2787 * @fileOverview A wrapper class for date related information.
2788 * @version 0.0.1
2789 */
2790
2791/**
2792 * @constructor
2793 */
2794(function(_,xfalib){
2795    var TimeInfo = xfalib.ut.TimeInfo = xfalib.ut.Class.extend({
2796
2797        initialize: function() {
2798            this.mHourOfMeriDiem = -1;
2799            this.mHourOfDay = -1;
2800            this.mMinuteOfHour = -1;
2801            this.mSecondOfMinute = -1;
2802            this.mThousandthOfSecond = -1;
2803        },
2804
2805        getISOTime : function(){
2806            var timeStr = "";
2807            if(this.mThousandthOfSecond>0){
2808                timeStr = "-" + this.formatNum(this.mThousandthOfSecond,3);
2809            }
2810            if(this.mSecondOfMinute>0 || timeStr!=""){
2811                timeStr = this.formatNum(this.mSecondOfMinute,2)+timeStr;
2812                timeStr = ":"+timeStr;
2813            }
2814            if(this.mMinuteOfHour>0 || timeStr!=""){
2815                timeStr = this.formatNum(this.mMinuteOfHour,2)+timeStr;
2816                timeStr = ":"+timeStr;
2817            }
2818            timeStr = this.formatNum(this.mHourOfDay,2) + timeStr;
2819
2820            return timeStr;
2821        },
2822
2823        formatNum : function(num, digits){
2824            if(num<0){
2825                num = 0;
2826            }
2827            return xfalib.ut.PictureUtils.padding(num, digits);
2828        },
2829
2830        getDate : function(){
2831            var date = new Date();
2832            this.setTime(date);
2833            return date;
2834        },
2835
2836        setTime : function(date){
2837            date.setHours(this.mHourOfDay);
2838            date.setMinutes(this.mMinuteOfHour);
2839            date.setSeconds(this.mSecondOfMinute);
2840            date.setMilliseconds(this.mThousandthOfSecond);
2841        }
2842    });
2843
2844    /**
2845     *
2846     * <p>Valid ISO8601/XFA time strings are in any one
2847     * of the following time patterns:
2848     * <ul>
2849     * <li> HH[MM[SS[.FFF][z]]]
2850     * <li> HH[MM[SS[.FFF][+HH[MM]]]]
2851     * <li> HH[MM[SS[.FFF][-HH[MM]]]]
2852     * <li> HH[:MM[:SS[.FFF][z]]]
2853     * <li> HH[:MM[:SS[.FFF][+HH[:MM]]]]
2854     * <li> HH[:MM[:SS[.FFF][-HH[:MM]]]]
2855     * </ul>
2856     */
2857    TimeInfo.Parse = function(isoDateStr, locale){
2858        var scanner = new xfalib.ut.Scanner({jsonModel:{_str:isoDateStr}});
2859        var hours = scanner.readInteger(2);
2860        var minitues = -1;
2861        if(!scanner.isEOF()){
2862            scanner.optionalConsumeChar(':');
2863            minitues = scanner.readInteger(2);
2864        }
2865        var seconds = -1;
2866        if(!scanner.isEOF()){
2867            scanner.optionalConsumeChar(':');
2868            seconds = scanner.readInteger(2);
2869        }
2870        var milliseconds = -1;
2871        if(!scanner.isEOF()){
2872            scanner.optionalConsumeChar('-');
2873            milliseconds = scanner.readInteger(3);
2874        }
2875        //TODO timezone
2876        var info = new xfalib.ut.TimeInfo();
2877       TimeInfo.setPropertyIfNotNull(info,hours,"mHourOfDay");
2878       TimeInfo.setPropertyIfNotNull(info,minitues,"mMinuteOfHour");
2879       TimeInfo.setPropertyIfNotNull(info,seconds,"mSecondOfMinute");
2880       TimeInfo.setPropertyIfNotNull(info,milliseconds,"mThousandthOfSecond");
2881        return info;
2882    };
2883
2884    /**
2885     *
2886     * static method
2887     */
2888    TimeInfo.setPropertyIfNotNull = function(object, value, proName){
2889        if(value!=null){
2890            var d = Number(value);
2891            if(!isNaN(d)){
2892                object[proName] = d;
2893            }
2894        }
2895    };
2896
2897})(_,xfalib);
2898/**
2899 * @package xfalib.ut.DateInfo
2900 * @import xfalib.ut.Class
2901 * @fileOverview A wrapper class for date related information.
2902 * @version 0.0.1
2903 */
2904
2905/**
2906 * @constructor
2907 */
2908
2909(function(_,xfalib) {
2910    var DateInfo = xfalib.ut.DateInfo = xfalib.ut.Class.extend({
2911
2912        initialize: function(options) {
2913            if (options && !options.isParsingCall ) { // skip setting internal values when called while parsing date formats
2914                this.date = new Date();
2915                this._year = this.date.getFullYear();
2916                this._month = this.date.getMonth() + 1;
2917                this._day = this.date.getDay();
2918            }
2919            DateInfo._super.initialize.call(this);
2920        },
2921
2922        formatNum : function(num, digits){
2923            if(num<0)
2924                num = 0;
2925            return xfalib.ut.PictureUtils.padding(num, digits);
2926        },
2927
2928        getDate : function(){
2929            return this.date;
2930        },
2931        setDate : function() {
2932          this.date = new Date(this._year,this._month-1,this._day)
2933        },
2934        getISODate : function(){
2935            var isoDate = [];
2936
2937            isoDate.push(this.formatNum(this._year, 4));
2938            isoDate.push("-");
2939            isoDate.push(this.formatNum(this._month, 2));
2940            isoDate.push("-");
2941            isoDate.push(this.formatNum(this._day, 2));
2942
2943            return isoDate.join("");
2944        },
2945
2946        year : function(y) {
2947            if(y && y > 0 && y <= 9999)
2948                this._year = y;
2949            else
2950                throw "undefined year";
2951        },
2952
2953        month : function(m) {
2954            if(m && m>0 && m < 13) {
2955               this._month = m;
2956            }
2957            else
2958                throw "Invalid month " + m;
2959        },
2960
2961        _leapYear : function() {
2962            var year = this._year;
2963            return year % 400 == 0 || (year % 100 != 0 && year % 4 == 0);
2964        },
2965
2966        _maxDate : function(m) {
2967              if(this._leapYear() && m == 2)
2968                 return 29;
2969              else return DateInfo.dates[m-1];
2970        },
2971
2972        day : function(d) {
2973            if(d && d > 0 && d <= this._maxDate(this._month || 0))
2974                this._day = d;
2975            else
2976                throw "Invalid Date "+ d + " for the month "+(this._month);
2977        },
2978
2979        validate : function(y, m, d) {
2980                this.year(y);
2981                this.month(m);
2982                this.day(d);
2983        }
2984    });
2985
2986    DateInfo.ParseIsoString = function(isoDateStr, locale){
2987		var isDateRegexp = /^(\d{4})(?:-?(\d{1,2})(?:-?(\d{1,2}))?)?(?:T((\d{2}):(\d{2}):(\d{2}))Z)?$/;
2988        var match = isDateRegexp.exec(isoDateStr);
2989        if(match && match.length >= 4){
2990            var dateInfo = new DateInfo();
2991            var date = new Date(isoDateStr);
2992            // TODO - check if date is invalid.
2993            if(match[4] && date != null) { // if time is available then use date object for conversion otherwise use previous approach to support invalid date like 2012-10-101, 2010-02-29 etc for RTC CQ-4201274
2994                dateInfo.year(date.getFullYear());
2995                dateInfo.month(date.getMonth()+1);
2996                dateInfo.day(date.getDate());
2997            } else {
2998                try {
2999                    dateInfo.year(Number(match[1]));
3000                    dateInfo.month(Number(match[2]));
3001                    dateInfo.day(Number(match[3]));
3002                } catch(e) {
3003                    return null;
3004                }
3005            }
3006            dateInfo.setDate();
3007            return dateInfo;
3008        }
3009        return null;
3010    };
3011
3012    DateInfo.Parse = function(dateStr, locale, validateWithDefaultPatterns){
3013        locale = locale || "en_US";
3014        var patterns = xfalib.ut.PictureUtils.getLocaleObject(locale,"datePatterns"),
3015            isoDate = this.ParseIsoString(dateStr, locale);
3016        if(!_.isEmpty(isoDate)) {
3017            return isoDate;  // in case edit pattern is present, it'll be parsed by the widget during input and return an iso date string.
3018        }
3019        //if edit pattern is present then don't try to match it from default locale patterns.
3020        if(validateWithDefaultPatterns === false){
3021            _.find(patterns, function(pattern) {
3022                try {
3023                    isoDate = xfalib.ut.PictureFmt.parseDate(dateStr,pattern,locale);
3024                    return true;
3025                } catch(exception) {
3026                    return false;
3027                }
3028            });
3029        }
3030        isoDate = isoDate || dateStr;
3031        return DateInfo.ParseIsoString(isoDate);
3032    };
3033
3034    DateInfo.dates = [31,28,31,30,31,30,31,31,30,31,30,31];
3035    DateInfo.daysOfWeek = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
3036})(_,xfalib);
3037/**
3038 * @package xfalib.ut.PictureEngine
3039 * @import xfalib.ut.Scanner
3040 * @fileOverview The file is a facade to assembly all components together.
3041 * @version 0.0.1
3042 */
3043(function(_,xfalib) {
3044
3045    var PictureEngine = xfalib.ut.PictureEngine = xfalib.ut.Class.extend({
3046
3047        _lookupNext: xfalib.ut.Scanner.lookupNext,
3048
3049        MAX_XFA_PREC	: 8,		// Max no. of fractional digits in XFA.
3050        MAX_DBL_DIG	:18,		// Max no. of significant digits in a double.
3051        MAX_INT_DIG	:10,		// Max no. of significant digits in an integer.
3052        MAX_DBL_WIDTH	:15,		// Max width before precision loss in a double.
3053        INTEGRAL_FMT :  0,
3054        DECIMAL_FMT : 1,
3055        CURRENCY_FMT : 2,
3056        PERCENT_FMT : 3,
3057
3058        parseDate : function(sSource, sPicture, locale){
3059            return this._acceptVisitor(new xfalib.ut.DateParsingVisitor({jsonModel:{_sPicture:sPicture,_dataString:sSource,_locale:this.jsonModel.locale}}));
3060        },
3061
3062        formatDate : function(dDate, sPicture){
3063            var validateWithDefaultPatterns = typeof sPicture !== 'undefined';
3064            var dateInfo = xfalib.ut.DateInfo.Parse(dDate, this.jsonModel.locale, validateWithDefaultPatterns);
3065            if(dateInfo == null){
3066                return null;
3067            }else{
3068                return this._acceptVisitor(new xfalib.ut.DateFormattingVisitor({jsonModel:{_sPicture:sPicture,_dateInfo:dateInfo,_locale:this.jsonModel.locale}}));
3069            }
3070        },
3071
3072        parseTime : function(sSource, sPicture){
3073            return this._acceptVisitor(new xfalib.ut.TimeParsingVisitor({jsonModel:{_sPicture:sPicture,_dataString:sSource}}));
3074        },
3075
3076        formatTime : function(dDate, sPicture){
3077            var timeInfo = xfalib.ut.TimeInfo.Parse(dDate, this.jsonModel.locale);
3078            if(timeInfo == null){
3079                return null;
3080            }else{
3081                return this._acceptVisitor(new xfalib.ut.TimeFormattingVisitor({jsonModel:{_sPicture:sPicture,_timeInfo:timeInfo}}));
3082            }
3083        },
3084
3085        parseText : function(sSource, sPicture){
3086            return this._acceptVisitor(new xfalib.ut.TextParsingVisitor({jsonModel:{_sPicture:sPicture,_dataString:sSource}}));
3087        },
3088
3089        formatText : function(sSource, sPicture,bRelaxed){
3090            return this._acceptVisitor(new xfalib.ut.TextFormattingVisitor({jsonModel:{_sPicture:sPicture,_text:sSource,relaxed:bRelaxed}}));
3091        },
3092
3093        parseNumeric : function(sSource, sPicture){
3094            var visitor = new xfalib.ut.NumParsingVisitor({jsonModel:{_sPicture:sPicture,_dataString:sSource,_locale:this.jsonModel.locale}}); // TODO : Is locale required
3095            visitor.parse();
3096            return visitor.getResult();
3097        },
3098
3099       formatNumeric : function(sSource, sPicture,locale,bRelaxed,bFormatNumberFromasDefaultPC){
3100
3101             var sFormatPicture =sPicture;
3102             if( bRelaxed && bFormatNumberFromasDefaultPC){
3103                 sFormatPicture = this.getNumberFormat(sPicture,1, {formatOption: "WITH_GROUPINGS",
3104                                      "precision"  : this.getNumberPrecision(sSource),
3105                                    "width"      : sSource.length
3106                                   });
3107             }
3108             return this._acceptVisitor(new xfalib.ut.NumFormattingVisitor({jsonModel:{_sPicture:sFormatPicture,_locale:this.jsonModel.locale},text:sSource}));
3109        },
3110
3111        _acceptVisitor : function(visitor){
3112            this._scanPattern(visitor);
3113            return visitor.getResult();
3114        },
3115
3116        _scanPattern : function(visitor){
3117            var patPos = 0;
3118            var sPicture = visitor.getPicture();
3119            for(var token = this._lookupNext(sPicture, patPos, visitor.acceptPatternChar); token != null;  ){
3120                visitor.consume(token);
3121                patPos = patPos + token.len;
3122                token = this._lookupNext(sPicture, patPos, visitor.acceptPatternChar);
3123            }
3124        },
3125
3126       /**
3127          * Removes n bytes from this string starting at position nOffset.
3128         *
3129          * @param nOffset - start position for the remove
3130          * @param nLength - the number of characters to remove
3131          * @return This string
3132          */
3133
3134         _swallow : function(sString , nOffset, nLenToSwallow)
3135         {
3136             if(_.isEmpty(sString) || nLenToSwallow ==0){
3137                 return sString;
3138             }
3139
3140             if( (nOffset + nLenToSwallow)> sString.length ) {
3141                 nLenToSwallow = (nOffset + nLenToSwallow) - sString.length;
3142             }
3143            var subStr = sString.substr(0,nOffset) + sString.substr(offset + nLenToSwallow);
3144
3145             return subStr
3146         },
3147         /**
3148         * Replace some portion of one string with another String.
3149          * @param sString - the String where it has to be replaced.
3150          * @param sReplacement - the replacement string.
3151          * @param nOffset - start position for the replacement. Default value = 0.
3152          * @param nCutLength - the number of bytes to remove from the
3153          * original string.
3154          */
3155
3156         _replaceAll : function(sString ,sReplacement , nOffset ,nCutlength) {
3157             return sString.substr(0,nOffset) + sReplacement  + sString.substr(nOffset + nCutlength)
3158         },
3159
3160         //----------------------------------------------------------------------
3161         // SkipOver
3162         //
3163         // Scan this string for the first byte of the character not in the given set.
3164         // Similar to strspn().
3165         //----------------------------------------------------------------------
3166         _skipOver : function(fromString,sSkip, nOffset)
3167         {
3168             // starting at the offset position, scan the characters in this string
3169             // until it does not match any of the characters in the given set.
3170            var nCharsSkipped = nOffset;
3171             var i = 0;
3172             while (nCharsSkipped < fromString.length)
3173             {
3174                 i = nCharsSkipped;
3175                 if (sSkip.indexOf(fromString[i]) ==-1) {
3176                     break;
3177                 }
3178                 i++;
3179                 nCharsSkipped = i;
3180             }
3181
3182             return nCharsSkipped - nOffset;
3183         },
3184
3185         /*
3186          * Get the numeric format in the given style.
3187          * @param style in the range of values 0-2,
3188          * where (0 = integral, 1 = decimal, 2 = currency).
3189          * @param option in the set of format options:
3190          */
3191         getNumberFormat : function(format , style, option)
3192        {
3193             if (style < this.INTEGRAL_FMT || this.PERCENT_FMT < style) {
3194                 style = this.DECIMAL_FMT;
3195             }
3196
3197             var sFormat = format;
3198
3199             //
3200             // Use any alternate part because they handle negative values.
3201             //
3202             var  nBar = 0;
3203             if ((nBar = sFormat.indexOf('|')) != -1) {
3204                 sFormat = this._swallow(sFormat, 0, nBar + 1);
3205             }
3206             //
3207             // Determine position of radix (or anything like it)
3208             // and the replicating part of the pattern, i.e., from
3209             // the separator to this radix.
3210            //
3211             var nDot;
3212             if ( (nDot = sFormat.indexOf('.')) == -1) {
3213                 if ((nDot = sFormat.indexOf('v')) == -1) {
3214                     if ((nDot = sFormat.indexOf('V')) == -1) {
3215                         if ((nDot = sFormat.indexOf('E')) == -1) {
3216                             if ((nDot = sFormat.indexOf(' ')) == -1) {
3217                                 if ((nDot = sFormat.indexOf('%')) == -1) {
3218                                     nDot = sFormat.length;
3219                                 }
3220                             }
3221                         }
3222                     }
3223                 }
3224             }
3225             if (nDot) {
3226                 if (this._skipOver(sFormat,"89zZ", nDot - 1) != 1) {
3227                     nDot = sFormat.length;
3228                 }
3229             }
3230             var sZZZ;
3231             var nZed;
3232             if ( (nZed = sFormat.indexOf("z,")) != -1) {
3233                 //
3234                 // Watson 1230768.  Handle locales, like India, that have
3235                 // pictures with more than one grouping symbol.
3236                //
3237                 var nSep = nDot;
3238                 var nComma;
3239                 if ((nComma = sFormat.indexOf(',', nZed + 2)) !=-1) {
3240                    nSep = nComma;
3241                 }
3242                 if (nSep > nZed + 2) {
3243                     sZZZ = Array(nSep - nZed).join('z');
3244                 }
3245                 else {
3246                     sZZZ = Array(1).join('z');
3247                 }
3248             }
3249             else {
3250                nZed = 0;
3251             }
3252             //
3253             // If non-integral styles Then determine width and precision.
3254             //
3255             var nPrec = 0;
3256             var nWidth = this.MAX_INT_DIG;
3257             if (style != this.INTEGRAL_FMT) {
3258                 nPrec = option.precision; // (option >> 8) & 0xff;
3259                 var trim = ((nPrec & 0x80) == 0);
3260                 nPrec &= 0x7f;
3261                 if (nPrec == 0x7f) {
3262                     nPrec = this._skipOver(sFormat, "89zZ", nDot + 1);
3263                 }
3264                 if ((option.width) != undefined) {
3265                     nWidth = option.width;
3266                 }
3267                 else {
3268                     nWidth = this.MAX_DBL_DIG;
3269                 }
3270                 //
3271                 // Fix for Watson 1229423.  If the locale's format contains
3272                 // any sign pictures Then widen accordingly.  Also widen if
3273                 // precision of locale's picture format is greater than requested.
3274                 //
3275                 if (sFormat.indexOf('s')!=-1) {
3276                     nWidth += 1;
3277                 }
3278                 if (sFormat.indexOf('(')!=-1) {
3279                     nWidth += 1;
3280                 }
3281                 if (sFormat.indexOf(')') !=-1) {
3282                     nWidth += 1;
3283                 }
3284                var nFmtPrec = this._skipOver(sFormat,"89zZ", nDot + 1);
3285                 if (0 < nPrec && nPrec < nFmtPrec) {
3286                     nWidth += nFmtPrec - nPrec;
3287                 }
3288
3289                 //
3290                 // Pare down the precision if the width is big enough to yield
3291                 // IEEE 754 64-bit double precision errors, which appears to be
3292                 // anything over 14 significant digits.
3293                 //
3294                 if (trim && nPrec > 0 && nWidth > nPrec) {
3295                     //
3296                     // Fix for Watson 1211481.  If the given precision is less
3297                     // than what the locale's format dictates then widen the given
3298                     // width.
3299                    //
3300                     if (nPrec <= sFormat.length - 1 - nDot) {
3301                         nWidth += sFormat.length - 1 - nDot - nPrec;
3302                     }
3303                     for (var i = nWidth - 1; i > this.MAX_DBL_WIDTH; i--) {
3304                         //
3305                         // Never pare down the precision below what the locale's
3306                         // format dictates.
3307                         //
3308                         if (nPrec <= sFormat.length - 1 - nDot)
3309                            break;
3310                         nPrec--;
3311                     }
3312                 }
3313             }
3314             //Watson 1483675 - If the locale's format contains
3315             // a dollar sign or a space then widen accordingly.
3316             if (style == this.CURRENCY_FMT) {
3317                 if (sFormat.indexOf('$')!=-1) {
3318                     nWidth++;
3319                 }
3320
3321                 if (sFormat.indexOf(' ')!=-1) {
3322                     nWidth += 1;
3323                }
3324             }
3325
3326             //
3327             // If percent style was wanted Then truncate after the percent character.
3328             //
3329             if (style == this.PERCENT_FMT) {
3330                 var nTrim = this._skipOver(sFormat,"89zZ", nDot + 1);
3331                 sFormat = this._replaceAll(sFormat,"",nTrim,0)
3332                 //sFormat.Replace(jfString::EmptyString(), nDot + 1, nTrim);
3333
3334                 //Watson 1483675 - If the locale's format contains
3335                 // a percent sign then widen accordingly.
3336                 if (sFormat.indexOf('%')!=-1) {
3337                     nWidth++;
3338                 }
3339             }
3340             //
3341             // Else if integral style was wanted Then truncate at the radix character.
3342             //
3343             //
3344             // If integral style was wanted Then truncate at the radix character.
3345             //
3346             else if (style == this.INTEGRAL_FMT || nPrec == 0){// && option.formatOption == "WITHOUT_RADIX") {
3347                 var nTrim = this._skipOver(sFormat,"89zZ", nDot + 1);
3348                 sFormat = this._replaceAll(sFormat,"",nDot,nTrim+1);
3349             }
3350             //
3351             // Otherwise for decimal and currency styles Do
3352             // replace fractional 'z' pictures with '8's to requested precision,
3353             //
3354             else if (option.formatOption == "WITH_EIGHTS") {
3355                 var nEight = nDot + 1;
3356                 while ((nEight =sFormat.indexOf('z'))!=-1) {
3357                     this._replaceAll(sFormat, '8', nEight,'8'.length);
3358                 }
3359                 while (sFormat.Length() - nDot <= nPrec) {
3360                     sFormat = this._replaceAll(sFormat, "8", nDot + 1, 0);
3361                 }
3362             }
3363             //
3364             // Or replace fractional '9' pictures with 'z's to requested precision
3365             // Watson 1322850 - add option to keep nines, previously this function
3366             // would force frac. digits to be either z's or 8's with no option for 9's.
3367             //
3368             else if ((option.formatOption) == "WITH_ZEDS" && !((option.formatOption) == "KEEP_NINES")) {
3369                 var nNine = nDot + 1;
3370                 while ((nNine = sFormat.indexOf('9'))!=-1) {
3371                     this._replaceAll(sFormat, 'z', nNine,1);
3372                 }
3373                 while (sFormat.Length() - nDot <= nPrec) {
3374                     this._replaceAll(sFormat, "z", nDot + 1, 0);
3375                 }
3376             }
3377             //
3378             // Replicate section from separator to radix to requested width.
3379             //
3380             if (!sZZZ) {
3381                 sZZZ = "z";
3382             }
3383            else if ((option.formatOption) == "WITHOUT_GROUPINGS" ) {
3384                 //
3385                 // Watson 1230768.  Handle locales, like India, that have
3386                 // pictures with more than one grouping symbol.
3387                 //
3388                 var nComma = nZed + 1 ;
3389                 this._replaceAll(sFormat, 'z' ,nComma,1);
3390                 while ( nComma!= -1 && (nComma < nDot)) {
3391                     nComma = sFormat.indexOf(',');
3392                     sFormat = this._replaceAll(sFormat,'z',nComma,1);
3393                 }
3394             }
3395             else if ((option.formatOption == "WITH_GROUPINGS")) {
3396                 sZZZ = this._replaceAll(sZZZ,',',0,1);
3397                 nWidth += (nWidth + sZZZ.length) / sZZZ.length;
3398             }
3399             while (sFormat.length < nWidth) {
3400                 sFormat = this._replaceAll(sFormat, sZZZ, nZed + 1, 0);
3401             }
3402             return sFormat;
3403         },
3404
3405         /**
3406          * Get the decimal precision of the given numeric string.
3407          * @return the decimal precision or 0 for integral values.
3408          */
3409         getNumberPrecision: function(sVal)
3410         {
3411             var nRadix = 0;
3412             var i = -1;
3413             // Reason for not using the commented line. We are always storing the value in model with . as decimal separator
3414             // Passing field locale/ browser locale would lead to precision width being zero for non-english locales where
3415             // decimal separater may be different.
3416             // var rIndex = xfalib.ut.PictureUtils.getLocaleObject(this.jsonModel.locale,"numberSymbols").decimal;
3417             // so hardcoding . for now
3418             var rIndex = ".";
3419             if( (nRadix = sVal.indexOf(rIndex))!=-1)
3420             {
3421                     for(; nRadix <=sVal.length ;nRadix++) {
3422                         i++;
3423                     }
3424
3425                 return i;
3426             }
3427             return 0;
3428          }
3429    })
3430})(_,xfalib);
3431/**
3432 * @package xfalib.ut.FormattingVisitorBase
3433 * @import xfalib.ut.VisitorBase
3434 * @fileOverview Base class for visitor
3435 * @version 0.0.1
3436 */
3437
3438/**
3439 * @constructor
3440 * @param Object {jsonModel: {_sPicture: String]}
3441 */
3442
3443(function(_,xfalib) {
3444    var FormattingVisitorBase = xfalib.ut.FormattingVisitorBase = xfalib.ut.VisitorBase.extend({
3445
3446        initialize: function() {
3447            this._buffer = []; //TODO: ASK Ren where does this _buffer comes from
3448            FormattingVisitorBase._super.initialize.call(this);
3449        },
3450
3451        consumeStringWildCard : function(token){
3452            //'?' '*' '+
3453            this._buffer.push(" ");
3454        },
3455
3456        consumeStringLiteral : function(token){
3457            this._buffer.push(this.jsonModel._sPicture.substr(token.startPos+1,token.len-2));
3458        },
3459
3460        consumeCharLiteral : function(token){
3461            this._buffer.push(""+ this.jsonModel._sPicture.charAt(token.startPos));
3462        }
3463    })
3464
3465})(_,xfalib);
3466/**
3467 * @package xfalib.ut.ParsingVisitorBase
3468 * @import xfalib.ut.VisitorBase
3469 * @fileOverview Base class for visitor
3470 * @version 0.0.1
3471 */
3472
3473/**
3474 * @constructor
3475 * @param Object {jsonModel: {_sPicture: String,_dataString: String}}
3476 */
3477
3478(function(_,xfalib){
3479    var ParsingVisitorBase = xfalib.ut.ParsingVisitorBase = xfalib.ut.VisitorBase.extend({
3480
3481        initialize: function() {
3482            this._strLen = this.jsonModel._dataString.length;
3483            this._strPos = 0;
3484            ParsingVisitorBase._super.initialize.call(this);
3485        },
3486
3487        consumeStringWildCard : function(token){
3488            if (chr == '?') {
3489                if (this._strPos < this._strLen)//&& Character.isDefined(str.charAt(strPos))
3490                    this._strPos += 1;
3491            } else if (chr == '+') {
3492                if (this._strPos >= this._strLen)// || ! Character.isWhitespace(str.charAt(strPos)))
3493                    throw "Mismatch";
3494                this._strPos += 1;
3495                while (this._strPos < this._strLen)// && Character.isWhitespace(str.charAt(strPos)))
3496                    this._strPos += 1;
3497            } else if (chr == '*') {
3498                while (this._strPos < this._strLen)// && Character.isWhitespace(str.charAt(strPos)))
3499                    this._strPos += 1;
3500            }
3501
3502        },
3503
3504        consumeStringLiteral : function(token){
3505            for(var offset=0; offset<token.len-2 ;offset++){ //-2, heading and trailing quote
3506                if(this.jsonModel._sPicture.charAt(token.startPos+offset+1) != this.jsonModel._dataString.charAt(this._strPos+offset)){
3507                    throw ("Mismatch" + this.jsonModel._sPicture.substr(token.startPos, token.len));
3508                }
3509            }
3510            this._strPos += token.len-2;
3511
3512        },
3513
3514        consumeCharLiteral : function(token){
3515            if(this.jsonModel._sPicture.charAt(token.startPos) == this.jsonModel._dataString.charAt(this._strPos)){
3516                this._strPos += 1;
3517            }else{
3518                throw "Mismatch";
3519            }
3520        }
3521    })
3522})(_,xfalib);
3523
3524/**
3525 * @package xfalib.ut.DateFormattingVisitor
3526 * @import xfalib.ut.FormattingVisitorBase
3527 * @fileOverview The file provides formating logic on date pattern characters.
3528 * @version 0.0.1
3529 */
3530
3531
3532/**
3533 * @constructor
3534 * @param object {jsonModel: {_sPicture:String,_dateInfo: xfalib.ut.DateInfo}}
3535 */
3536
3537(function(_,xfalib) {
3538    var PictureUtils =  xfalib.ut.PictureUtils;
3539    var DateFormattingVisitor = xfalib.ut.DateFormattingVisitor = xfalib.ut.FormattingVisitorBase.extend({
3540
3541        consumeSubPattern : function(token){
3542            var chr = token.patChar;
3543            var chrCnt = token.len;
3544
3545            switch (chr) {
3546                case 'D':
3547                    var dayOfMonth=this.jsonModel._dateInfo.date.getDate();
3548                    switch(chrCnt){
3549                        case 1:
3550                            break;
3551                        case 2:
3552                            dayOfMonth = PictureUtils.padding(dayOfMonth,2);
3553                            break;
3554                    }
3555                    this._buffer.push(PictureUtils.convertNumberToLocale(this.jsonModel._locale,dayOfMonth));
3556                    break;
3557                case 'J':
3558
3559                    //this._mDayOfYear;
3560                    break;
3561                case 'M':
3562                    var monthOfYear = this.jsonModel._dateInfo.date.getMonth();
3563                    switch(chrCnt){
3564                        case 1:
3565                            this._buffer.push(PictureUtils.convertNumberToLocale(this.jsonModel._locale,monthOfYear+1));
3566                            break;
3567                        case 2:
3568                            this._buffer.push(PictureUtils.convertNumberToLocale(this.jsonModel._locale,PictureUtils.padding(monthOfYear+1,2)));
3569                            break;
3570                        case 3:
3571                            var monthNames = PictureUtils.getLocaleObject(this.jsonModel._locale,"calendarSymbols.abbrmonthNames");
3572                            this._buffer.push(monthNames[monthOfYear]);
3573                            break;
3574                        case 4:
3575                            var monthNames = PictureUtils.getLocaleObject(this.jsonModel._locale,"calendarSymbols.monthNames");
3576                            this._buffer.push(monthNames[monthOfYear]);
3577                            break;
3578                    }
3579
3580                    break;
3581                case 'E':
3582                    var dayOfWeek = this.jsonModel._dateInfo.date.getDay();
3583                    var dayNames;
3584                    switch(chrCnt) {
3585                        case 1:
3586                            this._buffer.push(dayOfWeek);
3587                            break;
3588                        case 3:
3589                            dayNames =  PictureUtils.getLocaleObject(this.jsonModel._locale,"calendarSymbols.abbrdayNames");
3590                            this._buffer.push(dayNames[dayOfWeek]);
3591                            break;
3592                        case 4:
3593                            dayNames =   PictureUtils.getLocaleObject(this.jsonModel._locale,"calendarSymbols.dayNames");
3594                            this._buffer.push(dayNames[dayOfWeek]);
3595                            break;
3596                        default:
3597                            throw "unsupported Picture Clause ";
3598                    }
3599                    break;
3600                case 'e':
3601                    break;
3602                case 'G':
3603                    break;
3604                case 'Y':
3605
3606                    var yearOfEra = this.jsonModel._dateInfo.date.getFullYear()
3607                    switch(chrCnt){
3608                        case 2:
3609                            if(yearOfEra>2029 || yearOfEra < 1930){
3610                                throw "unsupported " + yearOfEra + " by pattern YY";
3611                            }
3612                            yearOfEra = PictureUtils.padding(yearOfEra % 100, 2);
3613                            break;
3614                        case 4:
3615                            yearOfEra = PictureUtils.padding(yearOfEra, 4); // 2 digit(0000-9999)
3616                            break;
3617                    }
3618                    this._buffer.push(PictureUtils.convertNumberToLocale(this.jsonModel._locale,yearOfEra));
3619                    break;
3620                case 'w':
3621                    break;
3622                case 'W':
3623                    break;
3624                default: throw "Unsupported pattern";
3625            }
3626
3627        },
3628        /**
3629         *
3630         * @override
3631         */
3632        getResult : function(){
3633            return this._buffer.join("");
3634        }
3635
3636    });
3637})(_,xfalib);
3638
3639
3640/**
3641 * @package xfalib.ut.TextFormattingVisitor
3642 * @import xfalib.ut.FormattingVisitorBase
3643 * @fileOverview Formats a string according to Text Picture.
3644 * @version 0.0.1
3645 */
3646
3647/**
3648 * @constructor
3649 * @param Object { jsonModel:{_sPicture: String, _text: String}}
3650 */
3651(function(_,xfalib){
3652    var TextFormattingVisitor = xfalib.ut.TextFormattingVisitor = xfalib.ut.FormattingVisitorBase.extend({
3653
3654        initialize: function() {
3655            this._textPos = 0;
3656            this._relaxed = typeof this.jsonModel.relaxed === "undefined" ? true: this.jsonModel.relaxed;
3657            TextFormattingVisitor._super.initialize.call(this);
3658        },
3659
3660        consumeSubPattern : function(token){
3661            var chr = token.patChar;
3662            var chrCnt = token.len;
3663            for(var index = 0; index < chrCnt && (!this._relaxed || this._textPos < this.jsonModel._text.length); index++){
3664                switch (chr) {
3665                    case '9': // Numeric
3666                        var cUni = this.jsonModel._text.charAt(this._textPos++);
3667                        if(!xfalib.ut.PictureUtils.isDigit(cUni)){
3668                            throw "TextFormatting: not a digit as expected";
3669                        }
3670                        this._buffer.push(cUni);
3671                        break;
3672                    case 'A': // Alphebetic
3673                        var cUni = this.jsonModel._text.charAt(this._textPos++);
3674                        if(!xfalib.ut.PictureUtils.isLetter(cUni)){
3675                            throw "TextFormatting: not a character as expected";
3676                        }
3677                        this._buffer.push(cUni);
3678                        break;
3679                    case 'O': // Alphanumeric
3680                    case '0':
3681                        var cUni = this.jsonModel._text.charAt(this._textPos++);
3682                        // cUni === "" is a hack for LC-6152
3683                        // To prevent extra loop[one more time than the length of the string] for which cUni was ""
3684                        // which was neither a letter nor a digit
3685                        // so we were getting textformatting error
3686                        //which caused email id validation to fail for chars less than picture clause
3687                        if(!(cUni ==="" || xfalib.ut.PictureUtils.isLetter(cUni) || xfalib.ut.PictureUtils.isDigit(cUni))){
3688                            throw "TextFormatting: not a character or digit as expected";
3689                        }
3690                        this._buffer.push(cUni);
3691                        break;
3692                    case 'X':
3693                        var cUni = this.jsonModel._text.charAt(this._textPos++);
3694                        this._buffer.push(cUni);
3695                        break;
3696                    case 't':
3697                        this._buffer.push("\t");
3698                        break;
3699                    default: this._buffer.push(chr);
3700                }
3701            }
3702
3703        },
3704
3705        /**
3706         *
3707         * @override
3708         */
3709        getResult : function(){
3710            if(this._textPos < this.jsonModel._text.length)
3711                throw "TextFormatting: picture clause smaller than input Text";
3712            return this._buffer.join("");
3713        },
3714
3715        /**
3716         *
3717         * @override
3718         */
3719        acceptPatternChar : function(chr){
3720            return xfalib.ut.PictureUtils.inString(chr, "9AO0Xt");
3721        },
3722
3723        consumeCharLiteral : function(token){
3724         this._buffer.push(""+ this.jsonModel._sPicture.charAt(token.startPos));
3725         // LC-3869 : forward the text pointer after literal is present and matched with the picture.
3726         if(this.jsonModel._sPicture.charAt(token.startPos) == this.jsonModel._text.charAt(token.startPos))
3727             this._textPos++;
3728        }
3729    })
3730
3731})(_,xfalib);
3732
3733
3734/**
3735 * @package xfalib.ut.TextFormattingVisitor
3736 * @import xfalib.ut.FormattingVisitorBase
3737 * @fileOverview The file provides formating logic on date pattern characters.
3738 * @version 0.0.1
3739 */
3740
3741/**
3742 * @constructor
3743 * @param object {jsonModel: {_sPicture:String,_timeInfo: xfalib.ut.TimeInfo}}
3744 */
3745
3746(function(_,xfalib){
3747    var TimeFormattingVisitor = xfalib.ut.TimeFormattingVisitor=  xfalib.ut.FormattingVisitorBase.extend({
3748
3749        consumeSubPattern : function(token){
3750            var chr = token.patChar;
3751            var chrCnt = token.len;
3752
3753            switch (chr) {
3754                case 'H':
3755                case 'K':
3756                    var hourOfDay = this.jsonModel._timeInfo.mHourOfDay;
3757                    if(chr=='K'){
3758                        hourOfDay += 1;
3759                    }
3760                    switch(chrCnt){
3761                        case 1:
3762                            this._buffer.push(hourOfDay);
3763                            break;
3764                        case 2:
3765                            this._buffer.push(xfalib.ut.PictureUtils.padding(hourOfDay,2));
3766                            break;
3767                    }
3768                    break;
3769
3770                case 'M':
3771                    var minuteOfHour = this.jsonModel._timeInfo.mMinuteOfHour;
3772                    switch(chrCnt){
3773                        case 1:
3774                            this._buffer.push(minuteOfHour);
3775                            break;
3776                        case 2:
3777                            this._buffer.push(xfalib.ut.PictureUtils.padding(minuteOfHour,2));
3778                            break;
3779                    }
3780
3781                    break;
3782                case 'S':
3783                    var secondOfMinute = this.jsonModel._timeInfo.mSecondOfMinute;
3784                    switch(chrCnt){
3785                        case 1:
3786                            this._buffer.push(secondOfMinute);
3787                            break;
3788                        case 2:
3789                            this._buffer.push(xfalib.ut.PictureUtils.padding(secondOfMinute,2));
3790                            break;
3791                    }
3792                    break;
3793                case 'F':
3794                    var Milliseconds =this.jsonModel._timeInfo.mThousandthOfSecond;
3795                    this._buffer.push(xfalib.ut.PictureUtils.padding(Milliseconds,3));
3796                    break;
3797
3798                default: throw "Unsupported pattern";
3799            };
3800
3801        },
3802
3803        /**
3804         *
3805         * @override
3806         */
3807        getResult : function(){
3808            return this._buffer.join("");
3809        }
3810
3811    });
3812
3813})(_,xfalib);
3814
3815
3816/**
3817 * @package xfalib.ut.NumFormattingVisitor
3818 * @import xfalib.ut.FormattingVisitorBase
3819 * @fileOverview Formats a string according to Text Picture.
3820 * @version 0.0.1
3821 */
3822
3823/**
3824 * @constructor
3825 * @param Object { jsonModel:{_sPicture: String}, text: String}
3826 */
3827
3828(function(_,xfalib){
3829    var PictureUtils =  xfalib.ut.PictureUtils;
3830    var NumFormattingVisitor = xfalib.ut.NumFormattingVisitor = xfalib.ut.FormattingVisitorBase.extend({
3831
3832        initialize: function(options) {
3833            NumFormattingVisitor._super.initialize.call(this);
3834            this._textPos = 0;
3835
3836            //boolean value used for internal state track
3837            this._mbDigitAddedToOutput = false; // at least one digit has been added to output
3838            this._mbSignAddedToOutput = false;
3839            this._nScannedPatternDigit = 0; //how many digit(98Zz) characters scanned in pattern, reset to 0 after '.Vv'
3840            this._mbRadixSeen = false;
3841
3842            this._pictureDesc = new xfalib.ut.NumPictureDesc({jsonModel:{_sPicture:this.jsonModel._sPicture}});
3843            this.jsonModel._sPicture= this._pictureDesc.getPicture();
3844            this._numberInfo = this._pictureDesc.parseNumberInfo(options.text);
3845
3846            this._mbNegative = this._numberInfo.isNegative;
3847            this._msText = this._numberInfo.msText;
3848            this._leadingPadding = this._numberInfo.padding;
3849            //
3850            this._mNumberSymbols = xfalib.ut.PictureUtils.getLocaleObject(this.jsonModel._locale,"numberSymbols");
3851            this._mCurrencySymbols = xfalib.ut.PictureUtils.getLocaleObject(this.jsonModel._locale,"currencySymbols");
3852        },
3853
3854        _checkAndAddDecimalPoint: function(fw) {
3855            if(this._mAddRadix) {
3856                this._buffer.push(this._fmtStr(this._mNumberSymbols.decimal, fw));
3857                this._mAddRadix = false;
3858            }
3859        },
3860
3861        consumeSubPattern : function(token){
3862            var chr = token.patChar,
3863                chrCnt = token.len;
3864            switch (chr) {
3865                case '9':
3866                case '8':
3867                case 'Z': // Digit or space if zero.
3868                case 'z':// Digit or nothing if zero.
3869                    if(!this._mbSignAddedToOutput)
3870                        this._ensureSignIsAdded();
3871                    while (chrCnt-- > 0 ) {
3872                        if(!this._mbRadixSeen){
3873                            if(this._leadingPadding > this._nScannedPatternDigit++){
3874                                var placeHolder = null;
3875                                if(this._mbDigitAddedToOutput){
3876                                    placeHolder = this._mNumberSymbols.zero;
3877                                }else{
3878                                    if(chr == '9' || chr =='8') {
3879                                        placeHolder = this._mNumberSymbols.zero;
3880                                        this._mbDigitAddedToOutput = true;
3881                                    }else if(chr == 'Z'){
3882                                        placeHolder = " ";
3883                                    }
3884                                }
3885                                if(placeHolder){
3886                                    this._buffer.push(this._matchChr(placeHolder));
3887                                }
3888                            }else {
3889                                var cValue = this._msText.charAt(this._textPos++);
3890                                this._ensureCharIsDigit(cValue);
3891                                this._buffer.push(PictureUtils.convertNumberToLocale(this.jsonModel._locale,cValue));
3892                                this._mbDigitAddedToOutput = true;
3893                            }
3894                        }else{  //handling fractional part
3895                            if(this._nScannedPatternDigit++  < this._numberInfo.fractionDigit ){
3896                                var cValue = this._msText.charAt(this._textPos++);
3897                                this._ensureCharIsDigit(cValue);
3898                                this._checkAndAddDecimalPoint();
3899                                this._buffer.push(PictureUtils.convertNumberToLocale(this.jsonModel._locale,cValue));
3900                                this._mbDigitAddedToOutput = true;
3901                            }else{
3902                                if(chr == '9'|| chr =='Z') {
3903                                    this._checkAndAddDecimalPoint();
3904                                    this._buffer.push(this._matchChr(this._mNumberSymbols.zero));
3905                                } else if(chr == '8') {
3906                                    var cValue = this._msText.charAt(this._textPos++);
3907                                    if(cValue != '' && this._ensureCharIsDigit(cValue)) {
3908                                        this._checkAndAddDecimalPoint();
3909                                        this._buffer.push(PictureUtils.convertNumberToLocale(this.jsonModel._locale,cValue));
3910                                        this._mbDigitAddedToOutput = true;
3911                                    }
3912                                }
3913                            }
3914                        }
3915
3916                    }
3917
3918                    break;
3919                case 'E': // Exponent.
3920                    this._buffer.push('E');
3921                    this._buffer.push("" + this._numberInfo.shift);
3922                    break;
3923                case 'C': // CR symbol if negative and spaces if positive.
3924                    this._buffer.push((this._mbNegative) ? xfalib.ut.NumPictureDesc.gsCR : xfalib.ut.NumPictureDesc.gsDSP);
3925                    break;
3926                case 'c': // CR symbol if negative and nothing if positive.
3927                    if (this._mbNegative){
3928                        this._buffer.push(xfalib.ut.NumPictureDesc.gsCR);
3929                    }
3930                    break;
3931                case 'D': // DB symbol if negative and spaces if positive.
3932                    this._buffer.push((this._mbNegative) ? xfalib.ut.NumPictureDesc.gsDB : xfalib.ut.NumPictureDesc.gsDSP);
3933                    break;
3934                case 'd': // DB symbol if negative and nothing if positive.
3935                    if (this._mbNegative){
3936                        this._buffer.push(xfalib.ut.NumPictureDesc.gsDB);
3937                    }
3938                    break;
3939                case 'S': // Minus sign if negative and a space if positive.
3940                case 's':
3941                    if (this._mbNegative){
3942                        this._buffer.push(this._fmtStr(	this._mNumberSymbols.minus));
3943                    }else{
3944                        if('S' == chr){
3945                            this._buffer.push(this._matchChr(' '));
3946                        }
3947                    }
3948                    break;
3949                case 'V': // Implied decimal sign if parsing.
3950                case '.':
3951                case 'v': // Implied decimal sign.
3952                    if (this._textPos < this._msText.length && this._msText.charAt(this._textPos) == '.'){
3953                        this._textPos++; //consume a '.'
3954                    }
3955                    if (chr == 'V' || chr == '.'){
3956                        this._mAddRadix = true;
3957                        //this._buffer.push(this._fmtStr(this._mNumberSymbols.decimal, ));
3958                    }
3959                    this._mbRadixSeen = true;
3960                    this._nScannedPatternDigit = 0;
3961                    break;
3962
3963                case 0xFF0C: // Fullwidth ','.
3964                case ',': // Grouping separator.
3965                    while (chrCnt-- > 0) {
3966                        if (this._mbDigitAddedToOutput){
3967                            this._buffer.push(this._fmtStr(	this._mNumberSymbols.grouping ));
3968                        }
3969                        this._mbCommaSeen = true;
3970                    }
3971                    break;
3972                case 0xFF04: // Fullwidth '$'.
3973                case '$': // Currency name or symbol.
3974                    while (chrCnt-- > 0) {
3975                        this._buffer.push(this._fmtStr(	this._mCurrencySymbol
3975s.symbol ));
3976                    }
3977                    break;
3978                case 0xFF05: // Fullwidth '%'.
3979                case '%': // Percent symbol.
3980                    while (chrCnt-- > 0) {
3981                        this._buffer.push(this._fmtStr(	this._mNumberSymbols.percent));
3982                    }
3983                    break;
3984                case 0xFF08: // Fullwidth '('.
3985                case 0xFF09: // Fullwidth ')'.
3986                case '(': // Left parenthesis.
3987                case ')': // Right parenthesis.
3988                    this._buffer.push(this._matchChr((this._mbNegative) ? chr : ' '));
3989                    break;
3990                default:
3991            }
3992        },
3993
3994        _ensureCharIsDigit : function(cValue){
3995            if ('0' > cValue || cValue > '9'){
3996                throw "Nuberic Formatting: not a digit as expected " + cValue;
3997            }
3998        },
3999
4000
4001        _fmtStr : function(str){
4002            return str;
4003        },
4004
4005        _matchStr : function(str){
4006            return str;
4007        },
4008
4009        _matchChr : function(str){
4010            return str;
4011        },
4012
4013        _ensureSignIsAdded : function(){
4014            if (this._mbNegative && ! this._mbDigitAddedToOutput && ! this._pictureDesc.hasSign) {
4015                this._buffer.push(this._mNumberSymbols.minus);
4016                this._mbSignAddedToOutput = true;
4017            }
4018        },
4019
4020        /**
4021         *
4022         * @override
4023         */
4024        getResult : function(){
4025            return this._buffer.join("");
4026        },
4027
4028        /**
4029         *
4030         * @override
4031         */
4032        acceptPatternChar : function(chr){
4033            return xfalib.ut.PictureUtils.inString(chr, "(%$,.)89BCDERSVZbcdrsvzt");
4034        }
4035
4036    });
4037
4038})(_,xfalib);
4039
4040
4041/**
4042 * @package xfalib.ut.TimeParsingVisitor
4043 * @import xfalib.ut.ParsingVisitorBase
4044 * @fileOverview The file provides parsing/formating logic on date pattern characters.
4045 * @version 0.0.1
4046 */
4047
4048/**
4049 * @constructor
4050 * @param Object {jsonModel: {_sPicture: String, _dataString: String]}
4051 */
4052
4053(function(_,xfalib){
4054    var TimeParsingVisitor = xfalib.ut.TimeParsingVisitor = xfalib.ut.ParsingVisitorBase.extend({
4055
4056        initialize: function() {
4057            this._timeInfo = new xfalib.ut.TimeInfo();
4058            TimeParsingVisitor._super.initialize.call(this);
4059        },
4060
4061        consumeSubPattern : function(token){
4062            var chr = token.patChar;
4063            var chrCnt = token.len;
4064            var curPos = this._strPos;
4065            var scannedChar = chrCnt;
4066            this._assert(curPos+chrCnt <=this.jsonModel._dataString.length, "Mismatch");
4067
4068            switch (chr) {
4069                case 'h':
4070                    if(this._timeInfo.mHourOfMeriDiem != -1 || this._timeInfo.mHourOfDay != -1){
4071                        throw "ambiguity time string";
4072                    }
4073                    var hourOfMeriDiem=-1;
4074                    switch(chrCnt){
4075                        case 1:
4076                            var parsed = this.parseIntAggressive(this.jsonModel._dataString, curPos, 2); // 1-2 digit(1-12)
4077                            hourOfMeriDiem = parsed.value;
4078                            scannedChar = parsed.len;
4079                            break;
4080                        case 2:
4081                            hourOfMeriDiem = this.parseIntExact(this.jsonModel._dataString, curPos, 2); // 1-2 digit(1-12)
4082                            break;
4083                    }
4084
4085                    this._timeInfo.mHourOfMeriDiem = hourOfMeriDiem -1;
4086                    this._assert(this._timeInfo.mHourOfMeriDiem>=0 && this._timeInfo.mHourOfMeriDiem<=11, "Invalid Hour Of MeriDiem value.");
4087                    break;
4088
4089                case 'k':
4090                    if(this._timeInfo.mHourOfMeriDiem != -1 || this._timeInfo.mHourOfDay != -1){
4091                        throw "ambiguity time string";
4092                    }
4093                    var hourOfMeriDiem=-1;
4094                    switch(chrCnt){
4095                        case 1:
4096                            var parsed = this.parseIntAggressive(this.jsonModel._dataString, curPos, 2); // 1-2 digit(0-11)
4097                            hourOfMeriDiem = parsed.value;
4098                            scannedChar = parsed.len;
4099                            break;
4100                        case 2:
4101                            hourOfMeriDiem = this.parseIntExact(this.jsonModel._dataString, curPos, 2); // 1-2 digit(0-11)
4102                            break;
4103                    }
4104
4105                    this._timeInfo.mHourOfMeriDiem = hourOfMeriDiem;
4106                    this._assert(this._timeInfo.mHourOfMeriDiem>=0 && this._timeInfo.mHourOfMeriDiem<=11, "Invalid hour of meriDiem value.");
4107                    break;
4108
4109                case 'H':
4110                    if(this._timeInfo.mHourOfMeriDiem != -1 || this._timeInfo.mHourOfDay != -1){
4111                        throw "ambiguity time string";
4112                    }
4113                    var hourOfDay=-1;
4114                    switch(chrCnt){
4115                        case 1:
4116                            var parsed = this.parseIntAggressive(this.jsonModel._dataString, curPos, 2); // 1-2 digit(0-23)
4117                            hourOfDay = parsed.value;
4118                            scannedChar = parsed.len;
4119                            break;
4120                        case 2:
4121                            hourOfDay = this.parseIntExact(this.jsonModel._dataString, curPos, 2); // 1-2 digit(0-23)
4122                            break;
4123                    }
4124
4125                    this._timeInfo.mHourOfDay = hourOfDay;
4126                    this._assert(this._timeInfo.mHourOfDay>=0 && this._timeInfo.mHourOfDay<=23, "Invalid hour of day value.");
4127                    break;
4128
4129                case 'K':
4130                    if(this._timeInfo.mHourOfMeriDiem != -1 || this._timeInfo.mHourOfDay != -1){
4131                        throw "ambiguity time string";
4132                    }
4133                    var hourOfDay=-1;
4134                    switch(chrCnt){
4135                        case 1:
4136                            var parsed = this.parseIntAggressive(this.jsonModel._dataString, curPos, 2); // 1-2 digit(0-23)
4137                            hourOfDay = parsed.value;
4138                            scannedChar = parsed.len;
4139                            break;
4140                        case 2:
4141                            hourOfDay = this.parseIntExact(this.jsonModel._dataString, curPos, 2); // 1-2 digit(0-23)
4142                            break;
4143                    }
4144
4145                    this._timeInfo.mHourOfDay = hourOfDay - 1;
4146                    this._assert(this._timeInfo.mHourOfDay>=0 && this._timeInfo.mHourOfDay<=23, "Invalid hour of day value.");
4147                    break;
4148                case 'M':
4149                    if(this._timeInfo.mMinuteOfHour != -1){
4150                        throw "ambiguity time string";
4151                    }
4152                    var minuteOfHour=-1;
4153                    switch(chrCnt){
4154                        case 1:
4155                            var parsed = this.parseIntAggressive(this.jsonModel._dataString, curPos, 2); // 1-2 digit(0-59)
4156                            minuteOfHour = parsed.value;
4157                            scannedChar = parsed.len;
4158                            break;
4159                        case 2:
4160                            minuteOfHour = this.parseIntExact(this.jsonModel._dataString, curPos, 2); // 1-2 digit(0-59)
4161                            break;
4162                    }
4163
4164                    this._timeInfo.mMinuteOfHour = minuteOfHour;
4165                    this._assert(this._timeInfo.mMinuteOfHour>=0 && this._timeInfo.mMinuteOfHour<=59, "Invalid minute of hour.");
4166                    break;
4167                case 'S':
4168                    if(this._timeInfo.mSecondOfMinute != -1){
4169                        throw "ambiguity time string";
4170                    }
4171                    var secondOfMinute=-1;
4172                    switch(chrCnt){
4173                        case 1:
4174                            var parsed = this.parseIntAggressive(this.jsonModel._dataString, curPos, 2); // 1-2 digit(0-59)
4175                            secondOfMinute = parsed.value;
4176                            scannedChar = parsed.len;
4177                            break;
4178                        case 2:
4179                            secondOfMinute = this.parseIntExact(this.jsonModel._dataString, curPos, 2); // 1-2 digit(0-59)
4180                            break;
4181                    }
4182
4183                    this._timeInfo.mSecondOfMinute = secondOfMinute;
4184                    this._assert(this._timeInfo.mSecondOfMinute>=0 && this._timeInfo.mSecondOfMinute<=59, "Invalid second of minute.");
4185                    break;
4186                case 'F':
4187
4188                    this._assert(chrCnt==3, "Invalid pattern F.");
4189                    this._timeInfo.mThousandthOfSecond = this.parseIntExact(this.jsonModel._dataString, curPos, 3);
4190                    this._assert(this._timeInfo.mThousandthOfSecond>=0 && this._timeInfo.mThousandthOfSecond<=999, "Invalid thousand of second.");
4191                    break;
4192
4193                default: throw "Unsupported pattern";
4194            }
4195
4196            this._strPos += scannedChar;
4197        },
4198
4199        parseIntAggressive : xfalib.ut.PictureUtils.parseIntAggressive,
4200
4201        parseIntExact : xfalib.ut.PictureUtils.parseIntExact,
4202
4203        getResult : function(){
4204            return this._timeInfo.getISOTime();
4205        },
4206
4207        getTimeInfo : function(){
4208            return this._timeInfo;
4209        },
4210
4211        _assert : function(condition, message){
4212            if(!condition){
4213                throw message;
4214            }
4215        }
4216    });
4217})(_,xfalib);
4218
4219
4220
4221/**
4222 * @package xfalib.ut.TextParsingVisitor
4223 * @import xfalib.ut.ParsingVisitorBase
4224 *
4225 * @fileOverview Parses a string according to Text Picture.
4226 * @version 0.0.1
4227 */
4228
4229/**
4230 * @constructor
4231 * @param Object {jsonModel: {_sPicture: String, _dataString: String]}
4232 */
4233(function(_,xfalib){
4234    var TextParsingVisitor = xfalib.ut.TextParsingVisitor = xfalib.ut.ParsingVisitorBase.extend({
4235
4236        initialize: function() {
4237            TextParsingVisitor._super.initialize.call(this);
4238            this._buffer = [];
4239        },
4240
4241        consumeSubPattern : function(token){
4242            var chr = token.patChar;
4243            var chrCnt = token.len;
4244            for(var index = 0; index < chrCnt; index++){
4245                switch (chr) {
4246                    case '9': // Numeric
4247                        var cUni = this.jsonModel._dataString.charAt(this._strPos++);
4248                        if(!xfalib.ut.PictureUtils.isDigit(cUni)){
4249                            throw "TextParsing: not a digit as expected";
4250                        }
4251                        this._buffer.push(cUni);
4252                        break;
4253                    case 'A': // Alphebetic
4254                        var cUni = this.jsonModel._dataString.charAt(this._strPos++);
4255                        if(!xfalib.ut.PictureUtils.isLetter(cUni)){
4256                            throw "TextParsing: not a character as expected";
4257                        }
4258                        this._buffer.push(cUni);
4259                        break;
4260                    case 'O': // Alphanumeric
4261                    case '0':
4262                        var cUni = this.jsonModel._dataString.charAt(this._strPos++);
4263                        if(!xfalib.ut.PictureUtils.isLetterOrDigit(cUni)){
4264                            throw "TextParsing: not a character or digit as expected";
4265                        }
4266                        this._buffer.push(cUni);
4267                        break;
4268                    case 'X':
4269                        var cUni = this.jsonModel._dataString.charAt(this._strPos++);
4270                        this._buffer.push(cUni);
4271                        break;
4272                    case 't':
4273                        if(this.jsonModel._dataString.charAt(this._strPos++)=="\t"){
4274                            this._buffer.push("\t");
4275                        }else{
4276                            throw "TextParsing: not a Tab as expected";
4277                        }
4278                        break;
4279                    default:
4280                        if(this.jsonModel._dataString.charAt(this._strPos++)== chr){
4281                            this._buffer.push(chr);
4282                        }else{
4283                            throw "TextParsing: not '" + chr+"' as expected";
4284                        }
4285                }
4286            }
4287
4288        },
4289        /**
4290         *
4291         * @override
4292         */
4293        getResult : function(){
4294            if(this._strPos < this.jsonModel._dataString.length)
4295                throw "TextParsing: picture clause smaller than input Text";
4296            return this._buffer.join("");
4297        },
4298        /**
4299         *
4300         * @override
4301         */
4302        acceptPatternChar : function(chr){
4303            return xfalib.ut.PictureUtils.inString(chr, "9AO0Xt");
4304        }
4305
4306    });
4307})(_,xfalib);
4308
4309
4310/**
4311 * @package xfalib.ut.NumParsingVisitor
4312 * @import xfalib.ut.ParsingVisitorBase
4313 * @fileOverview Parses a string according to Text Picture.
4314 * @version 0.0.1
4315 */
4316
4317/**
4318 * @constructor
4319 * @param Object {jsonModel: {_sPicture: String,_dataString: String}}
4320 */
4321
4322(function(_,xfalib){
4323    var NumParsingVisitor = xfalib.ut.NumParsingVisitor = xfalib.ut.ParsingVisitorBase.extend({
4324
4325        initialize: function(options) {
4326            this._pictureDesc = new xfalib.ut.NumPictureDesc({jsonModel:{_sPicture:this.jsonModel._sPicture}});
4327            this.jsonModel._sPicture = this._pictureDesc.getPicture();
4328            this._buffer = [];
4329            this._strPos = 0;
4330            this._hasRadix = false;
4331            this._mbNegative = false;
4332            this._mbDigitSeen = false; // at least one digit has been added to output
4333            this._mbSignSeen = false;
4334            this._mBacktrack = null;
4335            this._hasPercent = false;
4336            this._mbExponSeen = false;
4337
4338            this._mNumberSymbols = xfalib.ut.PictureUtils.getLocaleObject(this.options._locale,"numberSymbols");
4339            this._mCurrencySymbols = xfalib.ut.PictureUtils.getLocaleObject(this.options._locale,"currencySymbols");
4340        },
4341
4342        _lookupNext : xfalib.ut.Scanner.lookupNext,
4343
4344        parse : function(){
4345            var patPos = 0;
4346            while(true){
4347                try{
4348                    for(var token = this._lookupNext(this.jsonModel._sPicture, patPos, this.acceptPatternChar); token != null;  ){
4349                        this.consume(token);
4350                        patPos = patPos + token.len;
4351                        token = this._lookupNext(this.jsonModel._sPicture, patPos, this.acceptPatternChar);
4352                    }
4353                }catch(e){
4354                    //mismatch, try again!
4355                    if(this._mBacktrack){
4356                        patPos = this._mBacktrack.patPos;
4357                        this._buffer.length = 0;
4358                        this._strPos = this._mBacktrack.strPos;
4359                        this._mbDigitSeen = false;
4360                        this._mBacktrack = null;
4361                        continue;
4362                    }
4363                }
4364                break;
4365            }
4366        },
4367        consumeSubPattern : function(token){
4368
4369            var chr = token.patChar;
4370            var chrCnt = token.len;
4371            var fw = false;
4372            switch (chr) {
4373                case '9':
4374                case '8':
4375                case 'Z': // Digit or space if zero.
4376                case 'z':// Digit or nothing if zero.
4377                    while (chrCnt-- > 0 ) {
4378                        if(!this._mbDigitSeen){
4379                            var cUni = this.jsonModel._dataString.charAt(this._strPos);
4380                            if(cUni == '-'){
4381                                this._mbNegative = true;
4382                                cUni = this.jsonModel._dataString.charAt(++this._strPos);
4383                            }
4384                            if(chr== '9' || chr == '8'){
4385                                if(!xfalib.ut.PictureUtils.isDigit(cUni)){
4386                                    throw "TextParsing: not a digit as expected";
4387                                }
4388                                this._buffer.push(cUni);
4389                                this._mbDigitSeen =true;
4390                            }else if(chr =='Z'){
4391                                if(xfalib.ut.PictureUtils.isDigit(cUni)){
4392                                    this._buffer.push(cUni);
4393                                    this._mbDigitSeen =true;
4394                                }else if(cUni != ' '){
4395                                    throw "TextParsing: not a digit or space as expected";
4396                                }
4397                            }else {
4398                                // has to be 'z', eagerly try to match a digit, if a mismatch is latterly found, backtrack
4399                                if(xfalib.ut.PictureUtils.isDigit(cUni)){
4400                                    this._buffer.push(cUni);
4401                                    this._mbDigitSeen =true;
4402                                    this._mBacktrack = {
4403                                        "patPos" : token.patPos + token.len - chrCnt, //new position from next char after 'z'
4404                                        "strPos" : this._strPos
4405                                    };
4406                                }else {
4407                                    throw "TextParsing: not a digit or space as expected";
4408                                }
4409                            }
4410                            ++this._strPos;
4411                        }else{
4412                            var cUni = this.jsonModel._dataString.charAt(this._strPos);
4413                            if(xfalib.ut.PictureUtils.isDigit(cUni)){
4414                                this._buffer.push(cUni);
4415                                ++this._strPos;
4416                            }else{
4417                                if(chr !='z'){
4418                                    throw "TextParsing: not a digit as expected";
4419                                }else{
4420                                    ++this._strPos;
4421                                }
4422                            }
4423                        }
4424                    }
4425
4426                    break;
4427                case 'V' :
4428                case 'v' :
4429                case '.' :
4430                    if(this._matchStr(this._mNumberSymbols.decimal)){
4431                        this._hasRadix = true;
4432                        this._buffer.push('.');
4433                        this._mbDigitSeen =true;
4434                    }else{
4435                        throw "TextParsing: not a radix as expected";
4436                    }
4437                    break;
4438                case 'E': // Exponent.
4439                    if(this._matchStr('E')){
4440                        this._buffer.push('E');
4441                        if(this._matchStr('+')){
4442                            //
4443                        }else if(this._matchStr('-')){
4444                            this.jsonModel._buffer.push('-');
4445                        }
4446                        var strLen = this.jsonModel._dataString.length;
4447                        while(this._strPos < strLen &&
4448                            xfalib.ut.PictureUtils.isDigit(this.jsonModel._dataString.charAt(this._strPos))){
4449                            this._buffer.push(this.jsonModel._dataString.charAt(this._strPos++));
4450                        }
4451                    }
4452                    break;
4453
4454                case 'C': // CR symbol if negative and spaces if positive.
4455                    if(this._matchStr(xfalib.ut.NumPictureDesc.gsCR)){
4456                        this._mbNegative = true;
4457                    }else if(!this._matchStr(xfalib.ut.NumPictureDesc.gsDSP)){
4458                        throw "TextParsing: not a CR as expected";
4459                    }
4460                    break;
4461                case 'c': // CR symbol if negative and nothing if positive.
4462                    if(this._matchStr(xfalib.ut.NumPictureDesc.gsCR)){
4463                        this._mbNegative = true;
4464                    }
4465                    break;
4466                case 'D': // DB symbol if negative and spaces if positive.
4467                    if(this._matchStr(xfalib.ut.NumPictureDesc.gsDB)){
4468                        this._mbNegative = true;
4469                    }else if(!this._matchStr(xfalib.ut.NumPictureDesc.gsDSP)){
4470                        throw "TextParsing: not a CR as expected";
4471                    }
4472                    break;
4473                case 'd': // DB symbol if negative and nothing if positive.
4474                    if(this._matchStr(xfalib.ut.NumPictureDesc.gsDB)){
4475                        this._mbNegative = true;
4476                    }
4477                    break;
4478                case 'S': // Minus sign if negative and a space if positive.
4479                    if(this._matchStr(this._mNumberSymbols.negative,fw)){
4480                        this._mbNegative = true;
4481                    }else if(!this._matchStr(" ")){
4482                        throw "TextParsing: not a CR as expected";
4483                    }
4484                    break;
4485                case 's':
4486                    if(this._matchStr(this._mNumberSymbols.negative,fw)){
4487                        this._mbNegative = true;
4488                    }
4489                    break;
4490                case 0xFF0C: // Fullwidth ','.
4491                case ',': // Grouping separator.
4492                    while (chrCnt-- > 0) {
4493                        if(!this._matchStr(this._mNumberSymbols.grouping, fw)){
4494                            throw "TextParsing: not a grouping symbol as expected";
4495                        }
4496                    }
4497                    break;
4498                case 0xFF04: // Fullwidth '$'.
4499                case '$': // Currency name or symbol.
4500                    while (chrCnt-- > 0) {
4501                        if(!this._matchStr(this._mCurrencySymbol
4501s.symbol, fw)){
4502                            throw "TextParsing: not a grouping symbol as expected";
4503                        }
4504                    }
4505                    break;
4506                case 0xFF05: // Fullwidth '%'.
4507                case '%': // Percent symbol.
4508                    while (chrCnt-- > 0) {
4509                        if(!this._matchStr(this._mNumberSymbols.percent, fw)){
4510                            throw "TextParsing: not a grouping symbol as expected";
4511                        }
4512                    }
4513                    this._hasPercent = true;
4514                    break;
4515                case 0xFF08: // Fullwidth '('.
4516                case 0xFF09: // Fullwidth ')'.
4517                case '(': // Left parenthesis.
4518                case ')': // Right parenthesis.
4519                    if(this._matchStr(chr,fw)){
4520                        this._mbNegative = true;
4521                    }else if(!this._matchStr(" ")){
4522                        throw "TextParsing: not parentesis as expected";
4523                    }
4524                    break;
4525                case 't': // tab.
4526                    while (chrCnt-- > 0) this._matchStr('\t',fw);
4527            }
4528        },
4529        getResult : function(){
4530            var stringNum =  this._buffer.join("");
4531            if(this._hasPercent) {
4532                var buf = new Array();
4533                stringNum = Number(stringNum).toString();
4534                var dot = stringNum.indexOf('.');
4535
4536                var pos = dot-2;
4537                if(pos ==0) buf.push("0");
4538                else if(pos ==-1) buf.push("0.0");
4539                else if(pos ==-3) pos = stringNum.length - 2;
4540                for(var index=0;index < stringNum.length; index++){
4541                    if(index == pos){
4542                        buf.push(".");
4543                    }
4544                    if(index != dot){
4545                        buf.push(stringNum.charAt(index));
4546                    }
4547                }
4548                stringNum = buf.join("");
4549            }
4550            var number = Number(stringNum);
4551            if(this._mbNegative) number = -number;
4552            return number.toString();
4553        },
4554
4555        _matchStr : function(target){
4556            if(xfalib.ut.PictureUtils.matchString(this.jsonModel._dataString, this._strPos, target)){
4557                this._strPos+= target.length;
4558                return true;
4559            }else{
4560                return false;
4561            }
4562        },
4563
4564        /**
4565         *
4566         * @override
4567         */
4568        acceptPatternChar : function(chr){
4569            return xfalib.ut.PictureUtils.inString(chr, "(%$,.)89BCDERSVZbcdrsvzt");
4570        }
4571    });
4572})(_,xfalib);
4573/**
4574 * @package xfalib.ut.DateParsingVisitor
4575 * @import xfalib.ut.ParsingVisitorBase
4576 * @fileOverview The file provides parsing/formating logic on date pattern characters.
4577 * @version 0.0.1
4578 */
4579
4580/**
4581 * @constructor
4582 * @param Object {jsonModel: {_sPicture: String, _dataString: String]}
4583 */
4584
4585(function(_,xfalib) {
4586    var DateParsingVisitor = xfalib.ut.DateParsingVisitor = xfalib.ut.ParsingVisitorBase.extend({
4587
4588        initialize: function() {
4589            this._dateInfo = new xfalib.ut.DateInfo({isParsingCall : true});
4590            this._dayOfMonth = this._monthOfYear = this._yearOfEra = null; // used to validate date once all sub patterns are consumed
4591            DateParsingVisitor._super.initialize.call(this);
4592        },
4593
4594        consumeSubPattern : function(token){
4595            var chr = token.patChar;
4596            var chrCnt = token.len;
4597            var curPos = this._strPos;
4598            var scannedChar = chrCnt;
4599
4600            //TODO: need to remove this assert.
4601            this._assert(curPos+chrCnt <=this.jsonModel._dataString.length, "Mismatch");
4602
4603            switch (chr) {
4604                case 'D':
4605                    switch(chrCnt){
4606                        case 1:
4607                            var parsed = xfalib.ut.PictureUtils.parseIntAggressive(this.jsonModel._dataString, curPos, 2); // 1-2 digit(1-31)
4608                            this._dayOfMonth = parsed.value;
4609                            scannedChar = parsed.len;
4610                            break;
4611                        case 2:
4612                            this._dayOfMonth = xfalib.ut.PictureUtils.parseIntExact(this.jsonModel._dataString, curPos, 2); // 1-2 digit(1-31)
4613                            break;
4614                    }
4615                    this._assert(this._dayOfMonth <= 31 && this._dayOfMonth >0, "Invalid date string1");
4616                    break;
4617                case 'J':
4618
4619                    //this._mDayOfYear;
4620                    break;
4621                case 'M':
4622                    var symbol = "";
4623                    switch(chrCnt){
4624                        case 1:
4625                            var parsed = xfalib.ut.PictureUtils.parseIntAggressive(this.jsonModel._dataString, curPos, 2); // 1-2 digit(1-12)
4626                            this._monthOfYear = parsed.value;
4627                            scannedChar = parsed.len;
4628                            break;
4629                        case 2:
4630                            this._monthOfYear = xfalib.ut.PictureUtils.parseIntExact(this.jsonModel._dataString, curPos, 2); // 2 digit(01-12)
4631                            break;
4632                        case 3:
4633                            symbol = "calendarSymbols.abbrmonthNames";
4634                            break;
4635                        case 4:
4636                            symbol = "calendarSymbols.monthNames"
4637                            break;
4638
4639                    }
4640                    if(symbol) {
4641                        var hashObj = xfalib.ut.PictureUtils.getHashOfLocaleObject(this.jsonModel._locale,symbol),
4642                            str = this.jsonModel._dataString.toLowerCase(),
4643                            hash = 0,
4644                            curStr = ""
4645                        scannedChar = 0;
4646                        while(curPos+scannedChar < str.length) {
4647                            hash += (scannedChar+1)*str.charCodeAt(curPos+scannedChar)
4648                            curStr+= str.charAt(curPos+scannedChar);
4649                            scannedChar++;
4650                            if(hashObj[hash] && hashObj[hash].indexOf(curStr) > -1 ) break;
4651                        }
4652                        var monthNames = _.map(xfalib.ut.PictureUtils.getLocaleObject(this.jsonModel._locale, symbol), function (str) {
4653                            return str.toLowerCase();
4654                        });
4655                        this._monthOfYear = monthNames.indexOf(curStr) + 1; // months are from 1 to 12
4656                    }
4657                    //TODO: remove this assert
4658                    this._assert(this._monthOfYear <= 12 && this._monthOfYear >0, "Invalid date string2");
4659                    break;
4660                case 'E':
4661                    var symbol = ""
4662                    switch(chrCnt) {
4663                        case 1:
4664                            scannedChar = 1;
4665                            break;
4666                        case 3:
4667                            symbol = "calendarSymbols.abbrdayNames";
4668                            break;
4669                        case 4:
4670                            symbol = "calendarSymbols.dayNames"
4671                            break;
4672                        default:
4673                            throw "unsupported Picture Clause ";
4674                    }
4675                    if(symbol) {
4676                        var hashObj = xfalib.ut.PictureUtils.getHashOfLocaleObject(this.jsonModel._locale,symbol);
4677                        scannedChar = 0;
4678                        var str = this.jsonModel._dataString.toLowerCase();
4679                        var hash = 0;
4680                        var curStr = "";
4681                        while(curPos+scannedChar < str.length) {
4682                            hash += (scannedChar+1)*str.charCodeAt(curPos+scannedChar)
4683                            curStr+= str.charAt(curPos+scannedChar);
4684                            scannedChar++;
4685                            if(hashObj[hash] && hashObj[hash].indexOf(curStr) > -1) break;
4686                        }
4687                    }
4688                    break;
4689
4690                case 'e':
4691                    break;
4692                case 'G':
4693                    break;
4694                case 'Y':
4695
4696                    switch(chrCnt){
4697                        case 2:
4698                            this._yearOfEra = xfalib.ut.PictureUtils.parseIntExact(this.jsonModel._dataString, curPos, 2); // 2 digit(00-99)
4699                            this._yearOfEra+=2000;
4700                            if(this._yearOfEra >= 2029){
4701                                this._yearOfEra -=100;
4702                            }
4703                            break;
4704                        case 4:
4705                            this._yearOfEra = xfalib.ut.PictureUtils.parseIntExact(this.jsonModel._dataString, curPos, 4); // 2 digit(0000-9999)
4706                            break;
4707                    }
4708
4709                    this._assert(this._yearOfEra <= 9999 && this._yearOfEra >=0, "Invalid date string3");
4710                    break;
4711                case 'w':
4712                    break;
4713                case 'W':
4714                    break;
4715                default: throw "Unsupported pattern";
4716            }
4717
4718            if(this._yearOfEra && this._monthOfYear && this._dayOfMonth){
4719                this._dateInfo.validate(this._yearOfEra, this._monthOfYear, this._dayOfMonth);
4720            }
4721
4722            this._strPos += scannedChar;
4723        },
4724
4725        getDate : function(){
4726            return this._dateInfo.date;
4727        },
4728
4729        getResult: function(){
4730            if (this._strPos < this.jsonModel._dataString.length) {
4731                throw "DateParsing: picture clause smaller than input Date";
4732            }
4733            return this._dateInfo.getISODate();
4734        },
4735
4736        _assert : function(condition, message){
4737            if(!condition){
4738                throw message;
4739            }
4740        }
4741    });
4742})(_,xfalib);
4743
4744/*************************************************************************
4745 *
4746 * ADOBE CONFIDENTIAL
4747 * ___________________
4748 *
4749 *  Copyright 2013 Adobe Systems Incorporated
4750 *  All Rights Reserved.
4751 *
4752 * NOTICE:  All information contained herein is, and remains
4753 * the property of Adobe Systems Incorporated and its suppliers,
4754 * if any.  The intellectual and technical concepts contained
4755 * herein are proprietary to Adobe Systems Incorporated and its
4756 * suppliers and are protected by trade secret or copyright law.
4757 * Dissemination of this information or reproduction of this material
4758 * is strictly forbidden unless prior written permission is obtained
4759 * from Adobe Systems Incorporated.
4760 **************************************************************************/
4761
4762
4763
4764(function(_, $, xfalib){
4765
4766    var LocalizationUtil = xfalib.ut.LocalizationUtil = xfalib.ut.Class.extend({
4767
4768        getLocalizedMessage: function(category, message, snippets){
4769            var resolvedMessage = message;
4770            if(snippets){
4771                //resolve message with snippet
4772                resolvedMessage = resolvedMessage.replace(/{(\d+)}/g, function(match, number) {
4773                    return typeof snippets[number] != 'undefined'
4774                        ? snippets[number]
4775                        : match
4776                        ;
4777                });
4778            }
4779            var text = "";
4780            if (category) {
4781                text += " [" + category + "]";
4782            }
4783            text += "  " + resolvedMessage + "\r\n" ;
4784            return text;
4785        }
4786
4787    });
4788})(_, $, xfalib);
4789
4790
4791/*************************************************************************
4792 * ADOBE CONFIDENTIAL
4793 * ___________________
4794 *
4795 *  Copyright 2013 Adobe Systems Incorporated
4796 *  All Rights Reserved.
4797 *
4798 * NOTICE:  All information contained herein is, and remains
4799 * the property of Adobe Systems Incorporated and its suppliers,
4800 * if any.  The intellectual and technical concepts contained
4801 * herein are proprietary to Adobe Systems Incorporated and its
4802 * suppliers and are protected by all applicable intellectual property
4803 * laws, including trade secret and copyright laws.
4804 * Dissemination of this information or reproduction of this material
4805 * is strictly forbidden unless prior written permission is obtained
4806 * from Adobe Systems Incorporated.
4807 **************************************************************************/
4808
4809
4810
4811
4812(function(_, $, xfalib){
4813    xfalib.view.util.TextMetrics = {
4814        xfaUtil : xfalib.ut.XfaUtil.prototype,
4815        ERROR_MARGIN : 1,
4816        $measureEl : null,
4817        initialize : function(divEl){
4818            if(!divEl){
4819                var $div = $("<div></div>");
4820                $div.attr("id", "textMetrics");
4821                var divStyles = {};
4822                divStyles.left = -1000;
4823                divStyles.top = -1000;
4824                divStyles.position = "absolute";
4825                divStyles.visibility = "hidden";
4826                this.xfaUtil.$css($div.get(0), divStyles);
4827                this.$measureEl = $div;
4828                $("body").append(this.$measureEl);
4829            }else{
4830                this.$measureEl = divEl;
4831            }
4832        },
4833
4834        measureExtent : function(text, options){
4835            text = text + " ";
4836            if(!this.$measureEl){
4837                this.initialize();
4838            }
4839            options = options || {};
4840            var textStyles = {};
4841            var $refEl =  $(options.refEl || "<div></div>") ;
4842            var refEl = $refEl.get(0);
4843            textStyles.fontSize = $refEl.css("fontSize") || options["font-size"] || options["fontSize"];
4844            textStyles.fontStyle = $refEl.css("fontStyle") || options["font-style"] || options["fontStyle"];
4845            textStyles.fontWeight = $refEl.css("fontWeight") || options["font-weight"] || options["fontWeight"];
4846            textStyles.fontFamily = $refEl.css("fontFamily") || options["font-family"] || options["fontFamily"];
4847            textStyles.lineHeight = refEl.style.lineHeight || options["line-height"] || options["lineHeight"];
4848            textStyles.letterSpacing = $refEl.css("letterSpacing") || options["letter-spacing"] || options["letterSpacing"];
4849            textStyles.whiteSpace =  $refEl.css("whiteSpace") || options["white-space"] || options["whiteSpace"] || "pre-wrap";
4850            if( $.browser.mozilla && $refEl.is("textarea"))      // for Bug #3621180
4851                textStyles.whiteSpace = "pre-wrap";
4852            textStyles.wordBreak =  $refEl.css("wordBreak") || options["word-break"] || options["wordBreak"] || "break-all";
4853            textStyles.wordWrap =  $refEl.css("wordWrap") || options["word-wrap"] || options["wordWrap"] || "break-word";
4854            textStyles.width = this._elWidth(refEl, options);
4855            textStyles.height = this._elHeight(refEl, options);
4856            textStyles.minWidth = this._elMinWidth(refEl, options);
4857            textStyles.minHeight = this._elMinHeight(refEl, options);
4858            textStyles.maxWidth = this._elMaxWidth(refEl, options);
4859            textStyles.maxHeight = this._elMaxHeight(refEl, options);
4860            this.xfaUtil.$css(this.$measureEl.get(0), textStyles);
4861            // for text fields/areas and draw requiring rich text support
4862            if(options.contentType === "text/html"){
4863              // retaining for future use . If we use the above property for other rich text
4864               if(options.skipXSSProtection) {
4865                 this.$measureEl.html(text);
4866               } else {
4867                 this.$measureEl.html(xfalib.ut.XfaUtil.prototype.encodeScriptableTags(text));
4868               }
4869            }else {
4870               text = text.replace(/\n\r/g,"\n").replace(/\r\n/g,"\n").replace(/\r/g, "\n");
4871               this.$measureEl.text(text);
4872            }
4873            var measuredWidth =  this.$measureEl.width();
4874            var measuredHeight =  this.$measureEl.height();
4875
4876            if(measuredWidth == Math.ceil(options["width"]) || measuredWidth == Math.floor(options["width"])){
4877                measuredWidth = options["width"];
4878            }
4879
4880            if (options["maxWidth"] > measuredWidth || (measuredWidth > options["minWidth"] > 0 && (options["maxWidth"] || -1) < 0)) {
4881                //complicated, please simplify if below hurts you:  Add error margin if there is scope of further extension of extent
4882                measuredWidth = measuredWidth;
4883            }
4884
4885            if(measuredHeight == Math.ceil(options["height"]) || measuredHeight == Math.floor(options["height"])){
4886                measuredHeight = options["height"];
4887            }
4888            else if( $refEl.is("textarea") && (options["maxHeight"] > measuredHeight || (measuredHeight > options["minHeight"] > 0 && (options["maxHeight"] || -1) < 0))){
4889                measuredHeight = measuredHeight +1;
4890            }
4891            this.$measureEl.empty();
4892            return {width : measuredWidth, height : measuredHeight};
4893        },
4894
4895        _elWidth : function(refEl, options){
4896            if(options["minWidth"] && options["minWidth"] > -1)
4897                return "auto";
4898            else if(options["maxWidth"] && options["maxWidth"] > -1)
4899                return "auto";
4900            else
4901                return options["width"] || "auto";
4902        },
4903
4904        _elHeight : function(refEl, options){
4905            // TODO: check for calculations here for floating field and other cases.
4906            if(options["contentType"] === "text/html")
4907                return "auto";
4908            if(options.isDraw) { // for handling the case of draw having floating fields
4909                return "auto";
4910            }
4911            if(!$(refEl).is("textarea"))
4912                return options["height"] || "auto";
4913            if(options["minHeight"] && options["minHeight"] > -1)
4914                return "auto";
4915            else if(options["maxHeight"] && options["maxHeight"] > -1)
4916                return "auto";
4917            else
4918                return options["height"] || "auto";
4919        },
4920
4921        _elMinWidth : function(refEl, options){
4922            if(options["minWidth"] && options["minWidth"] > -1)
4923                return options["minWidth"];
4924            else
4925                return "0"; //default css value
4926        },
4927
4928        _elMinHeight : function(refEl, options){
4929            if(options["minHeight"] && options["minHeight"] > -1)
4930                return options["minHeight"];
4931            else
4932                return "0"; //default css value
4933        },
4934
4935        _elMaxWidth : function(refEl, options){
4936            if(options["maxWidth"] && options["maxWidth"] > -1)
4937                return options["maxWidth"];
4938            else
4939                return "none"; //default css value
4940        },
4941
4942        _elMaxHeight : function(refEl, options){
4943            if(options["maxHeight"] && options["maxHeight"] > -1)
4944                return options["maxHeight"];
4945            else
4946                return "none"; //default css value
4947        },
4948
4949        _destroy : function() {
4950            $("#textMetrics").remove();
4951            this.$measureEl = null;
4952        }
4953    }
4954})(_, $, xfalib);
4955(function($, _) {
4956
4957	$.alertBox = {
4958
4959		verticalOffset: -75,
4960		horizontalOffset: 0,
4961		repositionOnResize: true,
4962		overlayOpacity: 0.01,
4963		overlayColor: '#FFF',
4964		draggable: false,
4965		dialogClass: null,
4966		imageDirectory: "..",
4967		images: ["A_Warning_Lg_N.png", "A_Alert2_Lg_N.png", "C_QuestionBubble_Xl_N.png", "A_InfoBlue_32x32_N.png"],
4968
4969		alert: function(img, message, title, callback) {
4970			this._show(img, title, message, null, 'OK', function(result) {
4971				if( callback ) callback(result);
4972			});
4973		},
4974
4975		okCancel: function(img, message, title, callback) {
4976			this._show(img, title, message, null, 'OK-Cancel', function(result) {
4977				if( callback ) callback(result);
4978			});
4979		},
4980		yesNo: function(img, message, title, callback) {
4981			this._show(img, title, message, null, 'Yes-No', function(result) {
4982				if( callback ) callback(result);
4983			});
4984		},
4985
4986		yesNoCancel: function(img, message, title, callback) {
4987			this._show(img, title, message, null, 'Yes-No-Cancel', function(result) {
4988				if( callback ) callback(result);
4989			});
4990		},
4991
4992		_createBox: function(msgBox_message,buttons,callback) {
4993			var that = this;
4994			$("#"+msgBox_message).after("<div id='msgBox_panel'></div>");
4995			_.each(buttons.split("-"),function(val,i) {
4996                var dispval = (xfalib.locale.Strings && xfalib.locale.Strings[val.toLowerCase()]) ? xfalib.locale.Strings[val.toLowerCase()] : val;
4997                var idSuffix = val;
4998                var $button = $("<input>", {
4999                    type: "button",
5000                    value: dispval,
5001                    id: "msgBox_" + idSuffix,
5002                    "class": "msgbox_input"
5003                });
5004                $("#msgBox_panel").append($button);
5005				$button.click(function() {
5006					that._hide();
5007					callback(!i);
5008				});
5009			});
5010		},
5011
5012		_show: function(img, title, msg, value, type, callback) {
5013
5014			this._hide();
5015			// Remember where focus was so we can restore it when the dialog closes
5016			this._previousFocus = document.activeElement;
5017			this._overlay('show');
5018
5019			$("BODY").append(
5020			  '<div id="msgBox_container" role="dialog" aria-modal="true" aria-labelledby="msgBox_title" aria-describedby="msgBox_message">' +
5021			    '<h1 id="msgBox_title"></h1>' +
5022			    '<div id="msgBox_content">' +
5023			      '<div id="msgBox_message"></div>' +
5024				'</div>' +
5025			  '</div>');
5026
5027			if( this.dialogClass ) $("#msgBox_container").addClass($.alertBox.dialogClass);
5028
5029			$("#msgBox_container").css({
5030				position: 'absolute',
5031				zIndex: 99999,
5032				padding: 0,
5033				margin: 0
5034			});
5035
5036			$("#msgBox_title").text(title);
5037			$("#msgBox_content").addClass("msgBoxType"+img);
5038			msg = xfalib.ut.XfaUtil.prototype.encodeScriptableTags(msg.replace(/\n/g, '<br />'));
5039            $("#msgBox_message").html(msg);
5040
5041			$("#msgBox_container").css({
5042				minWidth: $("#msgBox_container").outerWidth(),
5043				maxWidth: $("#msgBox_container").outerWidth()
5044			});
5045
5046			this._reposition();
5047			this._maintainPosition(true);
5048
5049			this._createBox("msgBox_message",type,callback);
5050
5051			// Keyboard: Escape dismisses (last button = No/Cancel), Tab/Shift+Tab traps focus within dialog
5052			$("#msgBox_container").on("keydown", function(e) {
5053				var $buttons = $("#msgBox_panel input");
5054				var $focused = $(document.activeElement);
5055				if (e.keyCode === 27) {
5056					e.preventDefault();
5057					$buttons.last().trigger("click");
5058				} else if (e.keyCode === 9) {
5059					e.preventDefault();
5060					var idx = $buttons.index($focused);
5061					if (e.shiftKey) {
5062						idx = (idx <= 0) ? $buttons.length - 1 : idx - 1;
5063					} else {
5064						idx = (idx >= $buttons.length - 1) ? 0 : idx + 1;
5065					}
5066					$buttons.eq(idx).focus();
5067				}
5068			});
5069
5070			// Defer focus so the browser paints the dialog before screen readers announce it
5071			setTimeout(function() {
5072				$("#msgBox_panel input:first").focus();
5073			}, 0);
5074
5075		},
5076
5077		_hide: function() {
5078			$("#msgBox_container").remove();
5079			this._overlay('hide');
5080			this._maintainPosition(false);
5081			// Restore focus to the element that was focused before the dialog opened
5082			if (this._previousFocus && this._previousFocus.focus) {
5083				this._previousFocus.focus();
5084				this._previousFocus = null;
5085			}
5086		},
5087
5088		_overlay: function(status) {
5089			switch( status ) {
5090				case 'show':
5091					this._overlay('hide');
5092					$("BODY").append('<div id="msgBox_overlay"></div>');
5093					$("#msgBox_overlay").css({
5094						position: 'absolute',
5095						zIndex: 99998,
5096						top: '0px',
5097						left: '0px',
5098						width: '100%',
5099						height: $(document).height(),
5100						background: this.overlayColor,
5101						opacity: this.overlayOpacity
5102					});
5103				break;
5104				case 'hide':
5105					$("#msgBox_overlay").remove();
5106				break;
5107			}
5108		},
5109
5110		_reposition: function() {
5111            var windowHeight = $(window).height() / xfalib.ut.XfaUtil.prototype.formScaleFactor,
5112                windowWidth = $(window).width() / xfalib.ut.XfaUtil.prototype.formScaleFactor,
5113                windowScrollTop =  $(window).scrollTop() / xfalib.ut.XfaUtil.prototype.formScaleFactor,
5114                windowScrollLeft =  $(window).scrollLeft() / xfalib.ut.XfaUtil.prototype.formScaleFactor,
5115			    top = ((windowHeight / 2) - ($("#msgBox_container").outerHeight() / 2)) + this.verticalOffset,
5116			    left = ((windowWidth / 2) - ($("#msgBox_container").outerWidth() / 2)) + this.horizontalOffset;
5117			if( top < 0 ) top = 0;
5118			if( left < 0 ) left = 0;
5119
5120			// IE6 fix
5121			if( $.browser.msie && parseInt($.browser.version) <= 6 ) top = top + windowScrollTop;
5122
5123			$("#msgBox_container").css({
5124				top: top + windowScrollTop + 'px',
5125				left:  left + windowScrollLeft + 'px'
5126			});
5127			$("#msgBox_overlay").height( $(document).height() );
5128		},
5129
5130		_maintainPosition: function(status) {
5131			if( this.repositionOnResize ) {
5132				switch(status) {
5133					case true:
5134						$(window).on('resize', this._reposition);
5135					break;
5136					case false:
5137						$(window).off('resize', this._reposition);
5138					break;
5139				}
5140			}
5141		}
5142
5143	};
5144})($, window._);/*************************************************************************
5145 * ADOBE CONFIDENTIAL
5146 * ___________________
5147 *
5148 *  Copyright 2016 Adobe Systems Incorporated
5149 *  All Rights Reserved.
5150 *
5151 * NOTICE:  All information contained herein is, and remains
5152 * the property of Adobe Systems Incorporated and its suppliers,
5153 * if any.  The intellectual and technical concepts contained
5154 * herein are proprietary to Adobe Systems Incorporated and its
5155 * suppliers and are protected by all applicable intellectual property
5156 * laws, including trade secret and copyright laws.
5157 * Dissemination of this information or reproduction of this material
5158 * is strictly forbidden unless prior written permission is obtained
5159 * from Adobe Systems Incorporated.
5160 **************************************************************************/
5161
5162
5163(function(_, $, xfalib){
5164    xfalib.view.util.HtmlUtil = {
5165        /*
5166        * Most of the time it returns undefined while accessing an undefined attribute of a dom element.
5167        * But some browsers can throw specific exceptions while accessing an attribute which is un-supported for a specific case.
5168        * This API is to make this behaviour consistent across browsers and return undefined for un-supported attributes.
5169        * */
5170        getHTMLSupportedAttr : function($domElement, attr){
5171           try{
5172               return $domElement[attr];
5173            }
5174           catch (err){
5175               return undefined;
5176            }
5177        },
5178
5179        /**
5180         * Checks if the attribute is supported for the given HTML element.
5181         * This is primarily useful to support HTML5 features in widgets
5182         * @param element       name of HTML element
5183         * @param attribute     attribute to check on the element
5184         * @returns {boolean}
5185         */
5186        elementSupportsAttribute : function (element, attribute) {
5187            var test = document.createElement(element);
5188            if (attribute in test) {
5189                $(test).remove();
5190                test = null;
5191                return true;
5192            } else {
5193                $(test).remove();
5194                test = null;
5195                return false;
5196            }
5197        }
5198    }
5199})(_, $, xfalib);
5200/*************************************************************************
5201*
5202* ADOBE CONFIDENTIAL
5203* ___________________
5204*
5205*  Copyright 2013 Adobe Systems Incorporated
5206*  All Rights Reserved.
5207*
5208* NOTICE:  All information contained herein is, and remains
5209* the property of Adobe Systems Incorporated and its suppliers,
5210* if any.  The intellectual and technical concepts contained
5211* herein are proprietary to Adobe Systems Incorporated and its
5212* suppliers and are protected by trade secret or copyright law.
5213* Dissemination of this information or reproduction of this material
5214* is strictly forbidden unless prior written permission is obtained
5215* from Adobe Systems Incorporated.
5216**************************************************************************/
5217
5218
5219
5220(function(_, $, xfalib){
5221    xfalib.view.util.Styles = {
5222        xfaUtil : xfalib.ut.XfaUtil.prototype,
5223        _deviceResolution :  144.0, //DPI
5224        _in2mmFactor : 25.4,
5225        _pdfResolution : 72.0 ,
5226        getStyleForEdge : function (edgeElement, str, cssStyleObj){
5227            var style = { "raised" : "outset" ,
5228                "dashDot" : "dashed" ,
5229                "dashDotDot" : "dashed" ,
5230                "dashed" : "dashed" ,
5231                "dotted" : "dotted" ,
5232                "embossed" : "groove" ,
5233                "etched" : "inset" ,
5234                "lowered" : "ridge",
5235                "solid" : "solid"};
5236            if(edgeElement && edgeElement.jsonModel.presence != "hidden" && edgeElement.jsonModel.presence !="invisible") {
5237                cssStyleObj['border'+str+'width'] = this._subPixelValue(this._convertToPx(edgeElement.getAttribute('thickness'))) || "1px";
5238                if(edgeElement.getElement("color") && edgeElement.getElement("color").getAttribute("value") !="")  {
5239                    var color =   edgeElement.getElement("color").getAttribute("value");
5240                    color = "rgb(" + color + ")";
5241                    cssStyleObj['border'+str+'color']   = color  ;
5242                }
5243                else {
5244                    cssStyleObj['border'+str+'color'] = "rgb(0,0,0)"  ;
5245                }
5246                cssStyleObj['border'+str+'style']   = style[edgeElement.getAttribute('stroke')] || "solid" ;
5247            } else {
5248                cssStyleObj['border'+str+'width'] =  "0px";
5249                return 1;
5250            }
5251
5252        },
5253
5254        getStyleForBorder : function (border) {
5255            if(border) {
5256                var edge  =  border.getElement('edge', 0, true),
5257                    edge1 = border.getElement('edge', 1, true),
5258                    edge2 = border.getElement('edge', 2, true),
5259                    edge3 = border.getElement('edge', 3, true);
5260                if(edge || edge1 || edge2 || edge3) {
5261                    var cssStyleObj = {} ;
5262                    var e0 = this.getStyleForEdge(edge, "-top-",cssStyleObj);
5263                    var e1 = this.getStyleForEdge(edge1 || edge,"-right-",cssStyleObj);
5264                    var e2 = this.getStyleForEdge(edge2|| edge,"-bottom-",cssStyleObj);
5265                    var e3 = this.getStyleForEdge(edge3 || edge,"-left-",cssStyleObj);
5266                    if(e0 !=1|| e1 !=1|| e2 !=1|| e3!=1)
5267                        return cssStyleObj ;
5268                }
5269            }
5270                return null;
5271        },
5272
5273        _convertToPx : function(size){
5274            if(!size)
5275                return 0;
5276            size = "" + size;
5277            var pxSize = size;
5278            if(size.indexOf("in") >=0){
5279                pxSize = this._mm2px(parseFloat(size) * this._in2mmFactor);
5280            }
5281            else if(size.indexOf("mm") >=0){
5282                pxSize = this._mm2px(size);
5283            }
5284            else if(size.indexOf("cm") >=0){
5285                pxSize = this._mm2px(parseFloat(size) * 10);
5286            }
5287            else if(size.indexOf("pt") >=0){
5288                pxSize = parseFloat(size) * (this._deviceResolution/this._pdfResolution);
5289            }
5290            else if(size.indexOf("px") >=0){
5291                pxSize = parseFloat(size);
5292            }
5293            return pxSize;
5294        },
5295
5296        _mm2px : function(mmSize){
5297            var mmSizeNum = 0;
5298            if(_.isNumber(mmSize))
5299                mmSizeNum = mmSize;
5300            else{
5301                mmSizeNum = parseFloat(mmSize)
5302            }
5303            var mm2in = 1/25.4 ;
5304            var pxSize = mmSizeNum*mm2in*this._deviceResolution;
5305            return pxSize;
5306        },
5307
5308        _subPixelValue : function(value){
5309            if(value > 0.01)
5310                return Math.max(value, 1.0);
5311            else
5312                return value;
5313        }
5314    }
5315})(_, $, xfalib);
5316/*************************************************************************
5317 * ADOBE CONFIDENTIAL
5318 * ___________________
5319 *
5320 *  Copyright 2017 Adobe Systems Incorporated
5321 *  All Rights Reserved.
5322 *
5323 * NOTICE:  All information contained herein is, and remains
5324 * the property of Adobe Systems Incorporated and its suppliers,
5325 * if any.  The intellectual and technical concepts contained
5326 * herein are proprietary to Adobe Systems Incorporated and its
5327 * suppliers and are protected by all applicable intellectual property
5328 * laws, including trade secret and copyright laws.
5329 * Dissemination of this information or reproduction of this material
5330 * is strictly forbidden unless prior written permission is obtained
5331 * from Adobe Systems Incorporated.
5332 **************************************************************************/
5333
5334
5335
5336
5337(function(_, $, xfalib){
5338    xfalib.view.util.traversalManager = {
5339
5340        // compute tabIndex for the provided page
5341        _computTabIndex : function (pageView) {
5342            var pageNum = pageView._pageNumber(),
5343                tabIndex = this._tabIndexBasedOnRange(pageNum);
5344            this.geographicalOrder = [];
5345            this._createGeographicalOrder(pageView);
5346            this._createFinalTraversalOrder(tabIndex); // assign tab index using traversal element and geographicalOrder
5347            // keep tracks of the last field on the page to get tab index so that handler to render next page can be added on getting focus through tabbing
5348            this._lastFieldTabbed = null;
5349        },
5350
5351        _tabIndexBasedOnRange : function (pageNum) {
5352            var behaviorConfig = new xfalib.ut.Version(formBridge.userConfig["behaviorConfig"]),
5353                tabIndexConfig = (behaviorConfig.isOn('mfRangeTabIndex')|| behaviorConfig.isOn('rangeTabIndex')),
5354                /*assuming single page can not have more than 1000 fields.[index -> 0 to 999]
5355                  this is also configurable by passing the maximum number of fields allowable in the page
5356                  in the config parameter */
5357                maxFieldInPageForTabIndex = tabIndexConfig? parseInt(tabIndexConfig):1000;
5358
5359            return pageNum * maxFieldInPageForTabIndex;
5360        },
5361
5362        // to create geographical order array which will be containing all the views in the geographical order
5363        _createGeographicalOrder : function (currentView) {
5364            var sortedChildViewWrapper = this._sortViewGeographically(currentView.childViews);
5365            _.each(sortedChildViewWrapper, function (wrapper) {
5366                var currentView = wrapper.view,
5367                    instanceCheckMap = this._getMapOfInstanceCheck(currentView),
5368                    isViewEligibleForTabbing = this._isViewEligibleForTabbing(currentView);
5369                //  If the child view is fieldView, drawView, exclGroupView or subformView then we will push these views in this.geographicalOrder array,
5370                //  as we need their traverse object during final traversing
5371                if (((instanceCheckMap.isField && !instanceCheckMap.isChildOfExclGroup) || instanceCheckMap.isSubform || instanceCheckMap.isDraw
5372                    || instanceCheckMap.isExclGroup) && isViewEligibleForTabbing) {
5373                    this.geographicalOrder.push({
5374                        view : currentView,
5375                        visited : false
5376                    });
5377                }
5378                if (instanceCheckMap.isContainer && isViewEligibleForTabbing) {
5379                    this._createGeographicalOrder(currentView);
5380                }
5381            }, this);
5382        },
5383
5384        // to sort provided views in geographical order
5385        _sortViewGeographically : function (views) {
5386            var viewsWrapper = [];   // wrapper of view and their geographical reference
5387            _.each(views, function(view) {
5388                var position = view.$el.offset(),
5389                    paddedX = xfalib.ut.XfaUtil.prototype.padString(parseInt(position.left), 5, '0'),
5390                    marginTop = view._marginTop(),
5391                    paddedY = position.top - parseFloat(marginTop),
5392                    positionalReference = parseInt("" + parseInt(paddedY) + paddedX);
5393                viewsWrapper.push({
5394                    positionalReference: positionalReference,
5395                    view: view
5396                });
5397            });
5398            return _.sortBy(viewsWrapper, function(viewWrapper){ return viewWrapper.positionalReference; });
5399        },
5400
5401        // Walk through views in geographical order and assign tab index honouring traversal object if present
5402        _createFinalTraversalOrder : function (tabIndex) {
5403            var geographicalOrderLength = this.geographicalOrder.length,
5404                currentWrappedObj = null,
5405                index = -1,
5406                traversalIndex = 0,  // index of the element to be traversed
5407                viewTraversed = 0;  // counter of view traversed
5408
5409            while (1) {
5410                if (traversalIndex >= geographicalOrderLength) {
5411                    traversalIndex = 0;
5412                }
5413                currentWrappedObj = this.geographicalOrder[traversalIndex];
5414
5415                if (!currentWrappedObj || currentWrappedObj.visited) {  // if the wrapped object does not exist or it has been visited move to the next one
5416                    traversalIndex++;
5417                } else {
5418                    currentWrappedObj.visited = true;
5419                    viewTraversed++;
5420                    var currentView = currentWrappedObj.view,
5421                        instanceCheckMap = this._getMapOfInstanceCheck(currentView),
5422                        currentModel = currentView.model,
5423                        nextView = null,
5424                        nextViewSom = null;
5425
5426                    // get the first traversal of the subform if traversal object is present, else move to the next geographical element
5427                    // next of the subform will be taken care when we will be finding the next view to be traversed,
5428                    // as we will be checking if the ancestor contain next before moving to geographically next view
5429                    if (instanceCheckMap.isSubform) {
5430                        if (currentModel && currentModel.getTraversalObject()) {
5431                            // get the first element to be traversed and update traversalIndex
5432                            nextViewSom = currentModel.getNextTraversalSom(xfalib.template.Constants.firstTraversal);
5433                            index = this._findViewInGeographicalOrderArray(nextViewSom);
5434                            traversalIndex = index != -1 ? index : traversalIndex + 1;
5435                        } else {
5436                            traversalIndex++;
5437                        }
5438                    // get the next traversal for the field/draw if traversal object is present, else move to the next geographical element
5439                    // update the tabindex for the field
5440                    } else if (instanceCheckMap.isField || instanceCheckMap.isDraw) {
5441                        if (instanceCheckMap.isField) {
5442                            currentView.updateTabIndex(tabIndex);
5443                            this._lastFieldTabbed = currentView;
5444                            tabIndex++;
5445                        }
5446                        if (currentModel && currentModel.getTraversalObject()) {
5447                            //get next element to be traversed and update traversalIndex
5448                            nextViewSom = currentModel.getNextTraversalSom(xfalib.template.Constants.nextTraversal);
5449                            index = this._findViewInGeographicalOrderArray(nextViewSom);
5450                            traversalIndex = index != -1 ? index : traversalIndex + 1;
5451                        } else {
5452                            traversalIndex = this._findNextViewToBeTraversed(traversalIndex);
5453                        }
5454                    // if traversal object present get the next element to be traversed, if first is also present then update tab index of the first element
5455                    // else look for the traversal element in the children
5456                    } else if (instanceCheckMap.isExclGroup) {
5457                        if (currentModel && currentModel.getTraversalObject()) {
5458                            // get next element to be traversed and update traversalIndex
5459                            nextViewSom = currentModel.getNextTraversalSom(xfalib.template.Constants.nextTraversal);
5460                            index = this._findViewInGeographicalOrderArray(nextViewSom);
5461                            traversalIndex = index != -1 ? index : traversalIndex + 1;
5462                            // if first is also present assign tab index to that referred child else assign same tab index to all child
5463                            nextViewSom = currentModel.getNextTraversalSom(xfalib.template.Constants.firstTraversal);
5464                            tabIndex = this._updateTabIndexOfExclGroupChildren(currentView, tabIndex, nextViewSom);
5465                        } else {
5466                            tabIndex = this._updateTabIndexOfExclGroupChildren(currentView, tabIndex);
5467                            traversalIndex = this._findTraversalInExclGroupChildren(currentView, traversalIndex);
5468                        }
5469                    } else {
5470                        traversalIndex++;
5471                    }
5472                }
5473
5474                // if all the view are traversed, we have assigned tab index to all the views
5475                if (viewTraversed >= geographicalOrderLength) {
5476                    this._renderNextPageFuture();
5477                    break;
5478                }
5479            }
5480        },
5481
5482        // Check if the nextView is a sibling of the currentView (shares the same parent)
5483        // if it is not a sibling, check if the parent has a NEXT traversal.
5484        // if so get the node traversed to else recurse to see if nextView is a sibling of our parent
5485        // return -1 if the provided next node is sibling of current node or if no ancestor contain next traversal
5486        // else return index of the next traversal object of parent
5487        _getParentNextTraversal : function (currentView, nextView, traversalIndex) {
5488            var parentView = currentView.parentView,
5489                parentModel = parentView.model,
5490                nextViewParentModel = nextView.parentView.model,
5491                traversalObj = null,
5492                nextIndex = -1;
5493
5494            if (parentModel && nextViewParentModel && parentModel.somExpression != nextViewParentModel.somExpression) {
5495                if(parentView && parentView instanceof xfalib.view.SubformView) {
5496                    if (parentModel.getTraversalObject()) {
5497                        var nextViewSom = parentModel.getNextTraversalSom(xfalib.template.Constants.nextTraversal);
5498                        nextIndex = this._findViewInGeographicalOrderArray(nextViewSom);
5499                        if (nextIndex != -1 && !this.geographicalOrder[
5499nextIndex].visited) {
5500                            return nextIndex;
5501                        } else {
5502                            return traversalIndex++;
5503                        }
5504                    } else {
5505                        this._getParentNextTraversal(parentView, nextView, traversalIndex);
5506                    }
5507                } else {  // parentView is not a subform so skip up a level and re-check sibling
5508                    this._getParentNextTraversal(parentView, nextView, traversalIndex);
5509                }
5510            } else {
5511                return -1;  //provided currentView and nextView are sibling
5512            }
5513            return traversalIndex++;
5514        },
5515
5516        // return the index of the view having provided somExpression in the geographicalOrder array
5517        _findViewInGeographicalOrderArray : function (somExpression) {
5518            return _.findIndex(this.geographicalOrder, function (viewWrapper) {
5519                var currentViewModel = viewWrapper.view.model;
5520                return (currentViewModel && currentViewModel.somExpression == somExpression);
5521            });
5522        },
5523
5524        // find the next element to be traversed based on the provided traversalIndex
5525        _findNextViewToBeTraversed : function (traversalIndex) {
5526            var currentView = this.geographicalOrder[traversalIndex].view,
5527                index = this._getNextUnvisited(traversalIndex),   //get next unvisited based on geographical location
5528                nextView = null,
5529                nextIndex = -1;
5530
5531            if (index != -1) {
5532                nextView = this.geographicalOrder[index].view;
5533                //check if both are sibling and if not find the next of the parent and update traversalIndex
5534                nextIndex = this._getParentNextTraversal(currentView, nextView, traversalIndex);
5535                return nextIndex != -1 ? nextIndex : index;
5536            }
5537            return traversalIndex++;
5538        },
5539
5540        // return the next unvisited node based on geographical location
5541        // starting from the traversalIndex and wraps around to check all the views
5542        _getNextUnvisited : function (traversalIndex) {
5543            var geographicalOrderLength = this.geographicalOrder.length,
5544                index = 0,
5545                actualIndex = 0;
5546            while(index < geographicalOrderLength) {
5547                actualIndex = (index + traversalIndex) % geographicalOrderLength;
5548                if(!this.geographicalOrder[actualIndex].visited) {
5549                    return actualIndex;
5550                }
5551                index++;
5552            }
5553            return -1;
5554        },
5555
5556        // assign same tab index to all the child of exclude group
5557        // if exclude group contain first traverse object, then the child being referred as first should have less tabindex
5558        // compared to other child
5559        _updateTabIndexOfExclGroupChildren : function (exclGroupView, tabIndex, firstChildSom) {
5560            _.each(exclGroupView.childViews, function(child){
5561                if (this._isViewEligibleForTabbing(child)) {
5562                    if(firstChildSom && child.model.somExpression == firstChildSom) {
5563                        tabIndex++;
5564                        child.updateTabIndex(tabIndex-1);
5565                        this._lastFieldTabbed = child;
5566                    } else {
5567                        child.updateTabIndex(tabIndex);
5568                    }
5569                }
5570            }, this);
5571            if (!firstChildSom) {
5572                this._lastFieldTabbed = exclGroupView.childViews[0];
5573            }
5574            return ++tabIndex;
5575        },
5576
5577        // find if any child contains next pointer and update traversal index
5578        // start with the last in the geographical order of the children and find child which have next traversal
5579        _findTraversalInExclGroupChildren : function (exclGroupView, traversalIndex) {
5580            var sortedChildView = this._sortViewGeographically(exclGroupView.childViews),
5581                tempObj = null,
5582                childView = null,
5583                childModel = null,
5584                traversalObj = null,
5585                nextViewSom = null,
5586                index = -1;
5587
5588            sortedChildView.reverse();
5589            tempObj = _.find(sortedChildView, function(child) {
5590                childView = child.view;
5591                childModel = childView.model;
5592                if(childModel && (traversalObj = childModel.getTraversalObject())) {
5593                    return traversalObj.length > 0;
5594                }
5595            });
5596
5597            if (tempObj) {
5598                nextViewSom = tempObj.model.getNextTraversalSom(xfalib.template.Constants.nextTraversal);
5599                index = this._findViewInGeographicalOrderArray(nextViewSom);
5600                traversalIndex = index != -1 ? index : traversalIndex + 1;
5601            } else { // else get next unvisited based on geographical location
5602                traversalIndex = this._findNextViewToBeTraversed(traversalIndex);
5603            }
5604            return traversalIndex;
5605        },
5606
5607        // check if the view is initialized and visible
5608        _isViewEligibleForTabbing : function (view) {
5609            if (view._initialized && view.$el.css("visibility") != "hidden") {
5610                return true;
5611            }
5612            return false;
5613        },
5614
5615        // return map of whethter provided view is instance of the various views
5616        _getMapOfInstanceCheck : function (view) {
5617            var instanceCheckMap = {};
5618            instanceCheckMap.isSubform = view instanceof xfalib.view.SubformView;
5619            instanceCheckMap.isField = view instanceof xfalib.view.FieldView;
5620            instanceCheckMap.isDraw = view instanceof xfalib.view.XfaDrawView;
5621            instanceCheckMap.isExclGroup = view instanceof xfalib.view.ExclGroupView;
5622            instanceCheckMap.isChildOfExclGroup = view.parentView instanceof xfalib.view.ExclGroupView;
5623            instanceCheckMap.isContainer = view instanceof xfalib.view.ContainerView;
5624
5625            return instanceCheckMap;
5626        },
5627
5628        // add event handler for rendering next page on tabbing on last field of the page
5629        _renderNextPageFuture : function () {
5630            if (this._lastFieldTabbed) {
5631                this._lastFieldTabbed.$el.one('focusin.traversalManager', function() {
5632                    var pagingManager = window.formBridge ? window.formBridge.pagingManager() : null;
5633                    $(window).on( "keyup.traversalManager", function (e) {
5634                        var code = (e.keyCode ? e.keyCode : e.which);
5635                        if (code == 9 && pagingManager && pagingManager.hasMorePages()) {
5636                            pagingManager.renderNextPage();
5637                            $(window).off("keyup.traversalManager");
5638                        }
5639                    });
5640                });
5641            }
5642        },
5643        _destroy : function() {
5644            this.geographicalOrder = null;
5645        }
5646    }
5647})(_, $, xfalib);
5648/*************************************************************************
5649*
5650* ADOBE CONFIDENTIAL
5651* ___________________
5652*
5653*  Copyright 2013 Adobe Systems Incorporated
5654*  All Rights Reserved.
5655*
5656* NOTICE:  All information contained herein is, and remains
5657* the property of Adobe Systems Incorporated and its suppliers,
5658* if any.  The intellectual and technical concepts contained
5659* herein are proprietary to Adobe Systems Incorporated and its
5660* suppliers and are protected by trade secret or copyright law.
5661* Dissemination of this information or reproduction of this material
5662* is strictly forbidden unless prior written permission is obtained
5663* from Adobe Systems Incorporated.
5664**************************************************************************/
5665
5666
5667
5668(function(_, $, xfalib){
5669
5670    var ErrorManager = xfalib.view.util.ErrorManager = xfalib.ut.Class.extend({
5671
5672        options: {
5673            warningMessageVisible:false,
5674            errorMessageVisible: false
5675        },
5676
5677        initialize: function () {
5678            $(window).on("destroy.xfa", function () {
5679                $("#error-msg").hide();
5680                $("#warning-msg").hide();
5681            });
5682        },
5683
5684        onFieldEnter: function (jqWidget) {
5685            var element = jqWidget.element;
5686            if (jqWidget.option("errorMessage")|| jqWidget.option("warningMessage")) {
5687                var pos = $(element).offset(),
5688                    styles = {};
5689                styles.left = (pos.left * (1 / xfalib.ut.XfaUtil.prototype.formScaleFactor) + element.width() + 5) + "px";
5690                styles.top = pos.top * (1 / xfalib.ut.XfaUtil.prototype.formScaleFactor) + "px";
5691                if (jqWidget.option("errorMessage")) {
5692                    jqWidget.$css($("#error-msg").get(0), styles);
5693                    $("#error-msg").text(jqWidget.option("errorMessage")).show();
5694                    jqWidget.option("errorMessageVisible",true);
5695                }
5696                else if (jqWidget.option("warningMessage")) {
5697                    jqWidget.$css($("#warning-msg").get(0), styles);
5698                    $("#warning-msg").text(jqWidget.option("warningMessage")).show();
5699                    jqWidget.option("warningMessageVisible",true);
5700                }
5701            }
5702        },
5703
5704        onFieldExit: function (jqWidget) {
5705            if (jqWidget.option("errorMessageVisible")) {
5706                $("#error-msg").hide();
5707                jqWidget.option("errorMessageVisible",false);
5708            } else if (jqWidget.option("warningMessageVisible")) {
5709                $("#warning-msg").hide();
5710                jqWidget.option("warningMessageVisible",false);
5711            }
5712        },
5713
5714        markError: function (jqWidget, msg, type) {
5715            // assigning role="alert" so that JAWS reads-out the validation message
5716            if (type != "warning") {
5717                if ($("#error-msg").length < 1)
5718                    $("<div id='error-msg' role='alert'></div>").appendTo('body');
5719                jqWidget.option("errorMessage",msg);
5720                jqWidget.element.addClass("dataInvalid");
5721            } else {
5722                if ($("#warning-msg").length < 1)
5723                    $("<div id='warning-msg' role='alert'></div>").appendTo('body');
5724                jqWidget.option("warningMessage",msg);
5725            }
5726
5727        },
5728
5729        clearError: function (jqWidget) {
5730            this.onFieldExit(jqWidget);
5731            jqWidget.element.removeClass("dataInvalid");
5732            jqWidget.option("errorMessage",null);
5733            jqWidget.option("warningMessage",null);
5734        }
5735    });
5736})(_, $, xfalib);
5737(function(_,$, xfalib) {
5738    var xfaUtil = xfalib.ut.XfaUtil.prototype,
5739        BUFFER_SPC = 20;
5740
5741    /* template for the clear Button */
5742    var clearButtonTemplate = '<div class="dp-clear">' +
5743        '<a></a>' +
5744        '</div>';
5745
5746    /* template for the calendar
5747    * header contains the navigation icons (left and right arrows)
5748    * and the current caption (which can be date, year or month)
5749    *
5750    * monthview displays the grid for showing the dates for a particular
5751    * month
5752    *
5753    * yearview displays all the months of that year
5754    *
5755    * yearsetview displays a grid of 16 years. This can be configured
5756    * through the option: yearsPerView
5757    *
5758    */
5759    var calendarTemplate = '<div class="dp-header">' +
5760        '<div class="dp-leftnav"></div>' +
5761        '<div class="dp-caption"></div>' +
5762        '<div class="dp-rightnav"></div>' +
5763        '</div>' +
5764        '<div role="table" class="view dp-monthview"></div>' +
5765        '<div role="table" class="view dp-yearview"></div>' +
5766        '<div role="table" class="view dp-yearsetview"></div>';
5767
5768    /*template for the timer: not implemented yet */
5769    var watchTemplate = '<div class="dp-header">' +
5770        '<div class="dp-leftnav"></div>' +
5771        '<div class="dp-caption"></div>' +
5772        '<div class="dp-rightnav"></div>' +
5773        '</div>' +
5774        '<div class="view dp-monthview"></div>' +
5775        '<div class="view dp-yearview"></div>' +
5776        '<div class="view dp-yearsetview"></div>';
5777
5778    /** default configuration options
5779     *
5780     * container: the html element where the datepicker template will be added
5781     *
5782     * yearsPerView: number of years to show in the yearset view
5783     *
5784     * width: with of the widget
5785     *
5786     * viewHeight: Height of the month,year and yearset view. This doesn't include
5787     *             the height of the header
5788     *
5789     * locale: locale information for the locale in which to show the datepicker which comprises of
5790     *        days: day names to display in the monthview
5791     *        months: month names to display in the yearview
5792     *        zero: string representation of zero in the locale. Numbers will be
5793     *              displayed in that locale only
5794     *        clearText: Text to display for the reset button
5795     *        name: name of the locale
5796     *
5797     * format: input format for the datepicker (not implemented)
5798     *
5799     * pickerType: type of the datetimepicker (date, datetime and time)
5800     *
5801     * positioning: element around which datepicker will be displayed. if null then it
5802     *              will be displayed around the input element
5803     *
5804     * showCalendarIcon: to show the Calendar on the right of the text field or not
5805     */
5806
5807    var defaults = {
5808        container: "body",
5809        yearsPerView: 16,
5810        width: 340,
5811        viewHeight: 248,
5812        locale: {
5813            days:["S","M","T","W","T","F","S"],
5814            months: ["January","February","March","April","May","June","July","August","September","October","November","December"],
5815            zero: "0",
5816            clearText: "Clear",
5817            name:"en_US"
5818        },
5819        format:"YYYY-MM-DD",
5820        pickerType:"date",
5821        positioning: null,
5822        showCalendarIcon: false
5823    },
5824    dates = [31,28,31,30,31,30,31,31,30,31,30,31],
5825    /*
5826     *  Actions to perform when clicked on the datepicker buttons
5827     *  for different views
5828     *  caption: view to show when clicked on caption
5829     *           (Year/YearSet/Month/null) null means don't change the view
5830     *  li: view to show when clicked on date, month or year element
5831     *  upDown: add(up key) or subtract(down key) current date (for monthview),
5832     *          month(Year View) or year(YearSetView) with the number provided
5833     *  key: identifies the key that needs to be changed for that view
5834     */
5835    viewAction = {
5836        Month: {
5837            caption: 'Year',
5838            li: null,
5839            key:"day",
5840            upDown:7
5841        },
5842        Year: {
5843            caption: "Yearset",
5844            li: "Month",
5845            key:"month",
5846            upDown:3
5847        },
5848        Yearset: {
5849            caption: null,
5850            li: "Year",
5851            key:"year",
5852            upDown:4
5853        }
5854    },
5855    headerClass = "header",
5856
5857    DateTimePicker = function() {
5858        this.initialized = false;
5859    }
5860
5861    $.extend(DateTimePicker.prototype, {
5862        /*
5863         * create the widget using the provided options
5864         */
5865        create: function(options) {
5866            var $dp,self = this,html="",prevNavWidth,nextNavWidth;
5867            this.options = $.extend({},defaults,options);
5868            // prevent memory leak since options.positioning holds reference to HTML DOM
5869            this.options.positioning = null;
5870            // If width of date-picker exceeds screen width then it'll take up the entire screen width in AF
5871            if(window.guideBridge && this.options.width > window.innerWidth && window.innerWidth > 0) {
5872               this.options.width=window.innerWidth - BUFFER_SPC; // buffer
5873            }
5874            if(this.options.pickerType.match(/date/)) {
5875                html += calendarTemplate;
5876            }
5877
5878            if(this.options.pickerType.match(/time/)) {
5879                html += watchTemplate;
5880            }
5881
5882            html += clearButtonTemplate;
5883
5884            $.extend(this, {
5885                selectedDay:0,
5886                selectedMonth:0,
5887                selectedYear:0,
5888                currentDay:0,
5889                currentMonth:0,
5890                currentYear:0,
5891                touchSupported : xfalib.ut.TouchUtil.TOUCH_ENABLED,
5892                _visible:false,
5893                _defaultView:"Month",
5894                _keysEnabled:false,
5895                focusedOnDatepickerItem : false,
5896                keyboardAccessibility : true,
5897                $dp:$("<div></div>").addClass("datetimepicker")
5898                                    .width(this.options.width)
5899                                    .append(html)
5900                                    .addClass("datePickerTarget")
5901                                    .appendTo(this.options.container)
5902                                    .toggleClass("datetimepicker-notouch",this.touchSupported),
5903                $month: $(".dp-monthview",this.$dp).height(this.options.viewHeight),
5904                $year: $(".dp-yearview",this.$dp).height(this.options.viewHeight),
5905                $yearset : $(".dp-yearsetview",this.$dp).height(this.options.viewHeight)
5906            });
5907            this.actualWidth = Math.floor(this.$dp.width());
5908            this.$clear = $('.dp-clear a', this.$dp).on("click", $.proxy(this._clearDate, this));
5909            this.$prevNavWidthBtn = $(".dp-leftnav", this.$dp).on("click",
5910                                                            function(evnt) {
5911                                                                self._adjustDate(-1, self.view, false)
5912                                                            });
5913            this.$nextNavWidthBtn = $(".dp-rightnav", this.$dp).on("click",
5914                                                            function(evnt) {
5915                                                                self._adjustDate(1, self.view, false)
5916                                                            });
5917            prevNavWidth = this.$prevNavWidthBtn.outerWidth(true);
5918            nextNavWidth = this.$nextNavWidthBtn.outerWidth(true);
5919            this.$caption = $(".dp-caption", this.$dp).width(this.actualWidth - prevNavWidth - nextNavWidth)
5920                                                     .on("click",
5921                                                            function(evnt) {
5922                                                                if(!self.$caption.hasClass("disabled")) {
5923                                                                    self._layout(viewAction[self.view].caption);
5924                                                                }
5925                                                      });
5926            if (this.keyboardAccessibility) {
5927                _.each([this.$prevNavWidthBtn, this.$caption, this.$nextNavWidthBtn, this.$clear], function (elem, i) {
5928                    elem.attr("tabIndex", i + 1);
5929                });
5930            }
5931            // attach click event on entire datePicker popup
5932            $(this.$dp).on("click",
5933                function(evnt) {
5934                    //focus only if the device doesn't support touch
5935                    // input otherwise on screen keyboard will popup
5936                    if(!self.touchSupported)
5937                        self._curInstance.$field.focus();
5938                });
5939
5940            $(window).on("touchstart.datetimepicker mousedown.datetimepicker",self._checkWindowClicked);
5941            this._curInstance = null;
5942        },
5943
5944        /*
5945         * attaches the date picker to the field. This is a one time operation
5946         * First creates a configuration object and stores it in the field data attributes
5947         * then attaches event handlers on click, focus (to show the picker) and blur (to hide) events
5948         */
5949        _attachField: function($field,options, value) {
5950            var inst = this._newInst($field,options, value),
5951                self = this,
5952                activateField = function(evnt) {
5953                    var data = xfaUtil.$data(evnt.target,"datetimepicker");
5954                    if(self._isFieldDisabled(data)) {
5955                        return;
5956                    }
5957                    if(!self._curInstance)
5958                         self._activateField(evnt);
5959
5960                    if(self.options.showCalendarIcon) {
5961                        if (evnt.type === self.getEvent()) {
5962                            if (self._iconClicked) {
5963                                self._iconClicked = false;
5964                                if (self._visible) {
5965                                    self._hide(); // hide the calendar popup if visible when calendar icon is clicked
5966                                    self._curInstance.$field.focus(); // bring back focus in field
5967                                } else {
5968                                    self._show(); //// show the calendar popup if not visible when calendar icon is clicked
5969                                }
5970                            }
5971                        }
5972                    } else {
5973                        /*show the popup only if
5974                         1. click/touch event
5975                         2. focus event in case of non-touch devices and focus is not done using script
5976                         */
5977                        if (evnt.type === self.getEvent() || (evnt.type === "focus" && !self.touchSupported && !self.scriptFocus)) {
5978                            self._show(evnt);
5979                        }
5980                    }
5981
5982                    self._clickedWindow = true;
5983                    self.scriptFocus = false;
5984                },
5985                deactivateField = function(evnt) {
5986                    //deactivate only if clicked outside window
5987                    // on touch devices only keyboard or calander should be active at once, touching keyboard should deactivate calendar
5988                    if ((self._clickedWindow && !self.focusedOnDatepickerItem) && (self.options.showCalendarIcon || !self.touchSupported)) {
5989                        self._hide();
5990                        self._deactivateField();
5991                        self._clickedWindow = true;
5992                    }
5993                };
5994
5995            xfaUtil.$data($field[0],"datetimepicker",inst);
5996
5997            $field.on(this.getEvent(),activateField)
5998                  .focus(activateField)
5999                  .blur(deactivateField);
6000            if(options.showCalendarIcon) {
6001                var calendarIcon = $("<div></div>")
6002                                    .addClass("datepicker-calendar-icon")
6003                                    .css({
6004                                        "width": options.iconWidth + "px",
6005                                        "height": options.iconHeight + "px"
6006                                    });
6007                calendarIcon.insertAfter($field);
6008
6009                if (this.keyboardAccessibility) {
6010                    calendarIcon.attr("tabindex", 0);
6011                }
6012
6013                calendarIcon.on(this.getEvent(), function (evnt) {
6014                                self._iconClicked = true;
6015                                $field.click();
6016                              })
6017                              .on("keydown", function (event) {
6018                                    if (event.keyCode === 32 || event.keyCode === 13) {
6019                                        // Check if field is disabled before triggering click
6020                                        var data = xfaUtil.$data($field[0], "datetimepicker");
6021                                        if (data && !self._isFieldDisabled(data)) {
6022                                            $field.click();
6023                                        }
6024                                    }
6025                              });
6026            }
6027        },
6028
6029        _newInst: function($f,options, value) {
6030            return {
6031                $field:$f,
6032                locale: options.locale,
6033                positioning: options.positioning || $f,
6034                access:options.access,
6035                selectedDate:options.value,
6036                editValue :options.editValue,
6037                minValidDate : options.minValidDate,
6038                maxValidDate : options.maxValidDate,
6039                exclMinDate :  options.exclMinDate,
6040                exclMaxDate : options.exclMaxDate
6041            }
6042        },
6043
6044        /*
6045         * To check where the click happened, if happened outside the datepicker
6046         * then hide the picker. This is checked whether any ancestor of clicked target
6047         * has a class datePickerTarget. This class is added to the attached element as well
6048         */
6049        _checkWindowClicked : function(evnt) {
6050            var self = adobeDateTimePicker;
6051            if(self._curInstance) {
6052                // datepickerTarget class depicts that the component is a part of the Date Field
6053                // and on click of that class, we should not hide the datepicker or fire exit events.
6054                if(!$(evnt.target).closest(".datePickerTarget").length) {
6055                    //non-touch devices do not deactivate on blur. Hence needs to be done here
6056                    if(self.touchSupported) {
6057                        self._hide()
6058                        //clicking outside a field doesn't blur the field in IPad. Doing it by script
6059                        self._curInstance.$field[0].blur()
6060                        self._deactivateField()
6061                    } else{
6062                        self._clickedWindow = true;
6063                        // set focusedOnDatepickerItem to false, it hides the datepicker see method deactivateField.
6064                        self.focusedOnDatepickerItem = false;
6065                        self._curInstance.$field.blur()
6066                    }
6067                }
6068                else {
6069                    self._clickedWindow = false;
6070                }
6071            }
6072        },
6073
6074        /**
6075         * Checks if the current datepicker field is disabled.
6076         *
6077         * Fields marked as "readOnly" or with access set to false are considered
6078         * disabled and should not allow datepicker interaction.
6079         * 
6080         * @param {Object} [data] - Optional data object to check. If not provided, uses current instance.
6081         * @returns {boolean} True if the field is disabled (access is "readOnly" or false), false otherwise.
6082         *                   Returns false if no current instance exists.
6083         */
6084        _isFieldDisabled: function(data) {
6085            if (data) {
6086                return data.access === false || data.access === "readOnly";
6087            }
6088            return this._curInstance && (this._curInstance.access === false || this._curInstance.access === "readOnly");
6089        },
6090
6091        /*
6092         * handling of key strokes. All the key strokes prevent the default browser action
6093         * unless specified otherwise
6094         * tab: set focus on calendar icon when dateinput field is active, navigates through date picker buttons when datepicker is open,
6095         * otherwise perform default browser action
6096         * escape: hides the datepicker
6097         * down arrow key: navigate the picker downwards by the number specified in actionView.upDown of the current View
6098         * up arrow key: navigate the picker upwards by the number specified in actionView.upDown of the current View
6099         * left arrow key: navigate the picker one unit of that view backward
6100         * right arrow key: navigate the picker one unit of that view forward
6101         * shift + up: perform the action that happens on clicking the caption (as specified in actionView.caption)
6102         * shift + left: perform the action that happens on clicking the left navigation button
6103         * shift + right: perform the action that happens on clicking the right navigation button
6104         * space/enter: triggers the click event for the current focused element from datepicker/ opens datepicker when calendar icon is focused.
6105         */
6106        _hotKeys: function(evnt) {
6107            var handled = false, date;
6108            switch(evnt.keyCode) {
6109                case 9: //tab
6110                    // CQ-4239352 : Setting clickedWindow property to true on tabbing so that deactivateField logic gets executed
6111                    // When clicking on "x" on input field in in IE and when selecting the content and releasing the mouse select outside the field
6112                    // the click event is not trigerred on the field and hence activateField is not executed, so clickedWindow remains as false
6113                    adobeDateTimePicker._clickedWindow = true;
6114                    handled = false;
6115                    break;
6116                case 27://escape
6117                    if(this._visible) {
6118                        adobeDateTimePicker._hide();
6119                        this._curInstance.$field.focus();
6120                        handled = true;
6121                    }
6122                    break;
6123                case 32: //space
6124                case 13: // enter
6125                    if($(evnt.target).hasClass("datepicker-calendar-icon")){
6126                        // Check if field is disabled before showing datepicker
6127                        // disabled fields are marked as readOnly in the form
6128                        if(this._isFieldDisabled()) {
6129                            return;
6130                        }
6131                        if(!this._visible) {
6132                            this._show();
6133                            return;
6134                        }
6135                        this.$focusedDate.addClass("dp-focus");
6136                    }
6137                    break;
6138                case 40: //down arrow key
6139                    if(!this._visible) {
6140                        // Check if field is disabled before showing datepicker
6141                        if(this._isFieldDisabled()) {
6142                            return;
6143                        }
6144                        this._show();
6145                        return;
6146                    }
6147                    this.$focusedDate.addClass("dp-focus");
6148                    break;
6149            }
6150
6151            if(adobeDateTimePicker._visible && this._keysEnabled) {
6152                var v = viewAction[this.view].key,
6153                    updown=viewAction[this.view].upDown;
6154                switch(evnt.keyCode) {
6155                    case 9: // tab
6156                        if (evnt.shiftKey) {
6157                            if ($(evnt.target).hasClass("dp-leftnav") || $(evnt.target).hasClass("dp-focus")) {
6158                                this._hide();
6159                                this._curInstance.$field.focus();
6160                                handled = true;
6161                            } else {
6162                                handled = false;
6163                            }
6164                        } else {
6165                            var buttonTabindex = $(evnt.target).attr("tabindex");
6166                            if (buttonTabindex === '0') {
6167                                if (evnt.target.tagName.toLocaleLowerCase() === "input") {
6168                                    this._hide();
6169                                    handled = false;
6170                                } else {
6171                                    this.$prevNavWidthBtn.focus();
6172                                    handled = true;
6173                                }
6174                            } else if (buttonTabindex === '4') {
6175                                this._hide();
6176                                this._curInstance.$field.focus();
6177                                handled = true;
6178                            } else {
6179                                handled = false;
6180                            }
6181                        }
6182                        break;
6183                    case 32: //select on space
6184                    case 13: // select on enter
6185                        this.hotKeyPressed = true;
6186                        this.focusedOnDatepickerItem = false;
6187                        if (!this.focusedOnDatepickerItem) {
6188                            $(evnt.target, this.$dp).triggerHandler("click");
6189                        } else {
6190                            if (this.$focusedDate) {
6191                                this.$focusedDate.trigger("click");
6192                            }
6193                        }
6194                        this.hotKeyPressed = false;
6195                        handled = true;
6196                        break;
6197                    case 37: //left arrow key
6198                        if (evnt.shiftKey) {
6199                            $(".dp-leftnav", this.$dp).triggerHandler("click");
6200                        } else {
6201                            this._adjustDate(-1, v, true);
6202                        }
6203                        handled = true;
6204                        break;
6205                    case 38: //up arrow key
6206                        if (evnt.shiftKey) {
6207                            this.$caption.triggerHandler("click");
6208                        } else {
6209                            this._adjustDate(-updown, v, true);
6210                        }
6211                        handled = true;
6212                        break;
6213                    case 39: //right arrow key
6214                        if (evnt.shiftKey) {
6215                            $(".dp-rightnav", this.$dp).triggerHandler("click");
6216                        } else {
6217                            this._adjustDate(+1, v, true);
6218                        }
6219                        handled = true;
6220                        break;
6221                    case 40: //down arrow key
6222                        this._adjustDate(updown, v, true);
6223                        handled = true;
6224                        break;
6225                    default:
6226                }
6227            }
6228            if(handled) {
6229                evnt.preventDefault();
6230            }
6231        },
6232
6233        /*
6234         * show the datepicker.
6235         */
6236        _show: function() {
6237            if(this._isFieldDisabled())
6238                return;
6239            this.options.locale = this._curInstance.locale;
6240            if(!this._visible) {
6241                var self = this,
6242                    date = new Date(),
6243                    val,
6244                    maxDateInfo,
6245                    minDateInfo,
6246                    validDate;
6247                //Bug#3607735:
6248                // Date constructor in ipad 5.1 doesn't support "YYYY-MM-DD", hence parsing the date on our own
6249                validDate = xfalib.ut.DateInfo.ParseIsoString(this._curInstance.selectedDate);
6250                date = (validDate != null)? validDate.getDate(): new Date();
6251                this.selectedDay = this.currentDay = date.getDate();
6252                this.selectedMonth = this.currentMonth = date.getMonth();
6253                this.selectedYear = this.currentYear = date.getFullYear();
6254                maxDateInfo = this.options.maxValidDate ? xfalib.ut.DateInfo.ParseIsoString(this._curInstance.maxValidDate) : null;
6255                this.maxValidDate = maxDateInfo ? maxDateInfo.getDate() : null;
6256                minDateInfo = this.options.minValidDate ? xfalib.ut.DateInfo.ParseIsoString(this._curInstance.minValidDate) : null;
6257                this.minValidDate = minDateInfo ? minDateInfo.getDate() : null;
6258                this.exclMaxDate = this._curInstance.exclMaxDate;
6259                this.exclMinDate = this._curInstance.exclMinDate;
6260                $('.dp-clear a',this.$dp).text(this.options.locale.clearText);
6261                this._layout('Month');
6262                this._position();
6263                this.$dp.show();
6264                // if li element of datepicker is focused then set focusedOnDatepickerItem to true, it manages the visibility of the datepicker.
6265                this.focusedOnDatepickerItem = false;
6266                this._visible = true;
6267                if (this.options.showCalendarIcon) {
6268                    this._curInstance.$field.attr('readonly', true);    // when the datepicker is active, deactivate the field
6269                }
6270            }
6271
6272            //   Disabling the focus on ipad  due to a bug where value of
6273            // date picker is not being set
6274            // Removing this code will only hamper one use case
6275            // where on ipad if you click on the calander then
6276            // the field becomes read only so
6277            // there is no indication where the current focus is
6278            // And  if you remove this foucs code all together
6279            // then what happens is that on desktop MF in iframe the exit event
6280            // is not getting called hence calander getting remained open even
6281            // when you click somewhere on window or focus into some other field
6282            if (this.options.showCalendarIcon  && !this.touchSupported) {
6283                if(this.$focusedDate && this.$focusedDate.length > 0) {
6284                    this.$focusedDate.focus();  // shift focus on current date or selected date.
6285                } else {
6286                    this._curInstance.$field.focus(); // field loses focus after being marked readonly, causing blur event not to be fired later
6287                }
6288            }
6289        },
6290
6291        /*
6292         * position the datepicker around the positioning element
6293         * provided in the options
6294         */
6295        _position: function() {
6296            var $elem = this._curInstance.positioning,
6297                windowScrollX = window.scrollX/ xfalib.ut.XfaUtil.prototype.formScaleFactor,
6298                windowScrollY = window.scrollY/ xfalib.ut.XfaUtil.prototype.formScaleFactor,
6299                windowInnerHeight = window.innerHeight/ xfalib.ut.XfaUtil.prototype.formScaleFactor,
6300                windowInnerWidth = window.innerWidth/ xfalib.ut.XfaUtil.prototype.formScaleFactor,
6301                height = $elem.outerHeight(true),
6302                width  = $elem.outerWidth(true),
6303                top = $elem.offset().top / xfalib.ut.XfaUtil.prototype.formScaleFactor + height,
6304                left = $elem.offset().left / xfalib.ut.XfaUtil.prototype.formScaleFactor,
6305                styles = {"top": (top+"px"), "left": (left+"px")},
6306                diffBottom = top + this.$dp.outerHeight(true) - windowInnerHeight - windowScrollY,
6307                newLeft,
6308                newTop;
6309            if(diffBottom > 0) {
6310                //can't appear at the bottom
6311                //check top
6312                newTop = top - height - this.$dp.outerHeight(true) - BUFFER_SPC;
6313                if(newTop < windowScrollY) {
6314                    //can't appear at the top as well ... the datePicker pop up overlaps the date field
6315                    newTop = top - diffBottom;
6316                    // Fix for BUG #3626974
6317                    if(xfaUtil.isWebkit() && !this.options.showCalendarIcon) {
6318                        this._curInstance.$field.trigger("onoverlap.datetimepicker");
6319                    }
6320                }
6321                styles.top = newTop + "px";
6322            }
6323            if(left + this.$dp.outerWidth(true) > windowScrollX + windowInnerWidth ) {
6324                //align with the right edge
6325                newLeft = windowScrollX + windowInnerWidth - this.$dp.outerWidth(true) - BUFFER_SPC;
6326                styles.left = newLeft + "px";
6327            }
6328            xfaUtil.$css(this.$dp.get(0), styles);
6329            return this;
6330        },
6331
6332        /*
6333         * layout the nextView. if nextView is null return
6334         *
6335         */
6336        _layout: function(nextView) {
6337            if(nextView == null) {
6338                this._hide();
6339            } else {
6340                if(this.view)
6341                    this['$'+this.view.toLowerCase()].hide();
6342                this.view = nextView;
6343                this.$caption.toggleClass("disabled",!viewAction[this.view].caption);
6344                this['$'+this.view.toLowerCase()].show();
6345                this["show"+this.view]();
6346            }
6347            return this;
6348        },
6349
6350        /*
6351         * show the month view
6352         */
6353        showMonth: function() {
6354            var self = this,
6355                curDate = new Date(this.currentYear, this.currentMonth),
6356                maxDay =   this._maxDate(this.currentMonth),
6357                prevMaxDay = this._maxDate((this.currentMonth + 11)%12),
6358                day1 = new Date(this.currentYear,this.currentMonth,1).getDay(),
6359                data,display;
6360
6361            this.tabulateView(
6362                {
6363                    caption: this.options.locale.months[this.currentMonth] + ", "+ this._convertNumberToLocale(this.currentYear),
6364                    header:this.options.locale.days,
6365                    numRows:7,
6366                    numColumns:7,
6367                    elementAt: function(row,col) {
6368                        var day = (row-1)*7 + col - day1 + 1;
6369                        var monthVal = self.currentMonth + 1;
6370                        display = self._convertNumberToLocale(day);
6371                        data = day;
6372                        if(day < 1) {
6373                            display = self._convertNumberToLocale(prevMaxDay + day);
6374                            data = -1;
6375                            monthVal = self.currentMonth;
6376                        }
6377                        else if(day > maxDay) {
6378                            display = self._convertNumberToLocale(day-maxDay);
6379                            data = -1;
6380                            monthVal = self.currentMonth + 2;
6381                        }
6382                        else {
6383                            curDate.setDate(day);
6384                            var compareFn = xfalib.ut.XfaUtil.prototype._compareVal;
6385                            // check if the currentdate is valid based on max and min valid date
6386                            if(compareFn(curDate, self.maxValidDate, self.exclMaxDate) || compareFn(self.minValidDate, curDate, self.exclMinDate)) {
6387                                data = -1;
6388                            }
6389                        }
6390                        return {
6391                            data : data,
6392                            display : display,
6393                            ariaLabel : self.options.editValue(self.currentYear+"-"+self._pad2(monthVal)+"-"+self._pad2(display))
6394                        };
6395                    }
6396                });
6397        },
6398
6399
6400
6401        /*
6402         * show the year view
6403         */
6404        showYear: function() {
6405            var self = this,
6406                minDate = this.minValidDate ? new Date(this.minValidDate.getFullYear(), this.minValidDate.getMonth()) : null,
6407                maxDate = this.maxValidDate ? new Date(this.maxValidDate.getFullYear(), this.maxValidDate.getMonth()) : null,
6408                curDate = new Date(this.currentYear, 0), //can't omit month, if only one param present it is treated as millisecond
6409                data,
6410                month;
6411            this.tabulateView(
6412                {
6413                    caption : this._convertNumberToLocale(this.currentYear),
6414                    numRows : 4,
6415                    numColumns : 3,
6416                    elementAt : function(row,col) {
6417                        data = month =  row*3 + col;
6418                        curDate.setMonth(month);
6419                        if ((minDate && curDate < minDate) || (maxDate && curDate > maxDate)) {
6420                            data = -1;
6421                        }
6422                        return {
6423                            data : data,
6424                            display : self.options.locale.months[month],
6425                            ariaLabel : self.options.locale.months[month] + " " +self.currentYear
6426                        };
6427                    }
6428                });
6429        },
6430
6431        /*
6432         * show the year set view
6433         */
6434        showYearset: function() {
6435            var year,
6436                minDate = this.minValidDate ? new Date(this.minValidDate.getFullYear(), 0
6436) : null ,
6437                maxDate = this.maxValidDate ? new Date(this.maxValidDate.getFullYear() + 1, 0) : null,
6438                curDate = new Date(),
6439                data,
6440                self = this;
6441            this.tabulateView(
6442                {
6443                    caption: this._convertNumberToLocale(this.currentYear - this.options.yearsPerView/2) +"-"+this._convertNumberToLocale(this.currentYear - this.options.yearsPerView/2 + this.options.yearsPerView - 1),
6444                    numRows:4,
6445                    numColumns:4,
6446                    elementAt: function(row,col) {
6447                        data = year =  self.currentYear - 8 + (row*4 + col);
6448                        curDate.setFullYear(year);
6449                        if ((minDate && curDate < minDate) || (maxDate && curDate > maxDate)) {
6450                            data = -1;
6451                        }
6452                        return {
6453                            "data" : data,
6454                            "display" : self._convertNumberToLocale(year),
6455                            ariaLabel : year
6456                        };
6457                    }
6458                });
6459        },
6460
6461        insertRow :  function(rowNum,rowArray,isHeader,height) {
6462            var $view = this["$"+this.view.toLowerCase()],
6463                width = (this.actualWidth)/rowArray.length,
6464                $row = $("ul",$view).eq(rowNum),
6465                items,$li,element,$tmp,
6466                self= this;
6467            if(!$row.length)
6468                $row = $("<ul></ul>").attr("aria-label", "").attr("role", "row").appendTo($view).toggleClass(headerClass,isHeader);
6469            $row.height(height);
6470            items = $("li",$row).length;
6471            while(items++ < rowArray.length) {
6472                $tmp = $("<li></li>").attr("role", "cell").appendTo($row);
6473                if(!isHeader)
6474                    $tmp.on("click", $.proxy(this._selectDate,this));
6475            }
6476
6477            _.each(rowArray, function(el,index) {
6478                $li = $("li",$row).eq(index);
6479                if(isHeader)
6480                    $li.text(rowArray[index]);
6481                else {
6482                    element = rowArray[index];
6483                    xfaUtil.$data($li.get(0), "value", element.data);
6484                    if(self._checkDateIsFocussed(element.data)) {
6485                        if(self.$focusedDate) {
6486                            self.$focusedDate.removeClass("dp-focus");
6487                            self.$focusedDate.attr("tabindex", "-1");
6488                        }
6489                        self.$focusedDate = $li;
6490                        if(self._keysEnabled)
6491                            self.$focusedDate.addClass("dp-focus")
6492                    }
6493                    $li.toggleClass("dp-selected",self._checkDateIsSelected(element.data))
6494                        .toggleClass("disabled", element.data == -1).text(element.display)
6495                        .attr("title", element.ariaLabel)
6496                        .attr("aria-label", element.ariaLabel)
6497                        .attr("tabindex", -1);
6498                }
6499                $li.css( {"height":height+"px","width":width+"px","line-height":height+"px"});
6500            });
6501            return $row;
6502        },
6503
6504        /*
6505         * creates a tabular view based on the options provided. The options that can be passed are
6506         * numRows: number of rows that needs rendering
6507         * numCols: number of columns that needs rendering
6508         * caption: text for the datepickers caption element
6509         * header: an array of elements that identifies the header row
6510         * elementAt: a function(row, column) that returns an object (data: <data>, display: <display>) where
6511         *            <data> is the value to set for that view when the element at (row,column) is clicked and
6512         *            <display> is the value that will be visible to the user
6513         */
6514        tabulateView : function(options) {
6515            var r = 0,rows = 0,
6516                row = [],
6517                ht =  this.options.viewHeight/options.numRows,
6518                c;
6519            this.$caption.text(options.caption);
6520            if(options.header) {
6521                this.insertRow(r++,options.header,true,ht);
6522            }
6523            while(r < options.numRows) {
6524                c = 0;
6525                while(c < options.numColumns) {
6526                    row[c] = options.elementAt(r,c);
6527                    c++;
6528                }
6529                this.insertRow(r++,row,false,ht);
6530            }
6531        },
6532
6533        _activateField : function(evnt) {
6534            this._curInstance = xfaUtil.$data(evnt.target,"datetimepicker");
6535            this._curInstance.$field.trigger("onfocus1.datetimepicker").addClass("datePickerTarget");
6536            // Issue LC-7049:
6537            // datepickerTarget should be added when activate the field and should be removed
6538            // after the fields gets deactivated.
6539            if (this.options.showCalendarIcon) {
6540                this._curInstance.$field.parent().addClass("datePickerTarget");
6541            }
6542            //enable hot keys only for non touch devices
6543            if(!this.touchSupported && !this._keysEnabled) {
6544                $(window).on("keydown.datetimepicker", $.proxy(this._hotKeys,this));
6545                this._keysEnabled = true;
6546            }
6547        },
6548
6549        _deactivateField: function() {
6550            if(this._curInstance) {
6551                if(this._keysEnabled) {
6552                    $(window).off("keydown.datetimepicker")
6553                    this._keysEnabled = false;
6554                }
6555                //Bug#3607499: on deactivate check the value in the input box, if that is
6556                // different than the selected Date, change the selectedDate
6557                //if (this._curInstance.selectedDate != this._curInstance.$field.val()) {
6558                //    this._curInstance.selectedDate = this._curInstance.$field.val();
6559                //}
6560                this._curInstance.$field.trigger("onfocusout.datetimepicker").removeClass("datePickerTarget");
6561                // Issue LC-7049:
6562                // datepickerTarget should be added when activate the field and should be removed
6563                // after the fields gets deactivated. Otherwise clicking on any other datefield
6564                // will not hide the existing datepicker
6565                if (this.options.showCalendarIcon) {
6566                    this._curInstance.$field.parent().removeClass("datePickerTarget");
6567                }
6568                this._curInstance = null;
6569            }
6570        },
6571
6572        _hide: function() {
6573            if(this._visible) {
6574                this.$dp.hide();
6575                this._curInstance.$field.trigger("onclose.datetimepicker");
6576                this._visible = false;
6577                if (this.options.showCalendarIcon) {
6578                    this._curInstance.$field.attr('readonly', false);    // when the datepicker is deactivated, activate the field
6579                }
6580            }
6581        },
6582
6583        _adjustDate: function(step, view, focus) {
6584            var maxDate,prevMaxDate;
6585            var _focus = focus || false;
6586            switch(view.toLowerCase()) {
6587                case "day":
6588                    this.currentDay += step;
6589                    maxDate = this._maxDate(this.currentMonth)
6590                    if(this.currentDay < 1) {
6591                        prevMaxDate =  this._maxDate((this.currentMonth - 1 + 12)%12);
6592                        this.currentDay = prevMaxDate + this.currentDay;
6593                        return this._adjustDate(-1, "month", _focus);
6594                    }
6595                    if(this.currentDay > maxDate) {
6596                        this.currentDay -= maxDate;
6597                        return this._adjustDate(+1, "month", _focus);
6598                    }
6599                    break;
6600                case "month":
6601                    this.currentMonth += step;
6602                    if(this.currentMonth > 11) {
6603                        this.currentYear++;
6604                        this.currentMonth = 0;
6605                    }
6606                    if(this.currentMonth < 0) {
6607                        this.currentYear--;
6608                        this.currentMonth = 11;
6609                    }
6610                    break;
6611                case "year":
6612                    this.currentYear += step;
6613                    break;
6614                case "yearset":
6615                    this.currentYear += step*this.options.yearsPerView;
6616                    break;
6617            }
6618            this._layout(this.view);
6619            if (_focus) {
6620                this.focusedOnDatepickerItem = true;
6621                this.$focusedDate.attr("tabindex", 0)[0].focus();
6622            }
6623        },
6624
6625        _checkDateIsSelected: function(data) {
6626            switch(this.view.toLowerCase()) {
6627                case "month":
6628                    return this.currentYear == this.selectedYear && this.currentMonth == this.selectedMonth && data == this.selectedDay;
6629                case "year":
6630                    return this.currentYear == this.selectedYear && this.selectedMonth == data;
6631                case "yearset":
6632                    return this.selectedYear == data;
6633            }
6634        },
6635
6636        _checkDateIsFocussed: function(data) {
6637            switch(this.view.toLowerCase()) {
6638                case "month":
6639                    return data == this.currentDay;
6640                case "year":
6641                    return this.currentMonth == data;
6642                case "yearset":
6643                    return this.currentYear == data;
6644            }
6645        },
6646
6647        _convertNumberToLocale : function(number) {
6648            var zeroCode = this.options.locale.zero.charCodeAt(0);
6649            number += "";
6650            var newNumber = [];
6651            for(var i = 0;i < number.length;i++) {
6652                newNumber.push(String.fromCharCode(zeroCode + parseInt(number.charAt(i))));
6653            }
6654            return newNumber.join("");
6655        },
6656
6657        _clearDate: function() {
6658            var isDateEmpty = this._curInstance.$field.val() ? false : true;
6659            this.selectedYear
6660                = this.selectedMonth
6661                = this.selectedYear
6662                = -1;
6663            this._curInstance.selectedDate = "";
6664            this._curInstance.$field.val("");
6665            if (!isDateEmpty) {
6666                this._curInstance.$field.trigger("onvaluechange.datetimepicker", [
6667                    {selectedDate: ""}
6668                ]);
6669            }
6670            $(".dp-selected",this['$'+this.view.toLowerCase()]).removeClass("dp-selected");
6671        },
6672
6673        getEvent : function() {
6674            return "click";//this.touchSupported ? "touchstart" : "click";
6675        },
6676
6677        _pad2: function(m) {
6678            return m = m < 10 ?"0"+m:m;
6679        },
6680
6681        toString : function() {
6682            return this.selectedYear +"-"+this._pad2(this.selectedMonth + 1)+"-"+this._pad2(this.selectedDay);
6683        },
6684
6685        _selectDate : function(evnt) {
6686            var val = xfaUtil.$data(evnt.target, "value"),
6687                nextView = viewAction[this.view].li,
6688                editVal;
6689            //disabled dates have a value of -1. Do nothing in that case
6690            if(val == -1)
6691                return;
6692            switch(this.view.toLowerCase()) {
6693                case "month":
6694                    this.selectedMonth = this.currentMonth;
6695                    this.selectedYear = this.currentYear;
6696                    this.selectedDay = val;
6697                    this._curInstance.selectedDate = this.toString();
6698                    editVal = this._curInstance.editValue(this.toString());
6699                    this._curInstance.$field.val(editVal).focus();
6700                    this._curInstance.$field.trigger("onvaluechange.datetimepicker", [
6701                        {selectedDate: editVal}
6702                    ]);
6703                    $(".dp-selected",this['$'+this.view.toLowerCase()]).removeClass("dp-selected");
6704                    $(evnt.target).addClass("dp-selected");
6705                    break;
6706                case "year":
6707                    this.currentMonth = val;
6708                    break;
6709                case "yearset":
6710                    this.currentYear = val;
6711                    break;
6712            }
6713            this._layout(nextView);
6714            //manually focus on the field if clicked on the popup buttons for non-touch device
6715            if(!this.touchSupported) {
6716                //No need to focus if selection is made by pressing space.
6717                if(!this.hotKeyPressed) {
6718                    this.scriptFocus = true;
6719                    if(nextView == null) {
6720                        this.focusedOnDatepickerItem = false;
6721                    }
6722                }
6723            } else if(nextView == null){
6724                //For touch devices, deactivate the field if a selection is made
6725                this.focusedOnDatepickerItem = false;
6726                this._deactivateField()
6727            }
6728        },
6729
6730        _leapYear : function() {
6731            return this.currentYear % 400 == 0 || (this.currentYear % 100 != 0 && this.currentYear % 4 == 0);
6732        },
6733
6734        _maxDate : function(m) {
6735            if(this._leapYear() && m == 1)
6736                return 29;
6737            else return dates[m];
6738        },
6739
6740        _access: function(val) {
6741            if(typeof val == "undefined")
6742                return this.access
6743            this.access = val;
6744        },
6745
6746        _value:function(val) {
6747            if(typeof val == "undefined")
6748                return this.$field.val()
6749            else {
6750                this.selectedDate = val;
6751                var editValue = this.editValue(val);
6752                // update the field val with provided value instead of null
6753                if (!editValue) {
6754                    editValue = val;
6755                }
6756                this.$field.val(editValue);
6757            }
6758        }
6759    });
6760
6761    var adobeDateTimePicker = new DateTimePicker();
6762
6763    $.fn.adobeDateTimePicker = function(options, value) {
6764        if(!adobeDateTimePicker.initialized) {
6765            adobeDateTimePicker.create(options);
6766            adobeDateTimePicker.initialized = true;
6767        }
6768        if(typeof options === "object") {
6769            adobeDateTimePicker._attachField(this, options);
6770        }
6771        else if(typeof options === "string") {
6772            if(arguments.length == 2)
6773                adobeDateTimePicker["_"+options].apply(xfaUtil.$data(this[0],"datetimepicker"),[value])
6774            else
6775                return adobeDateTimePicker["_"+options].apply(xfaUtil.$data(this[0],"datetimepicker"))
6776        }
6777        return this;
6778    }
6779})(_, $, xfalib);
6780(function (xfalib) {
6781    xfalib.ut.TouchUtil = (function () {
6782        var touchAvailable = !!("ontouchstart" in window || window.DocumentTouch && document instanceof DocumentTouch) ,
6783            pointerEnabled = !!(window.MSPointerEvent || window.PointerEvent) ,
6784            POINTER_DOWN_EVENT = "mousedown",
6785            POINTER_MOVE_EVENT = "mousemove",
6786            POINTER_UP_EVENT = "mouseup",
6787            EVENT_TYPE = "MouseEvent";
6788
6789        if (window.PointerEvent) { //> IE11
6790            POINTER_DOWN_EVENT = "pointerdown";
6791            POINTER_MOVE_EVENT = "pointermove";
6792            POINTER_UP_EVENT = "pointerup";
6793            EVENT_TYPE = "PointerEvent";
6794
6795        } else if (window.MSPointerEvent) { // IE10
6796            POINTER_DOWN_EVENT = "MSPointerDown";
6797            POINTER_MOVE_EVENT = "MSPointerMove";
6798            POINTER_UP_EVENT = "MSPointerUp";
6799            EVENT_TYPE = "MSPointerEvent" ;
6800
6801        } else if (touchAvailable) {  // other touch devices
6802            POINTER_DOWN_EVENT = "touchstart";
6803            POINTER_MOVE_EVENT = "touchmove";
6804            POINTER_UP_EVENT = "touchend";
6805            EVENT_TYPE = "TouchEvent";
6806        }
6807        return {
6808            TOUCH_ENABLED: touchAvailable,
6809            // new MS Pointer Events
6810            POINTER_EVENT: EVENT_TYPE,
6811            POINTER_ENABLED: pointerEnabled,
6812            POINTER_DOWN: POINTER_DOWN_EVENT,
6813            POINTER_MOVE: POINTER_MOVE_EVENT,
6814            POINTER_UP: POINTER_UP_EVENT,
6815            getTouchEvent: function (evt) {
6816                var target;
6817                if (pointerEnabled) {
6818                    target = evt.originalEvent;
6819                } else if (touchAvailable) {
6820                    target = evt.originalEvent || evt;
6821                    target = target.touches[0];
6822                    //if (evt.originalEvent && evt.originalEvent.changedTouches && evt.originalEvent.changedTouches[0]) {
6823                    //    te = evt.originalEvent.changedTouches[0];
6824                    //}
6825                }
6826
6827                return target || evt;
6828            },
6829            getPointerEvent: function (eventType) {
6830                var event = null;
6831                if ((typeof PointerEvent) === "function") {
6832                    event = new PointerEvent(eventType, {
6833                        bubbles: true,
6834                        cancelable: true
6835                    });
6836                } else {
6837                    event = document.createEvent(EVENT_TYPE);
6838                    event.initEvent(eventType, true, true);
6839                }
6840                return event;
6841            },
6842            getTouches:function(evt){
6843                var touches = [];
6844                if(touchAvailable && evt.originalEvent && evt.originalEvent.touches ){
6845                    touches = evt.originalEvent.touches;
6846                }
6847                return touches;
6848            }
6849        };
6850    })();
6851})(xfalib);
6852(function ($, _) {
6853    $.widget("xfaWidget.abstractWidget", {
6854
6855        $userControl: null,
6856
6857        $data: xfalib.ut.XfaUtil.prototype.$data,
6858
6859        $css: xfalib.ut.XfaUtil.prototype.$css,
6860
6861        getOrElse: xfalib.ut.Class.prototype.getOrElse,
6862
6863        dIndexOf: xfalib.ut.XfaUtil.prototype.dIndexOf,
6864
6865        btwn: xfalib.ut.XfaUtil.prototype.btwn,
6866
6867        logger: xfalib.ut.XfaUtil.prototype.getLogger,
6868
6869        localeStrings: xfalib.ut.XfaUtil.prototype.getLocaleStrings,
6870
6871        logMsgs: xfalib.ut.XfaUtil.prototype.getLogMessages,
6872
6873        errorManager: xfalib.ut.XfaUtil.prototype.getErrorManager,
6874
6875        _widgetName: "abstractWidget",
6876
6877        // if there are any specific black listed attributes, each widget should define their own
6878        _blackListedAttributes : ["type"],
6879
6880        options: {
6881            name: "",
6882            value: null,
6883            commitProperty: "value",
6884            displayValue: null,
6885            screenReaderText: null,
6886            tabIndex: 0,
6887            role: null,
6888            paraStyles: null,
6889            dir: null,
6890            errorMessage: null,
6891            warningMessage: null,
6892            hScrollDisabled: false,
6893            placeholder:"",
6894            isValid:true,
6895            mandatory: false
6896        },
6897
6898        getOptionsMap: function () {
6899            return {
6900                "tabIndex": function (val) {
6901                    this.$userControl.attr("tabindex", val);
6902                },
6903                "role": function (val) {
6904                    if (val)
6905                        this.$userControl.attr("role", val);
6906                },
6907                "screenReaderText": function (val) {
6908                    if (val)
6909                        this.$userControl.attr("aria-label", val)
6910                },
6911                "paraStyles": function (val) {
6912                    if (val)
6913                        this.$css(this.$userControl.get(0), val);
6914                },
6915                "dir": function (val) {
6916                    if (val)
6917                        this.$userControl.attr("dir", this.options.dir);
6918                },
6919                "height": function (val) {
6920                    if (val) {
6921                        this.$css(this.$userControl[0], {"height": val})
6922                    }
6923                },
6924                "width": function (val) {
6925                    if (val)
6926                        this.$css(this.$userControl[0], {"width": val})
6927                },
6928                "isValid": function (val) {
6929                    if(val){
6930                      this.$userControl.removeAttr("aria-invalid");
6931                    } else {
6932                      this.$userControl.attr("aria-invalid",true);
6933                    }
6934                },
6935                "color" : function(value) {
6936                    if(!_.isEmpty(value)) {
6937                        var color = "rgb(" + value + ")";
6938                        this.$css(this.$userControl[0], {"color": color});
6939                    }
6940                },
6941                "font-style" : function (value) {
6942                    if (!_.isEmpty(value)) {
6943                        this.$css(this.$userControl[0], {"font-style": value});
6944                    }
6945                },
6946                "mandatory" : function (value) {
6947                    if(value){
6948                        this.$userControl.attr("aria-required", true);
6949                    } else {
6950                        this.$userControl.removeAttr("aria-required");
6951                    }
6952                }
6953            };
6954        },
6955
6956        getEventMap: function () {
6957            return {
6958                "focus": xfalib.ut.XfaUtil.prototype.XFA_ENTER_EVENT,
6959                "blur": xfalib.ut.XfaUtil.prototype.XFA_EXIT_EVENT,
6960                "click": xfalib.ut.XfaUtil.prototype.XFA_CLICK_EVENT
6961            };
6962        },
6963
6964        /**
6965         * Copies all the attributes from source jquery object to destination jquery object
6966         * @param $src      source jquery object
6967         * @param $dest     destination jquery object
6968         */
6969        copyAttributesFromSrcToDest : function($src, $dest){
6970            var that = this;
6971            // let's get all the attribute from the src element and copy it to dest jquery object
6972            if($src != null && $src[0] && $src[0].attributes && $dest != null){
6973                $.each($src[0].attributes, function() {
6974                    // we don't add the black listed set of attributes
6975                    if(this.specified && this.value != null && _.isString(this.value) && this.value.length > 0 && that._blackListedAttributes.indexOf(this.name) === -1) {
6976                        $dest.attr(this.name, this.value);
6977                    }
6978                });
6979            }
6980        },
6981
6982        _create: function () {
6983            this.widgetEventPrefix = "";
6984            this.element.addClass(this._widgetName);
6985            this.$userControl = this.render();
6986            this.optionsHandler = this.getOptionsMap();
6987            this.eventMap = this.getEventMap();
6988            this._initializeOptions();
6989            this._initializeEventHandlers();
6990            this.errObj = this.errorManager();
6991            //call it only after render
6992            // Dirty hack to prevent this being called in Guide
6993            if (typeof guidelib === "undefined") {
6994                this.$css(this.$userControl.get(0), {
6995                    "box-sizing": "border-box",
6996                    "position": "absolute"
6997                });
6998            }
6999        },
7000
7001        _initializeEventHandlers: function () {
7002            xfalib.ut.XfaUtil.prototype.getLogger().debug("xfa", "initialize event handlers for " + this._widgetName);
7003            _.each(this.eventMap, function (xfaevent, htmlevent) {
7004                var self = this;
7005                if (xfaevent) {
7006                    if (!(xfaevent instanceof  Array)) {
7007                        xfaevent = [xfaevent];
7008                    }
7009                    for (var i = 0; i < xfaevent.length; i++) {
7010                        xfalib.ut.XfaUtil.prototype.getLogger().debug("xfa", "binding " + htmlevent + " with " + xfaevent[i]);
7011                        this.$userControl.on(htmlevent,
7012                            (function (xfevnt) {
7013                                return function (evnt) {
7014                                    xfalib.ut.XfaUtil.prototype.getLogger().debug("xfa", "trigger " + evnt.type +
7015                                    " xfa-event " + xfevnt);
7016                                    self._preProcessEvent.apply(self, [xfevnt, evnt]);
7017                                    //since the fix https://github.com/jquery/jquery/pull/972, Fix for keeping namespace when triggering an event using an Event #972
7018                                    //we need to clear the namespace and its regular expression of triggering event, as the listeners are registered on un-namespaced events
7019                                    evnt.namespace = "";
7020                                    evnt.namespace_re = "";
7021                                    self._trigger(xfevnt, evnt);
7022                                    self._postProcessEvent.apply(self, [xfevnt, evnt]);
7023                                }
7024                            })(xfaevent[i])
7025                        )
7026
7027                    }
7028                }
7029            }, this)
7030        },
7031
7032        _preProcessEvent: function (xfaevent, htmlevent) {
7033            if (xfaevent == this.options.commitEvent) {
7034                this.preProcessCommit(htmlevent);
7035            }
7036            switch (xfaevent) {
7037                case xfalib.ut.XfaUtil.prototype.XFA_ENTER_EVENT:
7038                    this.preProcessEnter(htmlevent);
7039                    break;
7040                case xfalib.ut.XfaUtil.prototype.XFA_EXIT_EVENT:
7041                    this.preProcessExit(htmlevent);
7042                    break;
7043                case xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT:
7044                    this.preProcessChange(htmlevent);
7045                    break;
7046                case xfalib.ut.XfaUtil.prototype.XFA_CLICK_EVENT:
7047                    this.preProcessClick(htmlevent);
7048                    break;
7049            }
7050
7051        },
7052
7053        _postProcessEvent: function (xfaevent, htmlevent) {
7054            if (xfaevent == this.options.commitEvent) {
7055                this.postProcessCommit(htmlevent);
7056            }
7057            switch (xfaevent) {
7058                case xfalib.ut.XfaUtil.prototype.XFA_ENTER_EVENT:
7059                    this.postProcessEnter(htmlevent);
7060                    break;
7061                case xfalib.ut.XfaUtil.prototype.XFA_EXIT_EVENT:
7062                    this.postProcessExit(htmlevent);
7063                    break;
7064                case xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT:
7065                    this.postProcessChange(htmlevent);
7066                    break;
7067                case xfalib.ut.XfaUtil.prototype.XFA_CLICK_EVENT:
7068                    this.postProcessClick(htmlevent);
7069                    break;
7070            }
7071        },
7072
7073        _initializeOptions: function () {
7074            _.each(this.optionsHandler, function (value, key) {
7075                if (typeof value === "function")
7076                    value.apply(this, [this.options[key]]); // TODO: check whether it is needed for initialization or not
7077            }, this)
7078        },
7079
7080        _setOption: function (key, value) {
7081            if (this.options[key] != value) {
7082                this.options[ key ] = value;
7083                if (typeof this.optionsHandler[key] === "function") {
7084                    this.optionsHandler[key].apply(this, [this.options[key]])
7085                }
7086            }
7087        },
7088
7089        /**
7090         * @override
7091         */
7092        option: function (key, value) {
7093            if (arguments.length === 1 &&
7094                typeof key === "string" &&
7095                this.options.hasOwnProperty(key) &&
7096                this.options[key] === undefined) {
7097                return undefined;
7098            }
7099            return $.Widget.prototype.option.apply(this, arguments)
7100        },
7101
7102        destroy: function () {
7103            this.$userControl.removeClass(this._widgetName);
7104        },
7105
7106
7107        render: function () {
7108            var control;
7109            if (this.element.children().length > 0) {
7110                control = $(this.element.children().get(0));
7111            }
7112            else
7113                control = this.element;
7114            control.attr("name", this.options.name)
7115            return control;
7116        },
7117
7118
7119        preProcessCommit: function (evnt) {
7120            this.options.value = this.getCommitValue();
7121            xfalib.ut.XfaUtil.prototype.getLogger().debug("xfa", "passing commit value " + this.options.value +
7122            "to model ");
7123        },
7124
7125        getCommitValue: function () {
7126
7127        },
7128
7129        preProcessExit: function (evnt) {
7130
7131        },
7132
7133        preProcessEnter: function (evnt) {
7134            //Only focus the enabled widgets
7135            if (this.options.access === "open") {
7136                this._showError();
7137                this.showValue();
7138            }
7139        },
7140
7141        preProcessChange: function (evnt) {
7142
7143        },
7144
7145        preProcessClick: function (evnt) {
7146
7147        },
7148
7149        postProcessCommit: function (evnt) {
7150            this.showDisplayValue();
7151        },
7152
7153        postProcessExit: function (evnt) {
7154            //Only for the enabled widgets
7155            if (this.options.access === "open") {
7156                this.showDisplayValue();
7157                this._hideError();
7158            }
7159        },
7160
7161        postProcessEnter: function (evnt) {
7162        },
7163
7164        postProcessChange: function (evnt) {
7165
7166        },
7167
7168        postProcessClick: function (evnt) {
7169
7170        },
7171
7172        showDisplayValue: function () {
7173            this.$userControl.val(this.options.displayValue)
7174        },
7175
7176        /**
7177         * Checks if the edit value is same as value present in the user control(html form element)
7178         * @returns {boolean}
7179         */
7180        _isValueSame : function(){
7181            return (((this.options.value === null) && (this.$userControl.val() === "")) || (this.options.value === this.$userControl.val()));
7182        },
7183
7184        showValue: function () {
7185            // May be $userControl doesn't have val(), using it as of now
7186            // If the value of the field is not same as edit value, only then set the value, this also solves IE bug of cursor
7187            // moving to the end of field on click
7188            if(!this._isValueSame()) {
7189                this.$userControl.val(this.options.value)
7190            }
7191        },
7192
7193        focus: function () {
7194            var that = this;
7195            // setTimeout added to fix CQ-51141
7196            // While using setFocus API in adaptive form, the focus was not being set in TextBox on chrome
7197            // and also on click of caption of RadioButton/Checkbox, due to fast event execution, he
7197nce adding delay during focus.
7198            setTimeout(function(){
7199                that.$userControl[0].focus();
7200            }, 1);
7201        },
7202
7203        click: function () {
7204            this.focus();
7205            this.$userControl.triggerHandler("click"); // we do not want the exact click as might bubble up to the field.
7206        },
7207
7208        /* widget specific code */
7209
7210        _showError: function () {
7211            if(this.errObj && _.isFunction(this.errObj.onFieldEnter)) {
7212                this.errObj.onFieldEnter(this);
7213            }
7214        },
7215
7216        _calculatePaddingForVAlign:function(diff){
7217           var flagForMoz = $.browser.mozilla && !xfalib.ut.Utilities.isIE11() &&
7218                              this.options.multiLine,
7219               vAlignBottomOrTop = this.options.paraStyles &&
7220                                   (this.options.paraStyles["vertical-align"] == "bottom" ||
7221                                    this.options.paraStyles["vertical-align"] == "top");
7222
7223           if(flagForMoz && vAlignBottomOrTop || $.browser.msie && this.options.multiLine) {
7224              return;
7225           }
7226           // to handle the edge cases, if the diff is like -0.01 the whole operation is getting aborted
7227           // this diff comes mainly due to scroll height getting rounded off when widgetHeight is like x.999999
7228           diff = (diff > -0.01) ? Math.abs(diff) : diff;
7229           if (this.options.paraStyles && diff > 0) {
7230                var vAlign = this.options.paraStyles["vertical-align"];
7231                if (vAlign == "bottom") {
7232                    diff = diff - this.options.paraStyles["padding-bottom"];
7233                    this.$userControl.css("padding-top", diff);
7234                    this.padding = this.$userControl.css("padding-top");
7235                }
7236                else if (vAlign == "top" || (vAlign != "middle" && vAlign == undefined)) {
7237                    if (this.options.paraStyles["padding-top"])
7238                        diff = diff - this.options.paraStyles["padding-top"];
7239                    this.$userControl.css("padding-bottom", diff);
7240                    this.padding = this.$userControl.css("padding-bottom");
7241                }
7242                else if (this.options.multiLine && vAlign == "middle") {
7243                    var newDiff = diff / 2;
7244                    newDiff = newDiff - this.options.paraStyles["padding-bottom"];
7245                    if (this.options.paraStyles["padding-top"])
7246                        newDiff = newDiff + this.options.paraStyles["padding-top"];
7247                    this.$userControl.css("padding-top", newDiff);
7248                }
7249            }
7250        },
7251
7252        _handleVAlignOnExit: function (evnt) {
7253
7254            if (!this.options.paraStyles) {
7255                //vAlign has to be handled only if there is paraStyles
7256                return;
7257            }
7258            var value = this.options.displayValue,
7259                lineHeight = xfalib.view.util.TextMetrics.measureExtent(value, {refEl: this.$userControl.get(0), maxHeight: -1}).height,
7260                widgetHeight = this.options.height,
7261                diff = widgetHeight - lineHeight;
7262            this._calculatePaddingForVAlign(diff);
7263
7264        },
7265
7266        _handleVAlignOnEnter: function (evnt) {
7267            //Only align the enabled widgets
7268            var flagForIE = $.browser.msie && this.options.multiLine;
7269            if (this.options.paraStyles && !flagForIE) {
7270                 var vAlign = this.options.paraStyles["vertical-align"];
7271                 if (vAlign == "bottom" && this.padding)
7272                     this.$userControl.css("padding-top", this.padding);
7273                 else if (vAlign == "top" && this.padding)
7274                     this.$userControl.css("padding-bottom", this.padding);
7275            }
7276        },
7277
7278        _hideError: function () {
7279            if(this.errObj && _.isFunction(this.errObj.onFieldExit)) {
7280                this.errObj.onFieldExit(this);
7281            }
7282        },
7283
7284        markError: function (msg, type) {
7285            if(this.errObj && _.isFunction(this.errObj.markError)) {
7286                this.errObj.markError(this, msg, type);
7287            }
7288        },
7289
7290        clearError: function () {
7291            if(this.errObj && _.isFunction(this.errObj.clearError)) {
7292                this.errObj.clearError(this);
7293            }
7294        },
7295
7296        getEditValue: function(value) {
7297            if(this.options.editPattern == null) {
7298                return value;
7299            }
7300            try {
7301                return xfalib.ut.PictureFmt.format(value, this.options.editPattern);
7302            } catch(e) {
7303                return null;
7304            }
7305        },
7306
7307        parseEditValue: function(value) {
7308            if(this.options.editPattern == null) {
7309                return value;
7310            }
7311            try {
7312                return xfalib.ut.PictureFmt.parse(value, this.options.editPattern);
7313            } catch(e) {
7314                return value;
7315            }
7316        }
7317    });
7318})($, window._);
7319(function($) {
7320    $.widget( "xfaWidget.defaultWidget", $.xfaWidget.abstractWidget, {
7321
7322        _widgetName: "defaultWidget",
7323
7324        getOptionsMap: function() {
7325            var parentOptionsMap = $.xfaWidget.abstractWidget.prototype.getOptionsMap.apply(this,arguments);
7326            return $.extend({},parentOptionsMap,{
7327                "access": function(val) {
7328                    switch(val) {
7329                        case "open" :
7330                            this.$userControl.removeAttr("readOnly");
7331                            this.$userControl.removeAttr("aria-readonly");
7332                            this.$userControl.removeAttr("disabled");
7333                            this.$userControl.removeAttr("aria-disabled");
7334                            break;
7335                        case "nonInteractive" :
7336                        case "protected" :
7337                            this.$userControl.attr("disabled", "disabled");
7338                            this.$userControl.attr("aria-disabled", "true");
7339                            break;
7340                        case "readOnly" :
7341                            this.$userControl.attr("readOnly", "readOnly");
7342                            this.$userControl.attr("aria-readonly", "true");
7343                            break;
7344                        default  :
7345                            this.$userControl.removeAttr("disabled");
7346                            this.$userControl.removeAttr("aria-disabled");
7347                            break;
7348                    }
7349                },
7350
7351                "displayValue": function(val) {
7352                    if(this.options.commitProperty) {
7353                        if($.browser.mozilla && this.options.commitProperty == "value") {
7354                            // on submitting form firefox does not remember autocomplete values, if updated through attr()
7355                            this.$userControl.val(this._displayEmptyStringForIE(this.options.displayValue));
7356                        } else {
7357                            this.$userControl.prop(this.options.commitProperty, this._displayEmptyStringForIE(this.options.displayValue));
7358                            this.$userControl.attr(this.options.commitProperty, this._displayEmptyStringForIE(this.options.displayValue));
7359                        }
7360                    } else {
7361                        this.logger().debug("xfaView", "[DefaultWidget._update], User Control or Commit Property is null");
7362                    }
7363                },
7364
7365                "placeholder": function(value){
7366                    this.$userControl.attr("placeholder", value);
7367                }
7368            });
7369        },
7370
7371        _displayEmptyStringForIE: function(value){
7372            /*CQ-69417: By default "null" is displayed in the comments text box
7373              "null" values shown in IE */
7374            // CQ-69107 included check for edge as well
7375            return (value == null && xfalib.ut.XfaUtil.prototype.detectIE()) ? '' : value;
7376        },
7377
7378        render : function() {
7379            var control = $.xfaWidget.abstractWidget.prototype.render.apply(this,arguments)
7380            this._attachEventHandlers(control)
7381            return control
7382        },
7383
7384        getCommitValue: function() {
7385            var value = this.$userControl.val();
7386            if(this.options.hScrollDisabled && !this.options.multiLine)
7387                var value = xfalib.ut.XfaUtil.prototype.splitStringByWidth(this.$userControl.val(),this.$userControl.width(),this.$userControl.get(0)) ;
7388            return value;
7389        },
7390
7391        _attachEventHandlers: function($control) {
7392            $control.keydown($.proxy(this._handleKeyDown,this));
7393            $control.keypress($.proxy(this._handleKeyPress,this));
7394            $control.on('paste',$.proxy(this._handlePaste,this));
7395            $control.on('cut',$.proxy(this._handleCut,this));
7396        },
7397
7398        _compositionUpdateCallback : function (event) {
7399            return false;
7400        },
7401
7402        _attachCompositionEventHandlers : function($control) {
7403            var isComposing = false; // IME Composing going on
7404            var hasCompositionJustEnded = false; // Used to swallow keyup event related to compositionend
7405            // IME specific handling, to handle japanese languages max limit
7406            // since enter can also be invoked during composing, a special handling is done here
7407            var that = this,
7408                changeCaratPosition = function() {
7409                    // change the carat selection position to further limit input of characters
7410                    var range = window.getSelection();
7411                    range.selectAllChildren(that.$userControl[0]);
7412                    range.collapseToEnd();
7413                };
7414            $control.keyup(function(event) {
7415                if (/*isComposing || */hasCompositionJustEnded) {
7416                    if (that._compositionUpdateCallback(event)) {
7417                        changeCaratPosition();
7418                    }
7419                    // IME composing fires keydown/keyup events
7420                    hasCompositionJustEnded = false;
7421                }
7422            });
7423            $control.on("compositionstart",
7424                function(event) {
7425                    isComposing = true;
7426                })
7427                .on("compositionupdate",
7428                    function(event) {
7429                        // event.originalEvent.data refers to the actual content
7430                        if (that._compositionUpdateCallback(event)) {
7431                            changeCaratPosition();
7432                        }
7433                    })
7434                .on("compositionend",
7435                    function(event) {
7436                        isComposing = false;
7437                        // some browsers (IE, Firefox, Safari) send a keyup event after
7438                        //  compositionend, some (Chrome, Edge) don't. This is to swallow
7439                        // the next keyup event, unless a keydown event happens first
7440                        hasCompositionJustEnded = true;
7441                    })
7442                .on("keydown",
7443                    function(event) {
7444                        // Safari on OS X may send a keydown of 229 after compositionend
7445                        if (event.which !== 229) {
7446                            hasCompositionJustEnded = false;
7447                        }
7448                    });
7449        },
7450
7451        _handleKeyDown : function(event){
7452            if(event.keyCode == 13 || event.charCode == 13 || event.which == 13) // touch devices may return charCode
7453                event.preventDefault();
7454        },
7455
7456        _handleKeyPress : function(event){
7457            if(event.keyCode == 13 || event.charCode == 13 || event.which == 13) // touch devices may return charCode
7458                event.preventDefault();
7459        }
7460    });
7461})($);
7462(function($, _) {
7463    var xfaUtil = xfalib.ut.XfaUtil.prototype;
7464    $.widget( "xfaWidget.dateTimeEdit", $.xfaWidget.defaultWidget, {
7465
7466        _widgetName : "dateTimeEdit",
7467
7468        getEventMap: function() {
7469            var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getEventMap.apply(this,arguments);
7470            if(this._nativeWidget === false) {
7471                return $.extend({}, parentOptionsMap, {
7472                    "onfocus1.datetimepicker": xfalib.ut.XfaUtil.prototype.XFA_ENTER_EVENT,
7473                    "onvaluechange.datetimepicker": xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT,
7474                    "onfocusout.datetimepicker": xfalib.ut.XfaUtil.prototype.XFA_EXIT_EVENT,
7475                    "onoverlap.datetimepicker": xfalib.ut.XfaUtil.prototype.XFA_CLICK_EVENT, // Custom Event to fix BUG #3626974
7476                    "input": xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT, // TODO : add handler for xfa.event.change
7477                    "focus": null,
7478                    "blur": null
7479                })
7480            } else {
7481                return $.extend({}, parentOptionsMap, {
7482                    "change": xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT
7483                })
7484            }
7485        },
7486
7487        _getAdobeDatePickerOptionsMap : function(parentOptionsMap) {
7488            return {
7489                "access" : function (val) {
7490                    switch (val) {
7491                        case "open" :
7492                            this.$userControl.adobeDateTimePicker("access", true);
7493                            break;
7494                        case "nonInteractive" :
7495                        case "protected" :
7496                        case "readOnly" :
7497                            this.$userControl.adobeDateTimePicker("access", false);
7498                            break;
7499                    }
7500                    parentOptionsMap.access.apply(this, arguments);
7501                },
7502                "displayValue" : function (val) {
7503                    // set the value in the datepicker plugin
7504                    this.$userControl.adobeDateTimePicker("value", this.options.value);
7505                    // show the display value
7506                    this.showDisplayValue();
7507                }
7508            }
7509        },
7510
7511        _getNativeDatePickerOptionsMap: function (parentOptionsMap) {
7512            return {
7513                "displayValue": function (val) {
7514                    this.showDisplayValue();
7515                }
7516            }
7517        },
7518
7519
7520        getOptionsMap: function() {
7521            var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this,arguments),
7522                datePickerOptions = this._nativeWidget === false ? this._getAdobeDatePickerOptionsMap(parentOptionsMap)
7523                    : this._getNativeDatePickerOptionsMap(parentOptionsMap),
7524                commonOptions = {
7525                    "paraStyles": function (paraStyles) {
7526                        parentOptionsMap.paraStyles.apply(this, arguments);
7527                        this._handleVAlignOnExit();
7528                    },
7529
7530                     "access": function(val) {
7531                        // update width on change of access (as width of widget is dependent on access)
7532                        // The calender icon should be hidden, and widget should take full space when readOnly
7533                        parentOptionsMap.access.apply(this, arguments);
7534                        this.getOptionsMap().width.apply(this,[this.options.width]);
7535                      },
7536                     "width": function (val) {
7537                        parentOptionsMap.width.apply(this, arguments);
7538                        if (this.options.showCalendarIcon && val && this.options.access == "open") {
7539                            var effectiveWidth = val > this.options.calendarIconWidth ? val - this.options.calendarIconWidth : val;
7540                            this.$userControl.width(effectiveWidth);  // leave space for the cal icon
7541                        }
7542                    },
7543
7544                    "height": function(val) {
7545                        parentOptionsMap.height.apply(this, arguments);
7546                        this._handleVAlignOnExit();
7547                    },
7548                    "screenReaderText": function (val) {
7549                        var editPattern = this.options.editPattern;
7550                        var defaultEditPattern = this._nativeWidget ? "mm/dd/yyyy" : "YYYY-MM-DD";
7551                        var regex = /(?:date){0,1}{(.*)}/;
7551 // date{<pattern>} or {<pattern>} both are valid as per xfa spec
7552                        editPattern = typeof editPattern === "string" ? editPattern.match(regex)[1] : defaultEditPattern;
7553                        var defaultLabel = "Please Enter date in {0} format only";
7554                        if (editPattern) {
7555                            var ariaLabel = xfalib.ut.LocalizationUtil.prototype.getLocalizedMessage("",
7556                                xfalib.locale.Strings.datePickerAriaLabel || defaultLabel, [editPattern])
7557                        }
7558                        var finalVal = val !== undefined ? val + " " + ariaLabel : val;
7559                        this.$userControl.attr("aria-label", finalVal);
7560                    }
7561                };
7562            return $.extend({},parentOptionsMap,datePickerOptions, commonOptions);
7563        },
7564
7565        postProcessExit: function(evnt) {
7566            $.xfaWidget.defaultWidget.prototype.postProcessExit.apply(this,arguments);
7567            this._handleVAlignOnExit ();
7568        },
7569
7570        preProcessEnter: function(evnt) {
7571            $.xfaWidget.defaultWidget.prototype.preProcessEnter.apply(this,arguments);
7572            this._handleVAlignOnEnter();
7573        },
7574
7575        preProcessChange: function(evnt) {
7576           //CQ-46332:loss of date value in date-picker , setting the value here or else
7577           //it gets lost during focus
7578           if(this._nativeWidget === true){
7579            this.options.value = this.$userControl.val();
7580           }
7581        },
7582
7583        showDisplayValue: function() {
7584            if(this._nativeWidget === false) {
7585                $.xfaWidget.defaultWidget.prototype.showDisplayValue.apply(this, arguments);
7586            } else {
7587                this.showValue();
7588            }
7589        },
7590
7591
7592        showValue: function () {
7593            if (this._nativeWidget == false) {
7594                this.$userControl.adobeDateTimePicker("value", this.options.value);
7595            } else {
7596                $.xfaWidget.defaultWidget.prototype.showValue.apply(this, arguments);
7597            }
7598            $.xfaWidget.textField.prototype._selectOnFocusInIE.apply(this, arguments);
7599        },
7600
7601        getCommitValue: function() {
7602            if (this._nativeWidget === false) {
7603                var value = this.$userControl.adobeDateTimePicker("value"),
7604                    parsedValue = this.parseEditValue(value);
7605                return parsedValue;
7606            }
7607            return $.xfaWidget.defaultWidget.prototype.getCommitValue.apply(this, arguments);
7608        },
7609
7610        render: function() {
7611            var self = this,
7612                textStyle = this.getOrElse(this.$data(this.element.get(0), "xfamodel"), "textstyle", ""),
7613                $control = $.xfaWidget.abstractWidget.prototype.render.apply(this, arguments),
7614                $source = $control,
7615                id,
7616                existingInlineStyleAttributeValues,
7617                newInlineStyleAttributeValues,
7618                combinedInlineStyleAttributeValues;
7619            existingInlineStyleAttributeValues = this.element.find("input").attr("style") || '';
7620            this._nativeWidget = true;
7621            if(this.options.useNativeWidget === false || $control[0].type !== "date") {
7622                this._nativeWidget = false;
7623                id = this.element.find("input")[0].id;
7624                this.element.children().remove();
7625                $("<div></div>").css({position: "relative", width: "100%", height: "100%"}) // want to fill entire width of containing table cell
7626                    .append($("<input type='text'/>"))
7627                    .appendTo(this.element);
7628                $control = $("input", this.element).
7629                    attr("style", textStyle).
7630                    attr("name", this.options.name).
7631                    attr("id", id).
7632                    adobeDateTimePicker({
7633                        positioning: this.element,
7634                        locale: {
7635                            months: this.options.months,
7636                            days: this.options.days,
7637                            zero: this.options.zero,
7638                            clearText: this.options.clearText
7639                        },
7640                        access: this.options.access,
7641                        value: this.options.value,
7642                        showCalendarIcon: this.options.showCalendarIcon,
7643                        iconWidth: this.options.calendarIconWidth,
7644                        minValidDate : this.options.minValidDate,
7645                        maxValidDate : this.options.maxValidDate,
7646                        exclMinDate :  this.options.exclMinDate,
7647                        exclMaxDate : this.options.exclMaxDate,
7648                        editValue: function (value) {
7649                            return self.getEditValue(value);
7650                        }
7651                    });
7652            }
7653            this._attachEventHandlers($control);
7654            newInlineStyleAttributeValues = this.element.find("input").attr("style") || '';
7655            //append the previous inlineStyleAttributeValues to newInlineStyleAttributeValues so that the inline styles
7656            //added from the dialog are applied.
7657            combinedInlineStyleAttributeValues = newInlineStyleAttributeValues + existingInlineStyleAttributeValues;
7658            this.element.find("input").attr("style", combinedInlineStyleAttributeValues);
7659            // only in case of adaptive form, we would copy the attributes back
7660            if(window.guideBridge) {
7661                // restore the original attribute back to destination object
7662                this.copyAttributesFromSrcToDest($source, this.element.find("input"));
7663            }
7664            return $control;
7665        }
7666    }) ;
7667
7668})($, _);
7669(function($, _) {
7670$.widget("xfaWidget.numericInput", $.xfaWidget.defaultWidget, {
7671
7672    _widgetName: "numericInput",
7673
7674	options : {
7675		value : null,
7676		curValue: null,
7677        pos: 0,
7678        lengthLimitVisible: true,
7679        zero:"0",
7680        decimal:".",
7681        minus:"-"
7682	},
7683
7684    //TODO: to support writing in different locales \d should be replaced by [0-9] for different locales
7685    _matchArray : {
7686                    "integer":"^[+-]?{digits}*$",
7687                    "decimal":"^[+-]?{digits}{leading}({decimal}{digits}{fraction})?$",
7688                    "float":"^[+-]?{digits}*({decimal}{digits}*)?$"
7689                  },
7690
7691    _regex : null,
7692
7693    _engRegex : null,
7694
7695    _writtenInLocale : false,
7696
7697    _previousCompositionVal : "",
7698
7699
7700    _toLatinForm : function (halfOrFullWidthStr) {
7701        // refer http://www.fileformat.info/info/unicode/block/halfwidth_and_fullwidth_forms/utf8test.htm
7702        return halfOrFullWidthStr.replace(
7703            /[\uff00-\uffef]/g,
7704            function(ch) { return String.fromCharCode(ch.charCodeAt(0) - 0xfee0); }
7705        );
7706    },
7707
7708    getOptionsMap: function() {
7709        var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this,arguments);
7710        return $.extend({},parentOptionsMap,{
7711            "paraStyles": function(paraStyles){
7712                parentOptionsMap.paraStyles.apply(this,arguments);
7713                this._handleVAlignOnExit ();
7714            } ,
7715
7716            "height": function(val) {
7717                if(val)   {
7718                    this.$css(this.$userControl[0],{"height" :val});
7719                    this._handleVAlignOnExit();    // To Handle the case of expandable Fields
7720                }
7721            }
7722
7723        })
7724    },
7725
7726    getEventMap: function() {
7727        var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getEventMap.apply(this,arguments);
7728        return $.extend({},parentOptionsMap,{
7729            "onKeyInput.numericInput" : xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT
7730        })
7731    },
7732
7733    _getDigits: function() {
7734        var zeroCode = this.options.zero.charCodeAt(0),
7735            digits = "";
7736        for(var i = 0;i < 10;i++) {
7737            digits += String.fromCharCode(zeroCode + i);
7738        }
7739        return "["+digits+"]"
7740    },
7741
7742    _escape: function(str) {
7743      return str.replace(".","\\.")
7744    },
7745
7746    postProcessExit: function(evnt) {
7747        $.xfaWidget.defaultWidget.prototype.postProcessExit.apply(this,arguments);
7748        this._handleVAlignOnExit ();
7749    },
7750
7751    preProcessEnter: function(evnt) {
7752        $.xfaWidget.defaultWidget.prototype.preProcessEnter.apply(this,arguments);
7753        this._handleVAlignOnEnter();
7754    },
7755
7756	render : function() {
7757        var matchStr =  this._matchArray[this.options.dataType];
7758        if(matchStr) {
7759            var ld = this.options.leadDigits,
7760                fd = this.options.fracDigits,
7761                ldstr = ld && ld != -1 ? "{0,"+ld+"}"
7762                    : "*",
7763                fdstr = fd && fd != -1 ? "{0,"+fd+"}"
7764                    : "*",
7765                matchStr =  matchStr.replace("{leading}",ldstr)
7766                                    .replace("{fraction}",fdstr),
7767                localeStr = matchStr.replace(/{digits}/g,this._getDigits())
7768                                    .replace("{decimal}",this._escape(this.options.decimal)),
7769                engStr = matchStr.replace(/{digits}/g,"[0-9]")
7770                                .replace("{decimal}","\\.")
7771            this._processValue = !(this._getDigits() == "[0123456789]" && this.options.decimal == ".")
7772            this._regex = new RegExp(localeStr, "g");
7773            this._engRegex = new RegExp(engStr, "g");
7774        }
7775        return $.xfaWidget.defaultWidget.prototype.render.apply(this, arguments);
7776    },
7777
7778    getCommitValue: function() {
7779        var value = $.xfaWidget.defaultWidget.prototype.getCommitValue.apply(this, arguments);
7780        // we support full width, half width and locale specific numbers
7781        value = this._toLatinForm(value);
7782        if(value.length > 0 && this._processValue && !value.match(this._engRegex)) {
7783            this._writtenInLocale = true;
7784            value = this._convertValueFromLocale(value);
7785        } else {
7786            this._writtenInLocale = false
7787        }
7788        if(value && value.length >= this.options.combCells )
7789            value = value.slice(0,this.options.combCells);
7790        this._previousCompositionVal = value;
7791        return value;
7792    },
7793
7794    _compositionUpdateCallback : function (event) {
7795        var that = this;
7796        var flag = false;
7797        var leadDigits = that.options.leadDigits;
7798        var fracDigits = that.options.fracDigits;
7799        // we don't check use-case where just fracDigits is set since in case of composition update, the value to update is not known
7800        if (leadDigits !== -1) {
7801            var val = that.$userControl.val();
7802            if (event.type === "compositionupdate" && event.originalEvent.data) {
7803                val = val + event.originalEvent.data.substr(event.originalEvent.data.length - 1);
7804            }
7805            // can't use the existing regex (since current regex checks for english digits), rather doing leadDigit compare
7806            var totalLength = leadDigits + (fracDigits !== -1 ? (fracDigits + that.options.decimal.length) : 0);
7807            if (val.indexOf(that.options.decimal) === -1) {
7808                totalLength = leadDigits;
7809            }
7810            var latinVal = this._toLatinForm(val);
7811            // match both since we support full width, half width and locale specific input
7812            var match = latinVal.match(that._regex)|| latinVal.match(this._engRegex);
7813            flag  = !match;
7814            if (match === null) {
7815                // entered invalid character, revert to previous value
7816                that.$userControl.val(that._previousCompositionVal);
7817                flag = true;
7818            } else if (flag) {
7819                // if max reached
7820                var newVal = val.substr(0, totalLength);
7821                that.$userControl.val(newVal);
7822                that._previousCompositionVal = newVal;
7823                flag = true;
7824            } else {
7825                that._previousCompositionVal = val;
7826            }
7827        }
7828        return flag;
7829    },
7830
7831    _attachEventHandlers : function($control) {
7832        $.xfaWidget.defaultWidget.prototype._attachEventHandlers.apply(this, arguments);
7833        // IME specific handling, to handle japanese languages max limit
7834        $.xfaWidget.defaultWidget.prototype._attachCompositionEventHandlers.apply(this, arguments);
7835	},
7836
7837    _handleKeyInput : function(event, character, code){
7838        if(event.ctrlKey && !_.contains(['paste', 'cut'], event.type)) {
7839            return true;
7840        }
7841
7842        $.xfaWidget.defaultWidget.prototype._handleKeyDown.apply(this,arguments);
7843        this.options.lengthLimitVisible = true;
7844
7845        var val = this.$userControl.prop(this.options.commitProperty) || '',
7846            // if selectionStart attribute isn't supported then its value will be undefined
7847            selectionStart = xfalib.view.util.HtmlUtil.getHTMLSupportedAttr(this.$userControl[0], "selectionStart"),
7848            isSelectionAttrSupported = !(selectionStart === undefined || selectionStart === null),
7849            selectionStart = selectionStart || 0,
7850            selectionEnd = xfalib.view.util.HtmlUtil.getHTMLSupportedAttr(this.$userControl[0], "selectionEnd") || 0,
7851            combCells = parseInt(this.options.combCells) || 0,
7852            current,
7853            change = character;
7854
7855        if (combCells > 0 ) {
7856            change = character.substr(0, combCells - val.length + selectionEnd - selectionStart);
7857        }
7858
7859        current = val.substr(0, selectionStart) + change + val.substr(selectionEnd);
7860        // done to handle support for both full width, half width or mixed input in number field
7861        var latinCurrentValue = this._toLatinForm(current);
7862
7863        // we want to check regex first and then see whether it was numeric or not.
7864        if (!(this._regex == null || latinCurrentValue.match(this._regex) || latinCurrentValue.match(this._engRegex))) {
7865            event.preventDefault();
7866            return false;
7867        }
7868
7869        // CQ-4245407 : selectionStart and selectionEnd attributes aren't supported in case of input type = number
7870        // it is used for providing native HTML5 implementation for numeric field, so no further processing is required
7871        // As it is specific to AF and AF doesn't support change event on each keypress, so this change should be fine
7872        if (!isSelectionAttrSupported) {
7873            return true;
7874        }
7875
7876        if (!_.contains(['keydown', 'cut'], event.type) && combCells && (val.length >= combCells || current.length > combCells) && selectionStart === selectionEnd) {
7877            event.preventDefault();
7878            return false;
7879        }
7880
7881        this.options.curValue = val;
7882        this._previousCompositionVal = val;
7883        this.options.pos = selectionStart;
7884
7885        if(this.options.hScrollDisabled && !_.contains(['keydown', 'cut'], event.type)) {
7886            var expectedWidth = xfalib.view.util.TextMetrics.measureExtent(current, {refEl: this.$userControl[0], maxWidth:-1}).width;
7887            if(!event.ctrlKey && expectedWidth > this.$userControl.width() - 5){
7888                event.preventDefault();
7889                this.options.lengthLimitVisible = false;
7890            }
7891        }
7892
7893        this.$userControl.trigger({
7894            type : "onKeyInput.numericInput",
7895            originalType : event.type,
7896            character : character,  // contains the pasted string or pressed key
7897            keyCode : event.keyCode || 0,
7898            charCode : event.charCode || 0,
7899            which : event.which || 0,
7900            ctrlKey : event.ctrlKey || event.metaKey || false,
7901            shiftKey : event.shiftKey || false,
7902            keyDown : false, // This property is available only for list boxes and drop-down lists
7903            selectionStart: selectionStart,
7904            selectionEnd: selectionEnd
7905        });
7906    },
7907
7908    _handleKeyDown : function(event){
7909        if (event) {
7910            var code = event.charCode || event.which || event.keyCode || 0;
7911            if(code == 8 || code == 46) // backspace and del
7912               this._handleKeyInput(event, "", code);
7913            else if(code == 32) { // suppress space
7914                event.preventDefault();
7915                return false;
7916            }
7917        }
7918    },
7919
7920    _isValidChar: function (character) {
7921        character = this._toLatinForm(character);
7922        var lastSingleDigitChar = String.fromCharCode(this.options.zero.charCodeAt(0) + 9);
7923        // we only full width, half width and also locale specific if customer has overlayed the i18n file
7924        return (character >= "0" && character <= "9") || (character>=this.options.zero && character<=lastSingleDigitChar) || character===this.options.decimal || character===this.options.minus;
7925    },
7926
7927    _handleKeyPress : function(event){
7928        if (event) {
7929            var code = event.charCode || event.which || event.keyCode || 0,
7930                character = String.fromCharCode(code);
7931
7932            if(xfalib.ut.XfaUtil.prototype.isNonPrintableKey(event.key)) { // mozilla also generates a keypress, along with keydown
7933                return true;                                               // for all keys, so only handling printable keys in keypress
7934            }
7935
7936            if (this._isValidChar(character))
7937                this._handleKeyInput(event, character, code);
7938            else if (!event.ctrlKey){
7939                event.preventDefault();
7940                return false;
7941            }
7942        }
7943    },
7944
7945    _handlePaste : function(event){
7946        if (event) {
7947            var pastedChar = undefined;
7948            if (window.clipboardData && window.clipboardData.getData) { // IE
7949                pastedChar = window.clipboardData.getData('Text');
7950            } else if (event.originalEvent.clipboardData && event.originalEvent.clipboardData.getData) {
7951                pastedChar = event.originalEvent.clipboardData.getData('text/plain');
7952            }
7953
7954            if(pastedChar) {
7955                var allPastedCharsValid = _.every(pastedChar.split(''), function (character) {
7956                    return this._isValidChar(character);
7957                }, this);
7958                if (allPastedCharsValid) {
7959                    // during paste we support both half width, full width and locale specific numbers
7960                    pastedChar = this._toLatinForm(pastedChar);
7961                    this._handleKeyInput(event, pastedChar, 0);
7962                }
7963                else if (!event.ctrlKey) {
7964                    event.preventDefault();
7965                    return false;
7966                }
7967            }
7968        }
7969    },
7970
7971    _handleCut : function(event) {
7972        if (event) {
7973            this._handleKeyInput(event, "", 0);
7974        }
7975    },
7976    // CQ-107886 : added handling for negative values, as for '-', '-3' was getting returned
7977    _convertValueToLocale: function(val) {
7978        var zeroCode = this.options.zero.charCodeAt(0);
7979        return  _.map(val,function(c) {
7980            if(c == ".") {
7981                return this.options.decimal;
7982            } else if(c == "-") {
7983                return this.options.minus;
7984            } else {
7985                return String.fromCharCode(parseInt(c) + zeroCode);
7986            }
7987        },this).join("");
7988    },
7989
7990    _convertValueFromLocale: function(val) {
7991        val = this._toLatinForm(val);
7992        var zeroCode = this.options.zero.charCodeAt(0);
7993        return  _.map(val,function(c) {
7994            if(c == this.options.decimal) {
7995                return ".";
7996            } else if(c == this.options.minus) {
7997                return "-";
7998            } else {
7999                return (c.charCodeAt(0) - zeroCode).toString();
8000            }
8001        },this).join("");
8002    },
8003
8004    showValue : function() {
8005       // if the value is same, don't do anything
8006       if(!this._isValueSame()){
8007           if(this.options.value && this._writtenInLocale) {
8008               this.$userControl.val(this._convertValueToLocale(this.options.value))
8009           } else {
8010               this.$userControl.val(this.options.value)
8011           }
8012       }
8013       //IE doesn't show selected text if we focus and set its value all the time so force selection
8014       $.xfaWidget.textField.prototype._selectOnFocusInIE.apply(this, arguments);
8015    }
8016});
8017})($, window._);(function ($, _) {
8018    $.widget("xfaWidget.dropDownList", $.xfaWidget.defaultWidget, {            //commitEvent: change; commitProperty: value<Array>
8019
8020        _widgetName: "dropDownList",
8021
8022        options: {
8023            value: [],
8024            items: [],
8025            editable: false,
8026            placeholder: "",
8027            displayValue: []
8028        },
8029
8030        widgetSkeleton: '<select name="" style="" size = "1"></select>',
8031        optionSkeleton: '<option data-user-option></option>',
8032        optGroupSkeleton: '<optgroup label=""></optgroup>',
8033        AF_OPTGROUP_NAME: "afOptGroupName",
8034        PLACE_HOLDER_STYLE_CLASS : "placeHolder",
8035
8036        getOptionsMap: function () {
8037            var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this, arguments);
8038            return $.extend({}, parentOptionsMap, {
8039                "value": function (val) {
8040                    if (!_.isArray(val)) {
8041                        val = [val];
8042                    }
8043                    var selectedOptionFound = false,
8044                        that = this;
8045                    //sync option selection as per new values
8046                    $("option", this.$userControl).each(function (index) {
8047                        var selectValue = $(this).val();
8048                        //Check if this value is present in options value array
8049                        if (_.contains(val, selectValue)) {
8050                            $(this).prop("selected", true);
8051                            selectedOptionFound = true;
8052                        } else {
8053                            $(this).prop("selected", false);
8054                            if (this.id === "emptyValue") {
8055                                $(this).val("").html(that.options.placeholder);
8056                                //Hiding emptyValue with no placeholder text configured.
8057                                if(that.options.placeholder.length == 0) {
8058                                    $(this).hide();
8059                                }
8060                            }
8061                        }
8062                    });
8063
8064                    /* Add default option if :
8065                    / 1. If placeholder add an extra option
8066                    / 2. If the value is set anything other than the options (and null/"") create a new option
8067                     */
8068                    if ((!selectedOptionFound && val.length != 0 && val[0] != null) || that.options.placeholder.length != 0) {
8069                        if (this.$userControl.children('[data-empty-option]').length == 0) {
8070                            var extraOption = document.createElement("option");
8071                            extraOption.setAttribute("data-empty-option", "");
8072                            extraOption.setAttribute("role", "none");
8073                            extraOption.setAttribute("value", "")
8074                            this.$userControl[0].insertBefore(extraOption, this.$userControl[0].firstChild);
8075                        }
8076                        // If placeholder is present the set value of empty option to placeholder
8077                        if (that.options.placeholder.length != 0) {
8078                            this.$userControl.children('[data-empty-option]').text(that.options.placeholder);
8079                        }
8080                        // If placeholder is present and value is not present then select placeholder
8081                        if (val.length == 0 || val[0] == null) {
8082                            this.$userControl.children('[data-empty-option]').prop("selected", true);
8083                        } // If value is set anything other than option then set empty option to value
8084                        else if (!selectedOptionFound && val.length != 0 && val[0] != null) {
8085                            this.$userControl.children('[data-empty-option]').text(val[0]).
8086                            prop("selected", true).
8087                            val(_.escape(val[0])).
8088                            show();
8089                        }
8090
8091                    }
8092                    else if (that.options.placeholder.length == 0) {
8093                        // Delete default option if value is found in options while adding options
8094                        if (selectedOptionFound && this.$userControl.children('[data-empty-option]').val() != that.options.displayValue) {
8095                            if (this.$userControl.children('[data-empty-option]').length > 0) {
8096                                this.$userControl[0].removeChild(this.$userControl.children('[data-empty-option]')[0]);
8097                            }
8098                        }
8099                        // Reset the value of dropdown based on rule
8100                        else if (!selectedOptionFound && (val.length == 0 || val == null || val[0] == null)) {
8101                            this.$userControl[0].value = "";
8102                        }
8103                    }
8104                    this.$userControl.toggleClass(this.PLACE_HOLDER_STYLE_CLASS, val.length == 0 || val == null);
8105                },
8106
8107                "items": function (val) {
8108                    if (!_.isArray(val)) {
8109                        val = [val];
8110                    }
8111
8112                    var AF_OPTGROUP_NAME = "afOptGroupName";
8113                    var i, j, optgroupOptions = [], element, $viewOptgroup, $preOptgroup;
8114                    var viewOptgroups = $("optgroup", this.$userControl);
8115                    // Removes all options which earlier didn't belong to any optgroup.
8116                    if (viewOptgroups.length == 0) {
8117                        // save selected value because when value is set before items in setWidgetOptions
8118                        // the selected value would get lost in html
8119                        var selectedOption = this.$userControl.find('[selected]');
8120                        this.$userControl.children("option[data-user-option]").remove();
8121                    }
8122                    for (i = 0, j = 0; j < val.length; j++) {
8123                        element = val[j];
8124                        if (element.save != AF_OPTGROUP_NAME) {
8125                            // Add options to String[] which will be later synced to the optgroup.
8126                            optgroupOptions.push(element);
8127                        } else {
8128                            $viewOptgroup = viewOptgroups[i++];
8129                            // When optgroup is less than the required optgroups.
8130                            if (i > viewOptgroups.length) {
8131                                $viewOptgroup = this.addGroup(element.display);
8132                            }
8133                            // Undefined as it may not occur even once when list is purely of options.
8134                            if (!_.isUndefined($viewOptgroup) && $viewOptgroup.label != element.display) {
8135                                $viewOptgroup.label = element.display || '';
8136                            }
8137                            // Check to skip the first optgroup.
8138                            if (j != 0) {
8139                                // Syncs options to the prev optgroup.
8140                                // Prev optgroup because current optgroup marks the end of options of prev.
8141                                this.handleOptions($preOptgroup, optgroupOptions);
8142                                // Clear options of the optgroup for next optgroup.
8143                                optgroupOptions = [];
8144                            }
8145                            $preOptgroup = $viewOptgroup;
8146                        }
8147                    }
8148                    // Removes all extra optgroups.
8149                    while (i < viewOptgroups.length) {
8150                        $viewOptgroup = viewOptgroups[i++];
8151                        this.deleteGroup($viewOptgroup.label);
8152                    }
8153                    //Add remaining options to respective optgroup.
8154                    if (optgroupOptions.length != 0) {
8155                        this.handleOptions($preOptgroup, optgroupOptions, selectedOption);
8156                    }
8157
8158                    //Intentionally left the selection check -> I am relying on the fact that "value" sync event is called after "items" sync.
8159                },
8160
8161                "displayValue": function () {
8162                },
8163                "placeholder": function(value){
8164                    // overriding the default handling of place holder options setter
8165                },
8166                "access": function (val) {
8167                    switch (val) {
8168                        case "open" :
8169                            this.$userControl.removeAttr("disabled");
8170                            this.$userControl.removeAttr("aria-disabled");
8171                            this.$userControl.removeAttr("aria-readonly");
8172                            var options = this.$userControl[0];
8173                            if(options && options.length > 0) {
8174                                _.each(this.$userControl[0], function (element) {
8175                                    element.removeAttribute("disabled");
8176                                });
8177                            }
8178                            break;
8179                        case "nonInteractive" :
8180                        case "protected" :
8181                            // In case of nonInteractive and protected, field should be disabled and cannot be tabbed.
8182                            this.$userControl.attr("disabled", "disabled");
8183                        case "readOnly" :
8184                            this.$userControl.attr("aria-disabled", "true");
8185                            this.$userControl.attr("aria-readonly", "true");
8186                            var options = this.$userControl[0];
8187                            if(options && options.length > 0) {
8188                                _.each(this.$userControl[0], function (element) {
8189                                    element.disabled = true;
8190                                });
8191                            }
8192                            break;
8193                        default  :
8194                            this.$userControl.removeAttr("disabled");
8195                            this.$userControl.removeAttr("aria-disabled");
8196                            this.$userControl.removeAttr("aria-readonly");
8197                            break;
8198                    }
8199                }
8200            })
8201        },
8202
8203        getEventMap: function () {
8204            var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getEventMap.apply(this, arguments);
8205            return $.extend({}, parentOptionsMap, {
8206                "focus": [xfalib.ut.XfaUtil.prototype.XFA_ENTER_EVENT, xfalib.ut.XfaUtil.prototype.XFA_PREOPEN_EVENT],
8207                "change": xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT
8208            })
8209        },
8210
8211        render: func
8211tion () {
8212            var existingInlineStyleAttributeValues = this.element.find("select").attr("style"),
8213                newInlineStyleAttributeValues,
8214                combinedInlineStyleAttributeValues,
8215                size = 1;
8216
8217            this.element.addClass(this._widgetName);
8218            this.element.children().remove();
8219
8220            var inputName = _.uniqueId("select"),  //Unique Id
8221                textStyle = this.getOrElse(this.$data(this.element.get(0), "xfamodel"), "textstyle", ""),
8222                $widgetSkeleton = $(this.widgetSkeleton)
8223                                    .attr('style', textStyle)
8224                                    .attr('name', inputName);
8225            if(this.options.editable) {
8226                $widgetSkeleton.addClass('combobox');
8227            }
8228
8229            if(this.options.items && this.options.items.length>0){
8230                size = this.options.items.length
8231            }
8232            if(this.options.multiSelect) {
8233                $widgetSkeleton.addClass('multiDropdown');
8234                $widgetSkeleton.attr('multiple','multiple');
8235                $widgetSkeleton.attr('size',size);
8236                $widgetSkeleton.attr('data-multiple-selection',"true");
8237            }
8238
8239            var $parEl = $widgetSkeleton;
8240            _.each(this.options.items, function(item){
8241                var saveItem = _.isString(item.save) ? item.save.replace(/\"/g, "&quot;") : "";
8242                if (saveItem === this.AF_OPTGROUP_NAME){ // assuming optgroups appear before options
8243                    $parEl = $(this.optGroupSkeleton).attr('label', item.display).appendTo($widgetSkeleton);
8244                } else {
8245                    $(this.optionSkeleton).val(saveItem).text(item.display).appendTo($parEl);
8246                }
8247            },this);
8248
8249            this.element.append($widgetSkeleton);
8250
8251            var control = this.element.children().eq(0).attr("name", this.options.name);
8252            this._attachEventHandlers(control);
8253            newInlineStyleAttributeValues = this.element.find("select").attr("style");
8254            //append the previous inlineStyleAttributeValues to newInlineStyleAttributeValues so that the inline styles
8255            //added from the dialog are applied.
8256            combinedInlineStyleAttributeValues = newInlineStyleAttributeValues + existingInlineStyleAttributeValues;
8257            this.element.find("select").attr("style", combinedInlineStyleAttributeValues);
8258            return control;
8259        },
8260
8261        //syncs the options to the optgroup dynamically.
8262        handleOptions : function ($viewOptgroup, val, selectedOption) {
8263            //When the list so far consists purely of options.
8264            if (_.isUndefined($viewOptgroup)) {
8265                $viewOptgroup = this.$userControl[0];
8266            }
8267            var viewOptions = $("option[data-user-option]", $viewOptgroup);
8268            //Syncs the value of options.
8269            for (var i = 0, j = 0; i < viewOptions.length && j < val.length; i++, j++) {
8270                var $viewOption = viewOptions[i];
8271                var element = val[j];
8272                if ($viewOption.text != element.display) {
8273                    $viewOption.text = element.display || '';
8274                }
8275                if ($viewOption.value != element.save) {
8276                    $viewOption.value = element.save || '';
8277                }
8278            }
8279            //Deletes options if count is more than required.
8280            while (i < viewOptions.length) {
8281                this.deleteOption(viewOptions[i++])
8282            }
8283            //Add options if count is less than required.
8284            while (j < val.length) {
8285                this.addOption($viewOptgroup, val[j++], selectedOption);
8286            }
8287            // Set empty value to dropdown if placeholder and default value is not present
8288            if (this.options.placeholder.length == 0) {
8289            	if (this.checkForEmptyValue(this.options.value)) {
8290            		this.$userControl[0].value = "";
8291            	}
8292            }
8293            // since options are removed and added again during items we need to set the access again options.
8294            this.optionsHandler["access"].apply(this, [this.options["access"]]);
8295        },
8296
8297        addOption : function ($viewOptgroup, element, selectedOption) {
8298            var $newOption = $(this.optionSkeleton).val(element.save).text(element.display);
8299            $newOption.appendTo($viewOptgroup);
8300            if(selectedOption) {
8301                if(element.save === selectedOption.val() && element.display === selectedOption.text()) {
8302                    $newOption.prop("selected", true);
8303                }
8304            }
8305            // Since the displayValue is a '\n' separated string of selected values in case of multiSelect,
8306            // we convert it to an array and check whether that array contains the save value of the element
8307            var values;
8308            if (this.options.value && _.isString(this.options.value)) {
8309                values = this.options.value.split('\n');
8310            } else if (_.isArray(this.options.value)) {
8311                // In the case of AF we have value/displayValue as an array
8312                values = this.options.value
8313            }
8314            if (values && values.indexOf(element.save) >= 0) {
8315                //Delete emptyValue with no placeholder text configured and value is found in options
8316                if (this.options.placeholder.length == 0 && this.$userControl.children('[data-empty-option]').length > 0) {
8317                    this.$userControl[0].removeChild(this.$userControl.children('[data-empty-option]')[0]);
8318                }
8319                this.$userControl.children().filter(function() {
8320                    return this.value == element.save;
8321                }).prop("selected", true);
8322            }
8323        },
8324
8325        deleteOption: function ($viewOption) {
8326            this.$userControl.find('option[value='+$viewOption.value+']').remove();
8327        },
8328
8329        checkForEmptyValue: function(value) {
8330            if ((value && _.isArray(value) && value[0] == null) || (this.options.value == null))
8331                return true;
8332            else
8333                return false;
8334        },
8335
8336        addGroup: function(label) {
8337            //Creates a optgroup Node.
8338            var optionGroup = document.createElement("OPTGROUP");
8339            optionGroup.label = label;
8340            this.$userControl[0].appendChild(optionGroup);
8341            return optionGroup;
8342        },
8343
8344        deleteGroup: function(label) {
8345            this.$userControl.children().remove('optgroup[label='+label+']');
8346        },
8347
8348        addItem: function(itemValues) {
8349            var newOption = new Option(itemValues.sDisplayVal || '', itemValues.sSaveVal || ''),
8350                val = this.options.value;
8351
8352            this.$userControl[0].add(newOption, null);
8353
8354            // if item has same value as present in options then mark it as selected
8355            if (_.contains(val, itemValues.sSaveVal)) {
8356                this.$userControl.find("option[value=" + itemValues.sSaveVal + "]").prop("selected", true);
8357                var emptyValue = this.$userControl.children('[data-empty-option]');
8358                if (emptyValue.length > 0 && emptyValue.val() === itemValues.sSaveVal) {
8359                    this.$userControl[0].removeChild(emptyValue[0]);
8360                }
8361            } else if ((val == null || val.length == 0 || val[0] == null) && this.options.placeholder.length == 0) {
8362                // Value should remain empty if option is not already selected & placeholder is empty
8363                this.$userControl[0].value = "";
8364            }
8365        },
8366
8367        clearItems: function () {
8368            //Deleting all the options including optGroup except the empty value.
8369            this.$userControl.children().not('[data-empty-option]').remove();
8370        },
8371
8372        deleteItem: function (nIndex) {
8373            //check for emptyValue instead of blindly doing + 1
8374            if (this.$userControl[0].item(0) && this.$userControl[0].item(0).id == "emptyValue")
8375                nIndex = nIndex + 1;
8376            //if there is emptyValue element then just delete one index higher
8377            //this check is must instead of blindly increasing the index by 1 because NWKListBox extends this class and that doesn't maintain emptyValue
8378            this.$userControl[0].remove(nIndex);
8379        },
8380
8381        getCommitValue: function (event) {
8382            var value = $("option:selected", this.$userControl).map(function () {
8383                return $(this).val();
8384            }).get();
8385            return value;
8386        },
8387
8388        showDisplayValue: function () {
8389        },
8390
8391        destroy: function () {
8392            this.element.
8393                removeClass(this._widgetName).
8394                children().remove().
8395                text("");
8396
8397            // call the base destroy function
8398            $.xfaWidget.defaultWidget.prototype.destroy.apply(this, arguments);
8399        },
8400
8401        _handleKeyDown: function (event) {
8402
8403            if (event.keyCode == 13) {
8404                //do nothing
8405                //just override the return key behaviour and over to defaultWidget for rest of the stuff.
8406                //return key is intercepted to avoid submission of form which is default behavior of html form element
8407                //but as a side effect it also stops the closing of drop down only in IE -> probably I should use IE condition but
8408                // this code works fine in          chrome as well so keeping it that way.
8409                //watson bug#3675141
8410            }
8411            else
8412                $.xfaWidget.defaultWidget.prototype._handleKeyDown.apply(this, arguments);
8413        },
8414
8415        // CQ-51462 : focus and commit event (change) happen together hence first selection was modifying the value
8416        // we do not want focus to modify the value that is about to be committed
8417        showValue : function() {
8418
8419        }
8420    });
8421})($, _);
8422(function($, _){
8423	$.widget( "xfaWidget.listBox", $.xfaWidget.defaultWidget, {
8424
8425    _widgetName: "listBoxWidget",
8426
8427    options : {
8428        value : [],
8429        items : [],
8430        multiSelect : false
8431    },
8432
8433    getOptionsMap: function() {
8434        var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this,arguments);
8435        return $.extend({},parentOptionsMap,{
8436            "width" : function(val) {
8437                //Bug#3597771. setting the height more than 0.95 brings scrollbar
8438                this.options.width = val*0.95
8439                parentOptionsMap.width.apply(this,[this.options.width])
8440            },
8441            "access" : function() {},
8442            "value": function(val) {
8443                var newValues = this.options.value,
8444                    self = this,
8445                    tabSet = false;
8446                if(!_.isArray(newValues))
8447                    newValues = [newValues];
8448                var tabSet
8449                this.$userControl.children().each(function(){
8450                    var saveVal = $(this).attr("data-save");
8451
8452                    // Check if this value is present in options value array
8453                    if(newValues && _.contains(newValues, saveVal)){
8454                        self._selectListItem($(this));
8455                        tabSet = true;
8456
8457                        // Set the selected data attribute to true.
8458                        if (!$.data(this, "_xfaInitialized")) {
8459                            //Initialized data- attributes parse for once using this call.
8460                            // Next onward don't use this. Instead use $.data which is cheap/
8461                            $(this).data();
8462                            $.data(this, "_xfaInitialized", true); //Mark the element to say that data has been initialized.
8463                        }
8464                        $.data(this, "selected", true);
8465
8466                    }
8467                    else{
8468                        $(this).removeClass("item-selected");
8469                        $(this).addClass("item-selectable");
8470                        $(this).attr("tabIndex", "-1");
8471                    }
8472                });
8473                if(!tabSet) {
8474                    $(this.$userControl.children().get(0)).attr("tabIndex", this.options.tabIndex);
8475                }
8476            },
8477
8478            "items" : function(val) {
8479                if(!_.isArray(val))
8480                    val = [val];
8481                var viewItems = this.$userControl.children();
8482
8483                //if number of items are not same in model and view then balance it
8484                if((viewItems.length) > val.length){
8485                    for(var i=viewItems.length; i >  val.length; i--){
8486                        this.deleteItem(i-1);
8487                    }
8488                }
8489                else if((viewItems.length) < val.length){
8490                    for(var i=viewItems.length; i < (val.length); i++){
8491                        this.addItem({sDisplayVal: val[i].display, sSaveVal: val[i].save});
8492                    }
8493                }
8494
8495                _.each(val, function(element, index){
8496                    var $viewItem = $(viewItems[index]);
8497                    if( $viewItem.text() != element.display){
8498                        $viewItem.text(element.display || '');
8499                    }
8500
8501                    if( $viewItem.attr("data-save") != element.save){
8502                        $viewItem.attr("data-save", element.save || '');
8503                    }
8504                });
8505
8506                //Intentionally left the selection check -> I am relying on the fact that "value" sync event is called after "items" sync.
8507            },
8508
8509            "displayValue" : function(){;},
8510
8511            "tabIndex": function() {
8512                var selectedItem = this.$userControl.children(".item-selected"),
8513                    children =this.$userControl.children()
8514                if(selectedItem.length) {
8515                    selectedItem.eq(0).attr("tabIndex", this.options.tabIndex);
8516                }
8517                else if(children.length > 0) {
8518                    children.eq(0).attr("tabIndex", this.options.tabIndex);
8519                }
8520            }
8521        })
8522    },
8523
8524    getEventMap: function() {
8525        var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getEventMap.apply(this,arguments);
8526        return $.extend({},parentOptionsMap,{
8527            "listboxenter":xfalib.ut.XfaUtil.prototype.XFA_ENTER_EVENT,
8528            "listboxexit":xfalib.ut.XfaUtil.prototype.XFA_EXIT_EVENT,
8529            "listboxchange":xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT,
8530            "focus":null,
8531            "blur":null
8532        })
8533    },
8534
8535    showDisplayValue : function() {
8536        },
8537
8538    render : function() {
8539        this.element.addClass( this._widgetName);
8540        this.element.children().remove();
8541
8542        //TODO: add a function for geting textStyle
8543        var textStyle = this.getOrElse(this.$data(this.element.get(0), "xfamodel"), "textstyle", ""),
8544            that = this,
8545            //Bug#3597771 width and height are provided by the view itself.
8546            listElTemplate =
8547            '<ol style="position:absolute;<%=textStyle%>" role="listbox">' +
8548                '<% _.each(items, function(item){ %>' +
8549                '<% var saveItem = item.save ? item.save.replace(/\"/g,"&quot;"):null %>'+
8550                    '<li role="option" data-save="<% print(saveItem) %>" data-selected="false"><% print(item.display) %></li>'+
8551                '<%})%>'+
8552            '</ol>',
8553            compiledListElTemplate = _.template(listElTemplate),
8554            templateOptions = _.extend({
8555                "textStyle" : textStyle
8556                }, this.options),
8557            resolvedListEl = compiledListElTemplate(templateOptions);
8558        that.element.html(xfalib.ut.XfaUtil.prototype.encodeScriptableTags(resolvedListEl));
8559        var control = $(that.element.children().get(0)).attr("name",this.options.name);
8560        this._attachEventHandlers(control);
8561        return control
8562    },
8563
8564    focus: function() {
8565        if(this.$userControl.children(".item-selected").length > 0) {
8566            this.$userControl.children(".item-selected")[0].focus();
8567        }
8568        else if(this.$userControl.children().length > 0) {
8569            this.$userControl.children()[0].focus();
8570        }
8571    },
8572
8573    addItem : function(itemValues){
8574        $("<li></li>")
8575            .attr("data-save", itemValues.sSaveVal || '')
8576            .text(itemValues.sDisplayVal || '')
8577            .appendTo(this.$userControl)
8578            .click($.proxy(this._handleItemClick, this))
8579            .focus($.proxy(this._handleItemFocus, this));
8580
8581        // add new item as selected if the value is already present in options
8582        if (_.contains(this.options.value, itemValues.sSaveVal)) {
8583            this._selectListItem(this.$userControl.find("[data-save=" + itemValues.sSaveVal+ "]"));
8584        }
8585    },
8586
8587    clearItems : function(){
8588        $(this.$userControl).empty();
8589    },
8590
8591    deleteItem : function(nIndex){
8592        $(this.$userControl).children('li').each(function(index,element){
8593            if(index==nIndex){
8594                $(element).off("click").off("focus").remove();
8595            }
8596        })
8597    },
8598
8599
8600    _attachEventHandlers : function($control){
8601        var self = this;
8602        $control.keydown($.proxy(this._hotKeys,this))
8603            .children().on("mousedown",function() {
8604                    if(self.inFocus == true) {
8605                        self.mouseDown = true;
8606                    }
8607                })
8608            .click($.proxy(this._handleItemClick, this))
8609            .focus($.proxy(this._handleItemFocus, this))
8610            .blur($.proxy(this._handleFocusOut,this))
8611
8612    },
8613
8614     _hotKeys : function(event){
8615         if(this.options.access != "open")
8616             return;
8617         if(this.itemInFocus){
8618             switch(event.which) {
8619                 case 38: //arrow up
8620                     var prevSibling = $(this.itemInFocus).prev();
8621                     if(prevSibling){
8622                         this.keyDown = true;
8623                         prevSibling.focus();
8624                         this.keyDown = false;
8625                     }
8626                     event.preventDefault();
8627                     break;
8628                 case 40: //arrow down
8629                     var nextSibling = $(this.itemInFocus).next();
8630                     if(nextSibling){
8631                         this.keyDown = true;
8632                         nextSibling.focus();
8633                         this.keyDown = false;
8634                     }
8635                     event.preventDefault();
8636                     break;
8637                 case 91: //left arrow
8638                 case 92: //right arrow
8639                     event.preventDefault();
8640                     break;
8641                 case 32:
8642                     this._toggleItem(this.itemInFocus);
8643                     event.preventDefault();
8644                     break;
8645                 default:
8646             }
8647         }
8648     },
8649
8650     _toggleItem: function(item) {
8651         var $item = $(item),
8652             multiMode = this.options.multiSelect, // && event.ctrlKey ;
8653             that = this;
8654             //toggle selected state of this item
8655             this.$data(item, "selected", !this.$data(item, "selected"));
8656         var state = this.$data(item, "selected")
8657
8658         if(!multiMode) {
8659             var $selectedItem = this.$userControl.children(".item-selected")
8660             if($selectedItem.length) {
8661                 this.$data($selectedItem[0],"selected",false)
8662                 $selectedItem.removeClass("item-selected").addClass("item-selectable")
8663             }
8664         }
8665         $item.toggleClass("item-selectable",!state).
8666               toggleClass("item-selected",state)
8667
8668         this.$userControl.trigger("listboxchange");
8669     },
8670
8671     getCommitValue: function() {
8672         var that = this,
8673             multiMode = this.options.multiSelect;
8674
8675
8676         return this.$userControl.children().map(function(){
8677             // intentionally using $this.attr("data-save") instead of $this.data("data")
8678             return that.$data(this, "selected") ? $(this).attr("data-save") : null;
8679         }).get();
8680     },
8681
8682      _handleItemFocus : function(event){
8683          if(this.options.access != "open")
8684              return;
8685          var item = event.target;
8686          this.itemInFocus = item;
8687
8688          // overriding default widgets handleFocus
8689          if(!(this.keyDown || this.mouseDown)) {        //we do not need to fire focus event if
8690              this.$userControl.trigger("listboxenter")  // clicked on another li element or pressed a key to move the selectio
8691          }
8692          this.mouseDown = false;
8693          this.inFocus = true;
8694      },
8695
8696     _handleItemClick : function(event){
8697        // Bug#3501811 If clicked onlistbox entry more than once, exit event is not fired
8698        // Clicking on the same entry does not call focus and hence we were not resetting the state. Doing it in onClick
8699        if(this.mouseDown == true)
8700            this.mouseDown = false;
8701        if(this.options.access != "open")
8702             return;
8703        this._toggleItem(event.target)
8704    },
8705
8706    _handleFocusOut: function(){
8707        if(!(this.keyDown || this.mouseDown)) {
8708            this.$userControl.trigger("listboxexit");
8709            this.inFocus = false
8710        }
8711    },
8712
8713    _selectListItem : function ($elem) {
8714        if ($elem && $elem.length) {
8715            $elem.removeClass("item-selectable")
8716                .addClass("item-selected")
8717                .attr("tabIndex", this.options.tabIndex);
8718        }
8719    },
8720
8721    destroy: function() {
8722        this.element.
8723            removeClass(this._widgetName).
8724            children().remove().
8725            text("");
8726
8727        $.xfaWidget.defaultWidget.prototype.destroy.apply(this, arguments);
8728    }
8729});
8730})($, window._);
8731(function($) {
8732    $.widget( "xfaWidget.nwkListBox",  $.xfaWidget.dropDownList, {            //non-webkit listbox
8733
8734        _widgetName : "nwkListBox",
8735
8736        options : {
8737            value : [],
8738            multiSelect : false
8739        },
8740
8741        render : function() {
8742            var $control = $.xfaWidget.dropDownList.prototype.render.apply(this, arguments);
8743            if($control){
8744                $control.children("#emptyValue").remove();
8745                if(this.options.multiSelect)
8746                    $control.attr("multiple", "multiple");
8747            }
8748            this._updateSelectSize($control);
8749            return $control;
8750        },
8751
8752        addItem : function(itemValues){
8753            $.xfaWidget.dropDownList.prototype.addItem.apply(this, arguments);
8754            this._updateSelectSize();
8755        },
8756
8757        clearItems : function(){
8758            $.xfaWidget.dropDownList.prototype.clearItems.apply(this, arguments);
8759            this._updateSelectSize();
8760        },
8761
8762        deleteItem : function(nIndex){
8763            $.xfaWidget.dropDownList.prototype.deleteItem.apply(this, arguments);
8764            this._updateSelectSize();
8765        },
8766
8767        _updateSelectSize : function($control){
8768            $control = $control || this.$userControl;
8769            $control.attr("size", (this.options.items || []).length);
8770        },
8771
8772        // Bug#3597771
8773        // focus and commit event happen together hence first selection was modifying the value
8774        // we do not want focus to modify the value that is about to be committed
8775        showValue : function() {
8776
8777        }
8778
8779  });
8780})($);
8781(function ($) {
8782    $.widget("xfaWidget.xfaButton", $.xfaWidget.defaultWidget, {            //commitEvent: change; commitProperty: value<Array>
8783
8784        _widgetName: "xfaButton",
8785
8786        options: {
8787            value: null,
8788            svgCaption: false //option to indicate if button already has an SVG caption
8789        },
8790
8791        getOptionsMap: function () {
8792            var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this, arguments);
8793            return $.extend({}, parentOptionsMap, {
8794                "access": function (val) {
8795                    switch (val) {
8796                        case "open" :
8797                            this.$userControl.removeAttr("disabled");
8798                            this.$userControl.removeAttr("aria-disabled");
8799                            break;
8800                        case "nonInteractive" :
8801                        case "protected" :
8802                        case "readOnly" :
8803                            this.$userControl.attr("disabled", "disabled");
8804                            this.$userControl.attr("aria-disabled", "true");
8805                            break;
8806                        default  :
8807                            this.$userControl.removeAttr("disabled");
8808                            this.$userControl.removeAttr("aria-disabled");
8809                            break;
8810                    }
8811                },
8812                "value": function () {
8813                },
8814                "displayValue": function () {
8815                },
8816                "svgCaption": function (val) {
8817                    if (val) {
8818                        this.$userControl.removeAttr("value");
8819                    }
8820                }
8821            })
8822        },
8823
8824        _attachEventHandlers: function ($control) {
8825            $control.click(function () {
8826                this.focus()
8827            });
8828        },
8829
8830        getCommitValue: function () {
8831            return this.options.value;
8832        },
8833
8834        showValue: function () {
8835        },
8836
8837        showDisplayValue: function () {
8838        }
8839    });
8840})($);(function ($) {
8841    $.widget("xfaWidget.XfaCheckBox", $.xfaWidget.defaultWidget, {            //commitEvent: change; commitProperty: value<Array>
8842
8843        _widgetName: "XfaCheckBox",
8844
8845        options: {
8846            value: null,
8847            state: -1,
8848            states: 2,
8849            values: [],
8850            mandatory: false
8851        },
8852
8853        checkedState: false,
8854        clickPending: false,
8855
8856        getOptionsMap: function () {
8857            var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this, arguments);
8858            return $.extend({}, parentOptionsMap, {
8859                "access": function (val) {
8860                    switch (val) {
8861                        case "open" :
8862                            this.$userControl.removeAttr("disabled");
8863                            this.$userControl.removeAttr("aria-disabled");
8864                            break;
8865                        case "nonInteractive" :
8866                        case "protected" :
8867                        case "readOnly" :
8868                            this.$userControl.attr("disabled", "disabled");
8869                            this.$userControl.attr("aria-disabled", "true");
8870                            break;
8871                        default  :
8872                            this.$userControl.removeAttr("disabled");
8873                            this.$userControl.removeAttr("aria-disabled");
8874                            break;
8875                    }
8876                },
8877
8878                "displayValue": function (val) {
8879                    this.$userControl.attr(this.options.commitProperty, this.options.value);
8880                    this._state(this.dIndexOf(this.options.values, this.options.value));
8881                    this.$userControl.attr("checked", this.checkedState ? "checked" : null);
8882                    this.$userControl.prop("checked", this.checkedState ? "checked" : null);
8883                    //for accessibility
8884                    this.$userControl.attr("aria-checked", this.checkedState);
8885                    if (this.options.state == 2)
8886                        this.$userControl.addClass("neutral");
8887                    else if (this.options.states == 3)
8888                        this.$userControl.removeClass("neutral");   // since current state != neutral
8889                },
8890
8891                "allowNeutral": function (val) {
8892                    var intVal = parseInt(val);
8893                    if (intVal == 0 || intVal == 1) {
8894                        this.options.states = 2 + intVal;
8895                    }
8896                },
8897
8898                "paraStyles": function (paraStyles) {
8899                    parentOptionsMap.paraStyles.apply(this, arguments);
8900                    this._handleVAlignOnExit();
8901                }
8902            })
8903        },
8904
8905        getEventMap: function () {
8906            var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getEventMap.apply(this, arguments);
8907            return $.extend({}, parentOptionsMap, {
8908                 "xfacheckboxchange" :  xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT,
8909                 "xfacheckboxclick" :   xfalib.ut.XfaUtil.prototype.XFA_CLICK_EVENT,
8910                 "change": null,
8911                 "click" : null
8912               })
8913        },
8914
8915        _attachEventHandlers: function ($control) {
8916            var that = this;
8917            var focusFunc = function (evnt) {
8918                if (!that.inFocus) {
8919                    that.focus();
8920                    that.inFocus = true;
8921                }
8922            }
8923            var focusOutFunc = function (evnt) {
8924                that.inFocus = false;
8925            }
8926            $control.click(focusFunc).change(focusFunc).blur(focusOutFunc);
8927            $control.change($.proxy(this._handleChange,this)).click($.proxy(this._handleClick,this));   //LC-5106
8928        },
8929
8930        getCommitValue: function () {
8931            this._state((this.options.state + 1) % this.options.states);
8932            this.$userControl.attr("checked", this.checkedState ? "checked" : null);
8933            //for accessibility
8934            this.$userControl.attr("aria-checked", this.checkedState)
8935            if (this.options.state == 2) {
8936                this.$userControl.addClass("neutral");
8937            }
8938            else if (this.options.states == 3)
8939                this.$userControl.removeClass("neutral"); // since current state != neutral
8940
8941            return this.options.values[this.options.state];
8942        },
8943
8944        _handleVAlignOnExit: function (evnt) {
8945            //--this is being kept empty as no other browser (i.e Mozilla and Chrome) take the padding-bottom or padding-top into account.
8946            // the only browser to take it into consideration is IE. And moreover the alignment and padding considerations have already been taken into account in
8947            // calculations in CheckButtonFieldView.js. And on removing the entire function it takes up the _handleVAlignOnExit() of AbstractWidget.
8948
8949        },
8950
8951        _handleChange: function (evnt) {
8952            this.$userControl.trigger("xfacheckboxchange"); //change is always fired
8953            if(this.clickPending === true) {
8954              this.clickPending = false;
8955              this.$userControl.trigger("xfacheckboxclick");
8956            } else {
8957                // handling of this.clickPending is added to handle the case when clicked on checkbox/radiobutton label/caption
8958                this.clickPending = true;
8959            }
8960        },
8961
8962        _handleClick: function (evnt) {
8963             var isChrome = xfalib.ut.XfaUtil.prototype.detectChrome(),
8964                 isIE = xfalib.ut.XfaUtil.prototype.detectIE(),
8965                 isSafari = xfalib.ut.XfaUtil.prototype.isSafari(),
8966                 userControlType = this.$userControl.attr("type");
8967             // click will not be fired if the previous state of the radiobutton is 'on'.
8968             // CQ-4312095: Checkbox movement - Click event works fine on chrome but not in iOS safari for collapsible fields
8969             // CQ-103023 : Click Event on Radio Button not working correctly in Chrome 53
8970             // CQ-103715 : CQ-103715 : Click Event on Check Box not working correctly in Chrome and Firefox, added handling for checkbox also
8971             // handling of this.clickPending is added to handle the case when clicked on checkbox/radiobutton label/caption
8972             if(($.browser.mozilla || isChrome || isSafari) && !isIE && this.clickPending === false && ((userControlType === "radio" && this.checkedState === false) || (userControlType === "checkbox"))) {
8973               this.clickPending = true;
8974             }
8975             else {
8976                this.$userControl.trigger("xfacheckboxclick");
8977                this.clickPending = false;
8978             }
8979        },
8980
8981        _state: function (newState) {
8982            if (newState == undefined)
8983                return this.options.state;
8984            else
8985                this.options.state = newState;
8986            this.checkedState = (newState == 0 || newState == 2);
8987        },
8988
8989        click: function () {
8990            // trigger change for check box and for radio only if it is not selected
8991            // otherwise radio button will go in deselected state
8992            if (this.$userControl.attr("type") !== "radio" || this.options.state !== 0) {
8993                this.$userControl.trigger("change");
8994            }
8995            //we should call only the handler since calling click will trigger change.
8996            this.$userControl.triggerHandler("click");
8997        }
8998    });
8999})($);
9000(function($, _){
9001    $.widget( "xfaWidget.textField", $.xfaWidget.defaultWidget, {
9002
9003        _widgetName: "textField",
9004
9005        options: {
9006            curValue : null ,
9007            pos:0,
9008            lengthLimitVisible: true,
9009            maxChars:0 ,
9010            flag:"",
9011            // by default html5Type is set to true
9012            // we leverage pattern, maxLength support from HTML5 browser for mobile forms
9013            html5Type : "text",
9014            length : null,
9015            minLength : 0,
9016            totalLengthMessage : "",
9017            minimumLengthMessage : "",
9018        },
9019
9020        getOptionsMap: function() {
9021            var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this,arguments);
9022            return $.extend({},parentOptionsMap,{
9023                "maxChars": function(maxchars) {
9024                    if(this._maxCharsReached(this.options.value)) {
9025                        var value = this.options.value.slice(0,maxchars)
9026                        this._setOption("value", value);
9027                        this._setOption("displayValue", value);
9028                    }
9029
9030                },
9031
9032                "multiLine ": function(val) {
9033                    if(this.options.multiLine)
9034                        this.$userControl.attr("aria-multiline", "true");
9035                    else
9036                        this.$userControl.removeAttr("aria-multiline", "false");
9037                },
9038
9039                "height": function(val) {
9040                    if(val)   {
9041                        this.$css(this.$userControl[0],{"height" :val})
9042                        this._handleVAlignOnExit();    // To Handle the case of expandable Fields
9043                    }
9044                },
9045                "width": function(val){
9046                    parentOptionsMap.width.apply(this,arguments);
9047                    // handle valign on width change as well
9048                    // as content height(scrollHeight) varies according to width
9049                    this._handleVAlignOnExit();
9050                },
9051                "paraStyles": function(paraStyles){
9052                    parentOptionsMap.paraStyles.apply(this,arguments);
9053                    this._handleVAlignOnExit();
9054                }
9055
9056            })
9057        },
9058
9059        render : function() {
9060            var control = $.xfaWidget.defaultWidget.prototype.render.apply(this, arguments);
9061            // use the control to set HTML5 attributes
9062            if (control && control.length > 0 && this.options.html5Type) {
9063                var minLength = this.options.minLength,
9064                    maxLength = this.options.maxChars,
9065                    length = this.options.length;
9066                    isMinLengthSet = minLength != null && minLength > 0,
9067                    isMaxLengthSet = maxLength != null && maxLength > 0,
9068                    isLengthSet = length != null && length > 0,
9069                    isMultiline = this.options.multiLine,
9070                    minLengthMsg = this.options.minimumLengthMessage,
9071                    totLengthMsg = this.options.totalLengthMessage,
9072                    pattern = ""; // html5 pattern is not supported for textarea
9073
9074                // order of execution matters for the below code snippet
9075                if (isMinLengthSet) {
9076                    // add minLength though it is not fully supported in all browsers
9077                    // hence also adding pattern attribute
9078                    control.attr("minlength", parseInt(minLength));
9079                    if(minLengthMsg && minLengthMsg.length > 0) {
9080                        control.attr("title", this.options.minimumLengthMessage); // html5 supported message on pattern validation failure
9081                    }
9082                }
9083
9084                if (isMaxLengthSet) {
9085                    control.attr("maxlength", parseInt(maxLength));
9086                }
9087
9088                // if both min and max length is set
9089                if(isMinLengthSet && isMaxLengthSet){
9090                    pattern += ".{" + minLength + "," + maxLength + "}";
9091                } else if(isMinLengthSet) {
9092                    // if only min length set
9093                    pattern += ".{" + minLength + ",}";
9094                }
9095
9096                // if length is set then set min and max length in pattern equal to length
9097                if (isLengthSet) {
9098                    if(isMultiline){ // set both min and maxlength as pattern is not supported
9099                        control.attr("minlength", parseInt(length));
9100                        control.attr("maxlength", parseInt(length));
9101                    }
9102                    if(totLengthMsg && totLengthMsg.length > 0) {
9103                        control.attr("title", this.options.totalLengthMessage);
9104                    }
9105                    // reset the pattern string
9106                    pattern = ".{" + length + "," + length + "}";
9107                }
9108                // if required is set, set the required attribute, it is necessary else an empty value will be excluded from constraint validation
9109                if (this.options.required) {
9110                    control.attr("required", true);
9111                }
9112                // set the pattern if not empty and check if this is not multiline, since pattern is not supported for textarea
9113                if (pattern && pattern.length > 0 && !isMultiline) {
9114                    control.attr("pattern", pattern);
9115                }
9116            }
9117            return control;
9118        },
9119
9120        /*  This function aligns vAlign when:
9121         1. parastyles is present and the widget contains a value.
9122         2. During initial rendering if no content present fallback to the previous logic.
9123         3. Presence of content in widget.
9124        */
9125        _handleVAlignOnExit: function(){
9126             var value = this.options.displayValue,
9127                 noContentPresent = _.isEmpty(this.$userControl.val() || this.options.displayValue),
9128                 contentHeight,widgetHeight,diff,tempCSS;
9129
9130             //the widget doesn't have value as yet but content exists [ Rendering of widget]
9131             if (!this.options.paraStyles || noContentPresent) {
9132                //vAlign has to be handled only if there is paraStyles and widget has content
9133                return;
9134             }
9135
9136             // mozilla results in vAlign regression hence made this change only for textarea
9137             if($(this.element[0]).find("textarea").length >0 && !noContentPresent)  {
9138               /* measureExtent not returning correct height of content in textarea even with all
9139                 css values */
9140               tempCSS={'height':this.$userControl.css('height'),'padding':this.$userControl.css('padding')};
9141               this.$css(this.$userControl[0],{'height':'1px','padding':'0px'});
9142
9143               contentHeight = this._getContentHeight();
9144               this.$css(this.$userControl[0],tempCSS);
9145               widgetHeight = this.options.height;
9146               diff = widgetHeight - contentHeight;
9147               this._calculatePaddingForVAlign(diff);
9148             } else {
9149                // widget has no initial content or is a textfield.Proceed as before.
9150                $.xfaWidget.defaultWidget.prototype._handleVAlignOnExit.apply(this,arguments);
9151             }
9152        },
9153
9154        getEventMap: function() {
9155            var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getEventMap.apply(this,arguments);
9156            return $.extend({},parentOptionsMap,{
9157                "onKeyInput.textField" : xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT
9158            })
9159        },
9160
9161        _maxCharsReached: function(val) {
9162            var isMaxLengthSupported = false,
9163                elementName = this.options.multiLine ? "textarea" : "input";
9164            // in browsers, where max length is supported, we don't custom javascript checks, we let HTML do the validation of max length
9165            if(this.options.html5Type && xfalib.view.util.HtmlUtil.elementSupportsAttribute(elementName, "maxLength")){
9166                isMaxLengthSupported = true;
9167            }
9168            return !isMaxLengthSupported && this.options.maxChars
9169                   && this.options.maxChars!=="0"
9170                   && val
9171                   &&  val.length >= this.options.maxChars
9172        },
9173
9174        _handleKeyInput : function(event, character, code) {
9175            if(event.ctrlKey && !_.contains(['paste', 'cut'], event.type)) {
9176                return true;
9177            }
9178
9179            if(!this.options.multiLine) {
9180                $.xfaWidget.defaultWidget.prototype._handleKeyDown.apply(this, arguments);
9181                character = (code == 13) ? '' : character ;
9182            }
9183
9184            var val =  this.$userControl.val(),
9185                selectionStart = xfalib.view.util.HtmlUtil.getHTMLSupportedAttr(this.$userControl[0], "selectionStart") || 0,
9186                selectionEnd = xfalib.view.util.HtmlUtil.getHTMLSupportedAttr(this.$userControl[0], "selectionEnd") || 0,
9187                pos = selectionStart,
9188                // CQ-4260239 : "&nbsp" taking space of 5 chars for restricting the length to visible area
9189                newVal = (val.substr(0, selectionStart) + character + val.substr(selectionEnd));
9190            this.options.curValue = val;
9191            if(!this.options.multiLine) { //TODO:looks like a bug
9192                this.options.lengthLimitVisible = true;
9193                this.options.pos = pos;
9194                if(this.options.hScrollDisabled && !_.contains(['keydown', 'cut'], event.type)) {
9195                    var expectedWidth = xfalib.view.util.TextMetrics.measureExtent(newVal, {refEl: this.$userControl[0], maxWidth:-1}).width;
9196                    if(!event.ctrlKey && expectedWidth > this.$userControl.width()){   // Why  allowance of 5 required??
9197                        this.options.lengthLimitVisible = false;
9198                        event.preventDefault();
9199                        return false;
9200                    }
9201                }
9202            } else if (this.options.multiLine && this.options.hScrollDisabled) {  // LC-4656 : wait till user input, if it causes an overflow revert to old text
9203                var $textArea = this.$userControl;
9204                $textArea.css("padding", "0px 0px 0px");  // TODO : take care of multiline selection & padding later
9205
9206                // TODO : find a scheme to avoid attaching and detaching listeners, currently $.val() causes 'input' to fire, resulting in an infinite loop
9207                $textArea.one("input", function () {
9208                    if ($textArea.prop('scrollHeight') > $textArea.prop('offsetHeight')) {
9209                        $textArea.val(val)
9210                                 .prop("selectionStart", selectionEnd)
9211                                 .prop("selectionEnd", selectionEnd);  // LC-4656 : reset the cursor pos, afterwards
9212                        character = null;
9213                        code = 0;
9214                    }
9215                });
9216            }
9217
9218            if (!_.contains(['keydown', 'cut'], event.type) && this._maxCharsReached(val) && selectionStart === selectionEnd) {
9219                event.preventDefault();
9220                return false;
9221            }
9222
9223            this.$userControl.trigger({
9224                type : "onKeyInput.textField",
9225                originalType : event.type,
9226                character : character,  // contains the pasted string or pressed key
9227                keyCode : event.keyCode || 0,
9228                charCode : event.charCode || 0,
9229                which : event.which || 0,
9230                ctrlKey : event.ctrlKey || event.metaKey || false,
9231                shiftKey : event.shiftKey || false,
9232                keyDown: false, // This property is available only for list boxes and drop-down lists
9233                selectionStart: selectionStart,
9234                selectionEnd: selectionEnd
9235            });
9236        },
9237
9238        _handleKeyDown : function(event){
9239            if (event) {
9240                var code = event.charCode || event.which || event.keyCode || 0;
9241                if(code == 8 || code == 46) // backspace and del
9242                   this._handleKeyInput(event, "", code);
9243            }
9244        },
9245
9246        _handleKeyPress : function(event){
9247            if (event) {
9248                var code = event.charCode || event.which || event.keyCode || 0,
9249                    character = (code == 13) ? "\n" : String.fromCharCode(code); // modified '\r\n' -> '\n'
9250
9251            if(xfalib.ut.XfaUtil.prototype.isNonPrintableKey(event.key)) { // mozilla also generates a keypress, along with keydown
9252                return true;                                               // for all keys, so only handling printable keys in keypress
9253            }
9254
9255            this._handleKeyInput(event, character, code);
9256            }
9257        },
9258
9259        _compositionUpdateCallback : function (event) {
9260            var that = this;
9261            var val = that.$userControl.val();
9262            if (event.type === "compositionupdate" && event.originalEvent.data) {
9263                // this has been deliberately done to get the actual data in case of max character.
9264                if (that.options.maxChars) {
9265                    val = event.originalEvent.data;
9266                } else {
9267                    val = val + event.originalEvent.data.substr(event.originalEvent.data.length - 1);
9268                }
9269            }
9270            var flag = that._maxCharsReached(val);
9271            if (flag) {
9272                // if max reached
9273                var newVal = val.substr(0, that.options.maxChars);
9274                //in case the value is not changed then we do not need to update value and close the android keyboard.
9275                if (val === newVal) {
9276                    return false;
9277                }
9278                that.$userControl.val(newVal);
9279            }
9280            return flag;
9281        },
9282
9283        _attachEventHandlers: function($control) {
9284            $.xfaWidget.defaultWidget.prototype._attachEventHandlers.apply(this, arguments);
9285            // IME specific handling, to handle japanese languages max limit
9286            $.xfaWidget.defaultWidget.prototype._attachCompositionEventHandlers.apply(this, arguments);
9287        },
9288
9289        _handlePaste : function(event){
9290            if (event) {
9291                var pastedChar = undefined;
9292                if (window.clipboardData && window.clipboardData.getData) { // IE
9293                    pastedChar = window.clipboardData.getData('Text');
9294                } else if (event.originalEvent.clipboardData && event.originalEvent.clipboardData.getData) {
9295                    pastedChar = event.originalEvent.clipboardData.getData('text/plain');
9296                }
9297                if(pastedChar) {
9298                    this._handleKeyInput(event, pastedChar, 0);
9299                }
9300            }
9301        },
9302
9303        _handleCut : function(event) {
9304            if (event) {
9305                this._handleKeyInput(event, "", 0);
9306            }
9307        },
9308
9309        postProcessExit: function(evnt) {
9310            $.xfaWidget.defaultWidget.prototype.postProcessExit.apply(this,arguments);
9311            if (this.options.multiLine && this.options.hScrollDisabled) {
9312                return;
9313            }
9314            this._handleVAlignOnExit();
9315        },
9316
9317        preProcessEnter: function(evnt) {
9318            $.xfaWidget.defaultWidget.prototype.preProcessEnter.apply(this,arguments);
9319            if(this.options.multiLine && this.options.hScrollDisabled)
9320                return;
9321            this._handleVAlignOnEnter();
9322        },
9323
9324        /**
9325         * @brief: Select the given field on focus in Internet Explorer
9326         *
9327         */
9328        _selectOnFocusInIE : function(){
9329            // if the value is not same only then do selection in IE
9330            // For Issue: LC-9895, we check if value not same
9331            if($.browser.msie && !this._isValueSame()) {
9332                this.$userControl.select();
9333            }
9334            else {
9335                //all other browsers behave like a good boy
9336            }
9337        },
9338
9339        showValue : function() {
9340            $.xfaWidget.defaultWidget.prototype.showValue.apply(this,arguments);
9341            //IE doesn't show selected text if we focus and set its value all the time so force selection
9342            this._selectOnFocusInIE();
9343        },
9344
9345        getCommitValue: function() {
9346            var value = $.xfaWidget.defaultWidget.prototype.getCommitValue.apply(this, arguments);
9347
9348            if(this._maxCharsReached(value)) {
9349                value = value.slice(0,this.options.maxChars);
9350            }
9351
9352            this.$userControl.val(this.options.value);
9353
9354            //TODO: ask Sharad whether it is right
9355            if(this.options.multiLine && this.options.hScrollDisabled)  {
9356                //var str= this._checkLines(value);
9357                //if(value != str) {
9358                    return value;
9359                //}
9360            }
9361            return value;
9362        },
9363
9364        /*
9365        ** returns the contentHeight which needs to be considered for padding for valign,
9366        ** if no contentHeight is present then fontSize is returned.
9367        */
9368        _getContentHeight: function () {
9369            var contentHeight = Math.ceil(this.$userControl.get(0).scrollHeight);
9370            return contentHeight ? contentHeight : this.options.fontSize;
9371        }
9372    });
9373})($, window._);
9374/*************************************************************************
9375 *
9376 * ADOBE CONFIDENTIAL
9377 * __________________
9378 *
9379 *  Copyright 2019 Adobe Systems Incorporated
9380 *  All Rights Reserved.
9381 *
9382 * NOTICE:  All information contained herein is, and remains
9383 * the property of Adobe Systems Incorporated and its suppliers,
9384 * if any.  The intellectual and technical concepts contained
9385 * herein are proprietary to Adobe Systems Incorporated and its
9386 * suppliers and may be covered by U.S. and Foreign Patents,
9387 * patents in process, and are protected by trade secret or copyright law.
9388 * Dissemination of this information or reproduction of this material
9389 * is strictly forbidden unless prior written permission is obtained
9390 * from Adobe Systems Incorporated.
9391 **************************************************************************/
9392
9393(function ($) {
9394    $.widget("xfaWidget.richTextField", $.xfaWidget.textField, {
9395
9396        _widgetName : "richTextField",
9397
9398        _richTextWidget : null,
9399
9400        _changeAccess : function (val) {
9401            switch (val) {
9402                case "open":
9403                    if (this._richTextWidget) {
9404                        this._richTextWidget.editor.enable();
9405                        this._richTextWidget.$toolbar.removeClass("hideToolbar");
9406                    }
9407                    break;
9408                case "readOnly":
9409                    if (this._richTextWidget) {
9410                        this._richTextWidget.editor.disable();
9411                        this._richTextWidget.$toolbar.addClass("hideToolbar");
9412                    }
9413                    break;
9414            }
9415        },
9416
9417        getOptionsMap : function () {
9418            var parentOptionsMap = $.xfaWidget.textField.prototype.getOptionsMap.apply(this, arguments);
9419            return $.extend({}, parentOptionsMap, {
9420                "value" : function (val) {
9421                    if (this._richTextWidget) {
9422                        this._richTextWidget.setRichTextEditorContent(val);
9423                    }
9424                },
9425                "access" : function (val) {
9426                    this._changeAccess(val);
9427                }
9428            });
9429        },
9430
9431        getEventMap : function () {
9432            // in case of IE browsers, focus event is delayed, hence adding activate method for content editable
9433            if (xfalib.ut.XfaUtil.prototype.isIE()) {
9434                var parentOptionsMap = $.xfaWidget.textField.prototype.getEventMap.apply(this, arguments);
9435                return $.extend({}, parentOptionsMap, {
9436                    "activate.richTextField" : xfalib.ut.XfaUtil.prototype.XFA_ENTER_EVENT
9437                });
9438            } else {
9439                return $.xfaWidget.textField.prototype.getEventMap.apply(this, arguments);
9440            }
9441        },
9442
9443        render : function () {
9444            var $richTextWidget = this.element.find("div.richTextWidget").eq(0);
9445            if(!$richTextWidget.length){
9446                var attachedTextareaClasses = this.element.children().attr('class');
9447                var richTextWidgetElement = '<div class="richTextWidget ' + attachedTextareaClasses + '" id="richTextField_' + this.options.name + '_' + attachedTextareaClasses + '"></div>';
9448                this.element.children().remove();
9449                this.element.append(richTextWidgetElement);
9450                $richTextWidget = this.element.find("div.richTextWidget").eq(0);
9451            }else{
9452                $richTextWidget.children().remove();
9453            }
9454            $richTextWidget.append(this.options.value);
9455            return $.xfaWidget.defaultWidget.prototype.render.apply(this, arguments);
9456        },
9457
9458        getCommitValue : function () {
9459            var value = "";
9460            if (this._richTextWidget) {
9461                value = this._richTextWidget.getRichTextEditorContent();
9462            }
9463            return value;
9464        },
9465
9466        preProcessEnter : function (evnt) {
9467            $.xfaWidget.textField.prototype.preProcessEnter.apply(this, arguments);
9468            var $richTextDiv = this.$userControl.find("div.richTextWidget").eq(0);
9469            if(!$richTextDiv.length){
9470                $richTextDiv = this.element.find("div.richTextWidget").eq(0);
9471                this.changeDefaultToolbarConfig();
9472                this.$userControl.parents('.richtextsupport').css('z-index', 'auto');
9473            }
9474            if (window.Form === undefined || window.Form.rte === undefined) {
9475                /* Forms RTE is part of Forms Addon package only. Dont do anything if addon is not installed.*/
9476                return;
9477            } else if (this._richTextWidget === null) {
9478                this._initializeRTEToolbar();
9479                this._richTextWidget = new window.Form.rte.RichTextEditor({
9480                    selector : $richTextDiv.attr("id"),
9481                    toolbar : window.Form.rte.RichTextEditor.MFToolbar,
9482                    data : this.options.value,
9483                    locale : $richTextDiv.data("locale")
9484                });
9485                var that = this;
9486                this._richTextWidget.editor.on("blur:composer", function () {
9487                    that.$userControl.trigger("blur");
9488                });
9489                // initialize the access
9490                if (this.options.access) {
9491                    this._changeAccess(this.options.access);
9492                }
9493            }
9494        },
9495
9496        changeDefaultToolbarConfig: function(){
9497            if(window.Form && window.Form.rte){
9498                var toolbarDefaultConfigData = window.Form.rte.DefaultConfig;
9499                toolbarDefaultConfigData.fontSize.defaultValue = this.options.fontSize;
9500                toolbarDefaultConfigData.fontFamily.defaultValue = this.options.fontFamily;
9501
9502                // Adding 'isFontInPx' flag and overriding two utility functions
9503                // 'getDefaultParaStyle' and 'getMissingParaStyle' are responsible for adding RTE font styling attributes to rich text elements
9504                toolbarDefaultConfigData.isFontInPx = true;
9505                this.changeDefaultParaStyleUtility();
9506                this.changeMissingParaStyleUtility();
9507
9508                // Adding dropdown values in default config if not available in options
9509                if(toolbarDefaultConfigData.fontSize.options.indexOf(this.options.fontSize) === -1){
9510                    toolbarDefaultConfigData.fontSize.options.push(this.options.fontSize);
9511                }
9512                if(toolbarDefaultConfigData.fontFamily.options.indexOf(this.options.fontFamily) === -1){
9513                    toolbarDefaultConfigData.fontFamily.options.push(this.options.fontFamily);
9514                }
9515            }
9516        },
9517
9518        changeDefaultParaStyleUtility: function(){
9519            Form.rte.util.HtmlUtils.getDefaultParaStyle = function (config) {
9520                var style = "";
9521                if (config) {
9522                    style += 'font-family:' + config.fontFamily.defaultValue + ';';
9523                    if(config.isFontInPx){
9524                        style += 'font-size:' + config.fontSize.defaultValue + 'px;';
9525                        style += 'letter-spacing:' + config.letterSpacing.defaultValue + 'px;';
9526                    }else{
9527                        style += 'font-size:' + config.fontSize.defaultValue + 'pt;';
9528                        style += 'letter-spacing:' + config.letterSpacing.defaultValue + 'pt;';
9529                    }
9530                    style += 'color:#000000;';
9531                    style += 'text-align:left;';
9532                }
9533
9534                return style;
9535            };
9536        },
9537
9538        changeMissingParaStyleUtility : function(){
9539            Form.rte.util.HtmlUtils.getMissingParaStyle = function (style, config) {
9540                if (style && style.length > 0) {
9541                    if (config) {
9542                        if (!Form.rte.util.StringHelper.endsWith(style, ";")) {
9543                            style += ";";
9544                        }
9545                        if (style.indexOf("font-family") < 0) {
9546                            style += 'font-family:' + config.fontFamily.defaultValue + ';';
9547                        }
9548                        if (style.indexOf("font-size") < 0) {
9549                            if(config.isFontInPx){
9550                                style += 'font-size:' + config.fontSize.defaultValue + 'px;';
9551                            }else{
9552                                style += 'font-size:' + config.fontSize.defaultValue + 'pt;';
9553                            }
9554                        }
9555                        if (style.indexOf("letter-spacing") < 0) {
9556                            if(config.isFontInPx){
9557                                style += 'letter-spacing:' + config.letterSpacing.defaultValue + 'px;';
9558                            }else{
9559                                style += 'letter-spacing:' + config.letterSpacing.defaultValue + 'pt;';
9560                            }
9561                        }
9562                        if (style.indexOf("color") < 0) {
9563                            style += 'color:#000000;';
9564                        }
9565                        if (style.indexOf("text-align") < 0) {
9566                            style += 'text-align:left;';
9567                        }
9568                    }
9569                } else {
9570                    style = Form.rte.util.HtmlUtils.getDefaultParaStyle(config);
9571                }
9572                return style;
9573            };
9574        },
9575
9576        _initializeRTEToolbar : function () {
9577            window.Form.rte.RichTextEditor.MFToolbar = window.Form.rte.RichTextEditor.MFToolbar || {
9578                defaultMode : 'basic',
9579                toolbars : {
9580                    basic : {
9581                        layout : [
9582                            {
9583                                items : [Form.rte.Commands.HEADER]
9584                            },
9585                            {
9586                                items : [Form.rte.Commands.BOLD, Form.rte.Commands.ITALIC, Form.rte.Commands.UNDERLINE]
9587                            },
9588                            {
9589                                command : 'lists',
9590                                icon : 'list',
9591                                title : "List Type",
9592                                type : 'popover',
9593                                placement : 'bottom',
9594                                items : [Form.rte.Commands.INSERT_UNORDERED_LIST,
9595                                    Form.rte.Commands.INSERT_ORDERED_LIST,
9596                                    Form.rte.Commands.INSERT_LOWERCASE_ALPHABET_LIST]
9597                            },
9598                            {
9599                                title : 'Expand',
9600                                command : Form.rte.Commands.MODE,
9601                                value : Form.rte.ToolbarMode.FULL,
9602                                icon : 'resize-full'
9603                            }
9604                        ],
9605                        floating : true
9606                    },
9607                    full : {
9608                        layout : [
9609                            {
9610                                items : [Form.rte.Commands.BOLD, Form.rte.Commands.ITALIC, Form.rte.Commands.UNDERLINE]
9611                            },
9612                            {
9613                                items : [Form.rte.Commands.SUPERSCRIPT, Form.rte.Commands.SUBSCRIPT]
9614                            },
9615                            {
9616                                items : [
9617                                    Form.rte.Commands.HEADER, Form.rte.Commands.FONT_FAMILY, Form.rte.Commands.LINE_HEIGHT, Form.rte.Commands.FORE_COLOR, Form.rte.Commands.HILITE_COLOR, Form.rte.Commands.LINK
9618                                ]
9619                            },
9620                            {
9621                                items : [Form.rte.Commands.INSERT_UNORDERED_LIST, Form.rte.Commands.INSERT_ORDERED_LIST, Form.rte.Commands.INSERT_LOWERCASE_ALPHABET_LIST
9622                                ]
9623                            },
9624                            {
9625                                title : 'Collapse',
9626                                command : Form.rte.Commands.MODE,
9627                                value : Form.rte.ToolbarMode.BASIC,
9628                                icon : 'resize-small',
9629                                selected : true
9630                            }
9631                        ]
9632                    }
9633                }
9634            };
9635        }
9636    });
9637
9638})($);
9639(function($){
9640	$.widget( "xfaWidget.imageField", $.xfaWidget.defaultWidget, {
9641
9642    _widgetName:"imageField",
9643
9644    options: {
9645        tabIndex: 0,
9646        "role": "img"
9647    },
9648
9649    getEventMap: function () {
9650        var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getEventMap.apply(this, arguments);
9651        return $.extend({}, parentOptionsMap, {
9652            "imagechange": xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT
9653        })
9654    },
9655
9656    getOptionsMap: function() {
9657        var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this,arguments);
9658        return $.extend({},parentOptionsMap,{
9659            "screenReaderText": function(val) {
9660                if(val)
9661                    this.$userControl.attr("alt", val)
9662            },
9663            "displayValue": function(val) {
9664                var widgetValue;
9665                if (this.options.value) {
9666                    widgetValue = "data:;base64," + this.options.value;
9667                } else {
9668                    widgetValue = "";
9669                }
9670                this.$userControl.prop(this.options.commitProperty, widgetValue);
9671                this.$userControl.attr(this.options.commitProperty, widgetValue);
9672            },
9673            "access" : function() {},
9674
9675            // CQ-85514 : use max-ht & max-wd to honor image's intrinsic ht & wd attributes & prevent distortion
9676            "height" : function (val) {
9677                // in case aspect is actual then we need to crop the image, which will be not possible if max height and width are set
9678                if (val && this.options.aspect != "actual") {
9679                    this.$css(this.$userControl[0], {"max-height": val});
9680                }
9681            },
9682            "width" : function (val) {
9683                if (val && this.options.aspect != "actual") {
9684                    this.$css(this.$userControl[0], {"max-width": val});
9685                }
9686            },
9687            "aspect" : function (val) {
9688                // value of actual turns off scaling, causing the image to be drawn at its native size,
9689                // as per xfa spec Adobe implementations crop the image
9690                if(this.options.aspect == "actual") {
9691                    var right = this.$userControl.attr("width"),
9692                        bottom = this.$userControl.attr("height");
9693                    right = right.indexOf("px") >= 0 ? right : right + "px";
9694                    bottom = bottom.indexOf("px") >= 0 ? bottom : bottom + "px";
9695                    this._cropImage("0px", right, bottom, "0px");
9696                    this.$userControl.removeAttr("height width");
9697                // value of none indicates no aspect ratio
9698                // as per xfa spec image is independently scaled in the horizontal and vertical directions to exactly f
9698ill the field,
9699                // which are already set to fill the field
9700                } else if (this.options.aspect != "none") {
9701                // A value of fit, which is the default, causes the scale to be such that the image fills as much of the field as possible
9702                // without overflowing it in either dimension.
9703                    this.$userControl.attr({"height" : "auto", "width" : "auto"});
9704                }
9705            }
9706        });
9707    },
9708
9709    // crop the image using top,right, bottom, left coordiantes of the image
9710    _cropImage : function (top, right, bottom, left) {
9711        var clipRect = "rect(" + top + "," + right + "," + bottom + "," + left + ")";
9712        var clipPathPolygon = "polygon( 0px 0px, 0px " + bottom + "," + right + " " + bottom +"," + right + " 0px)";
9713        // clip property is deprecated but still supported by all the major browsers
9714        // clip-path replaces the deprecated clip property but still is not fully supported by all major browser
9715        this.$userControl.css({"clip" : clipRect, "clip-path" : clipPathPolygon});
9716    },
9717
9718    render : function() {
9719        var self = this;
9720        if (typeof FileReader !== "undefined") {
9721            this.reader = new FileReader();
9722        } else {
9723            xfalib.ut.XfaUtil.prototype.getLogger().error("Image Field is supported only for HTML5 supported browsers.");
9724        }
9725        if (this.element) {
9726            // change event triggered when new image is selected
9727            this.$widgetInput = this.element.find("input").on("change.imageField", function() {
9728                self._handleInputChange();
9729            }).click(function(event) {
9730                // to stop bubbling of event from input to widget
9731                event.stopPropagation();
9732            });
9733            this.$widgetImg = this.element.on("click.imageField", function() {
9734                self._imageClick();
9735            }).find("img");
9736        }
9737        if (this.reader) {
9738            //load event is triggered each time the reading operation is successfully completed
9739            this.reader.addEventListener("load", function () {
9740                self.$widgetImg.attr("src",self.reader.result);
9741                self.$widgetImg.trigger("imagechange");
9742            }, false);
9743        }
9744        return $.xfaWidget.defaultWidget.prototype.render.apply(this, arguments);
9745    },
9746
9747    getCommitValue: function() {
9748        return this._extractData(this.$userControl.attr("src"));
9749    },
9750
9751    // hidden input change handler, input change will be triggered on selecting a new image
9752    _handleInputChange : function() {
9753        this._displayImage();
9754    },
9755
9756    _imageClick : function(clickEvent) {
9757        //as the input button is hidden we trigger click explicitly on click of the widget
9758        this.$widgetInput.trigger("click");
9759    },
9760
9761    // removes "data\:.*\;base64," from the image base64 string
9762    _extractData : function(value) {
9763        return value.replace(/data\:.*\;base64,/, "");
9764    },
9765
9766    // previews image in the imagefield widget
9767    _displayImage : function() {
9768        var imageFile = this.$widgetInput.get(0).files ? this.$widgetInput.get(0).files[0] : null;
9769        if (imageFile && this._isFileOfImageType(imageFile.name)) {
9770            if (this.reader) {
9771                //readAsDataURL method is used to read the contents of the specified file, result attribute contains  the data as a URL representing the file's data as a base64 encoded string
9772                this.reader.readAsDataURL(imageFile);
9773            }
9774        }
9775    },
9776
9777    // Test for supported image file(jpg,jpeg,png,gif,tif,bmp)
9778    _isFileOfImageType : function(fileName) {
9779        if (fileName) {
9780            return (/\.(jpe?g|png|gif|tif|bmp)$/i.test(fileName));
9781        }
9782        return false;
9783    }
9784});
9785})($);
9786/**
9787 * Created with IntelliJ IDEA.
9788 * User: rpandey
9789 * Date: 12/24/12
9790 * Time: 8:06 PM
9791 * To change this template use File | Settings | File Templates.
9792 */
9793
9794
9795(function($){
9796    $.widget( "xfaWidget.signatureField", $.xfaWidget.defaultWidget, {
9797
9798        _widgetName:"signatureField",
9799
9800        getOptionsMap: function() {
9801            var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this,arguments);
9802            return $.extend({},parentOptionsMap,{
9803                "displayValue": function(val) {},
9804                "access": function(val) {}
9805            })
9806        },
9807
9808        render : function() {
9809            var $control = $.xfaWidget.defaultWidget.prototype.render.apply(this, arguments);
9810            //pessimistic checks
9811            if($control) {
9812                $control.attr("readOnly","readonly").attr("disabled", true);
9813            }
9814            return $control;
9815        }
9816    });
9817})($);
9818/*
9819 * ADOBE CONFIDENTIAL
9820 * ___________________
9821 *
9822 * Copyright 2011-2012 Adobe Systems Incorporated
9823 * All Rights Reserved.
9824 *
9825 * NOTICE:  All information contained herein is, and remains
9826 * the property of Adobe Systems Incorporated and its suppliers,
9827 * if any.  The intellectual and technical concepts contained
9828 * herein are proprietary to Adobe Systems Incorporated and its
9829 * suppliers and may be covered by U.S. and Foreign Patents,
9830 * patents in process, and are protected by trade secret or copyright law.
9831 * Dissemination of this information or reproduction of this material
9832 * is strictly forbidden unless prior written permission is obtained
9833 * from Adobe Systems Incorporated.
9834 */
9835 
9836/**
9837 * widget definition for scribbleable field
9838 */
9839(function($,xfalib){
9840
9841 var TouchUtil=xfalib.ut.TouchUtil;
9842 var ScribbleUtil=(function(){
9843      return {
9844          localeString:function(id){
9845                    return xfalib.ut.XfaUtil.prototype.encodeScriptableTags($.xfaWidget.abstractWidget.prototype.localeStrings()[id])  || id;
9846          }
9847      };
9848 })();
9849 var DELETE_KEY = 46;
9850 var ESC_KEY = 27;
9851 var ENTER_KEY = 13;
9852/**
9853 * Scribble class definition, used for drawing on canvas using mouse or touch
9854 */
9855function Scribble( canvasID,image,_width,_height, callback) {
9856    this._callback = callback;
9857    this.canvasID = canvasID;
9858    this._lineWidth=5;
9859    this.canvas = $("#"+canvasID);
9860    this.context = this.canvas.get(0).getContext("2d"); 
9861    this.context.clearRect(0,0,this.canvas.width,this.canvas.height);
9862    this._enabled=true;
9863    this.context.strokeStyle = "#000000";
9864    this.canvasBorderWidth = parseInt(this.canvas.css('border-left-width'),10); // assuming top and left borders are same width
9865    this.context.lineWidth = this._lineWidth;
9866    this.lastMousePoint = {x:0, y:0};
9867    
9868    this.canvas[0].width = _width;// this.canvas.parent().innerWidth();
9869    this.canvas[0].height = _height;//this.canvas.parent().innerHeight();
9870    if(!image){
9871        this.context.fillStyle   = '#ffffff';
9872        this.context.clearRect(0,0,_width,_height);
9873    } else {
9874        this.context.drawImage(image,0,0);
9875    }
9876    this.canvas.on( TouchUtil.POINTER_DOWN, this.onCanvasMouseDown() );
9877}
9878Scribble.prototype.setLineWidth=function(w){
9879    this._lineWidth=w;
9880};
9881Scribble.prototype.onCanvasMouseDown = function () {
9882    var self = this;
9883    return function(event) {
9884        if(TouchUtil.getTouches(event).length < 2){
9885            self.mouseMoveHandler = self.onCanvasMouseMove();
9886            self.mouseUpHandler = self.onCanvasMouseUp();
9887            //CQ-4261765 : Scribble sign scroll issue with ios
9888            //https://stackoverflow.com/questions/49500339/cant-prevent-touchmove-from-scrolling-window-on-ios
9889            //https://github.com/jquery/jquery/issues/2871
9890            document.addEventListener(TouchUtil.POINTER_MOVE, self.mouseMoveHandler,{ passive: false });
9891            $(document).on(TouchUtil.POINTER_UP, self.mouseUpHandler );
9892            self.updateMousePosition( event );
9893            self.updateCanvas( event );
9894        }
9895    }
9896};
9897
9898Scribble.prototype.onCanvasMouseMove = function () {
9899    var self = this;
9900    return function(event) {
9901        if(TouchUtil.getTouches(event).length < 2){
9902            self.updateCanvas( event );
9903            event.preventDefault();
9904            return false;
9905        }
9906    }
9907};
9908
9909Scribble.prototype.onCanvasMouseUp = function (event) {
9910    var self = this;
9911    return function(event) {
9912        document.removeEventListener(TouchUtil.POINTER_MOVE, self.mouseMoveHandler,{ passive: false });
9913        $(document).off(TouchUtil.POINTER_UP, self.mouseUpHandler );
9914        self.mouseMoveHandler = null;
9915        self.mouseUpHandler = null;
9916    }
9917};
9918
9919Scribble.prototype.updateMousePosition = function (event) {
9920    if(!this._enabled) return ;
9921    var target = TouchUtil.getTouchEvent(event);
9922
9923    var offset = this.canvas.offset();
9924    /* In IE>=10 pageX values are incorrect when using zoom
9925     so calculate them using clientX and scrollLeft */
9926    this.lastMousePoint.x = target.clientX + $(window).scrollLeft() - offset.left - this.canvasBorderWidth;
9927    this.lastMousePoint.y = target.clientY + $(window).scrollTop() - offset.top - this.canvasBorderWidth;
9928
9929};
9930Scribble.prototype._isInsideCanvas = function(x,y){
9931    return y>=0 && y<this.canvas[0].height && x>=0 && x < this.canvas[0].width;
9932};
9933    Scribble.prototype.updateCanvas = function (event) {
9934    if(!this._enabled) {
9935       return;
9936    }
9937    var oldX,oldY,dX,dY,canDraw,scaleX,scaleY,cssWidth,cssHeight;
9938    cssWidth = parseInt(this.canvas[0].style.width,10);
9939    cssHeight = parseInt(this.canvas[0].style.height,10);
9940    scaleX =  cssWidth?this.canvas[0].width/cssWidth:1;
9941    scaleY = cssHeight?this.canvas[0].height/cssHeight:1;
9942
9943    scaleX /= xfalib.ut.XfaUtil.prototype.formScaleFactor;
9944    scaleY /= xfalib.ut.XfaUtil.prototype.formScaleFactor;
9945
9946    oldX = this.lastMousePoint.x*scaleX;
9947    oldY = this.lastMousePoint.y*scaleY;
9948   
9949    this.updateMousePosition( event );
9950
9951    var newX =  this.lastMousePoint.x*scaleX;
9952    var newY =  this.lastMousePoint.y*scaleY;
9953
9954    dX = Math.abs(newX - oldX );
9955    dY = Math.abs(newY - oldY );
9956
9957    canDraw = ( dX > 0 || dY > 0 ) && this._isInsideCanvas(oldX,oldY) && this._isInsideCanvas(newX,newY);;
9958
9959    if(canDraw){
9960        this.context.beginPath();
9961        this.context.moveTo( oldX, oldY );
9962        this.context.lineTo(newX, newY );
9963        this.context.lineWidth=this._lineWidth;
9964        this.context.lineCap='round';
9965        this.context.stroke();
9966		
9967        this._callback();
9968		
9969    }
9970};
9971
9972Scribble.prototype.toString = function () {
9973
9974    var dataString = this.canvas.get(0).toDataURL("image/png");
9975    //var index = dataString.indexOf( "," )+1;
9976    //dataString = dataString.substring( index );
9977
9978    return dataString;
9979};
9980Scribble.prototype.setEnabled=function(enable){
9981    this._enabled=enable;
9982};
9983Scribble.prototype.clear = function () {
9984
9985    var c = this.canvas[0];
9986    this.context.clearRect( 0, 0, c.width, c.height );
9987};
9988
9989
9990// ImageEdit dialog box
9991var imageEditDialog=(function(_){
9992  
9993    // html used to construct dialog box
9994    var htmlStr=(function(){
9995         var html=[
9996             '<div id="iEBox_container" tabindex="0" role="dialog" aria-label="'+ScribbleUtil.localeString("pleaseSignText")+'">',
9997                  '<div id="iEBox_panel">',
9998                      '<div  id = "iEBox_Cancel" class="iEBox_button" tabindex="0" role="button" aria-label="'+ScribbleUtil.localeString("cancel")+'" title="'+ScribbleUtil.localeString("cancel")+'" ></div>',
9999                  '</div>',
10000                  '<div id="iEBox_content">',
10001                      '<div id="iEBox_canvases" align=center>',
10002                          '<div style="display:inline-block; vertical-align:top;">',
10003                               '<canvas  id="iEBox_canvas" style="margin:0px;border-bottom:0px;" width="696" height="390" ></canvas>' ,
10004                               '<input type="text" id="keyboard_Sign_Box" name="signatureText" placeholder="'+ScribbleUtil.localeString("typeYourSignatureHere")+'">',
10005                               '<fieldset id="iEBox_caption"><legend align="center">
10005'+ScribbleUtil.localeString("pleaseSignText")+'</legend></fieldset>',
10006                          '</div>',
10007                          '<canvas id="iEBox_geoCanvasRight" width="0" height="0" ></canvas>',
10008                          '<div><canvas id="iEBox_geoCanvasBottom" width="0" height="0" ></canvas></div>',
10009                      '</div>',
10010                      '<div>',
10011                          '<div id="iEBox_Brush" class="iEBox_button" tabindex="0"  role="button" aria-label="'+ScribbleUtil.localeString("brushes")+'"  title="'+ScribbleUtil.localeString("brushes")+'"></div>',
10012                          '<div id="iEBox_Clear" class="iEBox_button" tabindex="0"  role="button" aria-label="'+ScribbleUtil.localeString("clear")+'"  title="'+ScribbleUtil.localeString("clear")+'" ></div>',
10013                          '<div id="iEBox_Geo" class="iEBox_button" tabindex="0"  role="button" aria-label="'+ScribbleUtil.localeString("geolocation")+'"  title="'+ScribbleUtil.localeString("geolocation")+'" ></div>',
10014                          '<div id="iEBox_Text" class="iEBox_button" tabindex="0"  role="button" aria-label="'+ScribbleUtil.localeString("typeYourName")+'"  title="'+ScribbleUtil.localeString("typeYourName")+'"></div>',
10015                          '<div id="iEBox_title"></div>',
10016                          '<div id="iEBox_Ok" class="iEBox_button" tabindex="0"  role="button" aria-label="'+ScribbleUtil.localeString("ok")+'"  title="'+ScribbleUtil.localeString("ok")+'" ></div>',
10017                      '</div>' ,
10018                  '</div>' ,
10019                  '<div id="iEBox_moveframe" ></div>',
10020                  '<div id="iEBox_brushList" ></div>',
10021              '</div>'].join("");
10022           return function(){
10023              return html;
10024           };
10025    });
10026	
10027    /**
10028	 *   
10029	 */
10030	
10031    var dialogObj = {
10032        verticalOffset: 0, // removing the magic value of -75 since it was not causing any impact
10033        horizontalOffset: 0,
10034        repositionOnResize: true,
10035        overlayOpacity: .75,
10036        overlayColor: '#CCCCCC',
10037        draggable: true,
10038        _brushes:[2,3,4,5,6,7,8,9,10],
10039		_buttonsEnabled:{},
10040		_isOpen:false,
10041        show:function(title,callback){
10042           this._show(callback);
10043		   this._buttonsEnabled={Geo:true,Clear:true,Ok:true,Cancel:true,Brush:true,Text:true};
10044        },
10045		setEnabled:function(button,enable){
10046		    if(this._buttonsEnabled[button]!=enable){
10047		           this._buttonsEnabled[button]=enable;
10048				   if(enable){
10049				       $('#iEBox_'+button).empty('<div style="background:white;width:100%;height:100%;opacity:0.75;"></div>').
10050				                  removeClass("disable_button");
10051				   } else {
10052				       $('#iEBox_'+button).append('<div style="background:white;width:100%;height:100%;opacity:0.75;"></div>').
10053				                  addClass("disable_button");
10054				   }
10055			       
10056			}
10057		},
10058		enableButtons:function(buttons){
10059		    for(var k in buttons){
10060				   this.setEnabled(k,buttons[k]);
10061			}
10062		},
10063        toggleBrushList:function(event){
10064                var that = this;
10065                if($('#iEBox_brushList').css('display')!='none'){
10066                    $('#iEBox_brushList').css({display:'none'});
10067                    return;
10068                }
10069                 var tmpFn =  document.onselectstart;
10070                 document.onselectstart=function(){return false;};
10071                 $('#iEBox_brushList').css({display:'block',visibility:'hidden'});
10072                    $('#iEBox_brushList').offset($('#iEBox_Brush').offset());
10073                    $('#iEBox_brushList').offset({top:$('#iEBox_Brush').offset().top-$('#iEBox_brushList').height()});
10074                    $('#iEBox_brushList').css({display:'block',visibility:'visible'});
10075                  //  $('#iEBox_brushList').focus();
10076                     $('#iEBox_brushList').one('mouseleave',function(event){
10077                         $('#iEBox_brushList').css({display:'none'});
10078                          document.onselectstart=tmpFn;
10079                     });
10080        },
10081        _attachCallbacks: function(callback) {
10082            var that = this;
10083            var sigCanvas = $('#iEBox_canvas')[0];
10084            var ctx=sigCanvas.getContext("2d");
10085            var minSigCanvasFontSize=10;
10086            var maxSigCanvasFontSize=70;
10087            var sigCanvasFontSize=minSigCanvasFontSize;
10088            var initialSigCanvasFontSize=sigCanvasFontSize;
10089            var initialFontCalculatedFlag=false;
10090            var sigCanvasFontFamily="sans-serif, Georgia";
10091            var sigCanvasFontStyle="italic";
10092           _.each("Cancel-Clear-Geo-Ok-Brush-Text".split("-"),function(val,idx){
10093                    $("#iEBox_"+val).click( function(event) {
10094				       if(that._buttonsEnabled[val]){
10095                          event.stopPropagation();
10096                          callback(val);
10097				       }
10098                    });
10099					$("#iEBox_"+val).keydown( function(event) {
10100				       if(that._buttonsEnabled[val] && (event.keyCode == ENTER_KEY || event.charCode == ENTER_KEY || event.which == ENTER_KEY) ){
10101                          event.stopPropagation();
10102                          callback(val);
10103				       }
10104                    });
10105            });
10106            _.each($("#iEBox_brushList").children(),function(itm,idx){
10107                  $(itm).on(TouchUtil.POINTER_UP,function(event){
10108                         callback("BrushSelect",that._brushes[idx]);
10109                         $('#iEBox_brushList').css({display:'none'});
10110                          // $(itm).css({backgroundColor:'#FFFFFF'});
10111                  });
10112                  $(itm).on(TouchUtil.POINTER_DOWN,function(event){
10113                          // $(itm).css({backgroundColor:'#AAAAAA'});
10114                           event.preventDefault();
10115                  });
10116             });
10117
10118            $('#keyboard_Sign_Box').keydown(function (event){
10119                var inputSign=$('#keyboard_Sign_Box')[0].value;
10120
10121                if(event.key==="Backspace") {
10122                    ctx.font=sigCanvasFontStyle+sigCanvasFontSize+"px "+sigCanvasFontFamily;
10123                    sigCanvasFontSize=dialogObj._increaseFontForSignature(ctx.measureText(inputSign).width,sigCanvas.width,
10124                        sigCanvasFontSize,initialSigCanvasFontSize);
10125                    ctx.font=sigCanvasFontStyle+" "+sigCanvasFontSize+"px "+sigCanvasFontFamily;
10126                    ctx.clearRect(0, 0, sigCanvas.width, sigCanvas.height);
10127                    ctx.fillText(inputSign, 3, sigCanvasFontSize, sigCanvas.width-5);
10128                }
10129                event.stopPropagation();
10130            });
10131
10132            $("#keyboard_Sign_Box").keyup(function (event){
10133                var inputSign=$('#keyboard_Sign_Box')[0].value;
10134                if(inputSign.length==0) {
10135                    dialogObj.enableButtons({Ok: false, Clear: false});
10136                }
10137                if(inputSign.length>=1 && inputSign.trim().length!=0) {
10138                    dialogObj.enableButtons({Ok: true, Clear: true});
10139                }
10140                if(initialFontCalculatedFlag===false){
10141                    sigCanvasFontSize=sigCanvas.height-20;
10142                    sigCanvasFontSize=sigCanvasFontSize<minSigCanvasFontSize?minSigCanvasFontSize:sigCanvasFontSize;
10143                    sigCanvasFontSize=sigCanvasFontSize>maxSigCanvasFontSize?maxSigCanvasFontSize:sigCanvasFontSize;
10144                    initialSigCanvasFontSize=sigCanvasFontSize;
10145                    $('#keyboard_Sign_Box')[0].style.font=sigCanvasFontStyle+" 2rem "+sigCanvasFontFamily;
10146                    initialFontCalculatedFlag=true;
10147                }
10148                ctx.font=sigCanvasFontStyle+sigCanvasFontSize+"px "+sigCanvasFontFamily;
10149                sigCanvasFontSize=dialogObj._decreaseFontForSignature(ctx,inputSign,sigCanvas.width,
10150                    sigCanvasFontSize,sigCanvasFontFamily);
10151                ctx.font=sigCanvasFontStyle+" "+sigCanvasFontSize+"px "+sigCanvasFontFamily;
10152                ctx.clearRect(0, 0, sigCanvas.width, sigCanvas.height);
10153                ctx.fillText(inputSign,3,sigCanvasFontSize,sigCanvas.width-5);
10154                event.stopPropagation();
10155            });
10156
10157            // capture tab key and escape
10158			$('#iEBox_container').keydown(function(event){
10159			    var firstFocusableItem = document.querySelector("#iEBox_container");
10160                var lastFocusableItem = document.querySelector("#iEBox_Ok");
10161                var KEYCODE_TAB = 9;
10162                var isTabPressed = (event.key === 'Tab' || event.keyCode === KEYCODE_TAB);
10163                if((event.keyCode == ESC_KEY || event.charCode == ESC_KEY || event.which == ESC_KEY)) {
10164                    event.stopPropagation();
10165               	    event.preventDefault();
10166               	    callback("Cancel");
10167                } else if (isTabPressed) {
10168                    // Trap focus inside the dialog box
10169                    if (event.shiftKey && document.activeElement === firstFocusableItem) {
10170                        // when shift + tab key is pressed
10171                        lastFocusableItem.focus();
10172                        event.preventDefault();
10173                    } else if (document.activeElement === lastFocusableItem) {
10174                        // when tab key is pressed
10175                        firstFocusableItem.focus();
10176                        event.preventDefault();
10177                    }
10178               }
10179
10180            });
10181
10182            if(this.draggable){
10183                this._makeDraggable(TouchUtil.TOUCH_ENABLED);
10184            }
10185        },
10186
10187        _decreaseFontForSignature:function(ctx,inputSign,sigCanvasWidth,fontSize,sigCanvasFontFamily){
10188            while(ctx.measureText(inputSign).width>sigCanvasWidth-5 && fontSize>20){
10189                fontSize=fontSize-10;
10190                ctx.font=fontSize+"px "+sigCanvasFontFamily;
10191            }
10192            return fontSize
10193        },
10194        _increaseFontForSignature:function(textWidth,sigCanvasWidth,fontSize,initialSigCanvasFontSize){
10195            if(sigCanvasWidth-textWidth>0){
10196                fontSize=initialSigCanvasFontSize;
10197            }
10198            return fontSize;
10199        },
10200        _makeDraggable:function(touchEnabled){
10201              var _isMouseDown=false;
10202              var _that=this;
10203              var dX;
10204              var dY;
10205              var offsetPos;
10206              var _mouseMovFun;
10207              var _mouseUpFun;
10208              $('#iEBox_panel').on(TouchUtil.POINTER_DOWN,function( event ){
10209              
10210                  if(TouchUtil.getTouches(event).length < 2){
10211                      if($(event.target).is('#iEBox_panel')){
10212                          $('body')[0].addEventListener(TouchUtil.POINTER_MO
10212VE,_mouseMovFun=function( event ){
10213                              if(TouchUtil.getTouches(event).length < 2 && _isMouseDown){
10214                                  event.preventDefault();
10215                                  var evt = TouchUtil.getTouchEvent(event);
10216                                  var delX = evt.pageX - dX;
10217                                  var delY = evt.pageY - dY;
10218                                  $('#iEBox_moveframe').offset({
10219                                      top: offsetPos.top+delY,
10220                                      left: offsetPos.left+delX
10221                                  });
10222                              }
10223                          }, { passive: false });
10224                          $('body').on(TouchUtil.POINTER_UP,_mouseUpFun=function(event){
10225                              if(_isMouseDown){
10226                                  var offsetMove = $('#iEBox_moveframe').offset();
10227                                  var topEdge  = $(window).scrollTop();
10228                                  var bottomEdge = topEdge + $(window).height();
10229                                  if(offsetMove.top - topEdge < 1){
10230                                      offsetMove.top = topEdge;
10231                                  }
10232                                  if(offsetMove.top - bottomEdge + $('#iEBox_panel').height() > 0 ){
10233                                      offsetMove.top = bottomEdge - $('#iEBox_panel').height();
10234                                  }
10235                                  $('#iEBox_container').offset(offsetMove );
10236                                  $('#iEBox_moveframe').css({display:'none'}).offset(offsetMove);
10237                                  _isMouseDown=false;
10238                                  $('body')[0].removeEventListener(TouchUtil.POINTER_MOVE,_mouseMovFun,{ passive: false });
10239                                  $('body').off(TouchUtil.POINTER_UP,_mouseUpFun);
10240                              }
10241                          });
10242
10243                          var evt = TouchUtil.getTouchEvent(event);
10244                          _isMouseDown=true; dX = evt.pageX;dY=evt.pageY;
10245                          offsetPos = $('#iEBox_container').offset();
10246                          $('#iEBox_moveframe').css({display:'block'});
10247                          $('#iEBox_moveframe').offset(offsetPos);
10248                          $('#iEBox_moveframe').css('width',$('#iEBox_container').css('width'));
10249                          $('#iEBox_moveframe').css('height',$('#iEBox_container').css('height'));
10250                      }
10251                  }
10252              });
10253             
10254        },
10255        _createBrushes:function(){
10256               var _that=this;
10257              _.each(this._brushes,function(val,idx){
10258                  var divel = document.createElement('DIV');
10259                  var cnv = document.createElement('CANVAS');
10260                  var ctx = cnv.getContext('2d');
10261                  cnv.style.border='1px solid #AAAAAA';
10262                  cnv.width=TouchUtil.TOUCH_ENABLED?200:100;
10263                  cnv.height=TouchUtil.TOUCH_ENABLED?40:20;;
10264                  ctx.lineWidth=val;
10265                  ctx.beginPath();
10266                  ctx.moveTo(10,cnv.height/2);
10267                  ctx.lineTo(cnv.width-10,cnv.height/2);
10268                  ctx.stroke();
10269                  divel.appendChild(cnv);
10270                  $('#iEBox_brushList').append(divel);
10271               });
10272        },
10273		getIsOpen:function(){
10274		    return dialogObj._isOpen;
10275		},
10276		setIsOpen:function(open){
10277		    dialogObj._isOpen = open;
10278		},
10279        _show: function(callback) {
10280            dialogObj.hide();
10281            dialogObj._overlay('show');
10282            
10283            $("BODY").append(htmlStr());
10284            dialogObj.setIsOpen(true);
10285            $('#iEBox_container').focus();
10286            dialogObj._createBrushes();
10287
10288            dialogObj._reposition();
10289
10290            // calculate spacing around canvas area
10291            // this will be used to find canvas dimensions based on available screen area.
10292            var container_el = $('#iEBox_container');
10293            var canvas_el =  $('#iEBox_canvas');
10294            var container_width = $('#iEBox_container').outerWidth(true);
10295            var container_height = $('#iEBox_container').outerHeight(true);
10296            var canvas_width = canvas_el[0].width;
10297            var canvas_height = canvas_el[0].height;
10298            dialogObj.canvas_spacing = { x:container_width - canvas_width, y:container_height-canvas_height};
10299
10300            dialogObj._maintainPosition(true);
10301            
10302            dialogObj._attachCallbacks(callback);
10303        },
10304
10305        hide: function() {
10306            $("#iEBox_container").remove();
10307            this._overlay('hide');
10308            dialogObj.setIsOpen(false);
10309            this._maintainPosition(false);
10310        },
10311        _overlayResize:function(event) {
10312            if($("#iEBox_overlay").height()!= $(document).height()){
10313                $("#iEBox_overlay").height( $(document).height() );
10314            }
10315
10316        },
10317        _disableMove:function(event) {
10318            event.preventDefault();
10319        },
10320        _overlay: function(status) {
10321            switch( status ) {
10322                case 'show':
10323                    this._overlay('hide');
10324                    $("BODY").append('<div id="iEBox_overlay"></div>');
10325                    $("#iEBox_overlay").css({
10326                        position: 'fixed',
10327                        zIndex: 99997,
10328                        top: '0px',
10329                        left: '0px',
10330                        width: '100%',
10331                        height: $(document).height(),
10332                        background: this.overlayColor,
10333                        opacity: this.overlayOpacity
10334                    });
10335                    if(xfalib.ut.XfaUtil.prototype.isSafari()) {
10336                        $("#iEBox_overlay").on('touchmove', this._disableMove);
10337                    }
10338                    $(document).on('scroll',this._overlayResize);
10339                break;
10340                case 'hide':
10341                    if(xfalib.ut.XfaUtil.prototype.isSafari()) {
10342                        $("#iEBox_overlay").off('touchmove');
10343                    }
10344                    $("#iEBox_overlay").remove();
10345                    $(document).off('scroll',this._overlayResize);
10346                break;
10347            }
10348        },
10349        /**
10350         * resize dialog based on available screen area
10351         */
10352        _resize:function(){
10353            // available screen area
10354            var aWidth = $(window).width();
10355            var aHeight = $(window).height();
10356
10357            var sigCnv = $('#iEBox_canvas')[0];
10358            var sigTextBox = $('#keyboard_Sign_Box')[0];
10359            var bGeoCnv = $('#iEBox_geoCanvasBottom')[0];
10360            var rGeoCnv = $('#iEBox_geoCanvasRight')[0];
10361
10362            // calculate amount of width height we need to reduce
10363
10364            var totalCnvWidth = sigCnv.width + rGeoCnv.width;
10365            var totalCnvHeight = sigCnv.height + bGeoCnv.height;
10366
10367
10368
10369
10370
10371            var diffW = totalCnvWidth + dialogObj.canvas_spacing.x - aWidth;
10372            if(diffW < 0) {
10373                diffW = 0;
10374            }
10375            var diffH = totalCnvHeight + dialogObj.canvas_spacing.y - aHeight;
10376            if(diffH < 0){
10377                diffH = 0;
10378            }
10379
10380            var newTotalCnvHeight, newTotalCnvWidth;
10381            if( diffW > 0 || diffH > 0 ){ // does any side need resize
10382
10383                if(diffH * totalCnvWidth > totalCnvHeight * diffW){ // need to reduce height
10384                   newTotalCnvHeight = totalCnvHeight - diffH;
10385                   newTotalCnvWidth = (newTotalCnvHeight * totalCnvWidth)/ totalCnvHeight;
10386                } else {
10387                   newTotalCnvWidth = totalCnvWidth - diffW;
10388                   newTotalCnvHeight = (newTotalCnvWidth * totalCnvHeight)/ totalCnvWidth;
10389                }
10390
10391                // distribute evenly the new dimensions
10392
10393
10394                var newSigCnvWidth   = (newTotalCnvWidth*sigCnv.width)/totalCnvWidth;
10395                var newSigCnvHeight = (newTotalCnvHeight*sigCnv.height)/totalCnvHeight;
10396
10397                sigCnv.style.width = newSigCnvWidth + "px";
10398                sigCnv.style.height = newSigCnvHeight + "px";
10399
10400                sigTextBox.style.width = newSigCnvWidth + "px";
10401                sigTextBox.style.height = newSigCnvHeight + "px";
10402
10403
10404                bGeoCnv.style.width = newSigCnvWidth +"px";
10405                bGeoCnv.style.height = (newTotalCnvHeight - newSigCnvHeight) +"px";
10406
10407                rGeoCnv.style.width = (newTotalCnvWidth - newSigCnvWidth) +"px";
10408                rGeoCnv.style.height = newSigCnvHeight + "px";
10409
10410
10411                $('#iEBox_caption').width(Math.floor(newSigCnvWidth));
10412
10413            } else {
10414                sigCnv.style.width =  sigCnv.width + "px";
10415                sigCnv.style.height = sigCnv.height + "px";
10416
10417                sigTextBox.style.width =  sigCnv.width + "px";
10418                sigTextBox.style.height = sigCnv.height + "px";
10419
10420                bGeoCnv.style.width =  bGeoCnv.width + "px";
10421                bGeoCnv.style.height = bGeoCnv.height + "px";
10422
10423                rGeoCnv.style.width =  rGeoCnv.width + "px";
10424                rGeoCnv.style.height = rGeoCnv.height + "px";
10425
10426                $('#iEBox_caption').width(sigCnv.width);
10427
10428            }
10429        },
10430        _reposition: function() {
10431            var top = (($(window).height() * (1 / xfalib.ut.XfaUtil.prototype.formScaleFactor) / 2) - ($("#iEBox_container").outerHeight() / 2)) + dialogOb
10431j.verticalOffset;
10432            var left = (($(window).width() * (1 / xfalib.ut.XfaUtil.prototype.formScaleFactor) / 2) - ($("#iEBox_container").outerWidth() / 2)) + dialogObj.horizontalOffset;
10433            if( top < 0 ) top = 0;
10434            if( left < 0 ) left = 0;
10435
10436            $("#iEBox_container").css({
10437                top: top + $(window).scrollTop() * (1 / xfalib.ut.XfaUtil.prototype.formScaleFactor) + 'px',
10438                left: left + $(window).scrollLeft() * (1 / xfalib.ut.XfaUtil.prototype.formScaleFactor) + 'px'
10439            });
10440            $("#iEBox_container").focus();   // scroll up to the canvas
10441            $("#iEBox_overlay").height( $(document).height() );
10442        },
10443        _maintainDialog:function(){
10444            dialogObj._resize();
10445            dialogObj._reposition();
10446        },
10447        _maintainPosition: function(status) {
10448            if(dialogObj.repositionOnResize ) {
10449                switch(status) {
10450                    case true:
10451                        $(window).on('orientationchange', dialogObj._maintainDialog); // also reposition if device is tilted
10452                    break;
10453                    case false:
10454                        $(window).off('orientationchange', dialogObj._maintainDialog);
10455                    break;
10456                }
10457            }
10458        }
10459        
10460    };
10461    return dialogObj;
10462})(window._);
10463
10464/**
10465 * class definition for GeoLocationQueryRequest
10466 * encapsulated success and error handlers 
10467 */
10468function GeoLocQuery(){}
10469GeoLocQuery.prototype={
10470    init:function(success,failure){
10471        this._successHandler = success;
10472        this._errorHandler = failure;
10473        this._active=true;
10474        return this;
10475    },
10476    _handleSuccess:function(data){
10477        this._successHandler(data); 
10478    },
10479    _handleError:function(err){
10480        this._errorHandler(err);   
10481    },
10482    query:function(){
10483         _that=this;
10484         navigator.geolocation.getCurrentPosition(function(pos){
10485          if(_that._active){
10486             _that._handleSuccess(pos);
10487          }
10488          _that._active=false;
10489       },function(err){
10490          if(_that._active){
10491             _that._handleError(err);
10492          }
10493          _that._active=false;
10494       },{timeout:10000});
10495    },
10496    cancel:function(){
10497        _that._active=false;
10498    }
10499
10500};
10501// GeoLocQuery definition ends here
10502
10503/**
10504*
10505*  Base64 encode / decode
10506*  http://www.webtoolkit.info/
10507*
10508**/
10509 
10510var Base64 = {
10511 
10512	// private property
10513	_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
10514 
10515	// public method for encoding
10516	encode : function (input) {
10517		var output = "";
10518		var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
10519		var i = 0;
10520 
10521		while (i < input.length) {
10522 
10523			chr1 = input.charCodeAt(i++);
10524			chr2 = input.charCodeAt(i++);
10525			chr3 = input.charCodeAt(i++);
10526 
10527			enc1 = chr1 >> 2;
10528			enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
10529			enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
10530			enc4 = chr3 & 63;
10531 
10532			if (isNaN(chr2)) {
10533				enc3 = enc4 = 64;
10534			} else if (isNaN(chr3)) {
10535				enc4 = 64;
10536			}
10537 
10538			output = output +
10539			this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
10540			this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
10541 
10542		}
10543 
10544		return output;
10545	},
10546 
10547	// public method for decoding
10548	decode : function (input) {
10549		var output = "";
10550		var chr1, chr2, chr3;
10551		var enc1, enc2, enc3, enc4;
10552		var i = 0;
10553 
10554		input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
10555 
10556		while (i < input.length) {
10557 
10558			enc1 = this._keyStr.indexOf(input.charAt(i++));
10559			enc2 = this._keyStr.indexOf(input.charAt(i++));
10560			enc3 = this._keyStr.indexOf(input.charAt(i++));
10561			enc4 = this._keyStr.indexOf(input.charAt(i++));
10562 
10563			chr1 = (enc1 << 2) | (enc2 >> 4);
10564			chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
10565			chr3 = ((enc3 & 3) << 6) | enc4;
10566 
10567			output = output + String.fromCharCode(chr1);
10568 
10569			if (enc3 != 64) {
10570				output = output + String.fromCharCode(chr2);
10571			}
10572			if (enc4 != 64) {
10573				output = output + String.fromCharCode(chr3);
10574			}
10575 
10576		}
10577 
10578		return output;
10579 
10580	}
10581 
10582	
10583 
10584};
10585
10586/**
10587 * Utility Singleton for handling PNG Data
10588 */
10589var PNGUtil=(function(){
10590    var slf={
10591   _LC_Scribble_MetaDataKey:"LC_SCIBBLE_METADATA",
10592           _isPng:function(b64data){
10593               return  b64data && b64data.replace(/\s+/g, "").indexOf("iVBORw0KGgo") == 0;   // LC-5711 : trim any leading WhiteSpace
10594               // TODO :  base64 encoding may have white spaces even between the magic numbers !! Think of a better way to stop stripping white spaces repeatedly in PNGUtil, and cache the result
10595           },
10596           _update_crc:function(crc,data){
10597               var c = crc;
10598               var n;
10599               for(n=0;n<data.length;n++){
10600                  c = this._XOR(slf._crc_table[(this._XOR(c,data.charCodeAt(n))&0xff)>>>0],(c>>>8));
10601               }
10602               return c;
10603           },
10604		   _XOR:function(a,b){
10605		       return (a^b)>>>0;
10606		   },
10607           _U32Int2Str:function(n){
10608                return String.fromCharCode((n>>>24)&0xFF)+String.fromCharCode((n>>>16)&0xFF)+String.fromCharCode((n>>>8)&0xFF)+String.fromCharCode(n>>>0&0xFF);
10609            },
10610           _init_crc_table:function(){
10611               var c=0;
10612               var n,k;
10613               slf._crc_table=[];
10614               for(n=0;n<256;n++){
10615                   c = n;
10616                   for(k=0;k<8;k++){
10617                      if(((c&1)>>>0)>0){
10618                          c = slf._XOR(0xedb88320 , (c>>>1));
10619                      } else {
10620                          c = c>>>1;
10621                      }
10622                   }
10623                   slf._crc_table[n]=c;
10624                }
10625           },
10626           _CRC:function(data){
10627                if(!this._crc_table) this._init_crc_table();
10628                return this._XOR(this._update_crc(0xffffffff,data) , 0xffffffff);
10629          },
10630          _prepareTextChunk:function(content,pad){
10631              // pad the data appropriately                      
10632               var len = content.length;
10633               var lenStr = slf._U32Int2Str(len);
10634               var chunkType="tEXt";
10635               var checkSumStr = slf._U32Int2Str(slf._CRC(chunkType+content));
10636               return lenStr+chunkType+content+checkSumStr;
10637           },
10638        _start:function(str){
10639           slf._startTime = new Date().getTime();
10640           slf._startFun=str;
10641        },
10642        _end:function(){
10643           var str = "Time "+slf._startFun+": "+(new Date().getTime()-slf._startTime);
10644          //  $('BODY').append("<p>"+str+"</p><br/>");
10645        },
10646        _readU32Int:function(ctx){
10647            var val=0;
10648            var d=ctx.d;
10649            val=((d.charCodeAt(ctx.p++)<<24)|(d.charCodeAt(ctx.p++)<<16)|(d.charCodeAt(ctx.p++)<<8)|(d.charCodeAt(ctx.p++)))>>>0;
10650             return val;
10651        },
10652       _readChunkType:function(ctx){
10653          var d = ctx.d;
10654          var str = d[ctx.p++]+d[ctx.p++]+d[ctx.p++]+d[ctx.p++];
10655          return str;
10656       },
10657        _makeReadOnly:function(b64data){
10658      slf._start("_makeReadOnly");
10659      // assume a valid png image encoded in base64;
10660      var bindata = slf._atob(b64data.replace(/\s+/g, '')); // remove white spaces that might have been inserted
10661      var pngctx={p:0,d:bindata};
10662      pngctx.p+=8;// skip pngheader
10663      // read IHDR
10664      var size = slf._readU32Int(pngctx);
10665      slf._readChunkType(pngctx); //IHDR
10666      pngctx.p+=size; //Data
10667      slf._readU32Int(pngctx);//CRC
10668      var metadataChunk = slf._prepareTextChunk(slf._LC_Scribble_MetaDataKey+String.fromCharCode(0)+"true");
10669      var newdata = pngctx.d.substring(0,pngctx.p)+metadataChunk+pngctx.d.substring(pngctx.p);
10670      var ret= slf._btoa(newdata);
10671      slf._end();
10672      return ret;
10673   },
10674   _atob:function(inp){
10675      if(window.atob){ return atob(inp); }
10676	  return Base64.decode(inp);
10677   },
10678   _btoa:function(inp){
10679      if(window.btoa){ return btoa(inp); }
10680	  return Base64.encode(inp);
10681   },
10682   _isReadOnly:function(b64data){
10683    slf._start("_isReadOnly");
10684       if(slf._isPng(b64data)){
10685           var testStr = slf._LC_Scribble_MetaDataKey+String.fromCharCode(0)+"true";
10686           var bindata = slf._atob(b64data.replace(/\s+/g, ''));
10686 // strip white spaces
10687           var pngctx={p:0,d:bindata};
10688           pngctx.p+=8;// skip header
10689           while(pngctx.p<pngctx.d.length){
10690               var size = slf._readU32Int(pngctx);
10691               var type = slf._readChunkType(pngctx);
10692               if(type=="tEXt"){
10693                   if(pngctx.d.indexOf(testStr,pngctx.p)==pngctx.p){
10694                       slf._end();
10695                       return true;
10696                   }
10697                  
10698              }
10699              pngctx.p+=size;
10700              slf._readU32Int(pngctx);// 
10701          }// while end
10702       }
10703       slf._end();
10704       return false;
10705   }
10706    };
10707    return slf;
10708})();
10709
10710/**
10711 * JQuery widget definition starts here
10712 */
10713$.widget( "xfaWidget.ScribbleImageField", $.xfaWidget.imageField, {
10714
10715    _widgetName:"ScribbleImageField",
10716    _geoLocQuery:null,
10717   _emptyImageVal:null,// should be null, but for now
10718   _extraInfo:null,
10719   _defaultStatus:"&nbsp;",
10720   _enforceGeoLoc:!!navigator.userAgent.match(/iPad/i),
10721   _sigCanvasWidth:696,
10722   _sigCanvasHeight:390,
10723   _geoCanvId:null,
10724    _geoLocAtBottom:false,
10725   _geoCanvasHeight:100,
10726   _geoCanvasWidth:696,
10727   
10728    _is_readonly:false,
10729	
10730    options: {
10731        tabIndex: 0,
10732        "role": "img"
10733    },
10734
10735    getOptionsMap: function() {
10736        var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getOptionsMap.apply(this,arguments);
10737        return $.extend({},parentOptionsMap,{
10738            "displayValue": function(val) {
10739                if(this.options.commitProperty) {
10740                    if(!val){
10741                        this._displayValue(this._extractData(this._createEmptyImageData()));
10742                        this.$userControl.addClass("emptyScribble");
10743                        this._is_readonly=false;
10744                    } else {
10745                        this.$userControl.removeClass("emptyScribble");
10746                        if(PNGUtil._isPng(val)){
10747                            var widgetValue = "data:image/png;base64,"+this.options.value;
10748                        }else {
10749                            var widgetValue = "data:;base64," + this.options.value;
10750                        }
10751                        this._setValue(widgetValue);
10752                    }
10753                }
10754            }
10755        })
10756    },
10757
10758    getEventMap: function() {
10759        var parentOptionsMap = $.xfaWidget.defaultWidget.prototype.getEventMap.apply(this,arguments);
10760        return $.extend({},parentOptionsMap,{
10761            "scribblefocus":xfalib.ut.XfaUtil.prototype.XFA_ENTER_EVENT,
10762            "click":null,
10763            "scribbleclick":xfalib.ut.XfaUtil.prototype.XFA_CLICK_EVENT,
10764            "change":null,
10765            "scribblechange":xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT,
10766            "blur":null,
10767            "scribbleclose":xfalib.ut.XfaUtil.prototype.XFA_EXIT_EVENT
10768        })
10769    },
10770
10771	/**
10772	 * This function achieves following
10773	 * 1. Calculate dimensions of canvases to be used
10774	 * 2. Findout if right or bottom canvas is to be used for geo location
10775	 */
10776
10777	 aspectRatioToBeUsed :function(){
10778        var aspectRatio ;
10779        if(this.options.aspectRatio && parseFloat(this.options.aspectRatio) > 0){
10780           aspectRatio = 1/parseFloat(this.options.aspectRatio);  //--in MF ratio is computed as height/width instead of width/height
10781        } else {
10782           var imgEl = this.element.children("img"),
10783               width = imgEl.attr('width'),
10784               height = imgEl.attr('height'),
10785               fieldWidth,
10786               fieldHeight;
10787
10788           if(width){
10789              fieldWidth = parseInt(width,10);
10790           } else {
10791              fieldWidth = imgEl.width();
10792           }
10793           if(height){
10794              fieldHeight = parseInt(height,10);
10795           } else {
10796              fieldHeight = imgEl.height();
10797           }
10798           aspectRatio = fieldHeight/fieldWidth;
10799        }
10800	    return aspectRatio;
10801	 },
10802
10803    _setUpCanvas:function(){
10804        var aspectRatio ;
10805		aspectRatio = this.aspectRatioToBeUsed();
10806       
10807        // max width, height of generated image
10808        var maxWidth = 640;
10809        var maxHeight = 480;
10810        
10811        // width of field scaled to fit max image size
10812        var scaledWidth;
10813        var scaledHeight;
10814        
10815        
10816		// approx pixels required for rendering geo loc info in 12pt Arial font 
10817		var approxGeoLocWidth=250;
10818		var approxGeoLocHeight=84;
10819        
10820        scaledWidth = maxWidth;
10821        scaledHeight = maxWidth*aspectRatio;
10822        if(scaledHeight>maxHeight){
10823            scaledHeight = maxHeight;
10824            scaledWidth = maxHeight/aspectRatio;
10825        }
10826        
10827        // set canvas dimensions
10828        if(aspectRatio>=1){
10829			this._geoCanvId='iEBox_geoCanvasBottom';
10830            this._geoLocAtBottom=true;
10831          
10832			
10833             this._geoCanvasWidth = scaledWidth;
10834			 // limit height to 30% of full height;
10835			 this._geoCanvasHeight=Math.min(approxGeoLocHeight,scaledHeight/3);
10836             this._sigCanvasWidth = scaledWidth;
10837             this._sigCanvasHeight= scaledHeight-(this._enforceGeoLoc?this._geoCanvasHeight:0);
10838        } else {
10839			this._geoCanvId='iEBox_geoCanvasRight';
10840            this._geoLocAtBottom=false;
10841           
10842			
10843            this._geoCanvasHeight = scaledHeight;
10844			// limit width to 30% of full width;
10845			this._geoCanvasWidth=Math.min(approxGeoLocWidth,scaledWidth/3);
10846            this._sigCanvasHeight= scaledHeight;
10847            this._sigCanvasWidth= scaledWidth-(this._enforceGeoLoc?this._geoCanvasWidth:0);
10848        }
10849       
10850    },
10851
10852   render : function() {
10853       var geoLocMandatoryOnIpad = this.options.geoLocMandatoryOnIpad;
10854       if(typeof(geoLocMandatoryOnIpad)!="undefined"){
10855           this._enforceGeoLoc= this._enforceGeoLoc && (/^(true|1)$/i).test($.trim(geoLocMandatoryOnIpad));
10856       }
10857       this._wgtId="wid"+~~(Math.random()*2000)+"_"+new Date().getTime();
10858
10859       var $control = $.xfaWidget.defaultWidget.prototype.render.apply(this, arguments)
10860
10861       if(this.options.value || this.options.value != this._emptyImageVal){
10862          this._is_readonly=!!PNGUtil._isReadOnly(this.options.value);
10863       }
10864   
10865       var clearSignatureLabel = ScribbleUtil.localeString("clearSignature");
10866       var $clearButton = $("<div></div>")
10867           .attr("id", this._wgtId)
10868           .attr("tabindex", "0")
10869           .attr("role", "button")
10870           .attr("aria-label", clearSignatureLabel)
10871           .attr("title", clearSignatureLabel)
10872           .addClass("sc_popUpMenu");
10873       $control.after($clearButton);
10874       $control.attr("aria-label", this._is_readonly ? clearSignatureLabel : ScribbleUtil.localeString("pleaseSignText"));
10875	   
10876	   this._setUpCanvas();
10877       return $control;
10878    },
10879
10880   click: function() {
10881        this.focus();
10882        var tmpEl = this.element.length?this.element[0]:this.element;
10883        if(this.options.access != "open")
10884          return;
10885       if (TouchUtil.POINTER_ENABLED || TouchUtil.TOUCH_ENABLED) {
10886           // simulate a click event
10887           tmpEl.dispatchEvent(TouchUtil.getPointerEvent(TouchUtil.POINTER_DOWN));
10888           tmpEl.dispatchEvent(TouchUtil.getPointerEvent(TouchUtil.POINTER_UP));
10889        }
10890        else {
10891              this.$userControl.triggerHandler("click");
10892        }
10893   },
10894
10895    _attachEventHandlers:function($control){
10896	     if(TouchUtil.POINTER_ENABLED || TouchUtil.TOUCH_ENABLED){
10897            this._attachTouchEventHandlers($control);
10898         } else {
10899            this._attachMouseEventHandlers($control);
10900         }
10901         $control.keydown($.proxy(this._handleKeyDown,this));
10902    },
10903	_attachEventHandlerForCrossIcon:function($control){
10904	    var _that = this;
10905	    if(_that._is_readonly){
10906	        $('#'+_that._wgtId).css({display:'block'});
10907	    }
10908           setTimeout(function(){
10909               var $icon = $("#"+_that._wgtId);
10910               $icon.click($.proxy(_that._onCrossClick,_that));
10911               $icon.keydown(function(event){
10912                   if(event.keyCode === ENTER_KEY || event.which === ENTER_KEY || event.keyCode === 32 || event.which === 32){
10913                       event.preventDefault();
10914                       _that._onCrossClick(event);
10915                   }
10916               });
10917           },50);
10918	},
10919    _attachTouchEventHandlers:function($control){
10920        var _timer,_that=this;
10921        var tmpEl = this.element.length?this.element[0]:this.element;
10922       tmpEl.addEventListener(TouchUtil.POINTER_DOWN,function(event){
10923           if(_that.options.access != "open")
10924              return;
10925             event.preventDefault();
10926           _timer = setTimeout(function(){
10927                _timer=0;
10928               _that._onCrossClick(event);
10929            },1000);
10930        });
10931       tmpEl.addEventListener(TouchUtil.POINTER_UP,function(event){
10932            if(_that.options.access != "open")
10933                return;
10934            event.preventDefault();
10935            if(_timer){
10936               clearTimeout(_timer);
10937               _that._onImageClick(event);
10938            } 
10939        });
10940		
10941	   if(TouchUtil.POINTER_ENABLED){
10942		     this._attachEventHandlerForCrossIcon($control);
10943			 setTimeout(function(){ $("#"+_that._wgtId).on(TouchUtil.POINTER_UP,function(event){
10944			        event.stopPropagation();
10945			 });},50);
10946	   }
10947    },
10948
10949    _attachMouseEventHandlers:function($control){
10950         var _timer=0,_that=this,_hoverTimer=0;
10951        $control.dblclick(function(event){
10952            if(_that.options.access != "open")
10953                return;
10954           event.preventDefault();event.stopPropagation();
10955           if(_timer.val){
10956             clearTimeout(_timer);_timer =0;
10957           }
10958           _that._onCrossClick(event);
10959        }).click(function(event){
10960           _that.$userControl.trigger("scribbleclick",event);
10961           if(_that.options.access != "open")
10962                return;
10963           event.preventDefault();
10964           event.stopPropagation();
10965           if(_timer){
10966              clearTimeout(_timer);_timer=0;
10967            } else {
10968              _timer = setTimeout(function(){
10969                 _timer=0;
10970                 _that._onImageClick(event);
10971              },500);
10972            }
10973       });
10974	   
10975	   this._attachEventHandlerForCrossIcon($control);
10976       
10977    },
10978
10979    _onCrossClick:function(event){
10980        if(!this._is_readonly) return;
10981        this.$userControl.trigger("scribblefocus",event);
10982        this.$userControl.trigger("scribbleclick",event);
10983        event.stopPropagation();
10984        $.alertBox.yesNo(null,
10985         this.localeStrings().clearSignatureConfirm,
10986         this.localeStrings().clearSignature,
10987         $.proxy(this._removeSigConfirmationHandler,this));
10988     },
10989
10990     _removeSigConfirmationHandler:function(isYes){
10991        if(isYes){
10992           this._saveValue(this._emptyImageVal);
10993           this._displayValue(this._extractData(this._createEmptyImageData()));
10994           this.$userControl.addClass("emptyScribble").trigger("scribbleclose",{});
10995           this._is_readonly=false;
10996           $('#'+this._wgtId).css({display:'none'});
10997           this.$userControl.attr("aria-label", ScribbleUtil.localeString("pleaseSignText"));
10998           // CrossIcon is now hidden so MsgBox's _previousFocus restore lands on a display:none element.
10999           // Explicitly move focus to the scribble field so keyboard users can continue.
11000           this.$userControl.focus();
11001        }
11002     },
11003
11004    _createEmptyImageData:function(){
11005         if(!this._emptyImageData){
11006            var emptyCanvasObj = document.createElement('canvas');
11007            emptyCanvasObj.style.width=this._sigCanvasWidth+'px';
11008            emptyCanvasObj.style.height=this._sigCanvasHeight+'px';
11009            emptyCanvasObj.width=this._sigCanvasWidth;
11010            emptyCanvasObj.height=this._sigCanvasHeight;
11011            var ctx = emptyCanvasObj.getContext('2d');
11012            ctx.fillStyle='#ffffff';
11013            ctx.clearRect(0,0,this._sigCanvasWidth,this._sigCanvasHeight);
11014            this._emptyImageData = emptyCanvasObj.toDataURL("image/png");
11015         }
11016         return this._emptyImageData;
11017     },
11018
11019    getCommitValue: function() {
11020        return this.options.value
11021    },
11022
11023    _saveValue:function(val){
11024        this.options.value=val;
11025        this.$userControl.trigger('scribblechange');
11026    },
11027
11028    _displayValue:function(val){
11029        if(this.options.commitProperty) {
11030            //hardcode the widget VALUE by unknown image type
11031            if(val){
11032              var widgetValue = "data:image/png;base64,"+val;
11033                this._setValue(widgetValue);
11034            }
11035        }
11036        else
11037            this.logger().debug("xfaView","[DefaultWidget._update], User Control or Commit Property is null" );
11038    },
11039
11040    _doOk:function(){
11041        var mainCanvas = document.createElement('CANVAS');
11042        var geoCnv = $('#'+this._geoCanvId)[0];
11043        var sigCnv = $('#iEBox_canvas')[0];
11044        var ctx = mainCanvas.getContext('2d');
11045       
11046        if(geoCnv.width>0&&geoCnv.height>0){
11047            
11048            if(this._geoLocAtBottom){
11049                mainCanvas.width=sigCnv.width;
11050                mainCanvas.height =sigCnv.height+geoCnv.height;
11051                ctx.drawImage(sigCnv,0,0);
11052                ctx.drawImage(geoCnv,0,sigCnv.height);
11053            } else {
11054                mainCanvas.width=sigCnv.width+geoCnv.width;
11055                mainCanvas.height =sigCnv.height;
11056                ctx.drawImage(sigCnv,0,0);
11057                ctx.drawImage(geoCnv,sigCnv.width,0);
11058            }
11059        } else {
11060             mainCanvas.width=sigCnv.width;
11061             mainCanvas.height =sigCnv.height;
11062             ctx.drawImage(sigCnv,0,0);
11063        }
11064        imageEditDialog.hide();
11065        var newdata = mainCanvas.toDataURL("image/png");//(this.myScribbleHandle||"").toString();
11066        
11067         var val,val1;
11068         if((val=/*=*/this._extractData(newdata))){
11069         //  val1 = PNGUtil._makeReadOnly(val);
11070            val = PNGUtil._makeReadOnly(val);
11071            this._saveValue(val);
11072            this._is_readonly=true;
11073            $('#'+this._wgtId).css({display:'block'});
11074            this.$userControl.attr("aria-label", ScribbleUtil.localeString("clearSignature"));
11075          }
11076          this.$userControl.focus();
11077          this._geoLocQuery&&this._geoLocQuery.cancel();// cancel current geo loc request;
11078        this.$userControl.trigger("scribbleclose")
11079    },
11080    _handleOk:function(){
11081        if(this._enforceGeoLoc){
11082           this._geoLocQuery = new GeoLocQuery().init($.proxy(function(data){
11083               this._geoQuerySuccessHandler(data);
11084               this._doOk();
11085           },this),$.proxy(this._geoQueryErrorHandler,this));
11086           this._geoLocQuery.query();
11087           this._showMessage(this.localeStrings().fetchGeoLocation);
11088        } else {
11089          this._doOk();
11090        }
11091    },
11092
11093    _handleCancel:function(){
11094         imageEditDialog.hide();
11095         this.$userControl.focus();
11096         this._geoLocQuery&&this._geoLocQuery.cancel();// cancel current geo loc request;
11097        this.$userControl.trigger("scribbleclose")
11098    },
11099
11100    _handleClear:function(){
11101        this.myScribbleHandle.setEnabled(true);
11102        this._is_readonly=false;
11103        this._makeReadOnly(this._is_readonly);
11104        $('#iEBox_canvas')[0].width=this._sigCanvasWidth;
11105         $('#iEBox_caption').width(this._sigCanvasWidth);
11106		$('#iEBox_canvas')[0].height=this._sigCanvasHeight;
11107        $('#keyboard_Sign_Box')[0].value="";
11108        var geoCanv = $('#'+this._geoCanvId)[0];
11109        imageEditDialog.enableButtons({Ok:false,Clear:false});
11110        geoCanv.width=0;
11111        geoCanv.height=0;
11112        imageEditDialog._resize();
11113        this._geoLocQuery&&this._geoLocQuery.cancel();// cancel current geo loc request;
11114    },
11115    _makeReadOnly:function(readonly){
11116       imageEditDialog.enableButtons({Ok:false,Clear:false,Geo:!readonly,Brush:!readonly,Text:!readonly});
11117       if(readonly){
11118		   $('#iEBox_canvas').css({border:'1px solid gray'});
11119           $('#iEBox_caption').css({display:'none'});
11120
11121       }
11122       this._defaultStatus = "&nbsp;";
11123       this._showMessage(this._defaultStatus);
11124    },
11125
11126    _showMessage:function(msg){
11127        var _that = this;
11128        if(this._msgTimeout) { clearTimeout(this._msgTimeout); this._msgTimeout=0; }
11129         $("#iEBox_title").replaceWith('<div id="iEBox_title">'+msg+'</div>');
11130         this._msgTimeout = window.setTimeout(function(){
11131             $("#iEBox_title").replaceWith('<div id="iEBox_title">'+_that._defaultStatus+'</div>');
11132         },15000);
11133    },
11134
11135    _geoQueryErrorHandler:function(err){
11136        this._showMessage(this.localeStrings().errorFetchGeoLocation);
11137    },
11138
11139	_getLogMessage:function(key){
11140		     return this.logMsgs()[key]||key;
11141	},
11142
11143    _handleGeo:function(){
11144          // initiate geolocation 
11145       if(navigator.geolocation){
11146           this._geoLocQuery = new GeoLocQuery().init($.proxy(this._geoQuerySuccessHandler,this),$.proxy(this._geoQueryErrorHandler,this));
11147           this._geoLocQuery.query();
11148           this._showMessage(this.localeStrings().fetchGeoLocation);
11149       } else {
11150           this.logger().debug("xfaView",this._getLogMessage("ALC-FRM-901-011"));
11151       }
11152    },
11153
11154    // This Function is used to fetch the geolocation.
11155    calculateGeolocation: function(){
11156      this._handleGeo();
11157    },
11158
11159    _handleText:function(){
11160        var signBoxEl=document.getElementById("keyboard_Sign_Box");
11161        var signCanvasEl=document.getElementById("iEBox_canvas");
11162        if(signBoxEl.value.length==0){
11163            this._handleClear();
11164        }
11165        this._disableSignatureCanvas();
11166        this._enableSignatureTextBox();
11167        signBoxEl.focus();
11168    },
11169
11170    _disableSignatureTextBox:function(){
11171        document.getElementById("keyboard_Sign_Box").style.display = "none";
11172    },
11173
11174    _enableSignatureTextBox:function(){
11175        document.getElementById("keyboard_Sign_Box").style.display = "inline-block";
11176    },
11177
11178    _disableSignatureCanvas:function(){
11179        document.getElementById("iEBox_canvas").style.display = "none";
11180    },
11181
11182    _enableSignatureCanvas:function(){
11183        document.getElementById("iEBox_canvas").style.display = "inline-block";
11184    },
11185
11186    _handleBrushSelect:function(w){
11187        if(this.myScribbleHandle&&!this._is_readonly) {
11188            this.myScribbleHandle.setLineWidth(w);
11189        }
11190    },
11191
11192    _handleBrush:function(evt){
11193        if($('#keyboard_Sign_Box')[0].value.length>0){
11194            this._handleClear();
11195        }
11196        this._disableSignatureTextBox();
11197        this._enableSignatureCanvas();
11198        imageEditDialog.toggleBrushList(evt);
11199    },
11200	_handleKeyDown:function(event){
11201		if(event.keyCode == ENTER_KEY || event.charCode == ENTER_KEY || event.which == ENTER_KEY) { // touch devices may return charCode
11202		    event.preventDefault();
11203		    this._onImageClick(event);
11204		} else if(event.keyCode == DELETE_KEY || event.charCode == DELETE_KEY || event.which == DELETE_KEY) {
11205		    this._onCrossClick(event);
11206		}
11207    },
11208    _dialogCallback:function(button_val,arg1){
11209           // add back on click handler
11210         //  this.$userControl.click($.proxy(this._onImageClick, this));
11211                     
11212           switch(button_val){
11213               case "Ok":
11214               this._handleOk();
11215               break;
11216               case "Cancel":
11217               this._handleCancel();
11218               break;
11219               case "Clear":
11220               this._handleClear();
11221               break;
11222               case "Geo":
11223               this.calculateGeolocation();
11224               break;
11225               case "BrushSelect":
11226               this._handleBrushSelect(arg1);
11227               break;
11228               case "Brush":
11229               this._handleBrush(arg1);
11230               break;
11231               case "Text":
11232               this._handleText();
11233               break;
11234              
11235           }
11236    },
11237
11238    _geoQuerySuccessHandler:function(data){
11239        this._renderPosition(data);
11240    },
11241
11242	_fitGeoLocText:function(latStr,longStr,timeStr,ctx,maxWidth,maxHeight){
11243	    var fontSize=12;
11244		ctx.font="bold "+fontSize+"pt Arial";
11245		var width = Math.max(ctx.measureText(latStr).width,ctx.measureText(longStr).width,ctx.measureText(timeStr).width);
11246		var lineHeight = ctx.measureText("m").width*1.5;
11247		while((width>maxWidth||3*lineHeight>maxHeight)&&fontSize>1){
11248		    fontSize--;
11249		    ctx.font="bold "+fontSize+"pt Arial";
11250		    width = Math.max(ctx.measureText(latStr).width,ctx.measureText(longStr).width,ctx.measureText(timeStr).width);
11251		    lineHeight = ctx.measureText("m").width*1.5;
11252		}
11253		return {width:width,lineHeight:lineHeight,fontSize:fontSize};
11254	},
11255
11256    _renderPosition:function(position){
11257        if(position&&position.coords){
11258         this._showMessage("&nbsp;");
11259            var latStr = this.localeStrings().latitude+": " + position.coords.latitude;
11260            var longStr = this.localeStrings().longitude+": " + position.coords.longitude;
11261            var dateObj = new Date();
11262            var tZone = (dateObj.getTimezoneOffset()/60*-1);
11263            
11264            var timeStr = this.localeStrings().time+": "+(dateObj.getMonth()+1)+"/"+dateObj.getDate()+"/"+dateObj.getFullYear()+" "+dateObj.getHours()+":"+dateObj.getMinutes()+":"+dateObj.getSeconds()+((tZone>0)?" +":" ")+(tZone);
11265            var canvasObj  = $('#'+this._geoCanvId)[0];
11266			var sigCanvas = $('#iEBox_canvas')[0];
11267            var sigTextBox = $('#keyboard_Sign_Box')[0];
11268			var dummyCanvas = document.createElement('canvas');
11269            if(canvasObj){
11270			   var ctx = canvasObj.getContext('2d');
11271			   ctx.font="bold 12pt Arial";
11272
11273			   canvasObj.width=this._geoCanvasWidth;
11274               canvasObj.height=this._geoCanvasHeight;
11275			   var layout = this._fitGeoLocText(latStr,longStr,timeStr,ctx,canvasObj.width,canvasObj.height);
11276               var aspectRatio ;
11277     		   aspectRatio = this.aspectRatioToBeUsed();
11278			   if(!this._enforceGeoLoc){
11279			       if(this._geoLocAtBottom){
11280                     dummyCanvas.height = this._sigCanvasHeight-canvasObj.height;
11281                     dummyCanvas.width = dummyCanvas.height/aspectRatio;
11282                   } else {
11283                     dummyCanvas.width = this._sigCanvasWidth-canvasObj.width;
11284					 dummyCanvas.height = dummyCanvas.width*aspectRatio;
11285				   }
11286				   // move drawn signature to a temporary canvas and scale it to new dimension
11287                   dummyCanvas.getContext('2d').drawImage(sigCanvas,0,0,dummyCanvas.width,dummyCanvas.height);
11288                   if(this._geoLocAtBottom){
11289                     sigCanvas.height = dummyCanvas.height;
11290                     sigTextBox.height = dummyCanvas.height;
11291                     sigCanvas.getContext('2d').drawImage(dummyCanvas,(sigCanvas.width-dummyCanvas.width)/2,0);
11292                   } else {
11293                     sigCanvas.width = dummyCanvas.width;
11294                     sigTextBox.width = dummyCanvas.width;
11295                     sigCanvas.getContext('2d').drawImage(dummyCanvas,0,(sigCanvas.height-dummyCanvas.height)/2);
11296                   }
11297                   $('#iEBox_caption').width(sigCanvas.width);
11298				   imageEditDialog.enableButtons({Clear:true});
11299			   }
11300			      
11301			   var fwidth = layout.width;
11302               var fheight = layout.lineHeight;
11303			   var bottomMargin=2;
11304               ctx.fillStyle='#555555';
11305               ctx.font="bold "+layout.fontSize+"pt Arial";
11306               ctx.fillText(latStr,0,canvasObj.height-2*fheight-bottomMargin);
11307               ctx.fillText(longStr,0,canvasObj.height-fheight-bottomMargin);
11308               ctx.fillText(timeStr,0,canvasObj.height-bottomMargin);
11309			   
11310			   imageEditDialog._resize();
11311            }
11312        }
11313    },
11314    _scribbleCallback:function(){
11315       imageEditDialog.enableButtons({Clear:true,Ok:true});  //  enable clear and ok buttons
11316    },
11317    _onImageClick:function(){
11318       if(!imageEditDialog.getIsOpen()){
11319           var _that = this;
11320           imageEditDialog.show("&nbsp;",$.proxy(this._dialogCallback, this));
11321           if(!this._enforceGeoLoc){
11322               $('#iEBox_Geo').css({display:'inline-block'});
11323           }
11324           var image = new Image();
11325           image.onload=function(){
11326               _that.myScribbleHandle = new Scribble("iEBox_canvas",image,image.width,image.height,$.proxy(_that._scribbleCallback,_that));
11327               _that.myScribbleHandle.setEnabled(!_that._is_readonly);
11328               $('#iEBox_caption').width(image.width);
11329               $('#iEBox_container').css({display:'table'});
11330               if($('#iEBox_container').length == 1){
11331                   $('#iEBox_container')[0].focus();
11332               }
11333               imageEditDialog._resize();
11334               imageEditDialog._reposition();      // recalculate position, so that the values are updated, esp. in iPad
11335           }
11336           if(!this.options.value||this.options.value==this._emptyImageVal){
11337               this._is_readonly=false;
11338               this.$userControl.addClass("emptyScribble");
11339               image.src = this._createEmptyImageData();
11340           } else {
11341               this.$userControl.removeClass("emptyScribble");
11342               if(PNGUtil._isPng(this.options.value)){
11343                   this._is_readonly = !!PNGUtil._isReadOnly(this.options.value);
11344			       image.src = "data:image/png;base64,"+this.options.value;//this.createBl _that.$userControl.attr(_that.options.commitProperty);
11345               } else {
11346                   image.src = "data:;base64," + this.options.value;//this.createBl _that.$userControl.attr(_that.options.commitProperty);
11347		       }
11348           }
11349           this._makeReadOnly(this._is_readonly);
11350       }
11351    },
11352
11353    _extractData:function(datauri){
11354        var idx;
11355        if(datauri!=null&&datauri.length>0&&datauri.indexOf("data:")==0){
11356            if((idx=datauri.indexOf(","))>0){
11357                return datauri.substr(idx+1);
11358            }
11359        }
11360    },
11361
11362    _setValue:function(val){
11363        this.$userControl.prop(this.options.commitProperty, val);
11364        this.$userControl.attr(this.options.commitProperty, val);
11365        if(this._dummyImg){
11366            this._dummyImg.setAttribute(this.options.commitProperty,val);
11367        }
11368    }
11369});
11370 //hack for IOS5 touch bug
11371  $(function(){
11372         $('body').on('touchstart', function(e) {});
11373  });
11374  
11375})($,xfalib);
11376(function ($, window, _) {
11377
11378    var _defaults = {
11379        placeHolderText : "Enter comments here"
11380    };
11381
11382    var AdobeFileAttachment = function (element, options) {
11383        this.options = options;
11384        this.$elementFileUploadBtn = [];
11385        this.$elementFileList = [];
11386        this.$element = $(element);
11387        if (this.$element.attr("multiple") && !xfalib.ut.Utilities._isDataContainerSupported()) {
11388            // remove multiple attribute if multi file selection in one go is not supported
11389            this.$element.removeAttr("multiple");
11390        }
11391        this.$parent = this.$element.parent();
11392        this.invalidFeature = {
11393            "SIZE":1,
11394            "NAME":2,
11395            "MIMETYPE":3
11396        };
11397        Object.freeze(this.invalidFeature);
11398        // initialize the regex initially
11399        this.regexMimeTypeList  = this.options.mimeType.map(function (value, i) {
11400            try {
11401                return new RegExp(value.trim());
11402            } catch (e) {
11403                // failure during regex parsing, don't return anything specific to this value since the value contains
11404                // incorrect regex string
11405                if(window.console) {
11406                    console.log(e);
11407                }
11408            }
11409        });
11410    };
11411
11412    var isBrowserIE9OrIE10 = ($.browser.msie && ($.browser.version === '9.0' || $.browser.version === '10.0')),
11413        fileLabelsCount = 0;
11414
11415
11416    AdobeFileAttachment.prototype = {
11417        _fileIframeName : "guide-fu-iframe",
11418        _addFile : "Add File",
11419
11420        clear: function () {
11421            this.$element.val('');
11422            this.$elementFileList.empty();
11423        },
11424
11425        destroy: function () {
11426            this.$fileDomElements = $.map(this.$fileDomElements, function(item){
11427                // since item can be null or object, doing this check
11428                if(_.isObject(item) && item.val().length === 0) {
11429                    //TODO: remove item from dom, since there is a memory leak
11430                    return item;
11431                }
11432            });
11433            this.values = [];
11434            if(isBrowserIE9OrIE10){
11435                if(_.last(this.$fileDomElements) == null){
11436                    this.cloneFileInputAndUpdateIdForIE9();
11437                } else {
11438                    this.updateLabelForAttr(_.last(this.$fileDomElements).attr("id"));
11439                }
11440            }
11441            this.$element.trigger("change.fileupload");
11442        },
11443
11444        _setUrl : function(url, index){
11445            this.$elementFileList.find("span.guide-fu-fileName").eq(index).data("key", url);
11446        },
11447
11448        _getUrl : function(index) {
11449            return this.$elementFileList.find("span.guide-fu-fileName").eq(index).data("key");
11450        },
11451        getSetFilePathAndReturnNamePathMap: function(valueList) {
11452
11453            var mapOfObjectsHavingTempPathAndFileNames = {},
11454                $temp,
11455                tempPath;
11456
11457            $.each(this.$elementFileList.children(), function ( index, childLiElement) {
11458                $temp = $(childLiElement).find("span.guide-fu-fileName");
11459                tempPath = $temp.data("key");
11460                if(!tempPath && valueList && valueList[index]) {
11461                    $temp.data("key", valueList[index]);
11462                }
11463                mapOfObjectsHavingTempPathAndFileNames[$temp.html()] = tempPath || $temp.data("key");
11464            });
11465            return mapOfObjectsHavingTempPathAndFileNames;
11466        },
11467
11468
11469        value : function(value) {
11470            if(!_.isUndefined(value)) {
11471                var _self = this,
11472                    comments = this.comment(),
11473                    isChange = false,
11474                    fileNames = _.isArray(this.options.fileNames) ? this.options.fileNames : null,
11475                    oldUrls = {};
11476                // Cache the url before deletion
11477                this.$elementFileList.children().find("span.guide-fu-fileName").each(function(){
11478                    var url = $(this).data("key");
11479                    if(!_.isUndefined(url)){
11480                        var fileName = url.substring(url.lastIndexOf("/") + 1);
11481                        oldUrls[fileName] = url;
11482                    }
11483                });
11484                this.$elementFileList.empty();
11485                if(value != null) {
11486                    var arr = value.split("\n");
11487                    // contruct initial file name and value map
11488                    // this is done only once in entire live cycle, its done here, since we get value here
11489                    if (fileNames && _.isEmpty(this._initialFileValueFileNameMap)) {
11490                        for (var index = 0; index < fileNames.length; index++) {
11491                            _self._initialFileValueFileNameMap[arr[index]] = fileNames[index]
11492                        }
11493                    }
11494                    // Update the value array with the file
11495                    this.values = _.map(arr, function(fileName, index){
11496                        // Check if file Name is a path, if yes get the last part after "/"
11497                        var slash = fileName.lastIndexOf("/"),
11498                            fileUrl = fileName,
11499                            fileUploadUrl = null;
11500                        if(slash !== -1) {
11501                            // Store the cached url here
11502                            fileUrl = fileUploadUrl = fileName;
11503                            fileName = fileName.substring(slash + 1);
11504                            // case: when you click on save second time
11505                            if((_.isObject(_self.$fileDomElements[index]) && _self.$fileDomElements[index].val().length > 0) || _.isString(_self.$fileDomElements[index])){
11506                                isChange = true;
11507                                _self.$fileDomElements[index] = null;
11508                            } else if(_self.$fileDomElements[index] !== null) { // create a dummy file dom for the cached value
11509                                 isChange = true;
11510                                _self.$fileDomElements.splice(index, 0, null);
11511                            }
11512                        } else if (oldUrls[fileName]) {
11513                            fileUploadUrl = oldUrls[fileName];
11514                        }
11515                        // if fileNames options is explicitly passed, use it
11516                        if (fileNames && _self._initialFileValueFileNameMap[fileUrl]) {
11517                            fileName = _self._initialFileValueFileNameMap[fileUrl];
11518                        }
11519                        _self.showFileList(fileName, comments[index], fileUploadUrl);
11520                        return fileUrl;
11521                    });
11522                    if(isChange){
11523                        this.$element.trigger("change.fileupload");
11524                    }
11525                } else {
11526                    if(_.isArray(this.values) && this.values.length !== 0){
11527                        this.destroy();
11528                    }
11529                }
11530            }
11531            else {
11532                return this.values;
11533            }
11534        },
11535
11536        fileAttachment: function(){
11537            return this.values;
11538        },
11539
11540        comment : function(value){
11541            var _self = this,
11542                $elem = null,
11543                comments;
11544            if (!_.isUndefined(value)) {
11545                if(value != null) {
11546                    comments = value.split("\n");
11547                    $elem = this.$elementFileList.find('div.guide-fu-comment');
11548                    $elem.each(function(index){
11549                        $(this).text(comments[index]);
11550                    });
11551                }
11552            }
11553            else {
11554                $elem = this.$elementFileList.find('div.guide-fu-comment');
11555                comments = [];
11556                $elem.each(function(){
11557                    comments.push($(this).text());
11558                });
11559                return comments;
11560            }
11561        },
11562
11563        multiSelect : function(value){
11564            if(value !== undefined)
11565                this.options.multiSelect = value;
11566            else
11567                return this.options.multiSelect;
11568        },
11569
11570        fileSizeLimit : function(value){
11571            if(value !== undefined)
11572                this.options.fileSizeLimit = value;
11573            else
11574                return this.options.fileSizeLimit;
11575        },
11576
11577        mimeType : function(value){
11578            if(value !== undefined)
11579                this.options.mimeType = value;
11580            else
11581                return this.options.mimeType;
11582        },
11583
11584        access : function(value){
11585            if(value == "readOnly") {
11586                this.$element.attr("disabled", "disabled");
11587                //for readOnly hide the delete icon in file list
11588                $(this.$parent).addClass('guide-fu-disabled');
11589            }
11590            else if(value == "open") {
11591                this.$element.removeAttr("disabled");
11592                $(this.$parent).removeClass('guide-fu-disabled');
11593            }
11594        },
11595
11596        fileList : function(value) {
11597            var filtered,
11598                _self = this;
11599            if(value !== undefined){
11600                this.$fileDomElements = [];
11601                _.each(value, function(item, index){
11602                    if((_.isObject(item) && (isBrowserIE9OrIE10 || item.val().length > 0)) || (_.isString(item))){
11603                         // check if index is within the length
11604                         // this is written for delete case
11605                         // if item is a string, then it should be set null
11606                         if(_.isString(item)){
11607                             item = null;
11608                         }
11609                         _self.$fileDomElements[index] = item;
11610                    }
11611                });
11612                filtered = this.$fileDomElements;
11613                // In case of IE9, get the last element of fileDom and update the id for label
11614                if(isBrowserIE9OrIE10 && value !== null){
11615                    // Case: if it is single select, and then we do a restore and then after attaching another file we click save
11616                    if(_.last(this.$fileDomElements) == null){
11617                        this.cloneFileInputAndUpdateIdForIE9();
11618                    } else {
11619                        this.updateLabelForAttr(_.last(this.$fileDomElements).attr("id"));
11620                    }
11621                }
11622            }
11623            else {
11624                // here filtered is a new array
11625                // A new array is returned over here so that the user of this API doesn't try to change the widget array directly
11626                filtered = $.map(this.$fileDomElements, function(item, index){
11627                    if(!item) {
11628                        return _self._getUrl(index);
11629                    } else if((item[0].files && item[0].files.length !== 0)
11630                            || (_self.options.multiSelect || item[0].value.length > 0)) {
11631                        return item;
11632                    }
11633                });
11634            }
11635            return filtered;
11636        },
11637
11638        // file preview html
11639        fileItemPreview: function(){
11640            return $("<span></span>").addClass("guide-fu-filePreview glyphicon glyphicon-ok");
11641        },
11642
11643        // force flag indicates that forcefully set the dom but don't update the options
11644        buttonText: function (value, force) {
11645            if (value !== undefined) {
11646                if(!force)
11647                    this.options.buttonText = value;
11648                this.$elementFileUploadBtn.find('span.guide-fu-label').html(value);
11649            } else {
11650                return this.options.buttonText;
11651            }
11652        },
11653
11654        // To change the icon of the button, the user should customize the class
11655        btnIcon: function () {
11656            return $("<span></span>").addClass("guide-fu-icon glyphicon glyphicon-folder-open");
11657        },
11658
11659        btnLabel: function(){
11660            return $("<span></span>").addClass("guide-fu-label").html(this.options.buttonText);
11661        },
11662
11663        fileItemList: function(){
11664            return this.$parent.find(this.options.fileItemListClass);
11665        },
11666
11667        getNewCommentElementSummary : function(text){
11668            return $("<div title='Click to edit' tabindex='0'></p>").addClass("guide-fu-comment").text(text || _defaults.placeHolderText);
11669        },
11670
11671        getNewCommentElement : function(text){
11672            return $("<div contenteditable='true' tabindex='0'></div>").addClass("guide-fu-comment").text(text || "");
11673        },
11674
11675        fileItem: function(fileName, comment, fileUrl){
11676            var $fileItem = $("<li></li>").addClass("guide-fu-fileItem");
11677            var nameWithoutMarker = xfalib.ut.Utilities._getNameWithoutMarker(fileName);
11678            var $elem = $("<span tabindex='0'></span>").addClass("guide-fu-fileName").attr("aria-label", nameWithoutMarker).text(nameWithoutMarker).appendTo($fileItem).keypress(function(e) {
11679                if (e.keyCode === 13 || e.charCode === 32) {
11680                    $(e.target).click();
11681                }
11682            }).click($.proxy(this.handleFilePreview, this));
11683            if(this.options.disablePreview) {
11684               $elem.addClass('non-preview-fileName');
11685            }
11686            if(fileUrl != null){
11687                $elem.attr("data-key", fileUrl);
11688            }
11689            $("<span tabindex='0'></span>").addClass("guide-fu-fileClose close").attr("role", "button").attr("aria-label", xfalib.locale.Strings.FileCloseAccessText 
11689+ nameWithoutMarker).text("x").appendTo($fileItem).keypress(function(e) {
11690                if (e.keyCode === 13 || e.charCode === 32) {
11691                    $(e.target).click();
11692                }
11693            })
11694                .click($.proxy(this.handleClick, this));
11695
11696            this.fileItemPreview().appendTo($fileItem);
11697
11698            if(this.options.showComment){
11699                this.getNewCommentElementSummary(comment).appendTo($fileItem).focus($.proxy(this.handleCommentClick, this)).click($.proxy(this.handleCommentClick, this));
11700            }
11701            return $fileItem;
11702        },
11703
11704        toggleFileUploadBtn: function(){
11705            if(this.options.multiSelect) {
11706                // Change the look of file upload button
11707                if(this.$elementFileList.children().length > 0){
11708                    // Change the text
11709                    this.buttonText(this._addFile, true);
11710                    // Change the icon too
11711                    this.$elementFileUploadBtn.find('span.guide-fu-icon').removeClass("glyphicon-folder-open").addClass("glyphicon-plus");
11712                } else {
11713                    this.buttonText(this.options.buttonText);
11714                    this.$elementFileUploadBtn.find('span.guide-fu-icon').removeClass("glyphicon-plus").addClass("glyphicon-folder-open");
11715                }
11716            }
11717        },
11718
11719        showInvalidMessage: function(fileName, invalidFeature){
11720            var that = this;
11721            var IS_IPAD = navigator.userAgent.match(/iPad/i) !== null,
11722                IS_IPHONE = (navigator.userAgent.match(/iPhone/i) !== null);
11723            if(IS_IPAD || IS_IPHONE){
11724                setTimeout(function() {
11725                  that.invalidMessage(that,fileName, invalidFeature);
11726                }, 0);
11727            }
11728            else {
11729               this.invalidMessage(this,fileName, invalidFeature);
11730            }
11731        },
11732
11733        invalidMessage: function(refObj,fileName, invalidFeature){
11734            if(invalidFeature === refObj.invalidFeature.SIZE) {
11735                alert(xfalib.ut.LocalizationUtil.prototype.getLocalizedMessage("", xfalib.locale.Strings["FileSizeGreater"], [fileName, refObj.options.fileSizeLimit]));
11736            } else if (invalidFeature === refObj.invalidFeature.NAME) {
11737                alert(xfalib.ut.LocalizationUtil.prototype.getLocalizedMessage("", xfalib.locale.Strings["FileNameInvalid"], [fileName]));
11738            } else if (invalidFeature === refObj.invalidFeature.MIMETYPE) {
11739                alert(xfalib.ut.LocalizationUtil.prototype.getLocalizedMessage("", xfalib.locale.Strings["FileMimeTypeInvalid"], [fileName]));
11740            }
11741        },
11742
11743        /***
11744         * Finds the value in the array, if the value is a url then it uses the filename in the url to search for the text
11745         * This is done since our model stores the URL too in case of draft restore or clicking on save in guide
11746         * @param text          string representing the text of which the index is to be found
11747         * @param $elem         reference to the jquery element. This is used if there are duplicate file names present in the file upload.
11748         * @returns {number}
11749         * @private
11750         */
11751        _getIndexOfText : function(text, $elem){
11752            var index = -1,
11753                self = this,
11754                isDuplicatePresent = false;
11755            _.find(this.values, function(value, iter){
11756                // if value is a url, then compare with last
11757                var tempValue = value,
11758                    // can't use getOrElse here since value can have "." in URL and getOrElse splits based on period to find key inside object
11759                    fileName =  (_.isObject(self._initialFileValueFileNameMap) && typeof self._initialFileValueFileNameMap[value] !== undefined) ? self._initialFileValueFileNameMap[value] : null;
11760                if(tempValue.match(/\//g) && tempValue.match(/\//g).length > 1){
11761                    tempValue =  value.substring(value.lastIndexOf("/")+1);
11762                    tempValue = xfalib.ut.Utilities._getNameWithoutMarker(tempValue);
11763                }
11764                // we pass file name explicityly as options, if passed use that as fallback to find the URL
11765                if(tempValue === text || fileName === text){
11766                    index = iter;
11767                    isDuplicatePresent = self.values.indexOf(value, index + 1) !== -1;
11768                    if($elem && isDuplicatePresent){
11769                        // now check if duplicate present and get its correct index
11770                        // today all files are wrapped under .guide-fu-fileItem node
11771                        index = $elem.closest(".guide-fu-fileItem").index();
11772                    }
11773                    // check if there is a duplicate
11774                    // this is to just break the loop
11775                    return value;
11776                }
11777            });
11778            return index;
11779        },
11780
11781
11782        /*
11783         * Since input file element might contain multiple files.
11784         * This function takes absolute file index as parameter & returns position of the file w.r.t input file elt
11785         */
11786        _getFileObjIdx : function (index) {
11787            if (index >= 0) {
11788                var currentIdx = 0;
11789                for (var fileInputEltIdx = 0; fileInputEltIdx < this.$fileDomElements.length; fileInputEltIdx++) {
11790                    if (this.$fileDomElements[fileInputEltIdx]) {
11791                        var files = this.$fileDomElements[fileInputEltIdx][0].files;
11792                        if (files) {
11793                            var filesLength =  files.length;
11794                            if ( index <= currentIdx + filesLength - 1 ) {
11795                                return [fileInputEltIdx, index - currentIdx];
11796                            }
11797                            currentIdx+=files.length;
11798                        }
11799                    } else {
11800                        if (index == currentIdx) {
11801                            return [fileInputEltIdx,0];
11802                        }
11803                        currentIdx++;
11804                    }
11805                }
11806            }
11807            return null;
11808        },
11809
11810        /*
11811         * This function returns FileList object of the passed file array
11812         */
11813        _getFileListItem : function (files) {
11814            try {
11815                var dataContainer = new DataTransfer() || (new ClipboardEvent("")).clipboardData;
11816                _.each(files, function (file) {
11817                    dataContainer.items.add(file);
11818                });
11819                return dataContainer.files;
11820            } catch(err) {
11821                console.error(err);
11822                throw err;
11823            }
11824        },
11825
11826        _updateFilesInDom : function($fileDom, files) {
11827            // in safari, a change event is trigged if files property is changed dynamically
11828            // hence adding this check to clear existing state only for safari browsers
11829            this._isFileUpdate = true;
11830            $fileDom[0].files = this._getFileListItem(files);
11831            this._isFileUpdate = false;
11832        },
11833
11834        /*
11835         * This function deletes files at specified indexes from input dom elt
11836         */
11837        _deleteFilesFromInputDom : function ($fileDomElt, deletedIndexes) {
11838            var remainingFiles = [];
11839            _.each($fileDomElt[0].files, function(file,idx){
11840                if(!deletedIndexes.includes(idx)){
11841                    remainingFiles.push(file);
11842                }
11843            });
11844            try {
11845                // in safari, a change event is trigged if files property is changed dynamically
11846                // hence adding this check to clear existing state only for safari browsers
11847                this._updateFilesInDom($fileDomElt, remainingFiles);
11848            } catch(err){
11849                console.error("Deleting files is not supported in your browser");
11850            }
11851        },
11852
11853        /**
11854         * This event listener gets called on click of close button in file upload
11855         *
11856         * @param event
11857         */
11858        handleClick: function(event){
11859
11860            var $elem = $(event.target),
11861                text = $elem.prev().text(),
11862                index = this._getIndexOfText(text, $elem),
11863                url = $elem.prev().data("key"),
11864                objectUrl = $elem.prev().data("objectUrl");
11865            if (index != -1) {
11866                this.values.splice(index, 1);
11867                var fileObjIdx = this._getFileObjIdx(index);
11868                var $fileDomElt = this.$fileDomElements[fileObjIdx[0]];
11869                if (!$fileDomElt || $fileDomElt[0].files.length === 1) {
11870                    this.$fileDomElements.splice(fileObjIdx[0], 1);
11871                } else {
11872                    this._deleteFilesFromInputDom($fileDomElt, [fileObjIdx[1]]);
11873                }
11874                if (isBrowserIE9OrIE10) {
11875                    this.cloneFileInputAndUpdateIdForIE9();
11876                }
11877                if (url != null) {
11878                    // remove the data so that others don't use this url
11879                    $elem.prev().removeData("key");
11880                }
11881                if(objectUrl) {
11882                    // revoke the object URL to avoid memory leaks in browser
11883                    // since file is anyways getting deleted, remove the object URL's too
11884                    window.URL.revokeObjectURL(objectUrl);
11885                }
11886            }
11887            // Remove the dom from view
11888            //All bound events and jQuery data associated with the element are also removed
11889            $elem.parent().remove();
11890            // trigger the change event to update the value
11891            this.$element.trigger("change.fileupload");
11892            // Set the focus on file upload button after click of close
11893            this.$elementFileUploadBtn.focus();
11894
11895        },
11896
11897
11898        displaySVG: function (objectUrl) {
11899            const url = objectUrl;
11900            const img = window.document.createElement('img');
11901            img.src = url;
11902            const newTab = window.open('', '_blank', 'scrollbars=no,menubar=no,height=600,width=800,resizable=yes,toolbar=no,status=no');
11903            newTab.document.body.appendChild(img);
11904        },
11905
11906
11907        _previewFileUsingObjectUrl : function (file) {
11908            if (file) {
11909                if (window.navigator && window.navigator.msSaveOrOpenBlob) { // for IE
11910                    window.navigator.msSaveOrOpenBlob(file, file.name);
11911                } else {
11912                    var url = window.URL.createObjectURL(file);
11913                    if (file.type === 'image/svg+xml') {
11914                        this.displaySVG(url);
11915                    } else {
11916                        window.open(url, '', 'scrollbars=no,menubar=no,height=600,width=800,resizable=yes,toolbar=no,status=no');
11917                    }
11918                    return url;
11919                }
11920            }
11921        },
11922
11923        // this function maintains a map for
11924        handleFilePreview: function(event){
11925            if(!this.options.disablePreview) {
11926                var $elem = $(event.target),
11927                    text = $elem.text(),
11928                    index = this._getIndexOfText(text, $elem),
11929                    fileDom = null,
11930                    fileName = null,
11931                    fileUrl = null,
11932                    timeStamp = new Date().getTime();
11933
11934                // for draft usecase, if text contains "/" in it, it means the file is already uploaded
11935                // text should contain the path, assuming that the fileUrl is stored in data element
11936
11937                if (index != -1) {
11938                    // Store the url of file as data
11939                    if(!_.isUndefined($elem.data("key")))
11940                        fileUrl = $elem.data("key");
11941
11942                    if(fileUrl)  {
11943                        //prepend context path if not already appended
11944                        if (!(fileUrl.lastIndexOf(this.options._getUrl, 0) === 0)) {
11945                            fileUrl =  this.options._getUrl + fileUrl;
11946                        }
11947                        this.previewFile.apply(this, [null, {"fileUrl" : fileUrl}]);
11948                    } else {
11949                        var previewFileObjIdx = this._getFileObjIdx(index);
11950                        var previewFile = this.$fileDomElements[previewFileObjIdx[0]][0].files[previewFileObjIdx[1]];
11951                        var objectUrl = this._previewFileUsingObjectUrl(previewFile);
11952                        if (objectUrl) {
11953                            $elem.data("objectUrl", objectUrl);
11954                        }
11955                    }
11956                }
11957            }
11958        },
11959
11960        previewFile: function(event){
11961            var url = null;
11962            if(_.isUndefined(arguments[1]))
11963                url = this.$element[this.options.uploaderPluginName]("getFileUrl");
11964            else
11965                url = arguments[1].fileUrl;
11966            var lastIndex = url.lastIndexOf('/');
11967            //to make sure url has a slash '/'
11968            // added check for query param since sas url contains query params & does not have file name, encoding is not required in this case
11969            if(lastIndex >= 0 && url.indexOf('?') == -1) {
11970                //encode the filename after last slash to ensure the handling of special characters
11971                url = url.substr(0, lastIndex) +'/'+ encodeURIComponent(url.substr(lastIndex + 1));
11972            }
11973            // this would work for dataURl or normal URL
11974            // todo: add support to preview base 64 encoded image, to preview base64 encoded binary, we would probably need
11975            // todo: the content type in the widget too
11976            window.open(url, '', 'scrollbars=no,menubar=no,height=600,width=800,resizable=yes,toolbar=no,status=no');
11977
11978        },
11979
11980        resetIfNotMultiSelect: function(){
11981            if(!this.options.multiSelect){
11982                // Reset the value and file array
11983                this.values = [];
11984                //this.comments = [];
11985            }
11986        },
11987
11988        showFileList: function(fileName, comment, fileUrl){
11989            if(!this.options.multiSelect || fileName == null || _.isUndefined(fileName)) {
11990                // if not multiselect, remove all the children of file list
11991                this.$elementFileList.empty();
11992            }
11993
11994            // Add the file item
11995            // On click of close, remove the element and update the model
11996            // handle on click of preview button
11997            if(fileName != null) {
11998                this.$fileItem = this.$elementFileList.append(this.fileItem(fileName, comment, fileUrl));
11999            }
12000        },
12001
12002        /**
12003         * Handles the click on comment field
12004         *
12005         * TODO: Implement show/hide behaviour instead of replaceWith
12006         * This may be cause problem during bubble up of event
12007         *
12008         * @param event
12009         */
12010        handleCommentClick : function(event){
12011            var $commentElem = null,
12012                $elem = $(event.target);
12013            if ($elem.text() === _defaults.placeHolderText) {
12014                $commentElem = this.getNewCommentElement()
12015            } else {
12016                $commentElem = this.getNewCommentElement($(event.target).text());
12017            }
12018            $elem.replaceWith($commentElem);
12019            // register the event again
12020            if(isBrowserIE9OrIE10){
12021                $commentElem.focus().focusout($.proxy(this.handleCommentBlur, this));
12022            } else {
12023                $commentElem.focus().blur($.proxy(this.handleCommentBlur, this));
12024            }
12025        },
12026
12027        handleCommentBlur : function(event){
12028            var $commentSummaryElem = null,
12029                $elem = $(event.target);
12030            if ($elem.text() === _defaults.placeHolderText) {
12031                $commentSummaryElem = this.getNewCommentElementSummary();
12032            } else {
12033                $commentSummaryElem = this.getNewCommentElementSummary($(event.target).text());
12034            }
12035            $elem.replaceWith($commentSummaryElem);
12036            $commentSummaryElem.focus($.proxy(this.handleCommentClick,this)).click($.proxy(this.handleCommentClick,this));
12037            // Add a div with the html
12038            this.$element.trigger("change.fileupload");
12039        },
12040
12041        // checks if file name is valid or not to prevent security threats
12042        isValid : function(fname) {
12043            var rg1=/^[^\\/:\*\;\$\%\?"<>\|]+$/; // forbidden characters \ / : * ? " < > | ; % $
12044            var rg2=/^\./; // cannot start with dot (.)
12045            var rg3=/^(nul|prn|con|lpt[0-9]|com[0-9])(\.|$)/i; // forbidden file names
12046            return rg1.test(fname) && !rg2.test(fname) && !rg3.test(fname);
12047        },
12048
12049        handleChange: function (evnt) {
12050            if (!this._isFileUpdate) {
12051                var currFileName = '',
12052                    inValidSizefileNames = '',
12053                    inValidNamefileNames = '',
12054                    inValidMimeTypefileNames = '',
12055                    $elem = $(evnt.target),
12056                    files = $elem[0].files;
12057                // Initially set the invalid flag to false
12058
12059                // if not multiselect then remove the extra domELement clone
12060                if (!this.options.multiSelect && this.$fileDomElements.length > 1) {
12061                    this.$fileDomElements.splice(0, 1)
12062                }
12063
12064                var isInvalidSize = false,
12065                    isInvalidFileName = false,
12066                    isInvalidMimeType = false;
12067                this.resetIfNotMultiSelect();
12068                // Iterate through all the files
12069                if (isBrowserIE9OrIE10) { // IE9 doesn't support FileList, hence files variable is undefined
12070                    currFileName = $elem.val().split("\\").pop();
12071                    //update the last element of array
12072                    if (this.$fileDomElements.length > 0) {
12073                        this.$fileDomElements[this.$fileDomElements.length - 1] = $elem;
12074                    }
12075                    this.cloneFileInputAndUpdateIdForIE9();
12076
12077                    // In case of IE9, only do this
12078                    if (_.isUndefined(files)) {
12079                        this.showFileList(currFileName);
12080                        this.values.push(currFileName);
12081                        // trigger the change event to update the value
12082                        this.$element.trigger("change.fileupload");
12083                    }
12084                }
12085                if (!_.isUndefined(files)) {
12086                    var invalidFilesIndexes = [];
12087                    _.each(files, function (file, fileIndex) {
12088                        var isCurrentInvalidFileSize = false,
12089                            isCurrentInvalidFileName = false,
12090                            isCurrentInvalidMimeType = false;
12091                        currFileName = file.name.split("\\").pop();
12092                        // Now size is in MB
12093                        var size = file.size / 1024 / 1024;
12094                        // check if file size limit is within limits
12095                        if ((size > parseFloat(this.options.fileSizeLimit))) {
12096                            isInvalidSize = isCurrentInvalidFileSize = true;
12097                            inValidSizefileNames = currFileName + "," + inValidSizefileNames;
12098                        } else if (!this.isValid(currFileName)) {
12099                            // check if file names are valid (ie) there are no control characters in file names
12100                            isInvalidFileName = isCurrentInvalidFileName = true;
12101                            inValidNamefileNames = currFileName + "," + inValidNamefileNames;
12102                        }  else if (file.type) {
12103                            var isMatch = this.regexMimeTypeList.some(function (rx) {
12104                                return rx.test(file.type);
12105                            });
12106                            if (!isMatch) {
12107                                isInvalidMimeType = isCurrentInvalidMimeType = true;
12108                                inValidMimeTypefileNames = currFileName + "," + inValidMimeTypefileNames;
12109                            }
12110                        } else {
12111                            var checkEmptyFileTypeFT = FD.isToggleEnabled("FT_FORMS-24171");
12112                            if (checkEmptyFileTypeFT) {
12113                                isInvalidMimeType = isCurrentInvalidMimeType = true;
12114                                inValidMimeTypefileNames = currFileName + "," + inValidMimeTypefileNames;
12115                            }
12116                        }
12117
12118                        // if the file is not invalid, show it and push it to internal array
12119                        if (!isCurrentInvalidFileSize && !isCurrentInvalidFileName && !isCurrentInvalidMimeType) {
12120                            this.showFileList(currFileName);
12121                            this.values.push(currFileName);
12122                        } else {
12123                            invalidFilesIndexes.push(fileIndex);
12124                        }
12125
12126
12127                    }, this);
12128
12129                    if (invalidFilesIndexes.length > 0) {
12130                        var currentFileDomIndex,
12131                            $currentFileDomElement,
12132                            filesCount;
12133                        if (this.$fileDomElements.length > 0) {
12134                            currentFileDomIndex = this.$fileDomElements.length - 1;
12135                            $currentFileDomElement = this.$fileDomElements[currentFileDomIndex];
12136                            if ($currentFileDomElement && $currentFileDomElement.length > 0) {
12137                                filesCount = $currentFileDomElement[0].files.length;
12138                                //if all the files are invalid remove the input element as well otherwise only remove the invalid files.
12139                                if (filesCount === invalidFilesIndexes.length) {
12140                                    this.$fileDomElements.splice(-1, 1);
12141                                } else {
12142                                    this._deleteFilesFromInputDom($currentFileDomElement, invalidFilesIndexes);
12143                                }
12144                            }
12145                        }
12146
12147                        // in case of IE10, create one extra element
12148                        if (isBrowserIE9OrIE10) {
12149                            this.cloneFileInputAndUpdateIdForIE9();
12150                        }
12151                    }
12152
12153                    // trigger the change event to update the value
12154                    this.$element.trigger("change.fileupload");
12155                }
12156
12157                if (isInvalidSize) {
12158                    this.showInvalidMessage(inValidSizefileNames.substring(0, inValidSizefileNames.lastIndexOf(',')), this.invalidFeature.SIZE);
12159                } else if (isInvalidFileName) {
12160                    this.showInvalidMessage(inValidNamefileNames.substring(0, inValidNamefileNames.lastIndexOf(',')), this.invalidFeature.NAME);
12161                } else if (isInvalidMimeType) {
12162                    this.showInvalidMessage(inValidMimeTypefileNames.substring(0, inValidMimeTypefileNames.lastIndexOf(',')), this.invalidFeature.MIMETYPE);
12163                }
12164            }
12165        },
12166
12167        cloneFileInputAndUpdateIdForIE9 : function(){
12168            var elem = _.last(this.$fileDomElements),
12169                elemExists = elem != null,
12170                elemHasValue = elemExists && elem.val().length > 0,
12171                elemId = null,
12172                selector = null;
12173
12174            // CQ-4237903 : create clone to handle the case when user clicks cancel in chrome and for multiselect
12175            // on clicking cancel in chrome file browser, chrome removes all the files from the input element
12176            // remove the extra clone in $fileDomElement on handleChange
12177            if(!elemExists || elemHasValue) {
12178                elem = this.$element.clone();
12179                // copy the data attributes
12180                elem.data(this.$element.data());
12181                if(isBrowserIE9OrIE10){
12182                    elemId = this.$element.attr("id") + (++fileLabelsCount);
12183                    elem.attr("id", elemId);
12184                    elem.css({
12185                        'position' : 'absolute',
12186                        'top' : '-2000px',
12187                        'left': '-2000px'
12188                    });
12189                    elem.appendTo('body');
12190                    this.updateLabelForAttr(elemId);
12191                }
12192                elem.change($.proxy(this.handleChange, this));
12193                this.$fileDomElements.push(elem);
12194            }
12195            // Case: if it is not multiselect and if the first file dom element is null
12196            // this case would hit when we restore a single select file attachment and attach a new file
12197            if(!this.options.multiSelect && this.$fileDomElements[0] === null){
12198                //Splice null out of it, since we are attaching a new file
12199                this.$fileDomElements.splice(0, 1);
12200            }
12201            // if the browser is not IE9, then click it
12202            if(!isBrowserIE9OrIE10) {
12203                elem.click();
12204            }
12205            return true;
12206        },
12207
12208        /**
12209         * In case of IE9, get the last element of fileDom and update the id for label
12210         *
12211         * @param fileInputId
12212         */
12213        updateLabelForAttr : function(fileInputId){
12214            this.$label.attr("for" , fileInputId);
12215        },
12216
12217        createLabelForFileInput : function (fileInputId){
12218            if(isBrowserIE9OrIE10) {
12219                this.$label = $("<label></label>").addClass("guide-fu-attach-button button")
12220                        .text(this.options.buttonText)
12221                        .attr('for',fileInputId);
12222                this.$elementFileUploadBtn.replaceWith(this.$label);
12223                this.$label.parent().attr("tabindex", 0).attr("role", "button").attr("aria-label", this.options.screenReaderText || "");
12224            }
12225        },
12226
12227
12228        constructor: function () {
12229            // Initialize the self instance
12230            var _self = this,
12231                isFirst = true;
12232            //jquery instance of file upload button
12233            this.$elementFileUploadBtn = this.$parent.find(this.options.buttonClass);
12234            this.$elementFileUploadBtn.attr("aria-label", this.options.screenReaderText || "");
12235            if(isBrowserIE9OrIE10){
12236                this.elementId = this.$element.attr("id");
12237                this.createLabelForFileInput(this.$element.attr("id"));
12238            }
12239
12240            // html for file list
12241            this.$elementFileList = $(this.fileItemList());
12242            // Initialize the value and file(Refer FileList class mdn)
12243            this.values = [];
12244            this._initialFileValueFileNameMap = {};
12245            // List of dom elements of input type file
12246            this.$fileDomElements = [];
12247
12248            var flag = false,
12249                $currElem = null;
12250
12251            $(document).mousedown(function(e) {
12252                $currElem = $(e.target);
12253            });
12254            // Enter key should result in click of button
12255            this.$elementFileUploadBtn
12256                .focus(function(){
12257                    _self.$element.trigger("focus.fileupload");
12258                })
12259                .click($.proxy(this.cloneFileInputAndUpdateIdForIE9, this))
12260                .blur(function(event){
12261                    // Check if the currElem does not belong to the fileItemList
12262                    if(!flag && $currElem!= null && $currElem.closest(".guide-fu-fileItemList").length <=0){
12263                        _self.$element.trigger("focusout.fileupload");
12264                    }
12265                    flag = false;
12266                });
12267            //Initialize the filePreview Plugin
12268            this.$element[this.options.uploaderPluginName]({
12269                iframeContainer: this.options.iframeContainer,
12270                _filePath: this.options._filePath,
12271                _uuidGenerator: this.options._uuidGenerator,
12272                _getUrl: this.options._getUrl
12273
12274            });
12275            // Getting input file value
12276            // listening on fileuploaded event
12277            this.$element.change($.proxy(this.handleChange, this))
12278                .on("adobeFileUploader.fileUploaded", $.proxy(this.previewFile, this));
12279        }
12280    };
12281
12282    $.fn.adobeFileAttachment = function (option, value) {
12283        var get = '',
12284            element = this.each(function () {
12285                // in case of input type file
12286                if ($(this).attr('type') === 'file') {
12287                    var $this = $(this),
12288                        data = $this.data('adobeFileAttachment'),
12289                        options = $.extend({}, AdobeFileAttachment.prototype.defaults, typeof option === 'object' && option);
12290
12291                    // Save the adobeFileAttachment data in jquery
12292                    if (!data) {
12293                        $this.data('adobeFileAttachment', (data = new AdobeFileAttachment(this, options)));
12294                        data.constructor();
12295                    }
12296
12297                    // code to get and set an option
12298                    if (typeof option === 'string') {
12299                        get = data[option](value);
12300                    }
12301                }
12302            });
12303
12304        if (typeof get !== 'undefined') {
12305            return get;
12306        } else {
12307            return element;
12308        }
12309    };
12310
12311    // fileSizeLimit is in MB, default value is 2MB
12312    AdobeFileAttachment.prototype.defaults = {
12313        'buttonText': 'Attach',
12314        'multiSelect': false,
12315        'fileSizeLimit': 2,
12316        'uploaderPluginName': "adobeFileUploader",
12317        'mimeType' : ['audio/*', 'video/*', 'image/*', 'text/*', 'application/pdf']
12318    };
12319
12320})($, window, window._);(function($, _) {
12321    var xfaUtil = xfalib.ut.XfaUtil.prototype;
12322    $.widget( "xfaWidget.fileUpload", $.xfaWidget.abstractWidget, {
12323
12324        _widgetName:"fileUpload",
12325        _superPrototype : $.xfaWidget.abstractWidget.prototype,
12326        getOptionsMap: function(){
12327            var parentOptionsMap = this._superPrototype.getOptionsMap.apply(this,arguments),
12328                newMap = $.extend({},parentOptionsMap, $.extend({}, this.options, {
12329                    "value" : function(value) {
12330                        this.$userControl.adobeFileAttachment("value", value);
12331                    },
12332                    "fileList": function(value){
12333                        this.$userControl.adobeFileAttachment("fileList", value);
12334                    },
12335                    "comment" : function(value){
12336                        this.$userControl.adobeFileAttachment("comment", value);
12337                    },
12338                    // "access" can be either open or readonly
12339                    "access" : function(value){
12340                        this.$userControl.adobeFileAttachment("access", value);
12341                    }
12342
12343                }));
12344
12345            return newMap;
12346
12347        },
12348        // TODO: Will need to remove this functions
12349        //  will be tracked by LC-391200
12350
12351        _initializeOptions: function () {
12352            _.each(this.optionsHandler, function (value, key) {
12353                // overriding the behaviour of _initializeOptions
12354                // only for _uuidGenerator
12355                // as we font want getUUID to be called at render time
12356                if (typeof value === "function" && key !== '_uuidGenerator' ) {
12357                        value.apply(this, [this.options[key]])
12358                }
12359            }, this)
12360        },
12361
12362        _getFileList: function(){
12363            return this.$userControl.adobeFileAttachment("fileList");
12364        },
12365
12366        _getComment: function(){
12367            return this.$userControl.adobeFileAttachment("comment");
12368        },
12369        _getFileNamePathMap: function (pathList) {
12370            return this.$userControl.adobeFileAttachment("getSetFilePathAndReturnNamePathMap", pathList);
12371        },
12372        getEventMap: function() {
12373            var parentEventMap = this._superPrototype.getEventMap.apply(this, arguments),
12374                newMap = $.extend({}, parentEventMap,
12375                    {
12376                        "change" : null,
12377                        "focusout.fileupload" : xfaUtil.XFA_EXIT_EVENT,
12378                        "focus.fileupload" : xfaUtil.XFA_ENTER_EVENT,
12379                        "change.fileupload" : xfaUtil.XFA_CHANGE_EVENT
12380                    });
12381            return newMap;
12382        },
12383        render: function() {
12384            var $el = this._superPrototype.render.apply(this,arguments);
12385            $el.adobeFileAttachment(this.getOptionsMap());
12386            return $el;
12387        },
12388        showDisplayValue: function() {
12389             //since value can't be set in file element input, leav
12389ing this fn empty
12390        },
12391        showValue: function() {
12392            //since value can't be set in file element input, leaving this fn empty
12393        },
12394        getCommitValue: function() {
12395            this.options.fileList = this._getFileList();
12396            this.options.comment = this._getComment();
12397            return this.$userControl.adobeFileAttachment("value");
12398        }
12399    });
12400})($, window._);
12401
12402/**
12403 * Adobe FilePreview Widget Plugin
12404 *
12405 * Options expected by file preview is the url
12406 *
12407 * Options Required Are:
12408 *
12409 *  iframeName: Name of the Iframe
12410 *  iframeContainer: Container of the iframe(eg Body)
12411 *  fileUploadPath: Path where the file is to be uploaded
12412 *  fileUploadServlet: Servlet where the file is to be uploaded
12413 *
12414 */
12415(function ($, _) {
12416
12417    var AdobeFileUploader = function (element, options) {
12418        this.options = options;
12419        this.$element = $(element);
12420    };
12421
12422    AdobeFileUploader.prototype = {
12423
12424        _fileIframeName: "guide-fu-iframe",
12425
12426        _filePath: "/tmp/fd/mf",
12427
12428        _iframeContainer: "body#formBody",
12429
12430
12431        fileIframe: function (name) {
12432            return $("<iframe></iframe>").attr({
12433                style: "display:none",
12434                name: name
12435            });
12436        },
12437
12438        uploadFile: function (fileObject) {
12439            var multiple = false,
12440                fileName = null,
12441                actionUrl = null,
12442                fileUploadPath = fileObject.fileUploadPath,
12443                uuid;
12444
12445            if (!fileUploadPath) {
12446                uuid = fileObject._uuidGenerator();
12447            }
12448
12449            // if uuid exists only then upload the file in the current  instance
12450            if (_.isObject(fileObject) && (fileUploadPath || uuid)) {
12451                var fileDom = fileObject.fileDom,
12452                    $form = $(this.options.iframeContainer).find(".filePreview");
12453                fileName = fileObject.fileName;
12454                multiple = fileObject.multiple;
12455                if(!fileUploadPath) {
12456                    fileUploadPath = this.options.fileUploadPath + "/" + uuid;
12457                }
12458                if (fileDom !== null) {
12459                    //prepend contextpath
12460                    actionUrl = fileObject._getUrl + fileUploadPath;
12461                    if (!multiple) {
12462                        if (!(fileUploadPath.lastIndexOf(fileObject._getUrl, 0) === 0)) {
12463                            this.fileUrl = fileObject._getUrl + fileUploadPath + "/" + fileName;
12464                        } else {
12465                            this.fileUrl = fileUploadPath + "/" + fileName;
12466                        }
12467                    } else {
12468                        this.fileUrl = actionUrl;
12469                    }
12470                    // done to solve issue LC-5835
12471                    if($form.length === 0) {
12472                        $form = $("<form method='post' enctype='multipart/form-data'></form>")
12473                            .addClass("filePreview")
12474                            // create id so that it does not intercept with other forms in the page
12475                            .attr({
12476                                id : "form" + new Date().valueOf(),
12477                                action : actionUrl,
12478                                target : this.options.iframeName
12479                            })
12480                            .appendTo(this.options.iframeContainer);
12481                    } else {
12482                        /// first empty all children, using detach so that data is not clear
12483                        $form.children().detach();
12484                        // now update the new attributes
12485                        $form.attr({
12486                            action : actionUrl,
12487                            target : this.options.iframeName
12488                        });
12489                    }
12490                    // this is done so that the other events attached at some other level in DOM Tree don't interfere
12491                    $form.one("submit", function(evnt){
12492                        evnt.stopPropagation();
12493                    });
12494
12495                     var data = new FormData();
12496
12497                    if (multiple) {
12498                        _.each(fileDom, function (fileDomElement, index) {
12499                            // OOTB, this code is still used in dashboard
12500                            if(fileDomElement !== null && !_.isString(fileDomElement)) {
12501                                $(fileDomElement[0]).attr('name', fileName[index]).appendTo($form);
12502                                // fileDomElement might contain multiple files so all the files needs to be added to formdata.
12503                                var currentFileNames = fileName[index].split("\n");
12504                                for(var fileIndex = 0; fileIndex < currentFileNames.length; fileIndex++) {
12505                                    data.append(currentFileNames[fileIndex], fileDomElement[0].files[fileIndex]);
12506                                }
12507                            }
12508                        }, this);
12509                    } else {
12510                        fileDom.attr('name', fileName).appendTo($form);
12511                        data.append(fileName, fileDom[0].files[0]);
12512                    }
12513
12514                    /* UseCase: Suppose the fileName is in other language, on click of fileName, it tries to upload the file
12515                     so that it could be preview, this change would ensure that the file is properly previewed supp
12515orting
12516                     the given UTF-8 charset */
12517                    $("<input type='hidden' name='_charset_' value='UTF-8'/>").appendTo($form);
12518                    data.append("_charset_", "UTF-8");
12519                    if (!multiple) {
12520                        this.fileMap[this.fileUrl] = this.$element;
12521                    }
12522                    var self = this;
12523                    $.ajax({
12524                        url: $form.attr("action"),
12525                        data: data,
12526                        cache: false,
12527                        contentType: false,
12528                        processData: false,
12529                        method: 'POST',
12530                        type: 'POST',
12531                        success: function(data){
12532                            if (!multiple) {
12533                                self.handleSingleFileUpload(data);
12534                            } else {
12535                                self.handleMultipleFileUpload(data);
12536                            }
12537                        },
12538                        error: function() {
12539                            this.$element.trigger("adobeFileUploader.fileUploadFailed");
12540                        }
12541                    });
12542                }
12543            }
12544            return this.fileUrl;
12545        },
12546
12547        handleMultipleFileUpload: function (data) {
12548            this.$element.trigger("adobeFileUploader.multipleFileUploaded");
12549        },
12550
12551        getFileUrl: function () {
12552            return this.fileUrl;
12553        },
12554
12555        getUrlContentsFromUploadData: function (data) {
12556            var temp;
12557            if(data != null) {
12558                temp = $(data).find("#ChangeLog").text().split("br", 2)[1];
12559            } else {
12560                var selector = this.options.iframeContainer + " iframe[name='" + this.options.iframeName + "']";
12561                temp = $(selector).contents().find("#ChangeLog").text().split("br", 2)[1];
12562            }
12563            
12564            temp = temp.substring(temp.indexOf("created") + 9, temp.indexOf(";<"));
12565            temp = temp.substring(0, temp.length - 2);
12566            var index = temp.indexOf("/jcr:content");
12567            if (index !== -1)
12568                temp = temp.substring(0, index);
12569            return temp;
12570        },
12571
12572        handleSingleFileUpload: function (data) {
12573            var url = this.getUrlContentsFromUploadData(data);
12574
12575            //prepend context path
12576            url = this.options._getUrl + url;
12577            if (url in this.fileMap) {
12578                this.fileMap[url].trigger("adobeFileUploader.fileUploaded");
12579            }
12580        },
12581
12582        initialize: function () {
12583            // Put iframe inside the iframe container
12584            // On the load of iframe, display the contents of file
12585            // since there is only one iframe for all the file attachments, there may be race condition
12586            if (this.$iframe == null || this.$iframe.length === 0) {
12587                this.$iframe = this.fileIframe(this.options.iframeName).appendTo(this.options.iframeContainer);
12588                // since there is only iframe for the preview of all file attachments
12589                // this map is added in the closure scope
12590                // map contains the url(key) vs fileDomElement(value)
12591                // it helps avoids the race condition
12592                this.fileMap = {};
12593            }
12594        }
12595    };
12596
12597    $.fn.adobeFileUploader = function (option, value) {
12598        var get = '',
12599            element = this.each(function () {
12600                // in case of input type file
12601                if ($(this).attr('type') === 'file') {
12602                    var $this = $(this),
12603                        data = $this.data('adobeFileUploader'),
12604                        options = $.extend({}, AdobeFileUploader.prototype.defaults(option, value), typeof option === 'object' && option);
12605
12606                    // Save the adobeFileAttachment data in jquery
12607                    if (!data) {
12608                        $this.data('adobeFileUploader', (data = new AdobeFileUploader(this, options)));
12609                        data.initialize();
12610                    } else {
12611                        // update elements if not equal, since sometimes one can clone too
12612                        if(data.$element.get(0) !== this) {
12613                            data.$element = $(this);
12614                        }
12615                    }
12616
12617                    // code to get and set an option
12618                    if (typeof option === 'string') {
12619                        get = data[option](value);
12620                    }
12621                }
12622            });
12623
12624        if (typeof get !== 'undefined') {
12625            return get;
12626        } else {
12627            return element;
12628        }
12629    };
12630
12631
12632    AdobeFileUploader.prototype.defaults = function (options,value)  {
12633        var propertyObject = {};
12634        if(typeof options == 'object') {
12635            propertyObject._fileIframeName = options._fileIframeName;
12636            propertyObject._filePath = options._filePath;
12637            propertyObject.actionUrl = options.actionUrl;
12638            propertyObject._getUrl = options._getUrl;
12639        }
12640        if(typeof  value == 'object') {
12641            propertyObject._fileIframeName = value._fileIframeName;
12642            propertyObject._filePath = value._filePath;
12643            propertyObject.actionUrl = value.actionUrl;
12644            propertyObject._getUrl = options._getUrl;
12645        }
12646        return {
12647            'fileUploadPath': propertyObject._filePath || AdobeFileUploader.prototype._filePath,
12648            'iframeName': AdobeFileUploader.prototype._fileIframeName + new Date().valueOf(),
12649            'fileUploadServlet': propertyObject._filePath || AdobeFileUploader.prototype._filePath,
vendor: 4,462 bytes, lines 12650-12803
12650            'iframeContainer': propertyObject._iframeContainer || AdobeFileUploader.prototype._iframeContainer,
12651            '_getUrl': propertyObject._getUrl || ""
12652        };
12653    };
12654
12655})($, window._);
12656
12657/*!
12658 * Bootstrap v3.4.1 (https://getbootstrap.com/)
12659 * Copyright 2011-2019 Twitter, Inc.
12660 * Licensed under the MIT license
12661 */
12662
12663if (typeof jQuery === 'undefined') {
12664  throw new Error('Bootstrap\'s JavaScript requires jQuery')
12665}
12666
12667+function ($) {
12668  'use strict';
12669  var version = $.fn.jquery.split(' ')[0].split('.')
12670  if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) {
12671    throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4')
12672  }
12673}(jQuery);
12674
12675/* ========================================================================
12676 * Bootstrap: transition.js v3.4.1
12677 * https://getbootstrap.com/docs/3.4/javascript/#transitions
12678 * ========================================================================
12679 * Copyright 2011-2019 Twitter, Inc.
12680 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
12681 * ======================================================================== */
12682
12683
12684+function ($) {
12685  'use strict';
12686
12687  // CSS TRANSITION SUPPORT (Shoutout: https://modernizr.com/)
12688  // ============================================================
12689
12690  function transitionEnd() {
12691    var el = document.createElement('bootstrap')
12692
12693    var transEndEventNames = {
12694      WebkitTransition : 'webkitTransitionEnd',
12695      MozTransition    : 'transitionend',
12696      OTransition      : 'oTransitionEnd otransitionend',
12697      transition       : 'transitionend'
12698    }
12699
12700    for (var name in transEndEventNames) {
12701      if (el.style[name] !== undefined) {
12702        return { end: transEndEventNames[name] }
12703      }
12704    }
12705
12706    return false // explicit for ie8 (  ._.)
12707  }
12708
12709  // https://blog.alexmaccaw.com/css-transitions
12710  $.fn.emulateTransitionEnd = function (duration) {
12711    var called = false
12712    var $el = this
12713    $(this).one('bsTransitionEnd', function () { called = true })
12714    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
12715    setTimeout(callback, duration)
12716    return this
12717  }
12718
12719  $(function () {
12720    $.support.transition = transitionEnd()
12721
12722    if (!$.support.transition) return
12723
12724    $.event.special.bsTransitionEnd = {
12725      bindType: $.support.transition.end,
12726      delegateType: $.support.transition.end,
12727      handle: function (e) {
12728        if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
12729      }
12730    }
12731  })
12732
12733}(jQuery);
12734
12735/* ========================================================================
12736 * Bootstrap: alert.js v3.4.1
12737 * https://getbootstrap.com/docs/3.4/javascript/#alerts
12738 * ========================================================================
12739 * Copyright 2011-2019 Twitter, Inc.
12740 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
12741 * ======================================================================== */
12742
12743
12744+function ($) {
12745  'use strict';
12746
12747  // ALERT CLASS DEFINITION
12748  // ======================
12749
12750  var dismiss = '[data-dismiss="alert"]'
12751  var Alert   = function (el) {
12752    $(el).on('click', dismiss, this.close)
12753  }
12754
12755  Alert.VERSION = '3.4.1'
12756
12757  Alert.TRANSITION_DURATION = 150
12758
12759  Alert.prototype.close = function (e) {
12760    var $this    = $(this)
12761    var selector = $this.attr('data-target')
12762
12763    if (!selector) {
12764      selector = $this.attr('href')
12765      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
12766    }
12767
12768    selector    = selector === '#' ? [] : selector
12769    var $parent = $(document).find(selector)
12770
12771    if (e) e.preventDefault()
12772
12773    if (!$parent.length) {
12774      $parent = $this.closest('.alert')
12775    }
12776
12777    $parent.trigger(e = $.Event('close.bs.alert'))
12778
12779    if (e.isDefaultPrevented()) return
12780
12781    $parent.removeClass('in')
12782
12783    function removeElement() {
12784      // detach from parent, fire event then clean up data
12785      $parent.detach().trigger('closed.bs.alert').remove()
12786    }
12787
12788    $.support.transition && $parent.hasClass('fade') ?
12789        $parent
12790            .one('bsTransitionEnd', removeElement)
12791            .emulateTransitionEnd(Alert.TRANSITION_DURATION) :
12792        removeElement()
12793  }
12794
12795
12796  // ALERT PLUGIN DEFINITION
12797  // =======================
12798
12799  function Plugin(option) {
12800    return this.each(function () {
12801      var $this = $(this)
12802      var data  = $this.data('bs.alert')
12803
vendor: 59,455 bytes, lines 12804-14790
12804      if (!data) $this.data('bs.alert', (data = new Alert(this)))
12805      if (typeof option == 'string') data[option].call($this)
12806    })
12807  }
12808
12809  var old = $.fn.alert
12810
12811  $.fn.alert             = Plugin
12812  $.fn.alert.Constructor = Alert
12813
12814
12815  // ALERT NO CONFLICT
12816  // =================
12817
12818  $.fn.alert.noConflict = function () {
12819    $.fn.alert = old
12820    return this
12821  }
12822
12823
12824  // ALERT DATA-API
12825  // ==============
12826
12827  $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)
12828
12829}(jQuery);
12830
12831/* ========================================================================
12832 * Bootstrap: button.js v3.4.1
12833 * https://getbootstrap.com/docs/3.4/javascript/#buttons
12834 * ========================================================================
12835 * Copyright 2011-2019 Twitter, Inc.
12836 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
12837 * ======================================================================== */
12838
12839
12840+function ($) {
12841  'use strict';
12842
12843  // BUTTON PUBLIC CLASS DEFINITION
12844  // ==============================
12845
12846  var Button = function (element, options) {
12847    this.$element  = $(element)
12848    this.options   = $.extend({}, Button.DEFAULTS, options)
12849    this.isLoading = false
12850  }
12851
12852  Button.VERSION  = '3.4.1'
12853
12854  Button.DEFAULTS = {
12855    loadingText: 'loading...'
12856  }
12857
12858  Button.prototype.setState = function (state) {
12859    var d    = 'disabled'
12860    var $el  = this.$element
12861    var val  = $el.is('input') ? 'val' : 'html'
12862    var data = $el.data()
12863
12864    state += 'Text'
12865
12866    if (data.resetText == null) $el.data('resetText', $el[val]())
12867
12868    // push to event loop to allow forms to submit
12869    setTimeout($.proxy(function () {
12870      $el[val](data[state] == null ? this.options[state] : data[state])
12871
12872      if (state == 'loadingText') {
12873        this.isLoading = true
12874        $el.addClass(d).attr(d, d).prop(d, true)
12875      } else if (this.isLoading) {
12876        this.isLoading = false
12877        $el.removeClass(d).removeAttr(d).prop(d, false)
12878      }
12879    }, this), 0)
12880  }
12881
12882  Button.prototype.toggle = function () {
12883    var changed = true
12884    var $parent = this.$element.closest('[data-toggle="buttons"]')
12885
12886    if ($parent.length) {
12887      var $input = this.$element.find('input')
12888      if ($input.prop('type') == 'radio') {
12889        if ($input.prop('checked')) changed = false
12890        $parent.find('.active').removeClass('active')
12891        this.$element.addClass('active')
12892      } else if ($input.prop('type') == 'checkbox') {
12893        if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false
12894        this.$element.toggleClass('active')
12895      }
12896      $input.prop('checked', this.$element.hasClass('active'))
12897      if (changed) $input.trigger('change')
12898    } else {
12899      this.$element.attr('aria-pressed', !this.$element.hasClass('active'))
12900      this.$element.toggleClass('active')
12901    }
12902  }
12903
12904
12905  // BUTTON PLUGIN DEFINITION
12906  // ========================
12907
12908  function Plugin(option) {
12909    return this.each(function () {
12910      var $this   = $(this)
12911      var data    = $this.data('bs.button')
12912      var options = typeof option == 'object' && option
12913
12914      if (!data) $this.data('bs.button', (data = new Button(this, options)))
12915
12916      if (option == 'toggle') data.toggle()
12917      else if (option) data.setState(option)
12918    })
12919  }
12920
12921  var old = $.fn.button
12922
12923  $.fn.button             = Plugin
12924  $.fn.button.Constructor = Button
12925
12926
12927  // BUTTON NO CONFLICT
12928  // ==================
12929
12930  $.fn.button.noConflict = function () {
12931    $.fn.button = old
12932    return this
12933  }
12934
12935
12936  // BUTTON DATA-API
12937  // ===============
12938
12939  $(document)
12940      .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
12941        var $btn = $(e.target).closest('.btn')
12942        Plugin.call($btn, 'toggle')
12943        if (!($(e.target).is('input[type="radio"], input[type="checkbox"]'))) {
12944          // Prevent double click on radios, and the double selections (so cancellation) on checkboxes
12945          e.preventDefault()
12946          // The target component still receive the focus
12947          if ($btn.is('input,button')) $btn.trigger('focus')
12948          else $btn.find('input:visible,button:visible').first().trigger('focus')
12949        }
12950      })
12951      .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) {
12952        $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type))
12953      })
12954
12955}(jQuery);
12956
12957/* ========================================================================
12958 * Bootstrap: carousel.js v3.4.1
12959 * https://getbootstrap.com/docs/3.4/javascript/#carousel
12960 * ========================================================================
12961 * Copyright 2011-2019 Twitter, Inc.
12962 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
12963 * ======================================================================== */
12964
12965
12966+function ($) {
12967  'use strict';
12968
12969  // CAROUSEL CLASS DEFINITION
12970  // =========================
12971
12972  var Carousel = function (element, options) {
12973    this.$element    = $(element)
12974    this.$indicators = this.$element.find('.carousel-indicators')
12975    this.options     = options
12976    this.paused      = null
12977    this.sliding     = null
12978    this.interval    = null
12979    this.$active     = null
12980    this.$items      = null
12981
12982    this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this))
12983
12984    this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element
12985        .on('mouseenter.bs.carousel', $.proxy(this.pause, this))
12986        .on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
12987  }
12988
12989  Carousel.VERSION  = '3.4.1'
12990
12991  Carousel.TRANSITION_DURATION = 600
12992
12993  Carousel.DEFAULTS = {
12994    interval: 5000,
12995    pause: 'hover',
12996    wrap: true,
12997    keyboard: true
12998  }
12999
13000  Carousel.prototype.keydown = function (e) {
13001    if (/input|textarea/i.test(e.target.tagName)) return
13002    switch (e.which) {
13003      case 37: this.prev(); break
13004      case 39: this.next(); break
13005      default: return
13006    }
13007
13008    e.preventDefault()
13009  }
13010
13011  Carousel.prototype.cycle = function (e) {
13012    e || (this.paused = false)
13013
13014    this.interval && clearInterval(this.interval)
13015
13016    this.options.interval
13017    && !this.paused
13018    && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
13019
13020    return this
13021  }
13022
13023  Carousel.prototype.getItemIndex = function (item) {
13024    this.$items = item.parent().children('.item')
13025    return this.$items.index(item || this.$active)
13026  }
13027
13028  Carousel.prototype.getItemForDirection = function (direction, active) {
13029    var activeIndex = this.getItemIndex(active)
13030    var willWrap = (direction == 'prev' && activeIndex === 0)
13031        || (direction == 'next' && activeIndex == (this.$items.length - 1))
13032    if (willWrap && !this.options.wrap) return active
13033    var delta = direction == 'prev' ? -1 : 1
13034    var itemIndex = (activeIndex + delta) % this.$items.length
13035    return this.$items.eq(itemIndex)
13036  }
13037
13038  Carousel.prototype.to = function (pos) {
13039    var that        = this
13040    var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active'))
13041
13042    if (pos > (this.$items.length - 1) || pos < 0) return
13043
13044    if (this.sliding)       return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid"
13045    if (activeIndex == pos) return this.pause().cycle()
13046
13047    return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos))
13048  }
13049
13050  Carousel.prototype.pause = function (e) {
13051    e || (this.paused = true)
13052
13053    if (this.$element.find('.next, .prev').length && $.support.transition) {
13054      this.$element.trigger($.support.transition.end)
13055      this.cycle(true)
13056    }
13057
13058    this.interval = clearInterval(this.interval)
13059
13060    return this
13061  }
13062
13063  Carousel.prototype.next = function () {
13064    if (this.sliding) return
13065    return this.slide('next')
13066  }
13067
13068  Carousel.prototype.prev = function () {
13069    if (this.sliding) return
13070    return this.slide('prev')
13071  }
13072
13073  Carousel.prototype.slide = function (type, next) {
13074    var $active   = this.$element.find('.item.active')
13075    var $next     = next || this.getItemForDirection(type, $active)
13076    var isCycling = this.interval
13077    var direction = type == 'next' ? 'left' : 'right'
13078    var that      = this
13079
13080    if ($next.hasClass('active')) return (this.sliding = false)
13081
13082    var relatedTarget = $next[0]
13083    var slideEvent = $.Event('slide.bs.carousel', {
13084      relatedTarget: relatedTarget,
13085      direction: direction
13086    })
13087    this.$element.trigger(slideEvent)
13088    if (slideEvent.isDefaultPrevented()) return
13089
13090    this.sliding = true
13091
13092    isCycling && this.pause()
13093
13094    if (this.$indicators.length) {
13095      this.$indicators.find('.active').removeClass('active')
13096      var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)])
13097      $nextIndicator && $nextIndicator.addClass('active')
13098    }
13099
13100    var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid"
13101    if ($.support.transition && this.$element.hasClass('slide')) {
13102      $next.addClass(type)
13103      if (typeof $next === 'object' && $next.length) {
13104        $next[0].offsetWidth // force reflow
13105      }
13106      $active.addClass(direction)
13107      $next.addClass(direction)
13108      $active
13109          .one('bsTransitionEnd', function () {
13110            $next.removeClass([type, direction].join(' ')).addClass('active')
13111            $active.removeClass(['active', direction].join(' '))
13112            that.sliding = false
13113            setTimeout(function () {
13114              that.$element.trigger(slidEvent)
13115            }, 0)
13116          })
13117          .emulateTransitionEnd(Carousel.TRANSITION_DURATION)
13118    } else {
13119      $active.removeClass('active')
13120      $next.addClass('active')
13121      this.sliding = false
13122      this.$element.trigger(slidEvent)
13123    }
13124
13125    isCycling && this.cycle()
13126
13127    return this
13128  }
13129
13130
13131  // CAROUSEL PLUGIN DEFINITION
13132  // ==========================
13133
13134  function Plugin(option) {
13135    return this.each(function () {
13136      var $this   = $(this)
13137      var data    = $this.data('bs.carousel')
13138      var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)
13139      var action  = typeof option == 'string' ? option : options.slide
13140
13141      if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))
13142      if (typeof option == 'number') data.to(option)
13143      else if (action) data[action]()
13144      else if (options.interval) data.pause().cycle()
13145    })
13146  }
13147
13148  var old = $.fn.carousel
13149
13150  $.fn.carousel             = Plugin
13151  $.fn.carousel.Constructor = Carousel
13152
13153
13154  // CAROUSEL NO CONFLICT
13155  // ====================
13156
13157  $.fn.carousel.noConflict = function () {
13158    $.fn.carousel = old
13159    return this
13160  }
13161
13162
13163  // CAROUSEL DATA-API
13164  // =================
13165
13166  var clickHandler = function (e) {
13167    var $this   = $(this)
13168    var href    = $this.attr('href')
13169    if (href) {
13170      href = href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
13171    }
13172
13173    var target  = $this.attr('data-target') || href
13174    var $target = $(document).find(target)
13175
13176    if (!$target.hasClass('carousel')) return
13177
13178    var options = $.extend({}, $target.data(), $this.data())
13179    var slideIndex = $this.attr('data-slide-to')
13180    if (slideIndex) options.interval = false
13181
13182    Plugin.call($target, options)
13183
13184    if (slideIndex) {
13185      $target.data('bs.carousel').to(slideIndex)
13186    }
13187
13188    e.preventDefault()
13189  }
13190
13191  $(document)
13192      .on('click.bs.carousel.data-api', '[data-slide]', clickHandler)
13193      .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler)
13194
13195  $(window).on('load', function () {
13196    $('[data-ride="carousel"]').each(function () {
13197      var $carousel = $(this)
13198      Plugin.call($carousel, $carousel.data())
13199    })
13200  })
13201
13202}(jQuery);
13203
13204/* ========================================================================
13205 * Bootstrap: collapse.js v3.4.1
13206 * https://getbootstrap.com/docs/3.4/javascript/#collapse
13207 * ========================================================================
13208 * Copyright 2011-2019 Twitter, Inc.
13209 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
13210 * ======================================================================== */
13211
13212/* jshint latedef: false */
13213
13214+function ($) {
13215  'use strict';
13216
13217  // COLLAPSE PUBLIC CLASS DEFINITION
13218  // ================================
13219
13220  var Collapse = function (element, options) {
13221    this.$element      = $(element)
13222    this.options       = $.extend({}, Collapse.DEFAULTS, options)
13223    this.$trigger      = $('[data-toggle="collapse"][href="#' + element.id + '"],' +
13224        '[data-toggle="collapse"][data-target="#' + element.id + '"]')
13225    this.transitioning = null
13226
13227    if (this.options.parent) {
13228      this.$parent = this.getParent()
13229    } else {
13230      this.addAriaAndCollapsedClass(this.$element, this.$trigger)
13231    }
13232
13233    if (this.options.toggle) this.toggle()
13234  }
13235
13236  Collapse.VERSION  = '3.4.1'
13237
13238  Collapse.TRANSITION_DURATION = 350
13239
13240  Collapse.DEFAULTS = {
13241    toggle: true
13242  }
13243
13244  Collapse.prototype.dimension = function () {
13245    var hasWidth = this.$element.hasClass('width')
13246    return hasWidth ? 'width' : 'height'
13247  }
13248
13249  Collapse.prototype.show = function () {
13250    if (this.transitioning || this.$element.hasClass('in')) return
13251
13252    var activesData
13253    var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing')
13254
13255    if (actives && actives.length) {
13256      activesData = actives.data('bs.collapse')
13257      if (activesData && activesData.transitioning) return
13258    }
13259
13260    var startEvent = $.Event('show.bs.collapse')
13261    this.$element.trigger(startEvent)
13262    if (startEvent.isDefaultPrevented()) return
13263
13264    if (actives && actives.length) {
13265      Plugin.call(actives, 'hide')
13266      activesData || actives.data('bs.collapse', null)
13267    }
13268
13269    var dimension = this.dimension()
13270
13271    this.$element
13272        .removeClass('collapse')
13273        .addClass('collapsing')[dimension](0)
13274        .attr('aria-expanded', true)
13275
13276    this.$trigger
13277        .removeClass('collapsed')
13278        .attr('aria-expanded', true)
13279
13280    this.transitioning = 1
13281
13282    var complete = function () {
13283      this.$element
13284          .removeClass('collapsing')
13285          .addClass('collapse in')[dimension]('')
13286      this.transitioning = 0
13287      this.$element
13288          .trigger('shown.bs.collapse')
13289    }
13290
13291    if (!$.support.transition) return complete.call(this)
13292
13293    var scrollSize = $.camelCase(['scroll', dimension].join('-'))
13294
13295    this.$element
13296        .one('bsTransitionEnd', $.proxy(complete, this))
13297        .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])
13298  }
13299
13300  Collapse.prototype.hide = function () {
13301    if (this.transitioning || !this.$element.hasClass('in')) return
13302
13303    var startEvent = $.Event('hide.bs.collapse')
13304    this.$element.trigger(startEvent)
13305    if (startEvent.isDefaultPrevented()) return
13306
13307    var dimension = this.dimension()
13308
13309    this.$element[dimension](this.$element[dimension]())[0].offsetHeight
13310
13311    this.$element
13312        .addClass('collapsing')
13313        .removeClass('collapse in')
13314        .attr('aria-expanded', false)
13315
13316    this.$trigger
13317        .addClass('collapsed')
13318        .attr('aria-expanded', false)
13319
13320    this.transitioning = 1
13321
13322    var complete = function () {
13323      this.transitioning = 0
13324      this.$element
13325          .removeClass('collapsing')
13326          .addClass('collapse')
13327          .trigger('hidden.bs.collapse')
13328    }
13329
13330    if (!$.support.transition) return complete.call(this)
13331
13332    this.$element
13333        [dimension](0)
13334        .one('bsTransitionEnd', $.proxy(complete, this))
13335        .emulateTransitionEnd(Collapse.TRANSITION_DURATION)
13336  }
13337
13338  Collapse.prototype.toggle = function () {
13339    this[this.$element.hasClass('in') ? 'hide' : 'show']()
13340  }
13341
13342  Collapse.prototype.getParent = function () {
13343    return $(document).find(this.options.parent)
13344        .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]')
13345        .each($.proxy(function (i, element) {
13346          var $element = $(element)
13347          this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element)
13348        }, this))
13349        .end()
13350  }
13351
13352  Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) {
13353    var isOpen = $element.hasClass('in')
13354
13355    $element.attr('aria-expanded', isOpen)
13356    $trigger
13357        .toggleClass('collapsed', !isOpen)
13358        .attr('aria-expanded', isOpen)
13359  }
13360
13361  function getTargetFromTrigger($trigger) {
13362    var href
13363    var target = $trigger.attr('data-target')
13364        || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
13365
13366    return $(document).find(target)
13367  }
13368
13369
13370  // COLLAPSE PLUGIN DEFINITION
13371  // ==========================
13372
13373  function Plugin(option) {
13374    return this.each(function () {
13375      var $this   = $(this)
13376      var data    = $this.data('bs.collapse')
13377      var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
13378
13379      if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false
13380      if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
13381      if (typeof option == 'string') data[option]()
13382    })
13383  }
13384
13385  var old = $.fn.collapse
13386
13387  $.fn.collapse             = Plugin
13388  $.fn.collapse.Constructor = Collapse
13389
13390
13391  // COLLAPSE NO CONFLICT
13392  // ====================
13393
13394  $.fn.collapse.noConflict = function () {
13395    $.fn.collapse = old
13396    return this
13397  }
13398
13399
13400  // COLLAPSE DATA-API
13401  // =================
13402
13403  $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
13404    var $this   = $(this)
13405
13406    if (!$this.attr('data-target')) e.preventDefault()
13407
13408    var $target = getTargetFromTrigger($this)
13409    var data    = $target.data('bs.collapse')
13410    var option  = data ? 'toggle' : $this.data()
13411
13412    Plugin.call($target, option)
13413  })
13414
13415}(jQuery);
13416
13417/* ========================================================================
13418 * Bootstrap: dropdown.js v3.4.1
13419 * https://getbootstrap.com/docs/3.4/javascript/#dropdowns
13420 * ========================================================================
13421 * Copyright 2011-2019 Twitter, Inc.
13422 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
13423 * ======================================================================== */
13424
13425
13426+function ($) {
13427  'use strict';
13428
13429  // DROPDOWN CLASS DEFINITION
13430  // =========================
13431
13432  var backdrop = '.dropdown-backdrop'
13433  var toggle   = '[data-toggle="dropdown"]'
13434  var Dropdown = function (element) {
13435    $(element).on('click.bs.dropdown', this.toggle)
13436  }
13437
13438  Dropdown.VERSION = '3.4.1'
13439
13440  function getParent($this) {
13441    var selector = $this.attr('data-target')
13442
13443    if (!selector) {
13444      selector = $this.attr('href')
13445      selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
13446    }
13447
13448    var $parent = selector !== '#' ? $(document).find(selector) : null
13449
13450    return $parent && $parent.length ? $parent : $this.parent()
13451  }
13452
13453  function clearMenus(e) {
13454    if (e && e.which === 3) return
13455    $(backdrop).remove()
13456    $(toggle).each(function () {
13457      var $this         = $(this)
13458      var $parent       = getParent($this)
13459      var relatedTarget = { relatedTarget: this }
13460
13461      if (!$parent.hasClass('open')) return
13462
13463      if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return
13464
13465      $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
13466
13467      if (e.isDefaultPrevented()) return
13468
13469      $this.attr('aria-expanded', 'false')
13470      $parent.removeClass('open').trigger($.Event('hidden.bs.dropdown', relatedTarget))
13471    })
13472  }
13473
13474  Dropdown.prototype.toggle = function (e) {
13475    var $this = $(this)
13476
13477    if ($this.is('.disabled, :disabled')) return
13478
13479    var $parent  = getParent($this)
13480    var isActive = $parent.hasClass('open')
13481
13482    clearMenus()
13483
13484    if (!isActive) {
13485      if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
13486        // if mobile we use a backdrop because click events don't delegate
13487        $(document.createElement('div'))
13488            .addClass('dropdown-backdrop')
13489            .insertAfter($(this))
13490            .on('click', clearMenus)
13491      }
13492
13493      var relatedTarget = { relatedTarget: this }
13494      $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
13495
13496      if (e.isDefaultPrevented()) return
13497
13498      $this
13499          .trigger('focus')
13500          .attr('aria-expanded', 'true')
13501
13502      $parent
13503          .toggleClass('open')
13504          .trigger($.Event('shown.bs.dropdown', relatedTarget))
13505    }
13506
13507    return false
13508  }
13509
13510  Dropdown.prototype.keydown = function (e) {
13511    if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return
13512
13513    var $this = $(this)
13514
13515    e.preventDefault()
13516    e.stopPropagation()
13517
13518    if ($this.is('.disabled, :disabled')) return
13519
13520    var $parent  = getParent($this)
13521    var isActive = $parent.hasClass('open')
13522
13523    if (!isActive && e.which != 27 || isActive && e.which == 27) {
13524      if (e.which == 27) $parent.find(toggle).trigger('focus')
13525      return $this.trigger('click')
13526    }
13527
13528    var desc = ' li:not(.disabled):visible a'
13529    var $items = $parent.find('.dropdown-menu' + desc)
13530
13531    if (!$items.length) return
13532
13533    var index = $items.index(e.target)
13534
13535    if (e.which == 38 && index > 0)                 index--         // up
13536    if (e.which == 40 && index < $items.length - 1) index++         // down
13537    if (!~index)                                    index = 0
13538
13539    $items.eq(index).trigger('focus')
13540  }
13541
13542
13543  // DROPDOWN PLUGIN DEFINITION
13544  // ==========================
13545
13546  function Plugin(option) {
13547    return this.each(function () {
13548      var $this = $(this)
13549      var data  = $this.data('bs.dropdown')
13550
13551      if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
13552      if (typeof option == 'string') data[option].call($this)
13553    })
13554  }
13555
13556  var old = $.fn.dropdown
13557
13558  $.fn.dropdown             = Plugin
13559  $.fn.dropdown.Constructor = Dropdown
13560
13561
13562  // DROPDOWN NO CONFLICT
13563  // ====================
13564
13565  $.fn.dropdown.noConflict = function () {
13566    $.fn.dropdown = old
13567    return this
13568  }
13569
13570
13571  // APPLY TO STANDARD DROPDOWN ELEMENTS
13572  // ===================================
13573
13574  $(document)
13575      .on('click.bs.dropdown.data-api', clearMenus)
13576      .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
13577      .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
13578      .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
13579      .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown)
13580
13581}(jQuery);
13582
13583/* ========================================================================
13584 * Bootstrap: modal.js v3.4.1
13585 * https://getbootstrap.com/docs/3.4/javascript/#modals
13586 * ========================================================================
13587 * Copyright 2011-2019 Twitter, Inc.
13588 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
13589 * ======================================================================== */
13590
13591
13592+function ($) {
13593  'use strict';
13594
13595  // MODAL CLASS DEFINITION
13596  // ======================
13597
13598  var Modal = function (element, options) {
13599    this.options = options
13600    this.$body = $(document.body)
13601    this.$element = $(element)
13602    this.$dialog = this.$element.find('.modal-dialog')
13603    this.$backdrop = null
13604    this.isShown = null
13605    this.originalBodyPad = null
13606    this.scrollbarWidth = 0
13607    this.ignoreBackdropClick = false
13608    this.fixedContent = '.navbar-fixed-top, .navbar-fixed-bottom'
13609
13610    if (this.options.remote) {
13611      this.$element
13612          .find('.modal-content')
13613          .load(this.options.remote, $.proxy(function () {
13614            this.$element.trigger('loaded.bs.modal')
13615          }, this))
13616    }
13617  }
13618
13619  Modal.VERSION = '3.4.1'
13620
13621  Modal.TRANSITION_DURATION = 300
13622  Modal.BACKDROP_TRANSITION_DURATION = 150
13623
13624  Modal.DEFAULTS = {
13625    backdrop: true,
13626    keyboard: true,
13627    show: true
13628  }
13629
13630  Modal.prototype.toggle = function (_relatedTarget) {
13631    return this.isShown ? this.hide() : this.show(_relatedTarget)
13632  }
13633
13634  Modal.prototype.show = function (_relatedTarget) {
13635    var that = this
13636    var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
13637
13638    this.$element.trigger(e)
13639
13640    if (this.isShown || e.isDefaultPrevented()) return
13641
13642    this.isShown = true
13643
13644    this.checkScrollbar()
13645    this.setScrollbar()
13646    this.$body.addClass('modal-open')
13647
13648    this.escape()
13649    this.resize()
13650
13651    this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
13652
13653    this.$dialog.on('mousedown.dismiss.bs.modal', function () {
13654      that.$element.one('mouseup.dismiss.bs.modal', function (e) {
13655        if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true
13656      })
13657    })
13658
13659    this.backdrop(function () {
13660      var transition = $.support.transition && that.$element.hasClass('fade')
13661
13662      if (!that.$element.parent().length) {
13663        that.$element.appendTo(that.$body) // don't move modals dom position
13664      }
13665
13666      that.$element
13667          .show()
13668          .scrollTop(0)
13669
13670      that.adjustDialog()
13671
13672      if (transition) {
13673        that.$element[0].offsetWidth // force reflow
13674      }
13675
13676      that.$element.addClass('in')
13677
13678      that.enforceFocus()
13679
13680      var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
13681
13682      transition ?
13683          that.$dialog // wait for modal to slide in
13684              .one('bsTransitionEnd', function () {
13685                that.$element.trigger('focus').trigger(e)
13686              })
13687              .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
13688          that.$element.trigger('focus').trigger(e)
13689    })
13690  }
13691
13692  Modal.prototype.hide = function (e) {
13693    if (e) e.preventDefault()
13694
13695    e = $.Event('hide.bs.modal')
13696
13697    this.$element.trigger(e)
13698
13699    if (!this.isShown || e.isDefaultPrevented()) return
13700
13701    this.isShown = false
13702
13703    this.escape()
13704    this.resize()
13705
13706    $(document).off('focusin.bs.modal')
13707
13708    this.$element
13709        .removeClass('in')
13710        .off('click.dismiss.bs.modal')
13711        .off('mouseup.dismiss.bs.modal')
13712
13713    this.$dialog.off('mousedown.dismiss.bs.modal')
13714
13715    $.support.transition && this.$element.hasClass('fade') ?
13716        this.$element
13717            .one('bsTransitionEnd', $.proxy(this.hideModal, this))
13718            .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
13719        this.hideModal()
13720  }
13721
13722  Modal.prototype.enforceFocus = function () {
13723    $(document)
13724        .off('focusin.bs.modal') // guard against infinite focus loop
13725        .on('focusin.bs.modal', $.proxy(function (e) {
13726          if (document !== e.target &&
13727              this.$element[0] !== e.target &&
13728              !this.$element.has(e.target).length) {
13729            this.$element.trigger('focus')
13730          }
13731        }, this))
13732  }
13733
13734  Modal.prototype.escape = function () {
13735    if (this.isShown && this.options.keyboard) {
13736      this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {
13737        e.which == 27 && this.hide()
13738      }, this))
13739    } else if (!this.isShown) {
13740      this.$element.off('keydown.dismiss.bs.modal')
13741    }
13742  }
13743
13744  Modal.prototype.resize = function () {
13745    if (this.isShown) {
13746      $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this))
13747    } else {
13748      $(window).off('resize.bs.modal')
13749    }
13750  }
13751
13752  Modal.prototype.hideModal = function () {
13753    var that = this
13754    this.$element.hide()
13755    this.backdrop(function () {
13756      that.$body.removeClass('modal-open')
13757      that.resetAdjustments()
13758      that.resetScrollbar()
13759      that.$element.trigger('hidden.bs.modal')
13760    })
13761  }
13762
13763  Modal.prototype.removeBackdrop = function () {
13764    this.$backdrop && this.$backdrop.remove()
13765    this.$backdrop = null
13766  }
13767
13768  Modal.prototype.backdrop = function (callback) {
13769    var that = this
13770    var animate = this.$element.hasClass('fade') ? 'fade' : ''
13771
13772    if (this.isShown && this.options.backdrop) {
13773      var doAnimate = $.support.transition && animate
13774
13775      this.$backdrop = $(document.createElement('div'))
13776          .addClass('modal-backdrop ' + animate)
13777          .appendTo(this.$body)
13778
13779      this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {
13780        if (this.ignoreBackdropClick) {
13781          this.ignoreBackdropClick = false
13782          return
13783        }
13784        if (e.target !== e.currentTarget) return
13785        this.options.backdrop == 'static'
13786            ? this.$element[0].focus()
13787            : this.hide()
13788      }, this))
13789
13790      if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
13791
13792      this.$backdrop.addClass('in')
13793
13794      if (!callback) return
13795
13796      doAnimate ?
13797          this.$backdrop
13798              .one('bsTransitionEnd', callback)
13799              .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
13800          callback()
13801
13802    } else if (!this.isShown && this.$backdrop) {
13803      this.$backdrop.removeClass('in')
13804
13805      var callbackRemove = function () {
13806        that.removeBackdrop()
13807        callback && callback()
13808      }
13809      $.support.transition && this.$element.hasClass('fade') ?
13810          this.$backdrop
13811              .one('bsTransitionEnd', callbackRemove)
13812              .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
13813          callbackRemove()
13814
13815    } else if (callback) {
13816      callback()
13817    }
13818  }
13819
13820  // these following methods are used to handle overflowing modals
13821
13822  Modal.prototype.handleUpdate = function () {
13823    this.adjustDialog()
13824  }
13825
13826  Modal.prototype.adjustDialog = function () {
13827    var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight
13828
13829    this.$element.css({
13830      paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',
13831      paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''
13832    })
13833  }
13834
13835  Modal.prototype.resetAdjustments = function () {
13836    this.$element.css({
13837      paddingLeft: '',
13838      paddingRight: ''
13839    })
13840  }
13841
13842  Modal.prototype.checkScrollbar = function () {
13843    var fullWindowWidth = window.innerWidth
13844    if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8
13845      var documentElementRect = document.documentElement.getBoundingClientRect()
13846      fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left)
13847    }
13848    this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth
13849    this.scrollbarWidth = this.measureScrollbar()
13850  }
13851
13852  Modal.prototype.setScrollbar = function () {
13853    var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
13854    this.originalBodyPad = document.body.style.paddingRight || ''
13855    var scrollbarWidth = this.scrollbarWidth
13856    if (this.bodyIsOverflowing) {
13857      this.$body.css('padding-right', bodyPad + scrollbarWidth)
13858      $(this.fixedContent).each(function (index, element) {
13859        var actualPadding = element.style.paddingRight
13860        var calculatedPadding = $(element).css('padding-right')
13861        $(element)
13862            .data('padding-right', actualPadding)
13863            .css('padding-right', parseFloat(calculatedPadding) + scrollbarWidth + 'px')
13864      })
13865    }
13866  }
13867
13868  Modal.prototype.resetScrollbar = function () {
13869    this.$body.css('padding-right', this.originalBodyPad)
13870    $(this.fixedContent).each(function (index, element) {
13871      var padding = $(element).data('padding-right')
13872      $(element).removeData('padding-right')
13873      element.style.paddingRight = padding ? padding : ''
13874    })
13875  }
13876
13877  Modal.prototype.measureScrollbar = function () { // thx walsh
13878    var scrollDiv = document.createElement('div')
13879    scrollDiv.className = 'modal-scrollbar-measure'
13880    this.$body.append(scrollDiv)
13881    var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
13882    this.$body[0].removeChild(scrollDiv)
13883    return scrollbarWidth
13884  }
13885
13886
13887  // MODAL PLUGIN DEFINITION
13888  // =======================
13889
13890  function Plugin(option, _relatedTarget) {
13891    return this.each(function () {
13892      var $this = $(this)
13893      var data = $this.data('bs.modal')
13894      var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
13895
13896      if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
13897      if (typeof option == 'string') data[option](_relatedTarget)
13898      else if (options.show) data.show(_relatedTarget)
13899    })
13900  }
13901
13902  var old = $.fn.modal
13903
13904  $.fn.modal = Plugin
13905  $.fn.modal.Constructor = Modal
13906
13907
13908  // MODAL NO CONFLICT
13909  // =================
13910
13911  $.fn.modal.noConflict = function () {
13912    $.fn.modal = old
13913    return this
13914  }
13915
13916
13917  // MODAL DATA-API
13918  // ==============
13919
13920  $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
13921    var $this = $(this)
13922    var href = $this.attr('href')
13923    var target = $this.attr('data-target') ||
13924        (href && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
13925
13926    var $target = $(document).find(target)
13927    var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
13928
13929    if ($this.is('a')) e.preventDefault()
13930
13931    $target.one('show.bs.modal', function (showEvent) {
13932      if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
13933      $target.one('hidden.bs.modal', function () {
13934        $this.is(':visible') && $this.trigger('focus')
13935      })
13936    })
13937    Plugin.call($target, option, this)
13938  })
13939
13940}(jQuery);
13941
13942/* ========================================================================
13943 * Bootstrap: tooltip.js v3.4.1
13944 * https://getbootstrap.com/docs/3.4/javascript/#tooltip
13945 * Inspired by the original jQuery.tipsy by Jason Frame
13946 * ========================================================================
13947 * Copyright 2011-2019 Twitter, Inc.
13948 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
13949 * ======================================================================== */
13950
13951+function ($) {
13952  'use strict';
13953
13954  var DISALLOWED_ATTRIBUTES = ['sanitize', 'whiteList', 'sanitizeFn']
13955
13956  var uriAttrs = [
13957    'background',
13958    'cite',
13959    'href',
13960    'itemtype',
13961    'longdesc',
13962    'poster',
13963    'src',
13964    'xlink:href'
13965  ]
13966
13967  var ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i
13968
13969  var DefaultWhitelist = {
13970    // Global attributes allowed on any supplied element below.
13971    '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN],
13972    a: ['target', 'href', 'title', 'rel'],
13973    area: [],
13974    b: [],
13975    br: [],
13976    col: [],
13977    code: [],
13978    div: [],
13979    em: [],
13980    hr: [],
13981    h1: [],
13982    h2: [],
13983    h3: [],
13984    h4: [],
13985    h5: [],
13986    h6: [],
13987    i: [],
13988    img: ['src', 'alt', 'title', 'width', 'height'],
13989    li: [],
13990    ol: [],
13991    p: [],
13992    pre: [],
13993    s: [],
13994    small: [],
13995    span: [],
13996    sub: [],
13997    sup: [],
13998    strong: [],
13999    u: [],
14000    ul: []
14001  }
14002
14003  /**
14004   * A pattern that recognizes a commonly useful subset of URLs that are safe.
14005   *
14006   * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts
14007   */
14008  var SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi
14009
14010  /**
14011   * A pattern that matches safe data URLs. Only matches image, video and audio types.
14012   *
14013   * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts
14014   */
14015  var DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+/]+=*$/i
14016
14017  function allowedAttribute(attr, allowedAttributeList) {
14018    var attrName = attr.nodeName.toLowerCase()
14019
14020    if ($.inArray(attrName, allowedAttributeList) !== -1) {
14021      if ($.inArray(attrName, uriAttrs) !== -1) {
14022        return Boolean(attr.nodeValue.match(SAFE_URL_PATTERN) || attr.nodeValue.match(DATA_URL_PATTERN))
14023      }
14024
14025      return true
14026    }
14027
14028    var regExp = $(allowedAttributeList).filter(function (index, value) {
14029      return value instanceof RegExp
14030    })
14031
14032    // Check if a regular expression validates the attribute.
14033    for (var i = 0, l = regExp.length; i < l; i++) {
14034      if (attrName.match(regExp[i])) {
14035        return true
14036      }
14037    }
14038
14039    return false
14040  }
14041
14042  function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) {
14043    if (unsafeHtml.length === 0) {
14044      return unsafeHtml
14045    }
14046
14047    if (sanitizeFn && typeof sanitizeFn === 'function') {
14048      return sanitizeFn(unsafeHtml)
14049    }
14050
14051    // IE 8 and below don't support createHTMLDocument
14052    if (!document.implementation || !document.implementation.createHTMLDocument) {
14053      return unsafeHtml
14054    }
14055
14056    var createdDocument = document.implementation.createHTMLDocument('sanitization')
14057    createdDocument.body.innerHTML = unsafeHtml
14058
14059    var whitelistKeys = $.map(whiteList, function (el, i) { return i })
14060    var elements = $(createdDocument.body).find('*')
14061
14062    for (var i = 0, len = elements.length; i < len; i++) {
14063      var el = elements[i]
14064      var elName = el.nodeName.toLowerCase()
14065
14066      if ($.inArray(elName, whitelistKeys) === -1) {
14067        el.parentNode.removeChild(el)
14068
14069        continue
14070      }
14071
14072      var attributeList = $.map(el.attributes, function (el) { return el })
14073      var whitelistedAttributes = [].concat(whiteList['*'] || [], whiteList[elName] || [])
14074
14075      for (var j = 0, len2 = attributeList.length; j < len2; j++) {
14076        if (!allowedAttribute(attributeList[j], whitelistedAttributes)) {
14077          el.removeAttribute(attributeList[j].nodeName)
14078        }
14079      }
14080    }
14081
14082    return createdDocument.body.innerHTML
14083  }
14084
14085  // TOOLTIP PUBLIC CLASS DEFINITION
14086  // ===============================
14087
14088  var Tooltip = function (element, options) {
14089    this.type       = null
14090    this.options    = null
14091    this.enabled    = null
14092    this.timeout    = null
14093    this.hoverState = null
14094    this.$element   = null
14095    this.inState    = null
14096
14097    this.init('tooltip', element, options)
14098  }
14099
14100  Tooltip.VERSION  = '3.4.1'
14101
14102  Tooltip.TRANSITION_DURATION = 150
14103
14104  Tooltip.DEFAULTS = {
14105    animation: true,
14106    placement: 'top',
14107    selector: false,
14108    template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
14109    trigger: 'hover focus',
14110    title: '',
14111    delay: 0,
14112    html: false,
14113    container: false,
14114    viewport: {
14115      selector: 'body',
14116      padding: 0
14117    },
14118    sanitize : true,
14119    sanitizeFn : null,
14120    whiteList : DefaultWhitelist
14121  }
14122
14123  Tooltip.prototype.init = function (type, element, options) {
14124    this.enabled   = true
14125    this.type      = type
14126    this.$element  = $(element)
14127    this.options   = this.getOptions(options)
14128    this.$viewport = this.options.viewport && $(document).find($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport))
14129    this.inState   = { click: false, hover: false, focus: false }
14130
14131    if (this.$element[0] instanceof document.constructor && !this.options.selector) {
14132      throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!')
14133    }
14134
14135    var triggers = this.options.trigger.split(' ')
14136
14137    for (var i = triggers.length; i--;) {
14138      var trigger = triggers[i]
14139
14140      if (trigger == 'click') {
14141        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
14142      } else if (trigger != 'manual') {
14143        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focusin'
14144        var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
14145
14146        this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
14147        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
14148      }
14149    }
14150
14151    this.options.selector ?
14152        (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
14153        this.fixTitle()
14154  }
14155
14156  Tooltip.prototype.getDefaults = function () {
14157    return Tooltip.DEFAULTS
14158  }
14159
14160  Tooltip.prototype.getOptions = function (options) {
14161    var dataAttributes = this.$element.data()
14162
14163    for (var dataAttr in dataAttributes) {
14164      if (dataAttributes.hasOwnProperty(dataAttr) && $.inArray(dataAttr, DISALLOWED_ATTRIBUTES) !== -1) {
14165        delete dataAttributes[dataAttr]
14166      }
14167    }
14168
14169    options = $.extend({}, this.getDefaults(), dataAttributes, options)
14170
14171    if (options.delay && typeof options.delay == 'number') {
14172      options.delay = {
14173        show: options.delay,
14174        hide: options.delay
14175      }
14176    }
14177
14178    if (options.sanitize) {
14179      options.template = sanitizeHtml(options.template, options.whiteList, options.sanitizeFn)
14180    }
14181
14182    return options
14183  }
14184
14185  Tooltip.prototype.getDelegateOptions = function () {
14186    var options  = {}
14187    var defaults = this.getDefaults()
14188
14189    this._options && $.each(this._options, function (key, value) {
14190      if (defaults[key] != value) options[key] = value
14191    })
14192
14193    return options
14194  }
14195
14196  Tooltip.prototype.enter = function (obj) {
14197    var self = obj instanceof this.constructor ?
14198        obj : $(obj.currentTarget).data('bs.' + this.type)
14199
14200    if (!self) {
14201      self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
14202      $(obj.currentTarget).data('bs.' + this.type, self)
14203    }
14204
14205    if (obj instanceof $.Event) {
14206      self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true
14207    }
14208
14209    if (self.tip().hasClass('in') || self.hoverState == 'in') {
14210      self.hoverState = 'in'
14211      return
14212    }
14213
14214    clearTimeout(self.timeout)
14215
14216    self.hoverState = 'in'
14217
14218    if (!self.options.delay || !self.options.delay.show) return self.show()
14219
14220    self.timeout = setTimeout(function () {
14221      if (self.hoverState == 'in') self.show()
14222    }, self.options.delay.show)
14223  }
14224
14225  Tooltip.prototype.isInStateTrue = function () {
14226    for (var key in this.inState) {
14227      if (this.inState[key]) return true
14228    }
14229
14230    return false
14231  }
14232
14233  Tooltip.prototype.leave = function (obj) {
14234    var self = obj instanceof this.constructor ?
14235        obj : $(obj.currentTarget).data('bs.' + this.type)
14236
14237    if (!self) {
14238      self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
14239      $(obj.currentTarget).data('bs.' + this.type, self)
14240    }
14241
14242    if (obj instanceof $.Event) {
14243      self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false
14244    }
14245
14246    if (self.isInStateTrue()) return
14247
14248    clearTimeout(self.timeout)
14249
14250    self.hoverState = 'out'
14251
14252    if (!self.options.delay || !self.options.delay.hide) return self.hide()
14253
14254    self.timeout = setTimeout(function () {
14255      if (self.hoverState == 'out') self.hide()
14256    }, self.options.delay.hide)
14257  }
14258
14259  Tooltip.prototype.show = function () {
14260    var e = $.Event('show.bs.' + this.type)
14261
14262    if (this.hasContent() && this.enabled) {
14263      this.$element.trigger(e)
14264
14265      var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
14266      if (e.isDefaultPrevented() || !inDom) return
14267      var that = this
14268
14269      var $tip = this.tip()
14270
14271      var tipId = this.getUID(this.type)
14272
14273      this.setContent()
14274      $tip.attr('id', tipId)
14275      this.$element.attr('aria-describedby', tipId)
14276
14277      if (this.options.animation) $tip.addClass('fade')
14278
14279      var placement = typeof this.options.placement == 'function' ?
14280          this.options.placement.call(this, $tip[0], this.$element[0]) :
14281          this.options.placement
14282
14283      var autoToken = /\s?auto?\s?/i
14284      var autoPlace = autoToken.test(placement)
14285      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
14286
14287      $tip
14288          .detach()
14289          .css({ top: 0, left: 0, display: 'block' })
14290          .addClass(placement)
14291          .data('bs.' + this.type, this)
14292
14293      this.options.container ? $tip.appendTo($(document).find(this.options.container)) : $tip.insertAfter(this.$element)
14294      this.$element.trigger('inserted.bs.' + this.type)
14295
14296      var pos          = this.getPosition()
14297      var actualWidth  = $tip[0].offsetWidth
14298      var actualHeight = $tip[0].offsetHeight
14299
14300      if (autoPlace) {
14301        var orgPlacement = placement
14302        var viewportDim = this.getPosition(this.$viewport)
14303
14304        placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top'    :
14305            placement == 'top'    && pos.top    - actualHeight < viewportDim.top    ? 'bottom' :
14306                placement == 'right'  && pos.right  + actualWidth  > viewportDim.width  ? 'left'   :
14307                    placement == 'left'   && pos.left   - actualWidth  < viewportDim.left   ? 'right'  :
14308                        placement
14309
14310        $tip
14311            .removeClass(orgPlacement)
14312            .addClass(placement)
14313      }
14314
14315      var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
14316
14317      this.applyPlacement(calculatedOffset, placement)
14318
14319      var complete = function () {
14320        var prevHoverState = that.hoverState
14321        that.$element.trigger('shown.bs.' + that.type)
14322        that.hoverState = null
14323
14324        if (prevHoverState == 'out') that.leave(that)
14325      }
14326
14327      $.support.transition && this.$tip.hasClass('fade') ?
14328          $tip
14329              .one('bsTransitionEnd', complete)
14330              .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
14331          complete()
14332    }
14333  }
14334
14335  Tooltip.prototype.applyPlacement = function (offset, placement) {
14336    var $tip   = this.tip()
14337    var width  = $tip[0].offsetWidth
14338    var height = $tip[0].offsetHeight
14339
14340    // manually read margins because getBoundingClientRect includes difference
14341    var marginTop = parseInt($tip.css('margin-top'), 10)
14342    var marginLeft = parseInt($tip.css('margin-left'), 10)
14343
14344    // we must check for NaN for ie 8/9
14345    if (isNaN(marginTop))  marginTop  = 0
14346    if (isNaN(marginLeft)) marginLeft = 0
14347
14348    offset.top  += marginTop
14349    offset.left += marginLeft
14350
14351    // $.fn.offset doesn't round pixel values
14352    // so we use setOffset directly with our own function B-0
14353    $.offset.setOffset($tip[0], $.extend({
14354      using: function (props) {
14355        $tip.css({
14356          top: Math.round(props.top),
14357          left: Math.round(props.left)
14358        })
14359      }
14360    }, offset), 0)
14361
14362    $tip.addClass('in')
14363
14364    // check to see if placing tip in new offset caused the tip to resize itself
14365    var actualWidth  = $tip[0].offsetWidth
14366    var actualHeight = $tip[0].offsetHeight
14367
14368    if (placement == 'top' && actualHeight != height) {
14369      offset.top = offset.top + height - actualHeight
14370    }
14371
14372    var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
14373
14374    if (delta.left) offset.left += delta.left
14375    else offset.top += delta.top
14376
14377    var isVertical          = /top|bottom/.test(placement)
14378    var arrowDelta          = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
14379    var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
14380
14381    $tip.offset(offset)
14382    this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
14383  }
14384
14385  Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) {
14386    this.arrow()
14387        .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
14388        .css(isVertical ? 'top' : 'left', '')
14389  }
14390
14391  Tooltip.prototype.setContent = function () {
14392    var $tip  = this.tip()
14393    var title = this.getTitle()
14394
14395    if (this.options.html) {
14396      if (this.options.sanitize) {
14397        title = sanitizeHtml(title, this.options.whiteList, this.options.sanitizeFn)
14398      }
14399
14400      $tip.find('.tooltip-inner').html(title)
14401    } else {
14402      $tip.find('.tooltip-inner').text(title)
14403    }
14404
14405    $tip.removeClass('fade in top bottom left right')
14406  }
14407
14408  Tooltip.prototype.hide = function (callback) {
14409    var that = this
14410    var $tip = $(this.$tip)
14411    var e    = $.Event('hide.bs.' + this.type)
14412
14413    function complete() {
14414      if (that.hoverState != 'in') $tip.detach()
14415      if (that.$element) { // TODO: Check whether guarding this code with this `if` is really necessary.
14416        that.$element
14417            .removeAttr('aria-describedby')
14418            .trigger('hidden.bs.' + that.type)
14419      }
14420      callback && callback()
14421    }
14422
14423    this.$element.trigger(e)
14424
14425    if (e.isDefaultPrevented()) return
14426
14427    $tip.removeClass('in')
14428
14429    $.support.transition && $tip.hasClass('fade') ?
14430        $tip
14431            .one('bsTransitionEnd', complete)
14432            .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
14433        complete()
14434
14435    this.hoverState = null
14436
14437    return this
14438  }
14439
14440  Tooltip.prototype.fixTitle = function () {
14441    var $e = this.$element
14442    if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') {
14443      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
14444    }
14445  }
14446
14447  Tooltip.prototype.hasContent = function () {
14448    return this.getTitle()
14449  }
14450
14451  Tooltip.prototype.getPosition = function ($element) {
14452    $element   = $element || this.$element
14453
14454    var el     = $element[0]
14455    var isBody = el.tagName == 'BODY'
14456
14457    var elRect    = el.getBoundingClientRect()
14458    if (elRect.width == null) {
14459      // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
14460      elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
14461    }
14462    var isSvg = window.SVGElement && el instanceof window.SVGElement
14463    // Avoid using $.offset() on SVGs since it gives incorrect results in jQuery 3.
14464    // See https://github.com/twbs/bootstrap/issues/20280
14465    var elOffset  = isBody ? { top: 0, left: 0 } : (isSvg ? null : $element.offset())
14466    var scroll    = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
14467    var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
14468
14469    return $.extend({}, elRect, scroll, outerDims, elOffset)
14470  }
14471
14472  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
14473    return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2 } :
14474        placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
14475            placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
14476                /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
14477
14478  }
14479
14480  Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
14481    var delta = { top: 0, left: 0 }
14482    if (!this.$viewport) return delta
14483
14484    var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
14485    var viewportDimensions = this.getPosition(this.$viewport)
14486
14487    if (/right|left/.test(placement)) {
14488      var topEdgeOffset    = pos.top - viewportPadding - viewportDimensions.scroll
14489      var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
14490      if (topEdgeOffset < viewportDimensions.top) { // top overflow
14491        delta.top = viewportDimensions.top - topEdgeOffset
14492      } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
14493        delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
14494      }
14495    } else {
14496      var leftEdgeOffset  = pos.left - viewportPadding
14497      var rightEdgeOffset = pos.left + viewportPadding + actualWidth
14498      if (leftEdgeOffset < viewportDimensions.left) { // left overflow
14499        delta.left = viewportDimensions.left - leftEdgeOffset
14500      } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow
14501        delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
14502      }
14503    }
14504
14505    return delta
14506  }
14507
14508  Tooltip.prototype.getTitle = function () {
14509    var title
14510    var $e = this.$element
14511    var o  = this.options
14512
14513    title = $e.attr('data-original-title')
14514        || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)
14515
14516    return title
14517  }
14518
14519  Tooltip.prototype.getUID = function (prefix) {
14520    do prefix += ~~(Math.random() * 1000000)
14521    while (document.getElementById(prefix))
14522    return prefix
14523  }
14524
14525  Tooltip.prototype.tip = function () {
14526    if (!this.$tip) {
14527      this.$tip = $(this.options.template)
14528      if (this.$tip.length != 1) {
14529        throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!')
14530      }
14531    }
14532    return this.$tip
14533  }
14534
14535  Tooltip.prototype.arrow = function () {
14536    return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
14537  }
14538
14539  Tooltip.prototype.enable = function () {
14540    this.enabled = true
14541  }
14542
14543  Tooltip.prototype.disable = function () {
14544    this.enabled = false
14545  }
14546
14547  Tooltip.prototype.toggleEnabled = function () {
14548    this.enabled = !this.enabled
14549  }
14550
14551  Tooltip.prototype.toggle = function (e) {
14552    var self = this
14553    if (e) {
14554      self = $(e.currentTarget).data('bs.' + this.type)
14555      if (!self) {
14556        self = new this.constructor(e.currentTarget, this.getDelegateOptions())
14557        $(e.currentTarget).data('bs.' + this.type, self)
14558      }
14559    }
14560
14561    if (e) {
14562      self.inState.click = !self.inState.click
14563      if (self.isInStateTrue()) self.enter(self)
14564      else self.leave(self)
14565    } else {
14566      self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
14567    }
14568  }
14569
14570  Tooltip.prototype.destroy = function () {
14571    var that = this
14572    clearTimeout(this.timeout)
14573    this.hide(function () {
14574      that.$element.off('.' + that.type).removeData('bs.' + that.type)
14575      if (that.$tip) {
14576        that.$tip.detach()
14577      }
14578      that.$tip = null
14579      that.$arrow = null
14580      that.$viewport = null
14581      that.$element = null
14582    })
14583  }
14584
14585  Tooltip.prototype.sanitizeHtml = function (unsafeHtml) {
14586    return sanitizeHtml(unsafeHtml, this.options.whiteList, this.options.sanitizeFn)
14587  }
14588
14589  // TOOLTIP PLUGIN DEFINITION
14590  // =========================
14591
14592  function Plugin(option) {
14593    return this.each(function () {
14594      var $this   = $(this)
14595      var data    = $this.data('bs.tooltip')
14596      var options = typeof option == 'object' && option
14597
14598      if (!data && /destroy|hide/.test(option)) return
14599      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
14600      if (typeof option == 'string') data[option]()
14601    })
14602  }
14603
14604  var old = $.fn.tooltip
14605
14606  $.fn.tooltip             = Plugin
14607  $.fn.tooltip.Constructor = Tooltip
14608
14609
14610  // TOOLTIP NO CONFLICT
14611  // ===================
14612
14613  $.fn.tooltip.noConflict = function () {
14614    $.fn.tooltip = old
14615    return this
14616  }
14617
14618}(jQuery);
14619
14620/* ========================================================================
14621 * Bootstrap: popover.js v3.4.1
14622 * https://getbootstrap.com/docs/3.4/javascript/#popovers
14623 * ========================================================================
14624 * Copyright 2011-2019 Twitter, Inc.
14625 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
14626 * ======================================================================== */
14627
14628
14629+function ($) {
14630  'use strict';
14631
14632  // POPOVER PUBLIC CLASS DEFINITION
14633  // ===============================
14634
14635  var Popover = function (element, options) {
14636    this.init('popover', element, options)
14637  }
14638
14639  if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
14640
14641  Popover.VERSION  = '3.4.1'
14642
14643  Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
14644    placement: 'right',
14645    trigger: 'click',
14646    content: '',
14647    template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
14648  })
14649
14650
14651  // NOTE: POPOVER EXTENDS tooltip.js
14652  // ================================
14653
14654  Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
14655
14656  Popover.prototype.constructor = Popover
14657
14658  Popover.prototype.getDefaults = function () {
14659    return Popover.DEFAULTS
14660  }
14661
14662  Popover.prototype.setContent = function () {
14663    var $tip    = this.tip()
14664    var title   = this.getTitle()
14665    var content = this.getContent()
14666
14667    if (this.options.html) {
14668      var typeContent = typeof content
14669
14670      if (this.options.sanitize) {
14671        title = this.sanitizeHtml(title)
14672
14673        if (typeContent === 'string') {
14674          content = this.sanitizeHtml(content)
14675        }
14676      }
14677
14678      $tip.find('.popover-title').html(title)
14679      $tip.find('.popover-content').children().detach().end()[
14680          typeContent === 'string' ? 'html' : 'append'
14681          ](content)
14682    } else {
14683      $tip.find('.popover-title').text(title)
14684      $tip.find('.popover-content').children().detach().end().text(content)
14685    }
14686
14687    $tip.removeClass('fade top bottom left right in')
14688
14689    // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
14690    // this manually by checking the contents.
14691    if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
14692  }
14693
14694  Popover.prototype.hasContent = function () {
14695    return this.getTitle() || this.getContent()
14696  }
14697
14698  Popover.prototype.getContent = function () {
14699    var $e = this.$element
14700    var o  = this.options
14701
14702    return $e.attr('data-content')
14703        || (typeof o.content == 'function' ?
14704            o.content.call($e[0]) :
14705            o.content)
14706  }
14707
14708  Popover.prototype.arrow = function () {
14709    return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
14710  }
14711
14712
14713  // POPOVER PLUGIN DEFINITION
14714  // =========================
14715
14716  function Plugin(option) {
14717    return this.each(function () {
14718      var $this   = $(this)
14719      var data    = $this.data('bs.popover')
14720      var options = typeof option == 'object' && option
14721
14722      if (!data && /destroy|hide/.test(option)) return
14723      if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
14724      if (typeof option == 'string') data[option]()
14725    })
14726  }
14727
14728  var old = $.fn.popover
14729
14730  $.fn.popover             = Plugin
14731  $.fn.popover.Constructor = Popover
14732
14733
14734  // POPOVER NO CONFLICT
14735  // ===================
14736
14737  $.fn.popover.noConflict = function () {
14738    $.fn.popover = old
14739    return this
14740  }
14741
14742}(jQuery);
14743
14744/* ========================================================================
14745 * Bootstrap: scrollspy.js v3.4.1
14746 * https://getbootstrap.com/docs/3.4/javascript/#scrollspy
14747 * ========================================================================
14748 * Copyright 2011-2019 Twitter, Inc.
14749 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
14750 * ======================================================================== */
14751
14752
14753+function ($) {
14754  'use strict';
14755
14756  // SCROLLSPY CLASS DEFINITION
14757  // ==========================
14758
14759  function ScrollSpy(element, options) {
14760    this.$body          = $(document.body)
14761    this.$scrollElement = $(element).is(document.body) ? $(window) : $(element)
14762    this.options        = $.extend({}, ScrollSpy.DEFAULTS, options)
14763    this.selector       = (this.options.target || '') + ' .nav li > a'
14764    this.offsets        = []
14765    this.targets        = []
14766    this.activeTarget   = null
14767    this.scrollHeight   = 0
14768
14769    this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this))
14770    this.refresh()
14771    this.process()
14772  }
14773
14774  ScrollSpy.VERSION  = '3.4.1'
14775
14776  ScrollSpy.DEFAULTS = {
14777    offset: 10
14778  }
14779
14780  ScrollSpy.prototype.getScrollHeight = function () {
14781    return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
14782  }
14783
14784  ScrollSpy.prototype.refresh = function () {
14785    var that          = this
14786    var offsetMethod  = 'offset'
14787    var offsetBase    = 0
14788
14789    this.offsets      = []
14790    this.targets      = []
vendor: 10,384 bytes, lines 14791-15160
14791    this.scrollHeight = this.getScrollHeight()
14792
14793    if (!$.isWindow(this.$scrollElement[0])) {
14794      offsetMethod = 'position'
14795      offsetBase   = this.$scrollElement.scrollTop()
14796    }
14797
14798    this.$body
14799        .find(this.selector)
14800        .map(function () {
14801          var $el   = $(this)
14802          var href  = $el.data('target') || $el.attr('href')
14803          var $href = /^#./.test(href) && $(href)
14804
14805          return ($href
14806              && $href.length
14807              && $href.is(':visible')
14808              && [[$href[offsetMethod]().top + offsetBase, href]]) || null
14809        })
14810        .sort(function (a, b) { return a[0] - b[0] })
14811        .each(function () {
14812          that.offsets.push(this[0])
14813          that.targets.push(this[1])
14814        })
14815  }
14816
14817  ScrollSpy.prototype.process = function () {
14818    var scrollTop    = this.$scrollElement.scrollTop() + this.options.offset
14819    var scrollHeight = this.getScrollHeight()
14820    var maxScroll    = this.options.offset + scrollHeight - this.$scrollElement.height()
14821    var offsets      = this.offsets
14822    var targets      = this.targets
14823    var activeTarget = this.activeTarget
14824    var i
14825
14826    if (this.scrollHeight != scrollHeight) {
14827      this.refresh()
14828    }
14829
14830    if (scrollTop >= maxScroll) {
14831      return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
14832    }
14833
14834    if (activeTarget && scrollTop < offsets[0]) {
14835      this.activeTarget = null
14836      return this.clear()
14837    }
14838
14839    for (i = offsets.length; i--;) {
14840      activeTarget != targets[i]
14841      && scrollTop >= offsets[i]
14842      && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1])
14843      && this.activate(targets[i])
14844    }
14845  }
14846
14847  ScrollSpy.prototype.activate = function (target) {
14848    this.activeTarget = target
14849
14850    this.clear()
14851
14852    var selector = this.selector +
14853        '[data-target="' + target + '"],' +
14854        this.selector + '[href="' + target + '"]'
14855
14856    var active = $(selector)
14857        .parents('li')
14858        .addClass('active')
14859
14860    if (active.parent('.dropdown-menu').length) {
14861      active = active
14862          .closest('li.dropdown')
14863          .addClass('active')
14864    }
14865
14866    active.trigger('activate.bs.scrollspy')
14867  }
14868
14869  ScrollSpy.prototype.clear = function () {
14870    $(this.selector)
14871        .parentsUntil(this.options.target, '.active')
14872        .removeClass('active')
14873  }
14874
14875
14876  // SCROLLSPY PLUGIN DEFINITION
14877  // ===========================
14878
14879  function Plugin(option) {
14880    return this.each(function () {
14881      var $this   = $(this)
14882      var data    = $this.data('bs.scrollspy')
14883      var options = typeof option == 'object' && option
14884
14885      if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
14886      if (typeof option == 'string') data[option]()
14887    })
14888  }
14889
14890  var old = $.fn.scrollspy
14891
14892  $.fn.scrollspy             = Plugin
14893  $.fn.scrollspy.Constructor = ScrollSpy
14894
14895
14896  // SCROLLSPY NO CONFLICT
14897  // =====================
14898
14899  $.fn.scrollspy.noConflict = function () {
14900    $.fn.scrollspy = old
14901    return this
14902  }
14903
14904
14905  // SCROLLSPY DATA-API
14906  // ==================
14907
14908  $(window).on('load.bs.scrollspy.data-api', function () {
14909    $('[data-spy="scroll"]').each(function () {
14910      var $spy = $(this)
14911      Plugin.call($spy, $spy.data())
14912    })
14913  })
14914
14915}(jQuery);
14916
14917/* ========================================================================
14918 * Bootstrap: tab.js v3.4.1
14919 * https://getbootstrap.com/docs/3.4/javascript/#tabs
14920 * ========================================================================
14921 * Copyright 2011-2019 Twitter, Inc.
14922 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
14923 * ======================================================================== */
14924
14925
14926+function ($) {
14927  'use strict';
14928
14929  // TAB CLASS DEFINITION
14930  // ====================
14931
14932  var Tab = function (element) {
14933    // jscs:disable requireDollarBeforejQueryAssignment
14934    this.element = $(element)
14935    // jscs:enable requireDollarBeforejQueryAssignment
14936  }
14937
14938  Tab.VERSION = '3.4.1'
14939
14940  Tab.TRANSITION_DURATION = 150
14941
14942  Tab.prototype.show = function () {
14943    var $this    = this.element
14944    var $ul      = $this.closest('ul:not(.dropdown-menu)')
14945    var selector = $this.data('target')
14946
14947    if (!selector) {
14948      selector = $this.attr('href')
14949      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
14950    }
14951
14952    if ($this.parent('li').hasClass('active')) return
14953
14954    var $previous = $ul.find('.active:last a')
14955    var hideEvent = $.Event('hide.bs.tab', {
14956      relatedTarget: $this[0]
14957    })
14958    var showEvent = $.Event('show.bs.tab', {
14959      relatedTarget: $previous[0]
14960    })
14961
14962    $previous.trigger(hideEvent)
14963    $this.trigger(showEvent)
14964
14965    if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
14966
14967    var $target = $(document).find(selector)
14968
14969    this.activate($this.closest('li'), $ul)
14970    this.activate($target, $target.parent(), function () {
14971      $previous.trigger({
14972        type: 'hidden.bs.tab',
14973        relatedTarget: $this[0]
14974      })
14975      $this.trigger({
14976        type: 'shown.bs.tab',
14977        relatedTarget: $previous[0]
14978      })
14979    })
14980  }
14981
14982  Tab.prototype.activate = function (element, container, callback) {
14983    var $active    = container.find('> .active')
14984    var transition = callback
14985        && $.support.transition
14986        && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length)
14987
14988    function next() {
14989      $active
14990          .removeClass('active')
14991          .find('> .dropdown-menu > .active')
14992          .removeClass('active')
14993          .end()
14994          .find('[data-toggle="tab"]')
14995          .attr('aria-expanded', false)
14996
14997      element
14998          .addClass('active')
14999          .find('[data-toggle="tab"]')
15000          .attr('aria-expanded', true)
15001
15002      if (transition) {
15003        element[0].offsetWidth // reflow for transition
15004        element.addClass('in')
15005      } else {
15006        element.removeClass('fade')
15007      }
15008
15009      if (element.parent('.dropdown-menu').length) {
15010        element
15011            .closest('li.dropdown')
15012            .addClass('active')
15013            .end()
15014            .find('[data-toggle="tab"]')
15015            .attr('aria-expanded', true)
15016      }
15017
15018      callback && callback()
15019    }
15020
15021    $active.length && transition ?
15022        $active
15023            .one('bsTransitionEnd', next)
15024            .emulateTransitionEnd(Tab.TRANSITION_DURATION) :
15025        next()
15026
15027    $active.removeClass('in')
15028  }
15029
15030
15031  // TAB PLUGIN DEFINITION
15032  // =====================
15033
15034  function Plugin(option) {
15035    return this.each(function () {
15036      var $this = $(this)
15037      var data  = $this.data('bs.tab')
15038
15039      if (!data) $this.data('bs.tab', (data = new Tab(this)))
15040      if (typeof option == 'string') data[option]()
15041    })
15042  }
15043
15044  var old = $.fn.tab
15045
15046  $.fn.tab             = Plugin
15047  $.fn.tab.Constructor = Tab
15048
15049
15050  // TAB NO CONFLICT
15051  // ===============
15052
15053  $.fn.tab.noConflict = function () {
15054    $.fn.tab = old
15055    return this
15056  }
15057
15058
15059  // TAB DATA-API
15060  // ============
15061
15062  var clickHandler = function (e) {
15063    e.preventDefault()
15064    Plugin.call($(this), 'show')
15065  }
15066
15067  $(document)
15068      .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler)
15069      .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)
15070
15071}(jQuery);
15072
15073/* ========================================================================
15074 * Bootstrap: affix.js v3.4.1
15075 * https://getbootstrap.com/docs/3.4/javascript/#affix
15076 * ========================================================================
15077 * Copyright 2011-2019 Twitter, Inc.
15078 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
15079 * ======================================================================== */
15080
15081
15082+function ($) {
15083  'use strict';
15084
15085  // AFFIX CLASS DEFINITION
15086  // ======================
15087
15088  var Affix = function (element, options) {
15089    this.options = $.extend({}, Affix.DEFAULTS, options)
15090
15091    var target = this.options.target === Affix.DEFAULTS.target ? $(this.options.target) : $(document).find(this.options.target)
15092
15093    this.$target = target
15094        .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
15095        .on('click.bs.affix.data-api',  $.proxy(this.checkPositionWithEventLoop, this))
15096
15097    this.$element     = $(element)
15098    this.affixed      = null
15099    this.unpin        = null
15100    this.pinnedOffset = null
15101
15102    this.checkPosition()
15103  }
15104
15105  Affix.VERSION  = '3.4.1'
15106
15107  Affix.RESET    = 'affix affix-top affix-bottom'
15108
15109  Affix.DEFAULTS = {
15110    offset: 0,
15111    target: window
15112  }
15113
15114  Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) {
15115    var scrollTop    = this.$target.scrollTop()
15116    var position     = this.$element.offset()
15117    var targetHeight = this.$target.height()
15118
15119    if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false
15120
15121    if (this.affixed == 'bottom') {
15122      if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom'
15123      return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom'
15124    }
15125
15126    var initializing   = this.affixed == null
15127    var colliderTop    = initializing ? scrollTop : position.top
15128    var colliderHeight = initializing ? targetHeight : height
15129
15130    if (offsetTop != null && scrollTop <= offsetTop) return 'top'
15131    if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom'
15132
15133    return false
15134  }
15135
15136  Affix.prototype.getPinnedOffset = function () {
15137    if (this.pinnedOffset) return this.pinnedOffset
15138    this.$element.removeClass(Affix.RESET).addClass('affix')
15139    var scrollTop = this.$target.scrollTop()
15140    var position  = this.$element.offset()
15141    return (this.pinnedOffset = position.top - scrollTop)
15142  }
15143
15144  Affix.prototype.checkPositionWithEventLoop = function () {
15145    setTimeout($.proxy(this.checkPosition, this), 1)
15146  }
15147
15148  Affix.prototype.checkPosition = function () {
15149    if (!this.$element.is(':visible')) return
15150
15151    var height       = this.$element.height()
15152    var offset       = this.options.offset
15153    var offsetTop    = offset.top
15154    var offsetBottom = offset.bottom
15155    var scrollHeight = Math.max($(document).height(), $(document.body).height())
15156
15157    if (typeof offset != 'object')         offsetBottom = offsetTop = offset
15158    if (typeof offsetTop == 'function')    offsetTop    = offset.top(this.$element)
15159    if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)
15160
15161    var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom)
15162
15163    if (this.affixed != affix) {
15164      if (this.unpin != null) this.$element.css('top', '')
15165
15166      var affixType = 'affix' + (affix ? '-' + affix : '')
15167      var e         = $.Event(affixType + '.bs.affix')
15168
15169      this.$element.trigger(e)
15170
15171      if (e.isDefaultPrevented()) return
15172
15173      this.affixed = affix
15174      this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
15175
15176      this.$element
15177          .removeClass(Affix.RESET)
15178          .addClass(affixType)
15179          .trigger(affixType.replace('affix', 'affixed') + '.bs.affix')
15180    }
15181
15182    if (affix == 'bottom') {
15183      this.$element.offset({
15184        top: scrollHeight - height - offsetBottom
15185      })
15186    }
15187  }
15188
15189
15190  // AFFIX PLUGIN DEFINITION
15191  // =======================
15192
15193  function Plugin(option) {
15194    return this.each(function () {
15195      var $this   = $(this)
15196      var data    = $this.data('bs.affix')
15197      var options = typeof option == 'object' && option
15198
15199      if (!data) $this.data('bs.affix', (data = new Affix(this, options)))
15200      if (typeof option == 'string') data[option]()
15201    })
15202  }
15203
15204  var old = $.fn.affix
15205
15206  $.fn.affix             = Plugin
15207  $.fn.affix.Constructor = Affix
15208
15209
15210  // AFFIX NO CONFLICT
15211  // =================
15212
15213  $.fn.affix.noConflict = function () {
15214    $.fn.affix = old
15215    return this
15216  }
15217
15218
15219  // AFFIX DATA-API
15220  // ==============
15221
15222  $(window).on('load', function () {
15223    $('[data-spy="affix"]').each(function () {
15224      var $spy = $(this)
15225      var data = $spy.data()
15226
15227      data.offset = data.offset || {}
15228
15229      if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom
15230      if (data.offsetTop    != null) data.offset.top    = data.offsetTop
15231
15232      Plugin.call($spy, data)
15233    })
15234  })
15235
15236}(jQuery);
15237
15238/*
15239 * jQuery Templating Plugin
15240 * Copyright 2010, John Resig
15241 * Dual licensed under the MIT or GPL Version 2 licenses.
15242 */
15243(function( jQuery, undefined ){
15244    var oldManip = jQuery.fn.domManip, tmplItmAtt = "_tmplitem", htmlExpr = /^[^<]*(<[\w\W]+>)[^>]*$|\{\{\! /,
15245        newTmplItems = {}, wrappedItems = {}, appendToTmplItems, topTmplItem = { key: 0, data: {} }, itemKey = 0, cloneIndex = 0, stack = [];
15246
15247    function newTmplItem( options, parentItem, fn, data ) {
15248        // Returns a template item data structure for a new rendered instance of a template (a 'template item').
15249        // The content field is a hierarchical array of strings and nested items (to be
15250        // removed and replaced by nodes field of dom elements, once inserted in DOM).
15251        var newItem = {
15252            data: data || (parentItem ? parentItem.data : {}),
15253            _wrap: parentItem ? parentItem._wrap : null,
15254            tmpl: null,
15255            parent: parentItem || null,
15256            nodes: [],
15257            calls: tiCalls,
15258            nest: tiNest,
15259            wrap: tiWrap,
15260            html: tiHtml,
15261            update: tiUpdate
15262        };
15263        if ( options ) {
15264            jQuery.extend( newItem, options, { nodes: [], parent: parentItem } );
15265        }
15266        if ( fn ) {
15267            // Build the hierarchical content to be used during insertion into DOM
15268            newItem.tmpl = fn;
15269            newItem._ctnt = newItem._ctnt || newItem.tmpl( jQuery, newItem );
15270            newItem.key = ++itemKey;
15271            // Keep track of new template item, until it is stored as jQuery Data on DOM element
15272            (stack.length ? wrappedItems : newTmplItems)[itemKey] = newItem;
15273        }
15274        return newItem;
15275    }
15276
15277    // Override appendTo etc., in order to provide support for targeting multiple elements. (This code would disappear if integrated in jquery core).
15278    jQuery.each({
15279        appendTo: "append",
15280        prependTo: "prepend",
15281        insertBefore: "before",
15282        insertAfter: "after",
15283        replaceAll: "replaceWith"
15284    }, function( name, original ) {
15285        jQuery.fn[ name ] = function( selector ) {
15286            var ret = [], insert = jQuery( selector ), elems, i, l, tmplItems,
15287                parent = this.length === 1 && this[0].parentNode;
15288
15289            appendToTmplItems = newTmplItems || {};
15290            if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
15291                insert[ original ]( this[0] );
15292                ret = this;
15293            } else {
15294                for ( i = 0, l = insert.length; i < l; i++ ) {
15295                    cloneIndex = i;
15296                    elems = (i > 0 ? this.clone(true) : this).get();
15297                    jQuery.fn[ original ].apply( jQuery(insert[i]), elems );
15298                    ret = ret.concat( elems );
15299                }
15300                cloneIndex = 0;
15301                ret = this.pushStack( ret, name, insert.selector );
15302            }
15303            tmplItems = appendToTmplItems;
15304            appendToTmplItems = null;
15305            jQuery.tmpl.complete( tmplItems );
15306            return ret;
15307        };
15308    });
15309
15310    jQuery.fn.extend({
15311        // Use first wrapped element as template markup.
15312        // Return wrapped set of template items, obtained by rendering template against data.
15313        tmpl: function( data, options, parentItem ) {
15314            return jQuery.tmpl( this[0], data, options, parentItem );
15315        },
15316
15317        // Find which rendered template item the first wrapped DOM element belongs to
15318        tmplItem: function() {
15319            return jQuery.tmplItem( this[0] );
15320        },
15321
15322        // Consider the first wrapped element as a template declaration, and get the compiled template or store it as a named template.
15323        template: function( name ) {
15324            return jQuery.template( name, this[0] );
15325        },
15326
15327        domManip: function( args, table, callback, options ) {
15328            // This appears to be a bug in the appendTo, etc. implementation
15329            // it should be doing .call() instead of .apply(). See #6227
15330            if ( args[0] && args[0].nodeType ) {
15331                var dmArgs = jQuery.makeArray( arguments ), argsLength = args.length, i = 0, tmplItem;
15332                while ( i < argsLength && !(tmplItem = jQuery.data( args[i++], "tmplItem" ))) {}
15333                if ( argsLength > 1 ) {
15334                    dmArgs[0] = [jQuery.makeArray( args )];
15335                }
15336                if ( tmplItem && cloneIndex ) {
15337                    dmArgs[2] = function( fragClone ) {
15338                        // Handler called by oldManip when rendered template has been inserted into DOM.
15339                        jQuery.tmpl.afterManip( this, fragClone, callback );
15340                    };
15341                }
15342                oldManip.apply( this, dmArgs );
15343            } else {
15344                oldManip.apply( this, arguments );
15345            }
15346            cloneIndex = 0;
15347            if ( !appendToTmplItems ) {
15348                jQuery.tmpl.complete( newTmplItems );
15349            }
15350            return this;
15351        }
15352    });
15353
15354    jQuery.extend({
15355        // Return wrapped set of template items, obtained by rendering template against data.
15356        tmpl: function( tmpl, data, options, parentItem ) {
15357            var ret, topLevel = !parentItem;
15358            if ( topLevel ) {
15359                // This is a top-level tmpl call (not from a nested template using {{tmpl}})
15360                parentItem = topTmplItem;
15361                tmpl = jQuery.template[tmpl] || jQuery.template( null, tmpl );
15362                wrappedItems = {}; // Any wrapped items will be rebuilt, since this is top level
15363            } else if ( !tmpl ) {
15364                // The template item is already associated with DOM - this is a refresh.
15365                // Re-evaluate rendered template for the parentItem
15366                tmpl = parentItem.tmpl;
15367                newTmplItems[parentItem.key] = parentItem;
15368                parentItem.nodes = [];
15369                if ( parentItem.wrapped ) {
15370                    updateWrapped( parentItem, parentItem.wrapped );
15371                }
15372                // Rebuild, without creating a new template item
15373                return jQuery( build( parentItem, null, parentItem.tmpl( jQuery, parentItem ) ));
15374            }
15375            if ( !tmpl ) {
15376                return []; // Could throw...
15377            }
15378            if ( typeof data === "function" ) {
15379                data = data.call( parentItem || {} );
15380            }
15381            if ( options && options.wrapped ) {
15382                updateWrapped( options, options.wrapped );
15383            }
15384            ret = jQuery.isArray( data ) ?
15385                jQuery.map( data, function( dataItem ) {
15386                    return dataItem ? newTmplItem( options, parentItem, tmpl, dataItem ) : null;
15387                }) :
15388                [ newTmplItem( options, parentItem, tmpl, data ) ];
15389            return topLevel ? jQuery( build( parentItem, null, ret ) ) : ret;
15390        },
15391
15392        // Return rendered template item for an element.
15393        tmplItem: function( elem ) {
15394            var tmplItem;
15395            if ( elem instanceof jQuery ) {
15396                elem = elem[0];
15397            }
15398            while ( elem && elem.nodeType === 1 && !(tmplItem = jQuery.data( elem, "tmplItem" )) && (elem = elem.parentNode) ) {}
15399            return tmplItem || topTmplItem;
15400        },
15401
15402        // Set:
15403        // Use $.template( name, tmpl ) to cache a named template,
15404        // where tmpl is a template string, a script element or a jQuery instance wrapping a script element, etc.
15405        // Use $( "selector" ).template( name ) to provide access by name to a script block template declaration.
15406
15407        // Get:
15408        // Use $.template( name ) to access a cached template.
15409        // Also $( selectorToScriptBlock ).template(), or $.template( null, templateString )
15410        // will return the compiled template, without adding a name reference.
15411        // If templateString includes at least one HTML tag, $.template( templateString ) 
vendor: 15,878 bytes, lines 15411-15741
15411is equivalent
15412        // to $.template( null, templateString )
15413        template: function( name, tmpl ) {
15414            if (tmpl) {
15415                // Compile template and associate with name
15416                if ( typeof tmpl === "string" ) {
15417                    // This is an HTML string being passed directly in.
15418                    tmpl = buildTmplFn( tmpl )
15419                } else if ( tmpl instanceof jQuery ) {
15420                    tmpl = tmpl[0] || {};
15421                }
15422                if ( tmpl.nodeType ) {
15423                    // If this is a template block, use cached copy, or generate tmpl function and cache.
15424                    tmpl = jQuery.data( tmpl, "tmpl" ) || jQuery.data( tmpl, "tmpl", buildTmplFn( tmpl.innerHTML ));
15425                }
15426                return typeof name === "string" ? (jQuery.template[name] = tmpl) : tmpl;
15427            }
15428            // Return named compiled template
15429            return name ? (typeof name !== "string" ? jQuery.template( null, name ):
15430                (jQuery.template[name] ||
15431                    // If not in map, treat as a selector. (If integrated with core, use quickExpr.exec)
15432                    jQuery.template( null, htmlExpr.test( name ) ? name : jQuery( name )))) : null;
15433        },
15434
15435        encode: function( text ) {
15436            // Do HTML encoding replacing < > & and ' and " by corresponding entities.
15437            return ("" + text).split("<").join("&lt;").split(">").join("&gt;").split('"').join("&#34;").split("'").join("&#39;");
15438        }
15439    });
15440
15441    jQuery.extend( jQuery.tmpl, {
15442        tag: {
15443            "tmpl": {
15444                _default: { $2: "null" },
15445                open: "if($notnull_1){_=_.concat($item.nest($1,$2));}"
15446                // tmpl target parameter can be of type function, so use $1, not $1a (so not auto detection of functions)
15447                // This means that {{tmpl foo}} treats foo as a template (which IS a function).
15448                // Explicit parens can be used if foo is a function that returns a template: {{tmpl foo()}}.
15449            },
15450            "wrap": {
15451                _default: { $2: "null" },
15452                open: "$item.calls(_,$1,$2);_=[];",
15453                close: "call=$item.calls();_=call._.concat($item.wrap(call,_));"
15454            },
15455            "each": {
15456                _default: { $2: "$index, $value" },
15457                open: "if($notnull_1){$.each($1a,function($2){with(this){",
15458                close: "}});}"
15459            },
15460            "if": {
15461                open: "if(($notnull_1) && $1a){",
15462                close: "}"
15463            },
15464            "else": {
15465                _default: { $1: "true" },
15466                open: "}else if(($notnull_1) && $1a){"
15467            },
15468            "html": {
15469                // Unecoded expression evaluation.
15470                open: "if($notnull_1){_.push($1a);}"
15471            },
15472            "=": {
15473                // Encoded expression evaluation. Abbreviated form is ${}.
15474                _default: { $1: "$data" },
15475                open: "if($notnull_1){_.push($.encode($1a));}"
15476            },
15477            "!": {
15478                // Comment tag. Skipped by parser
15479                open: ""
15480            }
15481        },
15482
15483        // This stub can be overridden, e.g. in jquery.tmplPlus for providing rendered events
15484        complete: function( items ) {
15485            newTmplItems = {};
15486        },
15487
15488        // Call this from code which overrides domManip, or equivalent
15489        // Manage cloning/storing template items etc.
15490        afterManip: function afterManip( elem, fragClone, callback ) {
15491            // Provides cloned fragment ready for fixup prior to and after insertion into DOM
15492            var content = fragClone.nodeType === 11 ?
15493                jQuery.makeArray(fragClone.childNodes) :
15494                fragClone.nodeType === 1 ? [fragClone] : [];
15495
15496            // Return fragment to original caller (e.g. append) for DOM insertion
15497            callback.call( elem, fragClone );
15498
15499            // Fragment has been inserted:- Add inserted nodes to tmplItem data structure. Replace inserted element annotations by jQuery.data.
15500            storeTmplItems( content );
15501            cloneIndex++;
15502        }
15503    });
15504
15505    //========================== Private helper functions, used by code above ==========================
15506
15507    function build( tmplItem, nested, content ) {
15508        // Convert hierarchical content into flat string array
15509        // and finally return array of fragments ready for DOM insertion
15510        var frag, ret = content ? jQuery.map( content, function( item ) {
15511            return (typeof item === "string") ?
15512                // Insert template item annotations, to be converted to jQuery.data( "tmplItem" ) when elems are inserted into DOM.
15513                (tmplItem.key ? item.replace( /(<\w+)(?=[\s>])(?![^>]*_tmplitem)([^>]*)/g, "$1 " + tmplItmAtt + "=\"" + tmplItem.key + "\" $2" ) : item) :
15514                // This is a child template item. Build nested template.
15515                build( item, tmplItem, item._ctnt );
15516        }) :
15517            // If content is not defined, insert tmplItem directly. Not a template item. May be a string, or a string array, e.g. from {{html $item.html()}}.
15518            tmplItem;
15519        if ( nested ) {
15520            return ret;
15521        }
15522
15523        // top-level template
15524        ret = ret.join("");
15525
15526        // Support templates which have initial or final text nodes, or consist only of text
15527        // Also support HTML entities within the HTML markup.
15528        ret.replace( /^\s*([^<\s][^<]*)?(<[\w\W]+>)([^>]*[^>\s])?\s*$/, function( all, before, middle, after) {
15529            frag = jQuery( middle ).get();
15530
15531            storeTmplItems( frag );
15532            if ( before ) {
15533                frag = unencode( before ).concat(frag);
15534            }
15535            if ( after ) {
15536                frag = frag.concat(unencode( after ));
15537            }
15538        });
15539        return frag ? frag : unencode( ret );
15540    }
15541
15542    function unencode( text ) {
15543        // Use createElement, since createTextNode will not render HTML entities correctly
15544        var el = document.createElement( "div" );
15545        el.innerHTML = text;
15546        return jQuery.makeArray(el.childNodes);
15547    }
15548
15549    // Generate a reusable function that will serve to render a template against data
15550    function buildTmplFn( markup ) {
15551        return new Function("jQuery","$item",
15552            "var $=jQuery,call,_=[],$data=$item.data;" +
15553
15554                // Introduce the data as local variables using with(){}
15555                "with($data){_.push('" +
15556
15557                // Convert the template into pure JavaScript
15558                jQuery.trim(markup)
15559                    .replace( /([\\'])/g, "\\$1" )
15560                    .replace( /[\r\t\n]/g, " " )
15561                    .replace( /\$\{([^\}]*)\}/g, "{{= $1}}" )
15562                    .replace( /\{\{(\/?)(\w+|.)(?:\(((?:[^\}]|\}(?!\}))*?)?\))?(?:\s+(.*?)?)?(\(((?:[^\}]|\}(?!\}))*?)\))?\s*\}\}/g,
15563                    function( all, slash, type, fnargs, target, parens, args ) {
15564                        var tag = jQuery.tmpl.tag[ type ], def, expr, exprAutoFnDetect;
15565                        if ( !tag ) {
15566                            throw "Template command not found: " + type;
15567                        }
15568                        def = tag._default || [];
15569                        if ( parens && !/\w$/.test(target)) {
15570                            target += parens;
15571                            parens = "";
15572                        }
15573                        if ( target ) {
15574                            target = unescape( target );
15575                            args = args ? ("," + unescape( args ) + ")") : (parens ? ")" : "");
15576                            // Support for target being things like a.toLowerCase();
15577                            // In that case don't call with template item as 'this' pointer. Just evaluate...
15578                            expr = parens ? (target.indexOf(".") > -1 ? target + parens : ("(" + target + ").call($item" + args)) : target;
15579                            exprAutoFnDetect = parens ? expr : "(typeof(" + target + ")==='function'?(" + target + ").call($item):(" + target + "))";
15580                        } else {
15581                            exprAutoFnDetect = expr = def.$1 || "null";
15582                        }
15583                        fnargs = unescape( fnargs );
15584                        return "');" +
15585                            tag[ slash ? "close" : "open" ]
15586                                .split( "$notnull_1" ).join( target ? "typeof(" + target + ")!=='undefined' && (" + target + ")!=null" : "true" )
15587                                .split( "$1a" ).join( exprAutoFnDetect )
15588                                .split( "$1" ).join( expr )
15589                                .split( "$2" ).join( fnargs ?
15590                                    fnargs.replace( /\s*([^\(]+)\s*(\((.*?)\))?/g, function( all, name, parens, params ) {
15591                                        params = params ? ("," + params + ")") : (parens ? ")" : "");
15592                                        return params ? ("(" + name + ").call($item" + params) : all;
15593                                    })
15594                                    : (def.$2||"")
15595                                ) +
15596                            "_.push('";
15597                    }) +
15598                "');}return _;"
15599        );
15600    }
15601    function updateWrapped( options, wrapped ) {
15602        // Build the wrapped content.
15603        options._wrap = build( options, true,
15604            // Suport imperative scenario in which options.wrapped can be set to a selector or an HTML string.
15605            jQuery.isArray( wrapped ) ? wrapped : [htmlExpr.test( wrapped ) ? wrapped : jQuery( wrapped ).html()]
15606        ).join("");
15607    }
15608
15609    function unescape( args ) {
15610        return args ? args.replace( /\\'/g, "'").replace(/\\\\/g, "\\" ) : null;
15611    }
15612    function outerHtml( elem ) {
15613        var div = document.createElement("div");
15614        div.appendChild( elem.cloneNode(true) );
15615        return div.innerHTML;
15616    }
15617
15618    // Store template items in jQuery.data(), ensuring a unique tmplItem data data structure for each rendered template instance.
15619    function storeTmplItems( content ) {
15620        var keySuffix = "_" + cloneIndex, elem, elems, newClonedItems = {}, i, l, m;
15621        for ( i = 0, l = content.length; i < l; i++ ) {
15622            if ( (elem = content[i]).nodeType !== 1 ) {
15623                continue;
15624            }
15625            elems = elem.getElementsByTagName("*");
15626            for ( m = elems.length - 1; m >= 0; m-- ) {
15627                processItemKey( elems[m] );
15628            }
15629            processItemKey( elem );
15630        }
15631        function processItemKey( el ) {
15632            var pntKey, pntNode = el, pntItem, tmplItem, key;
15633            // Ensure that each rendered template inserted into the DOM has its own template item,
15634            if ( (key = el.getAttribute( tmplItmAtt ))) {
15635                while ( pntNode.parentNode && (pntNode = pntNode.parentNode).nodeType === 1 && !(pntKey = pntNode.getAttribute( tmplItmAtt ))) { }
15636                if ( pntKey !== key ) {
15637                    // The next ancestor with a _tmplitem expando is on a different key than this one.
15638                    // So this is a top-level element within this template item
15639                    // Set pntNode to the key of the parentNode, or to 0 if pntNode.parentNode is null, or pntNode is a fragment.
15640                    pntNode = pntNode.parentNode ? (pntNode.nodeType === 11 ? 0 : (pntNode.getAttribute( tmplItmAtt ) || 0)) : 0;
15641                    if ( !(tmplItem = newTmplItems[key]) ) {
15642                        // The item is for wrapped content, and was copied from the temporary parent wrappedItem.
15643                        tmplItem = wrappedItems[key];
15644                        tmplItem = newTmplItem( tmplItem, newTmplItems[pntNode]||wrappedItems[pntNode], null, true );
15645                        tmplItem.key = ++itemKey;
15646                        newTmplItems[itemKey] = tmplItem;
15647                    }
15648                    if ( cloneIndex ) {
15649                        cloneTmplItem( key );
15650                    }
15651                }
15652                el.removeAttribute( tmplItmAtt );
15653            } else if ( cloneIndex && (tmplItem = jQuery.data( el, "tmplItem" )) ) {
15654                // This was a rendered element, cloned during append or appendTo etc.
15655                // TmplItem stored in jQuery data has already been cloned in cloneCopyEvent. We must replace it with a fresh cloned tmplItem.
15656                cloneTmplItem( tmplItem.key );
15657                newTmplItems[tmplItem.key] = tmplItem;
15658                pntNode = jQuery.data( el.parentNode, "tmplItem" );
15659                pntNode = pntNode ? pntNode.key : 0;
15660            }
15661            if ( tmplItem ) {
15662                pntItem = tmplItem;
15663                // Find the template item of the parent element.
15664                // (Using !=, not !==, since pntItem.key is number, and pntNode may be a string)
15665                while ( pntItem && pntItem.key != pntNode ) {
15666                    // Add this element as a top-level node for this rendered template item, as well as for any
15667                    // ancestor items between this item and the item of its parent element
15668                    pntItem.nodes.push( el );
15669                    pntItem = pntItem.parent;
15670                }
15671                // Delete content built during rendering - reduce API surface area and memory use, and avoid exposing of stale data after rendering...
15672                delete tmplItem._ctnt;
15673                delete tmplItem._wrap;
15674                // Store template item as jQuery data on the element
15675                jQuery.data( el, "tmplItem", tmplItem );
15676            }
15677            function cloneTmplItem( key ) {
15678                key = key + keySuffix;
15679                tmplItem = newClonedItems[key] =
15680                    (newClonedItems[key] || newTmplItem( tmplItem, newTmplItems[tmplItem.parent.key + keySuffix] || tmplItem.parent, null, true ));
15681            }
15682        }
15683    }
15684
15685    //---- Helper functions for template item ----
15686
15687    function tiCalls( content, tmpl, data, options ) {
15688        if ( !content ) {
15689            return stack.pop();
15690        }
15691        stack.push({ _: content, tmpl: tmpl, item:this, data: data, options: options });
15692    }
15693
15694    function tiNest( tmpl, data, options ) {
15695        // nested template, using {{tmpl}} tag
15696        return jQuery.tmpl( jQuery.template( tmpl ), data, options, this );
15697    }
15698
15699    function tiWrap( call, wrapped ) {
15700        // nested template, using {{wrap}} tag
15701        var options = call.options || {};
15702        options.wrapped = wrapped;
15703        // Apply the template, which may incorporate wrapped content,
15704        return jQuery.tmpl( jQuery.template( call.tmpl ), call.data, options, call.item );
15705    }
15706
15707    function tiHtml( filter, textOnly ) {
15708        var wrapped = this._wrap;
15709        return jQuery.map(
15710            jQuery( jQuery.isArray( wrapped ) ? wrapped.join("") : wrapped ).filter( filter || "*" ),
15711            function(e) {
15712                return textOnly ?
15713                    e.innerText || e.textContent :
15714                    e.outerHTML || outerHtml(e);
15715            });
15716    }
15717
15718    function tiUpdate() {
15719        var coll = this.nodes;
15720        jQuery.tmpl( null, null, null, this).insertBefore( coll[0] );
15721        jQuery( coll ).remove();
15722    }
15723})( jQuery );
15724/*!
15725 * jQuery Mobile 1.4.1
15726 * Git HEAD hash: 18c1e32bfc4e0e92756dedc105d799131607f5bb <> Date: Wed Feb 12 2014 22:15:20 UTC
15727 * http://jquerymobile.com
15728 *
15729 * Copyright 2010, 2014 jQuery Foundation, Inc. and other contributors
15730 * Released under the MIT license.
15731 * http://jquery.org/license
15732 *
15733 */
15734/*!
15735 * code snippet for just swipe-right and swipe-left
15736 */
15737(function( $, window, undefined ) {
15738    var $document = $(document),
15739        TouchUtil = xfalib.ut.TouchUtil,
15740        touchStartEvent = TouchUtil.POINTER_DOWN,
15741        touchStopEvent = TouchUtil.POINTER_UP,
15742        touchMoveEvent = TouchUtil.POINTER_MOVE;
15743
15744    function triggerCustomEvent( obj, eventType, event, bubble ) {
15745        var originalType = event.type;
15746        event.type = eventType;
15747        if ( bubble ) {
15748            $.event.trigger( event, undefined, obj );
15749        } else {
15750            $.event.dispatch.call( obj, event );
15751        }
15752        event.type = originalType;
15753    }
15754
15755    $.event.special.swipe = {
15756
15757        // More than this horizontal displacement, and we will suppress scrolling.
15758        scrollSupressionThreshold: 30,
15759
15760        // More time than this, and it isn't a swipe.
15761        durationThreshold: 1000,
15762
15763        // Swipe horizontal displacement must be more than this.
15764        horizontalDistanceThreshold: 30,
15765
15766        // Swipe vertical displacement must be less than this.
15767        verticalDistanceThreshold: 30,
15768
15769        getLocation: function ( event ) {
15770            var winPageX = window.pageXOffset,
15771                winPageY = window.pageYOffset,
15772                x = event.clientX || event.originalEvent.clientX,
15773                y = event.clientY || event.originalEvent.clientY;
15774
15775            if ( event.pageY === 0 && Math.floor( y ) > Math.floor( event.pageY ) ||
15776                event.pageX === 0 && Math.floor( x ) > Math.floor( event.pageX ) ) {
15777
15778                // iOS4 clientX/clientY have the value that should have been
15779                // in pageX/pageY. While pageX/page/ have the value 0
15780                x = x - winPageX;
15781                y = y - winPageY;
15782            } else if ( y < ( event.pageY - winPageY) || x < ( event.pageX - winPageX ) ) {
15783
15784                // Some Android browsers have totally bogus values for clientX/Y
15785                // when scrolling/zooming a page. Detectable since clientX/clientY
15786                // should never be smaller than pageX/pageY minus page scroll
15787                x = event.pageX - winPageX;
15788                y = event.pageY - winPageY;
15789            }
15790
15791            return {
15792                x: x,
15793                y: y
15794            };
15795        },
15796
15797        start: function( event ) {
15798            var data = event.originalEvent.touches ?
15799                    event.originalEvent.touches[ 0 ] : event,
15800                location = $.event.special.swipe.getLocation( data );
15801            return {
15802                time: ( new Date() ).getTime(),
15803                coords: [ location.x, location.y ],
15804                origin: $( event.target )
15805            };
15806        },
15807
15808        stop: function( event ) {
15809            var data = event.originalEvent.touches ?
15810                    event.originalEvent.touches[ 0 ] : event,
15811                location = $.event.special.swipe.getLocation( data );
15812            return {
15813                time: ( new Date() ).getTime(),
15814                coords: [ location.x, location.y ]
15815            };
15816        },
15817
15818        handleSwipe: function( start, stop, thisObject, origTarget ) {
15819            if ( stop.time - start.time < $.event.special.swipe.durationThreshold &&
15820                Math.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.horizontalDistanceThreshold &&
15821                Math.abs( start.coords[ 1 ] - stop.coords[ 1 ] ) < $.event.special.swipe.verticalDistanceThreshold ) {
15822                var direction = start.coords[0] > stop.coords[ 0 ] ? "swipeleft" : "swiperight";
15823
15824                triggerCustomEvent( thisObject, direction,$.Event( direction, { target: origTarget, swipestart: start, swipestop: stop } ), true );
15825                return true;
15826            }
15827            return false;
15828
15829        },
15830
15831        // This serves as a flag to ensure that at most one swipe event event is
15832        // in work at any given time
15833        eventInProgress: false,
15834
15835        setup: function() {
15836            var events,
15837                thisObject = this,
15838                $this = $( thisObject ),
15839                context = {};
15840
15841            // Retrieve the events data for this element and add the swipe context
15842            events = $.data( this, "mobile-events" );
15843            if ( !events ) {
15844                events = { length: 0 };
15845                $.data( this, "mobile-events", events );
15846            }
15847            events.length++;
15848            events.swipe = context;
15849
15850            context.start = function( event ) {
15851                // If its not a touch event on IE, ignore
15852                if (event.originalEvent.pointerType !== undefined && !(event.originalEvent.pointerType === 2 || event.originalEvent.pointerType === "touch")) {
15853                    return;
15854                }
15855
15856                // Bail if we're already working on a swipe event
15857                if ( $.event.special.swipe.eventInProgress ) {
15858                    return;
15859                }
15860                $.event.special.swipe.eventInProgress = true;
15861
15862                var stop,
15863                    start = $.event.special.swipe.start( event ),
15864                    origTarget = event.target,
15865                    emitted = false;
15866
15867                context.move = function( event ) {
15868                    if ( !start ) {
15869                        return;
15870                    }
15871
15872                    stop = $.event.special.swipe.stop( event );
15873                    if ( !emitted ) {
15874                        emitted = $.event.special.swipe.handleSwipe( start, stop, thisObject, origTarget );
15875                        if ( emitted ) {
15876
15877                            // Reset the context to make way for the next swipe event
15878                            $.event.special.swipe.eventInProgress = false;
15879                        }
15880                    }
15881                    // prevent scrolling
15882                    if ( Math.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.scrollSupressionThreshold ) {
15883                        event.preventDefault();
15884                    }
15885                };
15886
15887                context.stop = function() {
15888                    emitted = true;
15889
15890                    // Reset the context to make way for the next swipe event
15891                    $.event.special.swipe.eventInProgress = false;
15892                    $document.off( touchMoveEvent, context.move );
15893                    context.move = null;
15894                };
15895
15896                $document.on( touchMoveEvent, context.move )
15897                    .one( touchStopEvent, context.stop );
15898            };
15899            $this.on( touchStartEvent, context.start );
15900        },
15901
15902        teardown: function() {
15903            var events, context;
15904
15905            events = $.data( this, "mobile-events" );
15906            if ( events ) {
15907                context = events.swipe;
15908                delete events.swipe;
15909                events.length--;
15910                if ( events.length === 0 ) {
15911                    $.removeData( this, "mobile-events" );
15912                }
15913            }
15914
15915            if ( context ) {
15916                if ( context.start ) {
15917                    $( this ).off( touchStartEvent, context.start );
15918                }
15919                if ( context.move ) {
15920                    $document.off( touchMoveEvent, context.move );
15921                }
15922                if ( context.stop ) {
15923                    $document.off( touchStopEvent, context.stop );
15924                }
15925            }
15926        }
15927    };
15928    $.each({
15929        swipeleft: "swipe",
15930        swiperight: "swipe"
15931    }, function( event, sourceEvent ) {
15932		// Ignoring mouse events, for all browsers except IE 10>, which has pointer events.
15933        if (TouchUtil.POINTER_DOWN !== "mousedown") {
15934            $.event.special[ event ] = {
15935                setup: function() {
15936                    $( this ).on( sourceEvent, $.noop );
15937                },
15938                teardown: function() {
15939                    $( this ).off( sourceEvent );
15940                }
15941            };
15942        }
15943    });
15944
15945})( jQuery, this );
15946
15947/*************************************************************************
15948 *
15949 * ADOBE CONFIDENTIAL
15950 * __________________
15951 *
15952 *  Copyright 2017 Adobe Systems Incorporated
15953 *  All Rights Reserved.
15954 *
15955 * NOTICE:  All information contained herein is, and remains
15956 * the property of Adobe Systems Incorporated and its suppliers,
15957 * if any.  The intellectual and technical concepts contained
15958 * herein are proprietary to Adobe Systems Incorporated and its
15959 * suppliers and may be covered by U.S. and Foreign Patents,
15960 * patents in process, and are protected by trade secret or copyright law.
15961 * Dissemination of this information or reproduction of this material
15962 * is strictly forbidden unless prior written permission is obtained
15963 * from Adobe Systems Incorporated.
15964 **************************************************************************/
15965
15966(function (window, $) {
15967
15968    var DefaultPanelProvider = {
15969
15970        /**
15971         * Makes an ajax call and returns an object containing the template json of the template ids
15972         * Note: Constructs dispatcher/CDN friendly suffix-based URL internally (parameters embedded in path)
15973         * URL format: /path.jsonhtmlemitter/templateId-id1/templateId-id2/templateId-id3/fetchMultipleJson-true.json
15974         * @returns {Object}
15975         * @param options {Object}
15975 This object contains the base path, list of templateIds, and success handler
15976         */
15977        getMultipleTemplateJson : function (options) {
15978            var basePath = options.path,
15979                listOfTemplateIds = options.listOfTemplateIds;
15980            if (listOfTemplateIds.length > 0) {
15981                // Construct URL with multiple templateId parameters in suffix format
15982                // Example: /templateId-id1/templateId-id2/templateId-id3/fetchMultipleJson-true.json
15983                var urlSuffix = "";
15984                for (var i = 0; i < listOfTemplateIds.length; i++) {
15985                    urlSuffix += "/templateId-" + listOfTemplateIds[i];
15986                }
15987                urlSuffix += "/fetchMultipleJson-true.json";
15988                
15989                $.ajax({
15990                    url : basePath + urlSuffix,
15991                    type : "GET",
15992                    async : false,
15993                    success : function (response) {
15994                        options.success.call(this, JSON.parse(response.multipleJson));
15995                    },
15996                    error : function (error) {
15997                        window.guideBridge._guide().logger().log(error);
15998                    }
15999                });
16000            }
16001        },
16002
16003        /**
16004         * Makes an ajax call and gets json and html of the lazy loaded panel
16005         * @param options {Object}
16005 This object contains the templateId, fetchJson parameter and fetchHtml parameter.
16006         *                         These can be set to true or false depending on whether the respective content
16007         *                         needs to be fetched or not. Options object also contains the success, error, and complete handler as well.
16008         * @returns {JSONObject} The JSON object has two entries, json and html.
16009         */
16010        getHtmlJson : function (options) {
16011            var ajaxOptions = {
16012                url : options.path,
16013                type : "GET",
16014                async : options.async !== undefined ? options.async : false,
16015                success : options.success,
16016                error : options.error,
16017                complete : options.complete
16018            };
16019
16020            // Only add data parameters if they are present in options
16021            if (options.templateId || options.fetchJSON || options.fetchHTML) {
16022                ajaxOptions.data = {};
16023                if (options.templateId) {
16024                    ajaxOptions.data.templateId = options.templateId;
16025                }
16026                if (options.fetchJSON) {
16027                    ajaxOptions.data.fetchJSON = options.fetchJSON;
16028                }
16029                if (options.fetchHTML) {
16030                    ajaxOptions.data.fetchHTML = options.fetchHTML;
16031                }
16032            }
16033
16034            $.ajax(ajaxOptions);
16035        }
16036    };
16037
16038    window.addEventListener("bridgeInitializeStart", function (evnt) {
16039        var bridge = evnt.detail.guideBridge;
16040        if (bridge) {
16041            bridge.registerPanelProvider(DefaultPanelProvider);
16042        }
16043    });
16044
16045}(window, $));
16046
16047// jscs:disable requireDotNotation
16048/*************************************************************************
16049 *
16050 * ADOBE CONFIDENTIAL
16051 * __________________
16052 *
16053 *  Copyright 2014 Adobe Systems Incorporated
16054 *  All Rights Reserved.
16055 *
16056 * NOTICE:  All information contained herein is, and remains
16057 * the property of Adobe Systems Incorporated and its suppliers,
16058 * if any.  The intellectual and technical concepts contained
16059 * herein are proprietary to Adobe Systems Incorporated and its
16060 * suppliers and may be covered by U.S. and Foreign Patents,
16061 * patents in process, and are protected by trade secret or copyright law.
16062 * Dissemination of this information or reproduction of this material
16063 * is strictly forbidden unless prior written permission is obtained
16064 * from Adobe Systems Incorporated.
16065 **************************************************************************/
16066
16067(function ($, _) {
16068    Function.prototype.bind = Function.prototype.bind || function (ctx) {
16069            var that = this;
16070            return function () {
16071                that.call(ctx, arguments);
16072            };
16073        };
16074
16075    var nValidationContext = 0,
16076        /**
16077         * flag to check if adaptive forms is online or not
16078         * @type {boolean}
16079         */
16080        checkAFOffline = false,
16081        _focusedSubmitButtonModel = null,
16082        sValidationContext = "";
16083
16084    /**
16085     * Class representing the result of {@link GuideBridge} API. This class provides API to access the result of the
16086     * GuideBridge API and retrieve any error messages the API has thrown.
16087     * @class GuideResultObject
16088     * @docStatus review 2016-05-03
16089     * @since 6.0
16090     */
16091    var GuideResultObject = function () {
16092        var _message = [];
16093        var _errorCode = [];
16094        var _somExpression = [];
16095        /**
16096         * The value of this property is true if the API succeeded, otherwise false. The
16097         * {@link GuideResultObject#getNextMessage|getNextMessage} API can be used to retrieve the error messages in
16098         * case the value of this property is false.
16099         * @summary whether the API succeeded or failed.
16100         *
16101         * @type {boolean}
16102         * @member errors
16103         * @memberof GuideResultObject
16104         * @instance
16105         * @readonly
16106         * @since 6.0
16107         */
16108        this.errors = false;
16109        /**
16110         * The type of the data is specific to the API and documentation of that API provides more details about the
16111         * data
16112         * @summary data returned by GuideBridge API
16113         *
16114         * @member {*} data
16115         * @memberof GuideResultObject
16116         * @instance
16117         * @readonly
16118         * @since 6.0
16119         */
16120        this.data;
16121
16122        /**
16123         * API to add a message in the GuideResultObject
16124         * @private
16125         * @memberof GuideResultObject
16126         * @instance
16127         * @since 6.0
16128         */
16129        this.addMessage = function (code, msg, som) {
16130            this.errors = true;
16131            _message.push(msg);
16132            _somExpression.push(som);
16133            _errorCode.push(code);
16134        };
16135
16136        /**
16137         * Error Message returned by GuideBridge API
16138         * @typedef {object} GuideResultObject~ErrorMessage
16139         * @property {number} code Error Code
16140         * @property {?string} somExpression Som Expression of the GuideNode the error is related to. It can be null if
16141         * error is not related to a GuideNode. For example, server failure when submitting the form.
16142         * @property {string} message User friendly message for the error.
16143         * @see GuideNode#somExpression
16144         */
16145        /**
16146         * When a GuideBridge API fails, it throws an error message. This is indicated by the
16147         * {@link GuideResultObject#errors|errors} property. To get the errors, one has to call this API. The API can throw
16148         * multiple errors and the user has to call this API until it returns null indicating no more errors.
16149         * @summary Returns the error message thrown by the GuideBridge API.
16150         * @function getNextMessage
16151         * @memberof GuideResultObject
16152         * @instance
16153         * @return {GuideResultObject~ErrorMessage} object containing the error message
16154         * @since 6.0
16155         */
16156        this.getNextMessage = function () {
16157            if (_errorCode.length == 0) {
16158                return null;
16159            }
16160            return {
16161                code : _errorCode.pop(),
16162                somExpression : _somExpression.pop(),
16163                message : _message.pop()
16164            };
16165        };
16166    };
16167
16168    var GUIDE_BRIDGE_VERSION = "1.0";
16169    /*
16170     * Callback to accept result of asynchronous GuideBridge APIs.
16171     * @callback GuideBridge~AsyncAPIResultCallback
16172     * @param {GuideResultObject}
16172 guideResultObject object containing the result of the API
16173     */
16174    /*
16175     * Signature of the input to be passed to GuideBridge asynchronous APIs
16176     * @typedef {object} GuideBridge~AsyncAPIInput
16177     * @property {GuideBridge~AsyncAPIResultCallback} [success] callback which receives the result of the API in case of
16178     * success. The argument this callback will recieve will have its {@link GuideResultObject#errors|errors} property
16179     * as false.
16180     * @property {GuideBridge~AsyncAPIResultCallback} [error] callback which receives the result of the API in case of
16181     * failure. The argument this callback will recieve will have its {@link GuideResultObject#errors|errors} property
16182     * as true.
16183     * @param {object} [context] _this_ object inside the _success_ and _error_ callback will point to this
16184     * object
16185     */
16186    /**
16187     * GuideBridge provides an interface using which, wrapper html (page hosting/embedding adaptive forms) or external
16188     * window scripts like Parent window javascript (in case form is embedded in an iframe), can communicate with
16189     * current Adaptive Form and manipulate or query it's current state.
16190     *
16191     * Some of the use cases for using this API
16192     * * Submit Adaptive Form from a custom button present outside the Form.
16193     * * Get current Adaptive Form state and save it in local storage for restoring it later on.
16194     * * Plugging in custom widgets.
16195     * * Manipulate the Adaptive Form component properties, like value, visibility from outside the Form
16196     * * Listen to bridge events and send data to Analytics server for reporting
16197     *
16198     * ### Accessing the Instance of GuideBridge
16199     * To access the GuideBridge APIs, one needs to get hold of an instance of GuideBridge. The object is
16200     * available on the window after the GuideBridge script is loaded. One can directly access it by using
16201     * `window.guideBridge`. But
16202     * that requires the user script is written after the GuideBridge script is loaded. In certain cases, a user might
16203     * not be
16204     * aware of when their script gets loaded, in those cases the recommended approach is to listen to the
16205     * {@link GuideBridge.event:bridgeInitializeStart|bridgeInitializeStart} event which provides an instance of
16206     * GuideBridge object.
16207     *```
16208     * window.addEventListener("bridgeInitializeStart", function(evnt) {
16209     *      // get hold of the guideBridge object
16210     *      var gb = evnt.detail.guideBridge;
16211     * })
16212     * ```
16213     *
16214     * **Or**, if you are sure that your script will execute after GuideBridge Script is loaded, then you can directly
16215     * use `window.guideBridge`. In cases like your script is present at the bottom of the page or you are executing on
16216     * jquery dom ready event.
16217     * ```
16218     *    $(function () {
16219     *          // one can directly access guideBridge object here.
16220     *          window.guideBridge.connect(function () {
16221     *              //call guideBridge APIs
16222     *          })
16223     *    })
16224     * ```
16225     *
16226     * <a name="wait-form-ready"></a>
16227     * ### Wait for Form to get ready
16228     * After getting the GuideBridge object one needs to wait for the Form to get initialized. This can be done by
16229     * providing a callback to the {@link GuideBridge#connect|connect} API
16230     * ```
16231     * guideBridge.connect(function (){
16232     *    //this callback will be called after adaptive form is initialized
16233     *    // do your custom processing
16234     * })
16235     * ```
16236     *
16237     * _**Note:** There is no link between Dom ready events and the connect API. If one wants to access the HTML DOM
16238     * from inside the connect callback, the recommended approach is to listen on the jQuery
16239     * [ready](https://api.jquery.com/ready/) event or the native
16240     * [DOMContentLoaded](https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded) event. Similarly if one
16241     * wants to access GuideBridge APIs one needs to wait for the connect callback to get fired._
16242     *
16243     * <a name="guidebridge-api-usage"></a>
16244     * ### Using the GuideBridge API
16245     * APIs are provided for external applications to connect with Adaptive Form and FormDom. The APIs can be
16246     * loosely divided into two categories, **synchronous** and **asynchronous**.
16247     *
16248     * The synchronous getter API returns a {@link GuideResultObject} which represents the result of the API whereas
16249     * each setter API throws an exception in case of error(s) and it is the responsibility of the API to catch those
16250     * exceptions. The {@link GuideResultObject} either contains error or the return value of the API and provides easy
16251     * mechanism to access each of them.
16252     *
16253     * ```
16254     * var result = guideBridge.hideGlobalToolbar()
16255     * if (result.errors) {
16256     *     console.error("Unable to hide toolbar");
16257     *     var msg = guideResultObject.getNextMessage();
16258     *     while (msg != null) {
16259     *         console.error(msg.message);
16260     *         msg = guideResultObject.getNextMessage();
16261     *    }
16262     * } else {
16263     *      console.log("toolbar hidden successfully");
16264     * }
16265     * ```
16266     *
16267     * Each asynchronous API provides callback mechanism to return the result of the API. Each API takes a Javascript
16268     * Object having success and error handlers. The success and error handlers receive {@link GuideResultObject} as input.
16269     * In the success callback, the arguments {@link GuideResultObject#data|data} property is set to the return value
16270     * of the API, while in the error callback the {@link GuideResultObject#errors|errors} property is set to _true_.
16271     * Some APIs might need extra input and that will be defined by the API
16272     * ```
16273     * guideBridge.getData({
16274     *     success : function (guideResultObject) {
16275     *          console.log("data received" + guideResultObject.data);
16276     *     }
16277     *     error : function (guideResultObject) {
16278     *          console.error("API Failed");
16279     *          var msg = guideResultObject.getNextMessage();
16280     *          while (msg != null) {
16281     *              console.error(msg.message);
16282     *              msg = guideResultObject.getNextMessage();
16283     *          }
16284     *     }
16285     * });
16286     * ```
16287     * _**Note:** Some APIs do not follow the above norm and it is mentioned in the documentation of that API_
16288     *
16289     * <a name="guidebridge-events"></a>
16290     * ### GuideBridge Events
16291     *
16292     * GuideBridge API triggers a set of events to notify the current action a user has taken. Developers can listen on
16293     * that event using the {@link GuideBridge#on|on} API and perform some tasks. For example a developer can listen on
16294     * {@link GuideBridge.event:elementFocusChanged|elementFocusChanged} and capture for how long a user spends time
16295     * on that field. All the events triggered by GuideBridge are mentioned below.
16296     *
16297     * GuideBridge provides an event object which contains extra information about the event. For
16298     * example _elementFocusChanged_ event provides information about the previous field that was in focus and the
16299     * current field that came to focus.
16300     *
16301     * The {@link GuideBridge#on|on} API takes a {@link GuideBridge~GuideBridgeEventCallback|GuideBridgeEventCallback}
16302     * as input. The callback is passed two arguments, event and payload where the extra information is passed in the
16303     * payload argument. The documentation of each event lists the values of different properties of the payload
16304     * object.
16305     *
16306     * ```
16307     * guideBridge.on(eventName, function (event, payload) {
16308     *      // access payload properties
16309     *      ...
16310     * })
16311     * ```
16312     *
16313     * @class GuideBridge
16314     * @docStatus review 2016-05-03
16315     * @since 6.0
16316     */
16317    var GuideBridge = function () {
16318        this._$target = null;
16319        this._guide = null;
16320        this._guideView = null;
16321        this._version = GUIDE_BRIDGE_VERSION;
16322        this._guideInitHandler = {};
16323        // _guideModelInitHandler is for internal use only
16324        this._guideModelInitHandler = {};
16325        $(window).on("guideModelInitialized", this._guideModelInitialized.bind(this));
16326        $(window).on("guideInitialized", this._guideInitialized.bind(this));
16327        $(window).on("guideInitializationError", this._guideError);
16328        this.userConfig = {};
16329        this.panelProvider = null;
16330        // set the host name whether it is client or server, by default it is client
16331        this.hostName = "client";
16332    };
16333
16334    var _formInstanceUUID;
16335    var GUIDE_TEMP_STORAGE_PATH = "/tmp/fd/af",
16336        FM_DAM_ROOT = "/content/dam/formsanddocuments/",
16337        FM_AF_ROOT = "/content/forms/af/",
16338        _isAutoSaveEnabled = false,
16339        LOCAL_METADATA_SELECTOR = "local";
16340
16341    var defaultErrorHandler = function (obj) {
16342        if (typeof(console) == "undefined") {
16343            return;
16344        }
16345        var d = obj.getNextMessage();
16346        while (d) {
16347            this._guide.logger().log(d.message);
16348            d = obj.getNextMessage();
16349        }
16350    };
16351
16352    /**
16353     *
16354     * Default function to check Validations errors after getting the data from the
16355     * server with getDataXML call.
16356     * @private
16357     */
16358    var defaultValidationChecker = function (validations, obj) {
16359        if (validations && validations.length > 0) {
16360            for (var i = 0; i < validations.length; i++) {
16361                obj.addMessage(0, validations[i], "");
16362            }
16363            return false;
16364        }
16365        return true;
16366    };
16367
16368    function getOrElse() {
16369        return xfalib.ut.XfaUtil.prototype.getOrElse.apply(null, arguments);
16370    }
16371
16372    $.extend(GuideBridge.prototype, {
16373
16374        /**
16375         * Dispatched when the instance of GuideBridge is available. The GuideBridge object
16376         * will be passed to the listener and further communication can be done using that object.
16377         *
16378         * _**Note :** bridgeInitializeStart event is dispatched at window_
16379         *
16380         * @summary Notifies when the instance of GuideBridge is available.
16381         *
16382         * @event bridgeInitializeStart
16383         * @property {Object} detail an object containing guideBridge
16384         * @property {GuideBridge} detail.guideBridge GuideBridge Instance
16385         * @memberof GuideBridge
16386         * @since 6.0
16387         * @example
16388         * window.addEventListener("bridgeInitializeStart", function(evnt) {
16389         *      // get hold of the guideBridge object
16390         *      var gb = evnt.detail.guideBridge;
16391         *      //wait for the completion of adaptive forms
16392         *      gb.connect(function (){
16393         *         //this function will be called after adaptive form is initialized
16394         *      })
16395         * })
16396         */
16397        GUIDE_BRIDGE_INITIALIZE_START : "bridgeInitializeStart",
16398
16399        /**
16400         * @summary Dispatched when the initialization of Adaptive Form is complete.
16401         *
16402         * @name  bridgeInitializeComplete
16403         * @event
16404         * @property {object} payload payload passed to the event listener
16405         * @property {object} payload.target instance of GuideBridge object
16406         * @memberof GuideBridge
16407         * @deprecated since 6.3 this event is deprecated. Please use {@link GuideBridge#connect|connect} API
16408         * @since 6.0
16409         * @example
16410         * guideBridge.on("bridgeInitializeComplete" , function(event, payload) {
16411         *      var gb = payload.target;
16412         *      assert(gb === guideBridge)
16413         * }
16414         */
16415        GUIDE_BRIDGE_INITIALIZE_COMPLETE : "bridgeInitializeComplete",
16416
16417        /**
16418         * @summary Dispatched when visibility of any Adaptive Form component(Panel or Field) changes.
16419         * @name elementVisibleChanged
16420         * @event
16421         * @property {object} payload payload containing more information about the event
16422         * @property {Scriptable} payload.target Adaptive Form component whose {@link Scriptable#visible|visible} property has
16423         * changed.
16424         * @property {boolean} payload.oldText old value of the visible property
16425         * @property {boolean} payload.newText new value of the visible property
16426         * @memberof GuideBridge
16427         * @since 6.0
16428         * @example
16429         * guideBridge.on("elementVisibleChanged" , function(event, payload) {
16430         *      var component = payload.target; // scripting model of the component whose visibility has changed
16431         *      var newValue = payload.newText;
16432         *      if (newValue) {
16433         *          console.log(component.name + " is visible now";
16434         *      } else {
16435         *          console.log(component.name + " is hidden now";
16436         *      }
16437         * }
16438         *
16439         */
16440        GUIDE_ELEMENT_VISIBLE_CHANGED : "elementVisibleChanged",
16441
16442        /**
16443         * @summary Dispatched when any Adaptive Form component is enabled/disabled, i.e.
16444         * {@link Scriptable#enabled|enabled} property of a component changes.
16445         * @name elementEnableChanged
16446         * @event
16447         * @property {object} payload payload containing more information about the event
16448         * @property {Scriptable} payload.target component whose {@link Scriptable#enabled|enabled} property has changed
16449         * @property {boolean} payload.oldText old value of the enabled property
16450         * @property {boolean} payload.newText new value of the enabled property
16451         * @memberof GuideBridge
16452         * @since 6.0
16453         * @example
16454         * guideBridge.on("elementEnableChanged" , function(event, payload) {
16455         *      var component = payload.target; // scripting model of the component whose enabled property has changed
16456         *      var newValue = payload.newText;
16457         *      if (newValue) {
16458         *          console.log(component.name + " is enabled now";
16459         *      } else {
16460         *          console.log(component.name + " is disabled now";
16461         *      }
16462         * }
16463         */
16464        GUIDE_ELEMENT_ENABLE_CHANGED : "elementEnableChanged",
16465
16466        /**
16467         * @summary Dispatched when value of any Field changes.
16468         * @name elementValueChanged
16469         * @event
16470         * @property {object} payload payload containing more information about the event
16471         * @property {Field} payload.target Field whose {@link Field#value|value} has changed
16472         * @property {string|number} payload.oldText old value of the Field
16473         * @property {string|number} payload.newText new value of the Field
16474         * @memberof GuideBridge
16475         * @since 6.0
16476         * @example
16477         * guideBridge.on("elementValueChanged" , function(event, payload) {
16478         *      var component = payload.target; // Field whose value has changed
16479         *      console.log("Value of component " + component.name + " was " + payload.oldText);
16480         *      console.log("Value of component " + component.name + " is " + payload.newText);
16481         * }
16482         */
16483        GUIDE_ELEMENT_VALUE_CHANGED : "elementValueChanged",
16484
16485        /**
16486         * In layouts like Wizard or Tabbed layout, when a user navigates from one tab to another, this event is
16487         * triggered
16488         * @summary Event to notify that the user has navigated from one Panel to another.
16489         *
16490         * @name elementNavigationChanged
16491         * @event
16492         * @property {object} payload payload containing more information about the event
16493         * @property {Panel} payload.target Panel to which the user moved to
16494         * @property {string} payload.prevText SomExpression of the panel from which user moved
16495         * @property {string} payload.newText SomExpression of the panel to which user moved
16496         * @memberof GuideBridge
16497         * @see GuideNode#somExpression
16498         * @since 6.0
16499         * @example
16500         * guideBridge.on("elementNavigationChanged" , function(event, payload) {
16501         *      var component = payload.target;
16502         *      console.log("old panel's SOM Expression: " + payload.oldText);
16503         *      console.log("new panel's SOM Expression: " + payload.newText);
16504         * }
16505         */
16506        GUIDE_ELEMENT_NAVIGATION_CHANGED : "elementNavigationChanged",
16507
16508        /**
16509         * @summary Dispatched whenever a Field/Panel gets Focus
16510         * @name elementFocusChanged
16511         * @event
16512         * @property {object} payload payload containing more information about the event
16513         * @property {Panel|Field} payload.target new focused component
16514         * @property {string} oldText SOM Expression of  component  that was previously in focus or null
16515         * @property {string} newText SOM Expression of the component that is currently in focus or null
16516         * @memberof GuideBridge
16517         * @see GuideNode#somExpression
16518         * @see {@link GuideBridge#setFocus|setFocus API}
16519         * @since 6.0
16520         * @example
16521         * guideBridge.on("elementFocusChanged" , function(event, payload) {
16522         *      var component = payload.target;
16523         *      console.log("old elements's SOM Expression: " + payload.oldText);
16524         *      console.log("new elements's SOM Expression: " + payload.newText);
16525         * }
16526         */
16527        GUIDE_ELEMENT_FOCUS_CHANGED : "elementFocusChanged",
16528
16529        /**
16530         * @summary Dispatched when a user looks at the help description of any Adaptive Form component(Panel or field)
16531         * @name elementHelpShown
16532         * @event
16533         * @property {object} payload payload containing more information about the event
16534         * @property {Panel|Field} payload.target component whose help is being shown
16535         * @property {string} payload._property what kind of help is being shown. The value can be
16536         * * shortDescription (if Short Description becomes visible)
16537         * * longDescription (if Long Description becomes visible)
16538         * @property {string} payload.prevText empty string
16539         * @property {object} payload.newText object containing the help content
16540         * @property {string} payload.newText.help help content of the component
16541         * @memberof GuideBridge
16542         * @since 6.0
16543         * @see {@link https://helpx.adobe.com/aem-forms/6-1/authoring-in-field-help.html|Help Description in Adaptive Form}
16544         * @example
16545         * guideBridge.on("elementHelpShown" , function(event, payload) {
16546         *      var component = payload.target;
16547         *      console.log("component whose help is shown " + payload.target.name);
16548         *      console.log("Help shown: " + payload._property);
16549         *      console.log("Help Content: " + payload.newText.help);
16550         * }
16551         */
16552        GUIDE_ELEMENT_HELP_SHOWN : "elementHelpShown",
16553
16554        /**
16555         * @summary Dispatched when validity of a Field changes.
16556         * @name elementValidationStatusChanged
16557         * @event
16558         * @property {object} payload payload containing more information about the event
16559         * @property {Field} payload.target Field which either became valid/invalid
16560         * @property {boolean} payload.prevText old validation status
16561         * @property {boolean} payload.newText new validation status
16562         * @memberof GuideBridge
16563         * @see Field#validate
16564         * @see Field#validationState
16565         * @since 6.0
16566         * @example
16567         * guideBridge.on("elementValidationStatusChanged" , function(event, payload) {
16568         *      var component = payload.target;
16569         *      if (payload.prevText) {
16570         *          console.log("component became invalid" );
16571         *      } else {
16572         *         console.log("component became valid" );
16573         *      }
16574         * }
16575         */
16576        GUIDE_ELEMENT_VALIDATION_STATUS_CHANGED : "elementValidationStatusChanged",
16577
16578        /**
16579         * Developers must not modify the Form Fields inside the listener. This is mostly use to update the UI outside
16580         * the Form or capture some data for analytics. If you want to modify form field value on the click of a button
16581         * please use the [Click Expression](https://helpx.adobe.com/aem-forms/6-1/adaptive-form-expressions.html#main-pars_header_6)
16582         * provided in the Forms Authoring.
16583         *
16584         * @summary Dispatched when a Button component is clicked.
16585         *
16586         * @name elementButtonClicked
16587         * @event
16588         * @property {object} payload payload containing more information about the event
16589         * @property {Button} payload.target Button which was clicked
16590         * @memberof GuideBridge
16591         * @since 6.0
16592         * @see {@link https://helpx.adobe.com/aem-forms/6-1/adaptive-form-expressions.html#main-pars_header_6|Click Expression in Buttons}
16593         * @example
16594         * guideBridge.on("elementButtonClicked" , function(event, payload) {
16595         *      var component = payload.target; // Button which wass clicked
16596         *      console.log("Button which was clicked " + component.name);
16597         * }
16598         */
16599        GUIDE_ELEMENT_BUTTON_CLICKED : "elementButtonClicked",
16600
16601        /**
16602         * Whenever the full form validations are run via the {@link GuideBridge#validate|val
16602idate} API, this event is triggered.
16603         * @summary Dispatched when the validation of all the Adaptive Form fields are completed.
16604         *
16605         * @name validationComplete
16606         * @event
16607         * @property {object} payload payload containing more information about the event
16608         * @property {GuideContainerNode} payload.target root Node of the Adaptive Form
16609         * @property {boolean} payload.prevText result of running the validation. true if validations are successful,
16610         * false otherwise
16611         * @property {Field~ValidationError[]} payload.newText List of objects containing error messages.
16612         * @memberof GuideBridge
16613         * @since 6.0
16614         * @example
16615         * guideBridge.on("validationComplete" , function(event, payload) {
16616         *      if (payload.prevText) {
16617         *          console.log("validation success");
16618         *      } else {
16619         *          console.log("validation failure");
16620         *          if (payload.newText.length) {
16621         *              payload.newText.forEach(function (error) {
16622         *                 console.log("validation failed for " + error.som + " with message " + error.errorText);
16623         *              })
16624         *          }
16625         *      }
16626         * }
16627         */
16628        GUIDE_VALIDATION_COMPLETE : "validationComplete",
16629
16630        /**
16631         * Adaptive Form can be configured to be saved automatically at regular intervals. This can be controlled
16632         * dynamically based on the values filled in the Form. Authors can write custom scripts which can enable/disable
16633         * auto save functionality dynamically
16634         * @summary Dispatched when auto save gets enabled in the Form
16635         * @name guideAutoSaveStart
16636         * @event
16637         * @property {object} payload payload containing more information about the event
16638         * @property {GuideContainerNode} payload.target root Node of the Adaptive Form
16639         * @memberof GuideBridge
16640         * @since 6.1
16641         * @see {@link https://helpx.adobe.com/aem-forms/6-1/auto-save-an-adaptive-form.html|Auto Save an Adaptive Form}
16642         * @example
16643         * guideBridge.on("guideAutoSaveStart" , function(event, payload) {
16644         *      console.log("Forms is now being saved as draft automatically");
16645         * }
16646         */
16647        GUIDE_AUTO_SAVE_START : "guideAutoSaveStart",
16648
16649        /**
16650         * @summary Dispatched when save of adaptive form data has started
16651         * @name saveStarted
16652         * @event
16653         * @memberof GuideBridge
16654         * @since 6.1
16655         * @example
16656         * guideBridge.on("saveStarted" , function(event) {
16657         *      console.log("Save of Adaptive Form data is about to start");
16658         * }
16659         */
16660        GUIDE_SAVE_START : "saveStarted",
16661
16662        /**
16663         * @summary Dispatched when save of adaptive form data is completed
16664         * @name saveCompleted
16665         * @event
16666         * @memberof GuideBridge
16667         * @since 6.1
16668         * @example
16669         * guideBridge.on("saveCompleted" , function(event) {
16670         *      console.log("Save of Adaptive Form data is completed");
16671         * }
16672         */
16673        GUIDE_SAVE_COMPLETED : "saveCompleted",
16674
16675        /**
16676         * Users can add some pre submit code in the listener to this event.
16677         * @summary Dispatched when the user clicks on the submit button
16678         * @name submitStart
16679         * @event
16680         * @memberof GuideBridge
16681         * @since 6.0
16682         * @example
16683         * guideBridge.on("submitStart" , function(event) {
16684         *    // do some pre submit processing
16685         * }
16686         */
16687        GUIDE_SUBMIT_START : "submitStart",
16688        GUIDE_PATH : "guidePath",
16689        GUIDE_NAME : "guideName",
16690        GUIDE_DESC : "guideDesc",
16691        GUIDE_TYPE : "guideType",
16692
16693        /**
16694         * @summary Dispatched when an Adaptive Form fragment is lazily loaded successfully
16695         * @name elementLazyLoaded
16696         * @property {object} payload payload containing more information about the event
16697         * @property {Panel} payload.target Adaptive Form Fragment which is lazily loaded
16698         * @event
16699         * @memberof GuideBridge
16700         * @since 6.1 FP1
16701         * @see {@link https://helpx.adobe.com/aem-forms/6-1/lazy-loading-adaptive-forms.html|Lazy Loading Adaptive Form}
16702         * @example
16703         * guideBridge.on("elementLazyLoaded" , function(event, payload) {
16704         *      var component = payload.target;
16705         *      console.log("Panel " + component.name + " loaded");
16706         * }
16707         */
16708        GUIDE_ELEMENT_LAZY_LOADED : "elementLazyLoaded",
16709
16710        /**
16711         * All GuideBridge APIs (except {@link GuideBridge#connect|connect}) require Adaptive Form to be initialized.
16712         * Checking the return value of this API is not necessary if guideBridge API is called only after the
16713         * <a href="#wait-form-ready">Form is initialized</a>
16714         * @summary Whether the Adaptive Form has been initialized or not
16715         *
16716         * @method
16717         * @memberof GuideBridge
16718         * @returns {boolean} true if the Adaptive Form is ready for interaction, false otherwise
16719         * @since 6.0
16720         * @instance
16721         */
16722        isConnected : function () {
16723            if (this._guide) {
16724                return true;
16725            }
16726            return false;
16727        },
16728
16729        /**
16730         * Registers a callback that runs once the form model is created.
16731         *
16732         * This works perfectly when the server merges prefill data into the model
16733         * before delivering it to the browser (server-side merge). In that case,
16734         * by the time the model is created the data is already there, so connect()
16735         * callbacks see the full prefilled form.
16736         *
16737         * However, with client-side merge the browser fetches prefill data
16738         * asynchronously AFTER the model is created. connect() callbacks may
16739         * therefore run before fields have their prefilled values. This only
16740         * matters if your callback actually depends on prefilled data (e.g.
16741         * reading field values, setting up cascading dropdowns).
16742         *
16743         * On AEM 6.5 both server-side and client-side merge are available, so
16744         * connect() may work fine depending on the setup. On Forms as a Cloud
16745         * Service only client-side merge is used, so callbacks that depend on
16746         * prefilled data should use viewConnect instead.
16747         *
16748         * Recommended alternatives:
16749         *  - viewConnect  -- runs after model + prefill data + rendering are ALL done.
16750         *  - modelConnect -- runs after the model is created but before rendering.
16751         *
16752         * @summary Register a callback for form model initialization
16753         * @param {function} handler callback to run
16754         * @param {object} [context] "this" inside the callback
16755         * @since 6.0
16756         * @instance
16757         * @method
16758         * @memberof GuideBridge
16759         * @example
16760         * // Deprecated:
16761         * guideBridge.connect(function() { ... });
16762         *
16763         * // Recommended -- pick the one that fits:
16764         * guideBridge.viewConnect(function() { ... });   // after prefill + render
16765         * guideBridge.modelConnect(function() { ... });  // after model, before render
16766         */
16767        connect : function (handler, context) {
16768            context = context || guideBridge;
16769            if (this.isConnected()) {
16770                // handle exceptions gracefully since it executes in our thread
16771                try {
16772                    handler.call(context);
16773                } catch (exception) {
16774                    // guide model should be initialized in bridge in connect, still adding a null check
16775                    if (this._guide) {
16776                        this._guide.logger().log(exception);
16777                    }
16778                }
16779            } else {
16780                this._guideInitHandler.handler = this._guideInitHandler.handler || [];
16781                this._guideInitHandler.handler.push(handler);
16782                this._guideInitHandler.context = this._guideInitHandler.context || [];
16783                this._guideInitHandler.context.push(context);
16784            }
16785        },
16786
16787        /**
16788         * Register a callback to be executed when the Adaptive Form is fully initialized —
16789         * model created, prefill data merged, and view rendered.
16790         *
16791         * Use this when your callback depends on prefilled data being available --
16792         * for example, reading field values, setting up cascading dropdowns, or
16793         * toggling panel visibility based on prefilled data.
16794         *
16795         * Background:
16796         *   There are two ways prefill data reaches the form:
16797         *   - Server-side merge: the server merges data into the model before
16798         *     sending it to the browser. Data is already there when the model
16799         *     is created, so connect() works fine in this case.
16800         *   - Client-side merge: the browser fetches prefill data asynchronously
16801         *     after the model is created. connect() callbacks can run before
16802         *     that data arrives.
16803         *
16804         *   On AEM 6.5 both modes are available. On Forms as a Cloud Service
16805         *   only client-side merge is used. viewConnect works correctly in
16806         *   both modes -- it simply waits until everything is done.
16807         *
16808         * If the form is already fully initialized when you call this, the
16809         * callback runs immediately.
16810         *
16811         * @summary Register a callback for when model + prefill + view are all done
16812         * @param {function} handler callback to run when the form is fully ready
16813         * @param {object} [context] "this" inside the callback
16814         * @since Forms as a Cloud Service (FaaCS)
16815         * @instance
16816         * @method
16817         * @memberof GuideBridge
16818         * @example
16819         * guideBridge.viewConnect(function() {
16820         *    // Safe to read prefilled values here
16821         *    var province = guideBridge.getFieldValue("PROVINCIA");
16822         *    if (province) {
16823         *        loadComarcas(province);
16824         *    }
16825         * });
16826         */
16827        viewConnect : function (handler, context) {
16828            this._viewConnect(handler, context);
16829        },
16830
16831        _viewConnect : function (handler, context) {
16832            // ideally connect should do this but not changing the original function
16833            if (this._guideView && this._guide) {
16834                try {
16835                    handler.call(context);
16836                } catch (exception) {
16837                    // guide model should be initialized in bridge in connect, still adding a null check
16838                    if (this._guide) {
16839                        this._guide.logger().log(exception);
16840                    }
16841                }
16842            } else {
16843                this._guideInitHandler.handler = this._guideInitHandler.handler || [];
16844                this._guideInitHandler.handler.push(handler);
16845                this._guideInitHandler.context = this._guideInitHandler.context || [];
16846                this._guideInitHandler.context.push(context);
16847            }
16848        },
16849
16850        /**
16851         * Registers a callback that runs after the form model is created but BEFORE
16852         * the form is rendered on screen.
16853         *
16854         * Use this when you need to manipulate the model early -- for example,
16855         * pre-loading lazy fragment models so their fields exist by the time the
16856         * view renders.
16857         *
16858         * This is an early hook. Prefill data may not be available yet at this
16859         * point (especially with client-side merge). If your callback depends on
16860         * prefilled data, use viewConnect() instead.
16861         *
16862         * If the model is already created when you call this, the callback runs
16863         * immediately.
16864         *
16865         * @summary Register a callback for after model creation, before rendering
16866         * @param {function} handler callback to run when the model is ready
16867         * @param {object} [context] "this" inside the callback
16868         * @since Forms as a Cloud Service (FaaCS)
16869         * @instance
16870         * @method
16871         * @memberof GuideBridge
16872         * @example
16873         * guideBridge.modelConnect(function() {
16874         *    this.loadAllLazyFragmentModels();
16875         * });
16876         *
16877         * // For embedded forms, register via the bridgeInitializeStart event:
16878         * window.addEventListener("bridgeInitializeStart", function(evnt) {
16879         *    evnt.detail.guideBridge.modelConnect(function() {
16880         *        this.loadAllLazyFragmentModels();
16881         *    });
16882         * });
16883         * @example <caption>With custom context</caption>
16884         * var myContext = { customProp: "value" };
16885         * window.guideBridge._modelConnect(function() {
16886         *     console.log(this.customProp); // "value"
16887         *     window.guideBridge.loadAllLazyFragmentModels();
16888         * }, myContext);
16889         */
16890        modelConnect : function (handler, context) {
16891            this._modelConnect(handler, context);
16892        },
16893
16894        _modelConnect : function (handler, context) {
16895            context = context || guideBridge;
16896            if (this.isConnected()) {
16897                // handle exceptions gracefully since it executes in our thread
16898                try {
16899                    handler.call(context);
16900                } catch (exception) {
16901                    // guide model should be initialized in bridge in connect, still adding a null check
16902                    if (this._guide) {
16903                        this._guide.logger().log(exception);
16904                    }
16905                }
16906            } else {
16907                this._guideModelInitHandler.handler = this._guideModelInitHandler.handler || [];
16908                this._guideModelInitHandler.handler.push(handler);
16909                this._guideModelInitHandler.context = this._guideModelInitHandler.context || [];
16910                this._guideModelInitHandler.context.push(context);
16911            }
16912        },
16913
16914        _guideModelInitialized : function (e) {
16915            this._guide = e.guide;
16916            if (this._guideModelInitHandler.handler) {
16917                for (var i = 0; i < this._guideModelInitHandler.handler.length; i++) {
16918                    try {
16919                        this._guideModelInitHandler.handler[i].call(this._guideModelInitHandler.context[i]);
16920                    } catch (exception) {
16921                        // guide model should be initialized in bridge in connect, still adding a null check
16922                        if (this._guide) {
16923                            this._guide.logger().log(exception);
16924                        }
16925                    }
16926                }
16927            }
16928        },
16929
16930        /*
16931         *
16932         * Handler for guideInitialized event which is fired by Adaptive Form library after Adaptive Form Dom is initialized
16933         *
16934         * @private
16935         */
16936        _guideInitialized : function (e) {
16937            if (this._guideInitHandler.handler) {
16938                for (var i = 0; i < this._guideInitHandler.handler.length; i++) {
16939                    try {
16940                        this._guideInitHandler.handler[i].call(this._guideInitHandler.context[i]);
16941                    } catch (exception) {
16942                        // guide model should be initialized in bridge in connect, still adding a null check
16943                        if (this._guide) {
16944                            this._guide.logger().log(exception);
16945                        }
16946                    }
16947                }
16948            }
16949            window.guideBridge.trigger("bridgeInitializeComplete",
16950                guidelib.event.GuideModelEvent.createEvent(
16951                    "bridgeInitializeComplete",
16952                    guideBridge
16953                )
16954            );
16955        },
16956        _setGuideView : function (guideView) {
16957            this._guideView = guideView;
16958        },
16959        _guideError : function (e) {
16960            this._guide.logger().debug("AF", e);
16961        },
16962        _checkGuide : function (obj) {
16963            if (!this._guide) {
16964                obj.addMessage(1, "Guide Dom not Initialized", "");
16965                return false;
16966            }
16967            return true;
16968        },
16969        /**
16970         * @summary returns the version of GuideBridge library
16971         * @returns {string} the version of the GuideBridge library
16972         * @method getBridgeVersion
16973         * @memberof GuideBridge
16974         * @instance
16975         * @since 6.0
16976         */
16977        getBridgeVersion : function () {
16978            return this._version;
16979        },
16980
16981        /**
16982         * Callback to execute when bridgeInitializeStart is triggered.
16983         * @callback GuideBridge~postExternalCallback
16984         * @param {string} name constant string `bridgeInitializeStart`
16985         * @param {object} data object containing the GuideBridge instance
16986         * @param {GuideBridge} data.guideBridge instance of GuideBridge
16987         * @since 6.0
16988         * @deprecated since 6.3 this callback is deprecated. One must do the handling in
16989         * {@link GuideBridge.events:bridgeInitializeStart} event
16990         * @memberof GuideBridge
16991         * @see GuideBridge#registerConfig
16992         * @see GuideBridge~postExternalMessageConfig
16993         */
16994        /**
16995         * @typedef {object} GuideBridge~postExternalMessageConfig
16996         * @property {GuideBridge~postExternalCallback} postExternalHandler callback to be executed when GuideBridge
16997         * instance is available
16998         * @since 6.0
16999         * @deprecated since 6.3 this configuration is deprecated. One must do the handling in
17000         * {@link GuideBridge.events:bridgeInitializeStart} event
17001         * @memberof GuideBridge
17002         * @see GuideBridge#registerConfig
17003         */
17004        /**
17005         * @typedef {object} GuideBridge~submitConfig
17006         * @property {HTMLFormElement} form During submission Adaptive Form creates a new HTMLFormElement and puts all the
17007         * value in that Form. One can provide an existing HTMLFormElement that will be reused for submitting the Form. The
17008         * action and method property of the Form element will be ignored.
17009         * @property {boolean} useAjax submit the form via a XMLHttpRequest rather than using a HTMLFormElement
17010         * instance is available
17011         * @property {function} submitSuccessHandler success Handler to be called post submission. This option is ignored
17012         * if _useAjax_ is set to false
17013         * @since 6.0
17014         * @memberof GuideBridge
17015         * @see GuideBridge#registerConfig
17016         */
17017        /**
17018         * @typedef {object} GuideBridge~renderConfig
17019         * @property {boolean} enableFocusOnFirstField option to enable focus on first field. Default value is true.
17020         * @since 6.5
17021         * @memberof GuideBridge
17022         * @see GuideBridge#registerConfig
17023         */
17024        /**
17025         * Adaptive Form uses some default named configurations to provide its default behaviour. This configurations
17026         * can be modified by providing a new configuration.
17027         *
17028         * The API accepts the name of the configuration and updated configuration. Based on value of the new
17029         * configuration the behaviour of the Form gets changed.
17030         * Currently supported configurations are:
17031         * #### postExternalMessageConfig
17032         *
17033         * <div class="deprecated"><span class="deprecated-heading">Deprecated :</span><span> since 6.2 this
17034         * configuration is deprecated. Use the {@link GuideBridge.events:bridgeInitializeStart} event to do the same
17035         * handling</span>
17036         * </div>
17037         * In case Adaptive Form is embedded inside an iframe, this configuration allows developers to provide
17038         * GuideBridge Instance to parent or child windows.
17039         *
17040         * By default, GuideBridge instance is only available to the current window and to the parent window if it
17041         * doesn't violate the cross-origin policy. Now there may be a case when this doesn't solves the problem, then
17042         * one can take advantage of this configuration to extend this functionality.
17043         *
17044         * For the signature of the configuration see
17045         * {@link GuideBridge~postExternalMessageConfig|postExternalMessageConfig}
17046         * ##### Example
17047         * To provide the GuideBridge instance to a child window
17048         * ```
17049         * window.on("bridgeInitializeStart", function (evnt) {
17050         *      var gb = evnt.detail.guideBridge;
17051         *      gb.registerConfig("postExternalMessageConfig", {
17052         *          "postExternalHandler" : function(data) {
17053         *              // assume we have a child window with an id 'childWindowId'
17054         *              var childWindow = document.getElementById("#childWindowId").contentWindow;
17055         *              var tmpEvent = document.createEvent("CustomEvent");
17056         *              tmpEvent.initCustomEvent(data.name, true, true, data.data);
17057         *              childWindow.dispatchEvent(tmpEvent);
17058         *          }
17059         *      });
17060         * });
17061         * ```
17062         * #### widgetConfig
17063         * The configuration is used to modify the appearance of a specific Field. Adaptive Form allows developers to
17064         * [create custom widgets](http://helpx.adobe.com/aem-forms/6-1/custom-appearance-widget-adaptive-form.html) and
17065         * use them in their Forms.
17066         *
17067         * The signature of the config is
17068         * ```
17069         * { "<component-identifier> : "<widget-name>"}
17070         * ```
17071         * where `<component-identifier>` can be either the name or classname of Adaptive Form Field,
17072         * while widget name is the name of the jQuery Widget.
17073         *
17074         * #### submitConfig
17075         * To modify the default submit behaviour one can provide this configuration. The signature of the config is
17076         * defined {@link GuideBridge~submitConfig|below}
17077         * ```
17078         * guideBridge.registerConfig("submitConfig", {"useAjax" : true});
17079         * ```
17080         *
17081         * #### renderConfig
17082         * To modify the default render behaviour one can provide this configuration. The signature of the config is
17083         * defined {@link GuideBridge~renderConfig|below}
17084         * ```
17085         * guideBridge.registerConfig("renderConfig", {"enableFocusOnFirstField" : false});
17086         * ```
17087         * @summary Registers user/portal specific configurations to GuideBridge
17088         * @returns {GuideResultObject} {@link GuideResultObject} with {@link GuideResultObject#data|data} having the
17089         * old configuration against the same _key_
17090         *
17091         * @param key {string} configuration name. one of the following
17092         * * postExternalMessageConfig
17093         * * widgetConfig
17094         * * submitConfig
17095         * * renderConfig
17096         * @param {widgetConfig|GuideBridge~submitConfig|GuideBridge~renderConfig|GuideBridge~postExternalMessageConfig} [config] configuration object for the configuration
17097         * @method
17098         * @memberof GuideBridge
17099         * @since 6.0
17100         * @instance
17101         */
17102        registerConfig : function (key, config) {
17103            var obj = new GuideResultObject();
17104            obj.data = this.userConfig[key];
17105            this.userConfig[key] = config;
17106            obj.completed = true;
17107            return obj;
17108        },
17109
17110        /**
17111         * Their exists a customPropertyMap which can be set from the server. For prefilling files
17112         * fileAttachmentMap key should be present in the map.
17113         * @name customContextProperty
17114         * @param value {object} object to be replaced with the current customPropertyMap.
17115         * @memberof GuideBridge
17116         * @method
17117         * since 6.0
17118         */
17119
17120        /**
17121         * Their exists a customPropertyMap which can be set from the server. For prefilling files
17122         * fileAttachmentMap key should be present in the map.
17123         * @name customContextProperty
17124         * @param property {string} object to be replaced with the current customPropertyMap.
17125         * @method
17126         * @memberof GuideBridge
17127         * since 6.0
17128         */
17129
17130        /**
17131         * Their exists a customPropertyMap which can be set from the server. For prefilling files
17132         * fileAttachmentMap key should be present in the map.
17133         * @param property {string} property to update in the custom property map
17134         * @param value {*} value of the property
17135         * @return {*} old value of the property
17136         * since 6.0
17137         */
17138        customContextProperty : function (property, value) {
17139            var customPropertyMap = getOrElse(guidelib, "__runtime__.guideContext.customPropertyMap", {});
17140            // use both the customContextProperty map since customers also access that
17141            var newCustomPropertyMap = _.extend({}, customPropertyMap, getOrElse(this._guide, "runtime.guideContext.customPropertyMap", {}));
17142            if (_.isUndefined(value)) {
17143                if (_.isObject(property)) {
17144                    guideBridge._modelConnect((function (newCustomPropertyMap, property) {
17145                        return function () {
17146                            var localMap = _.extend({}, guideBridge._guide.runtime.guideContext.customPropertyMap, newCustomPropertyMap);
17147                            _.extend(localMap, property);
17148                            guideBridge._guide.runtime.guideContext.customPropertyMap = localMap;
17149                        };
17150                    })(newCustomPropertyMap, property));
17151                } else {
17152                    return newCustomPropertyMap[property];
17153                }
17154            } else {
17155                var oldValue = newCustomPropertyMap[property];
17156                guideBridge._modelConnect((function (property, value, newCustomPropertyMap) {
17157                    return function () {
17158                        var localMap = _.extend({}, guideBridge._guide.runtime.guideContext.customPropertyMap, newCustomPropertyMap);
17159                        localMap[property] = value;
17160                        guideBridge._guide.runtime.guideContext.customPropertyMap = localMap;
17161                    };
17162                })(property, value, newCustomPropertyMap));
17163                return oldValue;
17164            }
17165        },
17166
17167        getNavigablePanel : function (somExpression) {
17168            return this._guideView.getSomOnNavigableAncestor(somExpression);
17169        },
17170
17171        /**
17172         * Sets the value of a property for a set of {@link GuideNode} to a different value. Property must be a valid
17173         * writable property for that Node
17174         *
17175         * Each entry in _somList_ should have a corresponding entry in the _valueList_. Mismatch in the length of these
17176         * two arguments will make the function do nothing
17177         * @summary Modify a property for a set of Nodes
17178         * @method setProperty
17179         * @param {string[]} somList an array having someExpression for the nodes. Invalid SomExpressions and
17180         * the corresponding value in the _valueList_ are ignored.
17181         * @param {string} propertyName name of the property which has to be modified
17182         * @param {Array.<*>} valueList an array containing value of the _propertyName_ for each element in _somList_
17183         *
17184         * @memberof GuideBridge
17185         * @instance
17186         * @since 6.0
17187         * @see GuideNode#somExpression
17188         * @example <caption>Modifying the value of a set of fields</caption>
17189         * guideBridge.setProperty(["SOM_OF_FIELD_1", "SOM_OF_FIELD_2"...... "SOM_OF_FIELD_N"]
17190         *                          "value"
17191         *                          [VALUE_1, VALUE_2 .... VALUE_N]);
17192         * @example <caption>Hiding a single field</caption>
17193         * guideBridge.setProperty(["SOM_OF_FIELD_1"]
17194         *                          "visibility"
17195         *                          [false]);
17196         */
17197        setProperty : function (somList, propertyName, valueList) {
17198            if (!propertyName) {
17199                return;
17200            }
17201            if (!_.isArray(somList) || !_.isArray(valueList)) {
17202                return;
17203            }
17204            if (somList.length !== valueList.length) {
17205                return;
17206            }
17207            var gb = this;
17208            _.each(somList, function (som, index) {
17209                var node = gb.resolveNode(som);
17210                if (node) {
17211                    node[propertyName] = valueList[index];
17212                } else {
17213                    gb._guide.logger().log("som not valid:" + som);
17214                }
17215            });
17216            if (!this._guide._currentContext) {
17217                this._guide.runPendingExpressions();
17218            }
17219        },
17220
17221        /**
17222         * Used to retrieve the Form data as XML. The API gets the data xml synchronously/asynchronously based on the
17223         * _async_ option and invokes the success/error handlers passed in the arguments upon completion.
17224         *
17225         * In the success callback the {@link GuideResultObject#data|data} parameter contains the xml string.
17226         *
17227         * The success and error handlers receive {@link GuideResultObject} as input.
17228         * @summary Return Form data as XML.
17229         *
17230         * @param {object} options input to the getDataXML API
17231         * @param {function} [options.success] callback which receives the result of the API
17232         * in case of success.
17233         * @param {function} [options.error] callback which receives the result of the API in
17234         * case of failure.
17235         * {@link GuideResultObject#errors|errors} property as true.
17236         * @param {object} [options.context] _this_ object inside the _success_ and _error_ callback will point to this
17237         * object
17238         * @param {boolean} [options.async=true] whether to make the server call asynchronously or not. If false, the
17239         * browser will wait for the server to return the XML and then execute the success or error callbacks object
17240         * @see <a href="#guidebridge-api-usage" >GuideBridge API Usage</a>
17241         * @method
17242         * @memberof GuideBridge
17243         * @since 6.0
17244         * @instance
17245         * @example
17246         * guideBridge.getDataXML({
17247         *     success : function (guideResultObject) {
17248         *          console.log("xml data received" + guideResultObject.data);
17249         *     }
17250         *     error : function (guideResultObject) {
17251         *          console.error("API Failed");
17252         *          var msg = guideResultObject.getNextMessage();
17253         *          while (msg != null) {
17254         *              console.error(msg.message);
17255         *              msg = guideResultObject.getNextMessage();
17256         *          }
17257         *     }
17258         * });
17259         *
17260         * @deprecated since 6.3 this API is deprecated. Use getData API instead.
17261         * @param options
17262         */
17263        getDataXML : function (options) {
17264            guideBridge.getData(options);
17265        },
17266
17267        /**
17268         * Used to retrieve the Form data as XML or JSON depending on the Schema Type. Only for JSON Schema based Forms
17269         * and Form Data Model based forms, the data will be in JSON format while for others, the data will be in XML format.
17270         * The API gets the data synchronously/asynchronously based on the
17271         * _async_ option and invokes the success/error handlers passed in the arguments upon completion.
17272         *
17273         * In the success callback the {@link GuideResultObject#data|data} parameter contains the data string.
17274         *
17275         * The success and error handlers receive {@link GuideResultObject} as input.
17276         * @summary Return Form data as XML or JSON depending on the Schema Type.
17277         *
17278         * @param {object} options input to the getData API
17279         * @param {function} [options.success] callback which receives the result of the API
17280         * in case of success.
17281         * @param {function} [options.error] callback which receives the result of the API in
17282         * case of failure.
17283         * {@link GuideResultObject#errors|errors} property as true.
17284         * @param {object} [options.context] _this_ object inside the _success_ and _error_ callback will point to this
17285         * object
17286         * @param {boolean} [options.async=true] whether to make the server call asynchronously or not. If false, the
17287         * browser will wait for the server to return the data (XML or JSON) and then execute the success or error callbacks object
17288         * @see <a href="#guidebridge-api-usage" >GuideBridge API Usage</a>
17289         * @method
17290         * @memberof GuideBridge
17291         * @since 6.3
17292         * @instance
17293         * @example
17294         * guideBridge.getData({
17295         *     success : function (guideResultObject) {
17296         *          console.log("data received" + guideResultObject.data);
17297         *     }
17298         *     error : function (guideResultObject) {
17299         *          console.error("API Failed");
17300         *          var msg = guideResultObject.getNextMessage();
17301         *          while (msg != null) {
17302         *              console.error(msg.message);
17303         *              msg = guideResultObject.getNextMessage();
17304         *          }
17305         *     }
17306         * });
17307         * @deprecated use {@link GuideBridge#getFormDataString} instead
17308         */
17309        getData : function (options) {
17310            options = options || {};
17311
17312            /* Earlier this API would support boundData for getting data tro be merged in PDF. Now that flag has been renamed to dorData
17313             *  Earlier, boundData flag now maps to boundData for backward compatibility.
17314             * */
17315            options.dorData = options.dorData || options.boundData;
17316
17317            var resultObject = new GuideResultObject();
17318            if (!options.guideState && !this._checkGuide(resultObject)) {
17319                options.error.call(options.context, resultObject);
17320                return;
17321            }
17322
17323            this._submitInternal({
17324                success : function (data) {
17325                    var resultJson = data || {};
17326                    resultObject.completed = true;
17327                    if (options.dorData) {
17328                        resultObject.data = resultJson["dorDataXml"];
17329                    } else {
17330                        resultObject.data = resultJson["data"];
17331                    }
17332                    if (_.isFunction(options.success)) {
17333                        options.success.call(options.context, resultObject);
17334                    }
17335                },
17336                error : function (xhr, txtStatus, errorThrown) {
17337                    var msg = "Error in getData API";
17338                    resultObject.completed = false;
17339                    resultObject.addMessage(2, msg, "");
17340                    if (_.isFunction(options.error)) {
17341                        options.error.call(options.context, resultObject);
17342                    }
17343                },
17344                guideState : options.guideState,
17345                async : options.async,
17346                fileUploadPath : options.fileUploadPath,
17347                excludeFormState : options.excludeFormState || false,
17348                dorData : options.dorData || false
17349            });
17350        },
17351
17352        /**
17353         * returns form data object {@link FormData}
17354         * @returns {*}
17355         * @private
17356         */
17357        _getFormDataObj : function () {
17358            guideBridge._updateAFSubmissionInfo();
17359            guideBridge._guide.internal.liveDataUtils.updateLiveData(null, true); // fetching client side data
17360            guideBridge._guide.internal.liveDataUtils.insertSubmissionInfo(guideBridge._guide.runtime.guideContext.afSubmissionInfo);
17361            var data =  guideBridge._guide.internal.liveDataUtils.getLiveDataStr();
17362            var contentType = "application/xml";
17363            if (guideBridge._guide.internal.liveDataUtils instanceof guidelib.model.LiveJsonUtils) {
17364                contentType = "application/json";
17365            }
17366            return new guidelib.model.FormData({
17367                "data" : data,
17368                "contentType" : contentType,
17369                "attachments" : guideBridge.getFileAttachmentWrapper()
17370            });
17371        },
17372
17373        /**
17374         * invoked inside server-side-validation to return excludeFromDor data.
17375         * @param  {Object} guide input to _getExcludeFromDorData API
17376         * @returns {Array} containing excludeFromDoR info
17377         * */
17378        _getExcludeFromDorData : function (guide) {
17379            var newGuide = guide ? guide : guideBridge._guide;
17380            var excludeFromDorData = null;
17381            window.guideBridge._updateAFSubmissionInfo(newGuide);
17382            var afSubmissionInfo = newGuide.runtime.guideContext.afSubmissionInfo;
17383            if(afSubmissionInfo && afSubmissionInfo.excludeFromDoR) {
17384                excludeFromDorData = afSubmissionInfo.excludeFromDoR;
17385            }
17386            return excludeFromDorData;
17387        },
17388
17389        /**
17390         * returns FormData object {@link FormData} containing form data xml or json and attachments
17391         * @param {object} options input to the getFormDataObject API
17392         * @param {function} [options.success] callback which receives the result of the API
17393         * in case of success.
17394         * @method
17395         * @memberof GuideBridge
17396         * @since Forms As A Cloud Service
17397         * @instance
17398         */
17399        getFormDataObject : function (options) {
17400            var formDataObj = guideBridge._getFormDataObj();
17401            var resultObject = new GuideResultObject();
17402            resultObject.data = formDataObj;
17403            // using typeof for built in types
17404            if (options && typeof options.success === 'function') {
17405                options.success(resultObject);
17406            }
17407        },
17408
17409        /**
17410         * returns string representation of form data xml or json
17411         * @param {object} options input to the getData API
17412         * @param {function} [options.success] callback which receives the result of the API
17413         * in case of success.
17414         * @method
17415         * @memberof GuideBridge
17416         * @since 6.5
17417         * @instance
17418         */
17419        getFormDataString : function (options) {
17420            var formDataObj = guideBridge._getFormDataObj();
17421            var resultObject = new GuideResultObject();
17422            resultObject.data = formDataObj.data;
17423            if (options && typeof options.success === 'function') {
17424                options.success(resultObject);
17425            }
17426        },
17427
17428
17429        /**
17430         * Imports form data from a given string, which can be either JSON or XML format.
17431         * This is useful for initializing a form with pre-filled data received as a string.
17432         *
17433         * @param {Object} options - The options for importing data.
17434         * @param {string} options.data - The string representation of form data (XML or JSON).
17435         * @method
17436         * @memberof GuideBridge
17437         * @since Forms As A Cloud Service
17438         * @instance
17439         * @example
17440         * guideBridge.importData({ data: jsonString }); // For JSON data
17441         * guideBridge.importData({ data: xmlString });  // For XML data
17442         */
17443        importData : function (options) {
17444            // todo: add support for attachments and custom context later
17445            var prefillData = {
17446                data: options.data,
17447                isMergedJson: false
17448                // customContext: {}
17449                // fileAttachmentMap: {}
17450                // fileAttachmentWrappers:
17451                // attachments: '[]'
17452            };
17453            guidelib.model.mergeData(prefillData, guideBridge._guide, guideBridge._guide.runtime.guideContext);
17454        },
17455
17456        /**
17457         * @summary Hides all the submit buttons present in the Adaptive Form
17458         *
17459         * @returns {GuideResultObject} the data property of GuideResultObject would be undefined. The API will fail if
17460         * the Form is not initialized which would be indicated by the {@link GuideResultObject#errors|errors} property.
17461         * @memberof GuideBridge
17462         * @instance
17463         * @since 6.0
17464         */
17465        hideSubmitButtons : function () {
17466            return this._hideElements("guideButton", "submit");
17467        },
17468
17469        /**
17470         * @returns {string} Current Locale of the Form
17471         * @method
17472         * @memberof GuideBridge
17473         * @since Forms As A Cloud Service
17474         * @instance
17475         */
17476        getFormLocale : function() {
17477            return this._readRuntimeLocale();
17478        },
17479
17480        /**
17481         * @returns {string} ID of the Form
17482         * @method
17483         * @memberof GuideBridge
17484         * @since Forms As A Cloud Service
17485         * @instance
17486         */
17487        getFormId : function() {
17488            var guidePath = guideBridge._guide.jsonModel["jcr:path"];
17489            return btoa(guidePath);
17490        },
17491
17492        /**
17493         * Gets the Document of Record. If options is not passed or if success function is not defined,
17494         * then the default behaviour is to download the Document of Record PDF in user's system.
17495         * @param {object} options options to control the behaviour after Document of Record (DOR) is retrieved
17496         * @param {function} [options.success] callback which receives the result of the API
17497         * {@link GuideResultObject#errors|errors} property as false.
17498         * @param {function} [options.error] callback for error handling
17499         * {@link GuideResultObject#errors|errors} property as true.
17500         * @method
17501         * @memberof GuideBridge
17502         * @since Forms As A Cloud Service
17503         * @instance
17504         * @example <caption>Getting the Document of Record</caption>
17505         * guideBridge.getDocumentOfRecord({
17506         *   success: function (guideResultObject) {},
17507         *   error: function (guideResultObject) {}
17508         * })
17509         */
17510        getDocumentOfRecord : function(options) {
17511            var self = this;
17512            var formName = self._getFormName(self.getGuidePath());
17513            if (!options) {
17514                options = {};
17515            }
17516            if (!_.isFunction(options.success)) {
17517                options.success = function (guideResultObject) {
17518                    if (guideResultObject.completed && guideResultObject.data) {
17519                        var blob = new Blob([guideResultObject.data], {type: 'application/pdf'});
17520                        var downloadUrl = URL.createObjectURL(blob);
17521                        var a = document.createElement("a");
17522                        a.setAttribute('href', downloadUrl);
17523                        a.setAttribute('download', formName);
17524                        a.setAttribute('style', 'display:none');
17525                        document.body.appendChild(a);
17526                        a.click();
17527                    }
17528                }
17529            }
17530            if (!_.isFunction(options.error)) {
17531                options.error = function(guideResultObject) {
17532                    console.error(guideResultObject.data);
17533                }
17534            }
17535            function _getDocumentOfRecord(formData) {
17536                var formId = self.getFormId();
17537                var locale = self.getFormLocale();
17538                var dorGenerationURL = self._getUrl("/adobe/forms/af/dor/" + formId + "?locale=" + locale);
17539                $.ajax({
17540                    url : dorGenerationURL,
17541                    type : "POST",
17542                    processData : false,
17543                    cache : false,
17544                    contentType : false,
17545                    data : formData,
17546                    xhrFields:{
17547                        responseType: 'blob'
17548                    },
17549                    success : function(blob) {
17550                        var guideResultObject = new GuideResultObject();
17551                        guideResultObject.data = blob;
17552                        guideResultObject.completed = true;
17553                        options.success(guideResultObject);
17554                    },
17555                    error : function (exception) {
17556                        var guideResultObject = new GuideResultObject();
17557                        guideResultObject.data = exception;
17558                        guideResultObject.completed = false;
17559                        options.error(guideResultObject);
17560                    }
17561                });
17562            };
17563
17564            self.getFormDataString({
17565                success: function(result) {
17566                    var attachedFilesList = self._getFileAttachmentsList();
17567                    var fileNameDomMap = self._juiceOutNameAndFileDomMap(attachedFilesList);
17568                    var dataForm = new FormData();
17569                    var fileAttachmentPromise = self._appendFileAttachmentsToFormData(dataForm, fileNameDomMap, attachedFilesList);
17570                    fileAttachmentPromise.then(function (dataForm) {
17571                        dataForm.append('data', result.data);
17572                        _getDocumentOfRecord(dataForm);
17573                    }).catch(function (e) {
17574                        console.error(e);
17575                    });
17576                }
17577            })
17578        },
17579
17580        /**
17581         * This API is designed to evaluate the expression entered by the author.
17582         * This API is given only to enable Auto Save meta information use case.
17583         * @returns value obtained after executing the expression.
17584         * @method
17585         * @private
17586         * @memberof GuideBridge
17587         * @deprecated since 6.3 this API is deprecated
17588         */
17589        _evaluateExpression : function (expression) {
17590            if (this._guide) {
17591                var compiledExpression = this._guide._compileExpression(expression, null);
17592                return compiledExpression.apply(this._guide);
17593            }
17594        },
17595
17596        /**
17597         * Adaptive Form can be configured to save draft automatically. This property indicates whether Adaptive Form is
17598         * configured to save draft automatically or not.
17599         *
17600         * Enabling auto save doesn't mean that AF will create the draft when the Form is loaded. Based on the result of
17601         * **Auto save start expression** the draft will be created. Once the expression returns true, drafts will be
17602         * saved at regular interval or at specific events as configured.
17603         *
17604         * @summary Whether autoSave is enabled for this Adaptive Form or not
17605         * @returns {boolean} true if auto save is enabled otherwise false.
17606         * @method
17607         * @memberof GuideBridge
17608         * @instance
17609         * @since 6.1 FP1
17610         * @see {@link https://helpx.adobe.com/aem-forms/6-1/auto-save-an-adaptive-form.html|Saving an adaptive Form}
17611         */
17612        getAutoSaveEnabledStatus : function () {
17613            var _isAutoSaveEnable = false;
17614            // check if form is loaded or not, if loaded then check for auto save
17615            if (this.isConnected()) {
17616                _isAutoSaveEnable = this._guide.enableAutoSave;
17617            }
17618            return _isAutoSaveEnable;
17619        },
17620
17621        /**
17622         * This API indicates that auto save is enabled and draft is being saved at the configured location.
17623         * @summary Whether Adaptive Form data is being saved as draft or not.
17624         * @returns {Boolean} whether autoSave has started.
17625         * @method
17626         * @memberof GuideBridge
17627         * @instance
17628         * @since 6.1 FP1
17629         * @see {@link https://helpx.adobe.com/aem-forms/6-1/auto-save-an-adaptive-form.html|Saving an adaptive Form}
17630         **/
17631        hasAutoSaveStarted : function () {
17632            return this._guide && this._guide.enableAutoSave && this._guide.autoSaveStart;
17633        },
17634
17635        /**
17636         * @summary the autoSaveinfo that is stored at the guideContainer.
17637         * @returns {object}
17637 object contains the additional meta information stored along with form data
17638         * @method
17639         * @memberof GuideBridge
17640         * @instance
17641         * @since 6.1 FP1
17642         * @deprecated since 6.3
17643         */
17644        getAutoSaveInfo : function () {
17645            return this._guide.autoSaveInfo;
17646        },
17647
17648        /**
17649         * The API is used to provide extra information to be saved in Final data XML. It can also be used to retrieve
17650         * that information.
17651         *
17652         * If _value_ is null then the value of the _property_ is returned
17653         * @summary store or retrieve submission related information
17654         * @param {string} property name of the property against which to save the value or retrieve the value of
17655         * property
17656         * @param {string} [value] value to save.
17657         * @returns {*} old value of the property
17658         * @method
17659         * @since 6.1 FP1
17660         * @memberof GuideBridge
17661         * @instance
17662         * @deprecated since 6.3
17663         */
17664        afSubmissionInfo : function (property, value) {
17665            var afSubmissionInfo = guideBridge._guide.runtime.guideContext.afSubmissionInfo || {};
17666            if (_.isUndefined(value)) {
17667                return afSubmissionInfo[property];
17668            } else {
17669                var oldValue = afSubmissionInfo[property];
17670                afSubmissionInfo[property] = value;
17671                guideBridge._guide.runtime.guideContext.afSubmissionInfo = afSubmissionInfo;
17672                return oldValue;
17673            }
17674        },
17675
17676        /**
17677         * @summary this API returns the globalMetaInfo stored in global context (in globalMetaInfo tab).
17678         * @returns {object}
17679         * @method
17680         * @memberof GuideBridge
17681         * @instance
17682         * @deprecated since 6.3
17683         */
17684        getGlobalMetaInfo : function () {
17685            return this._guide.globalMetaInfo;
17686        },
17687
17688        /**
17689         * @summary this API returns the metadata configured for submission. Value depends on the selection of metadata
17690         * type, local or global.
17691         * @returns {Object}
17692         * @method
17693         * @since 6.1 FP1
17694         * @memberof GuideBridge
17695         * @instance
17696         * @deprecated since 6.3
17697         */
17698        getSubmissionMetadataInfo : function () {
17699            if (this._guide.submissionMetaInfo && this._guide.submissionMetaInfo.metadataselector === LOCAL_METADATA_SELECTOR) {
17700                // In order to maintain backward compatibility, this piece of code will always be here.
17701                // For the cases where metadata selection is being configured for submit actions
17702                return getOrElse(this._guide, "submissionMetaInfo.metadata", null);
17703            } else {
17704                //From 6.2 onwards, we are asking author to provide metadata only at one place, which is global to whole form
17705                // In case, metadataselector's value is "global" or not configured at all, this block will get executed
17706                return getOrElse(this._guide, "globalMetaInfo.metadata", null);
17707            }
17708        },
17709
17710        /**
17711         * The API enables auto save in Adaptive Form
17712         * @summary  enable auto save in Adaptive Form.
17713         * @param value {boolean} true to enable auto save otherwise false.
17714         * @method
17715         * @memberof GuideBridge
17716         * @instance
17717         * @since 6.1 FP1
17718         * @see {@link GuideBridge#getAutoSaveEnabledStatus|getAutoSaveEnabledStatus}
17719         * @see {@link https://helpx.adobe.com/aem-forms/6-1/auto-save-an-adaptive-form.html|Auto Save an Adaptive Form}
17720         */
17721        setEnabledAutoSave : function (value) {
17722            this._guide.enableAutoSave = value;
17723        },
17724
17725        /**
17726         * @summary Hides all the file attachment listing buttons present in the Adaptive Form
17727         *
17728         * @returns {GuideResultObject} the data property of GuideResultObject would be undefined. The API will fail if
17729         * the Form is not initialized which would be indicated by the {@link GuideResultObject#errors} property.
17730         * @memberof GuideBridge
17731         * @instance
17732         * @since 6.0
17733         */
17734        hideFileAttachmentListingButtons : function () {
17735            return this._hideElements("guideListFileAttachmentButton");
17736        },
17737
17738        /**
17739         * @todo: Function can change as per usecase, it can behave as a wrapper
17740         * where it can use the configuration provided through registerConfig and invoke any callback if required
17741         *
17742         * @returns {boolean} boolean indicating whether Adaptive Form is offline
17743         * @private
17744         */
17745        isOffline : function () {
17746            return checkAFOffline;
17747        },
17748
17749        /**
17750         * function to set the status of Adaptive Form (online or offline)
17751         * @type {boolean}
17752         * @private
17753         */
17754        setIsOffline : function (value) {
17755            checkAFOffline = value;
17756        },
17757
17758        /**
17759         * @summary Hide all the File Attachment component present in the Adaptive Form
17760         *
17761         * @returns {GuideResultObject} the data property of GuideResultObject would be undefined. The API will fail if
17762         * the Form is not initialized which would be indicated by the {@link GuideResultObject#errors} property.
17763         * @memberof GuideBridge
17764         * @instance
17765         * @since 6.0
17766         */
17767        hideFileAttachments : function () {
17768            return this._hideElements("guideFileUpload");
17769        },
17770
17771        /**
17772         * @summary Hides the global toolbar of the Adaptive Form.
17773         * @returns {GuideResultObject} the data property of GuideResultObject would be undefined. The API will fail if
17774         * the Form is not initialized which would be indicated by the {@link GuideResultObject#errors} property.
17775         * @memberof GuideBridge
17776         * @instance
17777         * @since 6.0
17778         */
17779        hideGlobalToolbar : function () {
17780            var resultObject = new GuideResultObject(),
17781                $toolbar;
17782
17783            // If guide dom not initialized, return
17784            if (!this._checkGuide(resultObject)) {
17785                return resultObject;
17786            }
17787
17788            if (guideBridge._guide.toolbar) {
17789                $toolbar = this._getGuideDomElement(guideBridge._guide.toolbar.somExpression);
17790                if ($toolbar && $toolbar.length > 0) {
17791                    $toolbar.hide();
17792                }
17793            }
17794
17795            resultObject.completed = true;
17796            return resultObject;
17797        },
17798
17799        /*
17800         *
17801         * This API is designed to return all the toolbar buttons present in the Adaptive Form(except submit, save, reset and file attachment listing)
17802         *
17803         * @returns {GuideResultObject} data contains an array of all the tool bar buttons available(except submit, save, reset and file attachment listing)
17804         * Each element of data property is an object holding model and html property.
17805         * The html string does not contain any script tags, this is to avoid crosss site scripting attacks
17806         */
17807        /*
17808         getToolbarButtons : function(){
17809         var resultObject = new GuideResultObject(),
17810         resultData = [],
17811         $elem = null;
17812         // If guide dom not initialized, return
17813         if (!this._checkGuide(resultObject)) {
17814         return resultObject;
17815         }
17816         resultObject.completed = true;
17817         this.visit(function(node){
17818         // Check if this node is a guide button and if it resides inside a guideToolBar
17819         if(node.className === "guideButton" && node.parent.className === "guideToolbar"){
17820         if(node.type !== "submit" && node.type !== "save" && node.type !== "fileattachmentlisting" && node.type !== "next" && node.type !=="prev") {
17821         $elem =  this._getGuideDomElement(node.somExpression);
17822         // Remove the script tag from the $html, we don't support execution of Adaptive Form Scripts in parent or other domain
17823         // This is to avoid cross site scripting attacks
17824         $elem.find("script").remove();
17825         resultData.push({
17826         "model" : node,
17827         "html"  : $elem.html()
17828         });
17829         }
17830         }
17831         });
17832         resultObject.data = resultData;
17833         return resultObject;
17834         }, */
17835
17836        /**
17837         * @summary Hides all the save buttons present in the Adaptive Form
17838         *
17839         * @returns {GuideResultObject} the data property of GuideResultObject would be undefined. The API will fail if
17840         * the Form is not initialized which would be indicated by the {@link GuideResultObject#errors} property.
17841         * @memberof GuideBridge
17842         * @instance
17843         * @since 6.0
17844         */
17845        hideSaveButtons : function () {
17846            return this._hideElements("guideButton", "save");
17847        },
17848
17849        /**
17850         * @summary Hides all the reset buttons present in the Adaptive Form
17851         *
17852         * @returns {GuideResultObject} the data property of GuideResultObject would be undefined. The API will fail if
17853         * the Form is not initialized which would be indicated by the {@link GuideResultObject#errors} property.
17854         * @memberof GuideBridge
17855         * @instance
17856         * @since 6.3
17857         */
17858        hideResetButtons : function () {
17859            return this._hideElements("guideButton", "reset");
17860        },
17861
17862        /**
17863         * The API can be used to retrieve the value of a specific property for a list of AF components. If the property
17864         * doesn't exists for a component then the corresponding value in the resulting array will be null.
17865         *
17866         * The {@link GuideResultObject#data|data} element of the return object will be an array containing the values
17867         * of the _property_ for each component in the list of components
17868         *
17869         * The API fails if the Form is not initiailzed
17870         *
17871         * **_Note:_** If a somExpression provided doesn't points to a valid {@link GuideNode} null is returned for
17872         * that element and an error message is added in the returned object
17873         * @summary returns the value of a specific property for a set of Adaptive Form Components
17874         *
17875         * @param {object}
17875 options input object containing the propertyName and the list of components
17876         * @param {string} options.propertyName name of the property whose value has to be returned
17877         * @param {string[]} options.somExpression list of somExpression of the components for which the value is to be
17878         * returned.
17879         *
17880         * @returns {GuideResultObject} The {@link GuideResultObject#data|data} member of the object contains the property
17881         * values
17882         * @method
17883         * @memberof GuideBridge
17884         * @since 6.0
17885         * @instance
17886         * @deprecated since 6.3
17887         * @see GuideNode#somExpression
17888         * @example
17889         * var result = guideBridge.getElementProperty({
17890         *    propertyName: "value",
17891         *   somExpression: ["somExpression1", "somExpression2"]
17892         * });
17893         * if (result.errors) {
17894         *      console.log("some som expressions were invalid");
17895         *      var err = result.getNextMessage();
17896         *     while(err != null) {
17897         *          //err.somExpression will point to the invalid somExpression in the Field.
17898         *          console.log(err.message);
17899         *     }
17900         * }
17901         * for(var i = 0; i< result.data.length; i++) {
17902         *      console.log(result.data[i]);
17903         * }
17904         */
17905        getElementProperty : function (options) {
17906            var somExpressions = options.somExpressions;
17907            var propertyName = options.propertyName;
17908            var resultObject = new GuideResultObject();
17909            if (!this._checkGuide(resultObject)) {
17910                return resultObject;
17911            }
17912            resultObject.data = [];
17913            for (var i = 0; i < somExpressions.length; i++) {
17914                var element = this.resolveNode(somExpressions[i]);
17915                if (element == null) {
17916                    resultObject.addMessage(0, "No element " + somExpressions[i] + " exists", somExpressions[i]);
17917                    resultObject.data.push(null);
17918                } else {
17919                    resultObject.completed = true;
17920                    resultObject.data.push(element[propertyName]);
17921                }
17922            }
17923            return resultObject;
17924        },
17925
17926        _getGuideDomElement : function (somExpression, option) {
17927            if (this._guideView) {
17928                return this._guideView._getGuideDomElement(somExpression, option);
17929            } else {
17930                return null;
17931            }
17932        },
17933
17934        /**
17935         * File Attachment object
17936         * @typedef {object} GuideBridge~FileAttachementObject
17937         * @property {string} name name of the uploaded File
17938         * @property {string} path path of the uploaded File
17939         * @memberof GuideBridge
17940         * @since 6.0
17941         */
17942        /**
17943         * Success callback that is called from {@link GuideBridge#getFileAttachmentsInfo} with the list of File
17944         * Attachments
17945         * @callback GuideBridge~FileAttachmentInfoHandler
17946         * @param {GuideBridge~FileAttachementObject[]} fileAttachementList list of file attachement objects uploaded
17947         * in the Form
17948         */
17949        /**
17950         * The API provides a list containing File Names and File URLS for the Files Attached by the user using the
17951         * File Attachment component. The API is a asynchronous API and takes success handler which is called with
17952         * the list of File Names and URLs.
17953         *
17954         * @param {object} options Object containing the callback which will be invoked with the result of this API
17955         * @param {function} options.success success callback which will be invoked. The signature of the callback should
17956         * match the signature of {@link GuideBridge~FileAttachmentInfoHandler|FileAttachmentInfoHandler}
17957         * @param {object} [options.context] _this_ parameter in the success handler will point to this object
17958         *
17959         * @example  <caption>Example usage of the getFileAttachmentsInfo API</caption>
17960         * guideBridge.getFileAttachmentsInfo({
17961         *        success:function(list) {
17962         *             for(var i = 0; i< list.length; i++) {
17963         *                  console.log(list[i].name + " "+ list[i].path);
17964         *             }
17965         *        }
17966         * });
17967         * @method
17968         * @memberof GuideBridge
17969         * @since 6.0
17970         * @deprecated since Forms As a Cloud Service
17971         * @instance
17972         */
17973        getFileAttachmentsInfo : function (options) {
17974            console.error("getFileAttachmentsInfo API is not supported on Forms As a Cloud Service");
17975            options.success.call(options.context, []);
17976        },
17977
17978        /**
17979         * Syntax - argObject : {"options" : options to be passed to the callback,
17980         *                   "fileAttachmentsList" : fileAttachmentsList,
17981         *                    "fileUploadPath" :fileUploadPath
17982         *                     "callback" :callback, "errorCallback" :errorCallback}
17983         * @param {object}
17983 argObject Input object containing the callbacks that will be invoked
17984         * to provide the result of the API
17985         * @private
17986         * @memberof GuideBridge
17987         * @since 6.0
17988         */
17989        _getGuideAttachments : function (argObject) {
17990            var fileDoms = [],
17991                fileNames = [],
17992                fileUrl = null,
17993                didSubmit = false,
17994                contextRoot = this._getContextRoot(),
17995                options = argObject.options,
17996                fileAttachmentsList = argObject.fileAttachmentsList,
17997                fileUploadPath = argObject.fileUploadPath,
17998                callback = argObject.callback,
17999                errorCallback = argObject.errorCallback,
18000                fileNameDomMap;
18001
18002            // In the case of draft, url comes with context root. Need to remove it so that correct
18003            // value gets stored in model
18004            if (contextRoot) {
18005                if (fileUploadPath.indexOf(contextRoot) === 0) {
18006                    fileUploadPath = fileUploadPath.substring(contextRoot.length);
18007                }
18008            }
18009            // File attachment list is an array containing the list of file attachments
18010            // We need to fetch the fileNameDomMap even when there's no fileAttachmentsList as there can be
18011            // lazy loaded file attachment models as well.
18012            fileNameDomMap = this._juiceOutNameAndFileDomMap(fileAttachmentsList);
18013            fileDoms = fileNameDomMap.fileDom;
18014            fileNames = fileNameDomMap.fileName;
18015            if (fileDoms.length > 0) {
18016                // since there can be a dom element which is null, in case of draft reload, get the first
18017                // non null file dom
18018                var firstNonNullFileDom = _.indexOf(fileDoms, _.find(fileDoms, function (item) {
18019                    return item !== null && !_.isString(item);
18020                }));
18021                // fileUploadPath doesn't contain the context path and hence we need to to pass the baseURL
18022                // FileUploader takes a _getUrl option which is baseUrl/contextPath
18023                if (firstNonNullFileDom !== -1 && fileUploadPath) {
18024                    var uploaderPluginName = guideBridge.userConfig.uploaderPluginName || "adobeFileUploader";
18025                    fileUrl = fileDoms[firstNonNullFileDom][uploaderPluginName]("uploadFile", {
18026                        'fileName' : fileNames,
18027                        'fileDom' : fileDoms,
18028                        'fileUploadPath' : fileUploadPath,
18029                        'multiple' : true,
18030                        _getUrl : guideBridge._getUrl("")
18031                    });
18032
18033                    // The file url returned by file upload widget can contain context root.
18034                    // Remove it so that correct value gets stored in model.
18035                    if (contextRoot) {
18036                        if (fileUrl.indexOf(contextRoot) === 0) {
18037                            fileUrl = fileUrl.substring(contextRoot.length);
18038                        }
18039                    }
18040
18041                    fileDoms[firstNonNullFileDom].one("adobeFileUploader.multipleFileUploaded",
18042                        $.proxy(callback, {
18043                            "attachments" : fileNames,
18044                            "fileUrl" : fileUrl,
18045                            "fileAttachmentsList" : fileAttachmentsList,
18046                            "options" : options
18047                        })
18048                    );
18049                    if (errorCallback) {
18050                        fileDoms[firstNonNullFileDom].one("adobeFileUploader.fileUploadFailed",
18051                                            $.proxy(errorCallback, {
18052                                                "attachments" : fileNames,
18053                                                "fileUrl" : fileUrl,
18054                                                "fileAttachmentsList" : fileAttachmentsList,
18055                                                "options" : options
18056                                            })
18057                                        );
18058                    }
18059                    didSubmit = true;
18060                }
18061                // if fileUrl is not yet set, default it to fileUploadPath
18062                if (fileUrl === null && fileUploadPath) {
18063                    fileUrl = fileUploadPath;
18064                }
18065            }
18066            if (!didSubmit) {
18067                // if there are no files attached, still call the callback to submit the json contents
18068                // if there is only one file attachment component with no files, in this case else is 
18068important
18069                callback.apply({
18070                    "attachments" : fileNames,
18071                    "fileUrl" : fileUrl,
18072                    "fileAttachmentsList" : fileAttachmentsList,
18073                    "options" : options
18074                });
18075            }
18076        },
18077        /**
18078         * Iterates over all the components in the Adaptive Form and invokes its {@link GuideNode#visit|visit} method
18079         * passing the _callback_ to the API.
18080         *
18081         * @summary Traverse all the components in the Adaptive Form and invoke callback function for each of the
18082         * component
18083         * @param {function} callback Function to be called for every Adaptive Form Component present
18084         * in the Form. The signature of the callback matches the signature of
18085         * {@link GuideNode~VisitorCallback|VisitorCallback}
18086         * @param {object} [context=window] _this_ object in the callback will point to this object
18087         *
18088         * @example <caption>Creating a list of all components having name <i>testName</i></caption>
18089         * var myList = []
18090         * guideBridge.visit(function(cmp) {
18091         *     if(cmp.name === "testName") {
18092         *          myList.push[cmp];
18093         *     }
18094         * }};
18095         * @method
18096         * @memberof GuideBridge
18097         * @since 6.0
18098         * @instance
18099         */
18100        visit : function (callback, context) {
18101            this._guide.visit(callback, context || window);
18102        },
18103
18104        /**
18105         *
18106         * Hides the elements of the specified class name.
18107         * In case of guideButton, it checks for type too, if no type is specified in "guideButton", then that button
18108         * cannot be made hidden
18109         *
18110         * @param className String representing the classname of the node
18111         * @param type [optional] type will be used only if the classname is "guideButton"
18112         * @private
18113         */
18114        _hideElements : function (className, type) {
18115            var resultObject = new GuideResultObject();
18116            // If guide dom not initialized, return
18117            if (!this._checkGuide(resultObject)) {
18118                return resultObject;
18119            }
18120            resultObject.completed = true;
18121            this.visit(function (node) {
18122                // if the class name is guide button only the use the type
18123                if (node.className === "guideButton") {
18124                    if (node.type === type) {
18125                        node.visible = false;
18126                    }
18127                } else {
18128                    // else just compare the classname and hide it
18129                    if (node.className === className) {
18130                        node.visible = false;
18131                    }
18132                }
18133            });
18134            return resultObject;
18135        },
18136
18137        /**
18138         * In Adaptive Form there is a summary component to show the summary of submission. This API hides the parent
18139         * panel of the summary component. If the component is not present inside the Form, this operation doesn't do
18140         * anything
18141         * @summary Hides the panel that contains the summary component.
18142         *
18143         * @returns {GuideResultObject} the data property of GuideResultObject would be undefined. The API will fail if
18144         * the Form is not initialized which would be indicated by the {@link GuideResultObject#errors} property.
18145         * @memberof GuideBridge
18146         * @instance
18147         * @since 6.0
18148         */
18149        hideSummaryPanel : function () {
18150            var resultObject = new GuideResultObject();
18151            // If guide dom not initialized, return
18152            if (!this._checkGuide(resultObject)) {
18153                return resultObject;
18154            }
18155            resultObject.completed = true;
18156            this.visit(function (node) {
18157                if (node.className === "guideNode" && node.jsonModel['sling:resourceType'] === "fd/afaddon/components/summary") {
18158                    node.panel.visible = false;
18159                }
18160            });
18161            return resultObject;
18162        },
18163
18164        _getFileAttachmentsList : function () {
18165            var fileAttachmentsList = [];
18166            this.visit(function (node) {
18167                if (node.className === "guideFileUpload") {
18168                    fileAttachmentsList.push(node);
18169                }
18170            });
18171            return fileAttachmentsList;
18172        },
18173
18174        /**
18175         * @summary the captchaData which will be submitted to server for validation purposes.
18176         * @param captchaModel
18177         * @returns {object}
18177 object contains the captchaData which includes captcha service provider name, its SOM exp and
18178         * data coming from OOTB/third-party captcha widget.
18179         * @method
18180         * @memberof GuideBridge
18181         * @instance
18182         * @since 6.3
18183         */
18184        _getCaptchaData : function (captchaModel) {
18185            if (captchaModel) {
18186                return {
18187                    serviceType : captchaModel.captchaService,
18188                    somExpression : captchaModel.somExpression,
18189                    validationMessage : captchaModel.validateExpMessage,
18190                    mandatoryMessage : captchaModel.mandatoryMessage,
18191                    data : captchaModel.value
18192                };
18193            }
18194            return {};
18195        },
18196
18197        /**
18198         * This function returns the additional action Field information that is required during submit.
18199         *
18200         * @returns {object} object having the action Field information.
18201         * @memberof GuideBridge
18202         */
18203        _getAdditionalSubmitInfo : function () {
18204            var additionalSubmitInfo = {},
18205                actionFieldDiv = $("#actionField");
18206            var thankYouPage = this._getThankYouPageFromConfig();
18207            if (typeof thankYouPage === "string") {
18208                document.getElementById(":redirect").value = thankYouPage;
18209            }
18210            var actionFields = actionFieldDiv.find('input')
18211                .each(function () {
18212                    additionalSubmitInfo[$(this).attr("name")] = $(this).val();
18213                    if ($(this).attr("name") == "_guideValueMap" && $(this).val() == "yes") {
18214                        var guideKeyValue = {};
18215                        window.guideBridge._guide._collectValues(guideKeyValue);
18216                        additionalSubmitInfo['_guideValuesMap'] = JSON.stringify(guideKeyValue);
18217                    }
18218                });
18219            return additionalSubmitInfo;
18220        },
18221
18222        /**
18223         * Gets the guideDom based on whether reducedJSON option is true or not.
18224         * If reducedJSON is true, only the white-listed properties are included.
18225         *
18226         * @returns {object} guideDom
18227         * @memberof GuideBridge
18228         */
18229
18230        _getGuideDom : function (options) {
18231            var guideDom;
18232            if (options.reducedJSON) {
18233                guideDom = guideBridge._guide._getReducedJSON();
18234            } else {
18235                guideDom = guideBridge._guide.jsonModel;
18236            }
18237            return guideDom;
18238        },
18239
18240        /**
18241         * Creates the guideState and the liveXml.
18242         *
18243         * @param options {object} options should contain a GuideResultObject [{obj:"<GuideResultObject type>"}]
18244         * @memberof GuideBridge
18245         * Steps performed by the function -
18246         * 1) creates the xfaState
18247         * 2) creates the guideState that consists of guideDom, guideContext and additionalSubmitInfo
18248         * 3) creates guideLiveData
18249         * 4) adds xfaState and guideLiveData to the guideState
18250         *
18251         * @private
18252         */
18253        _createGuideStateAndLiveXml : function (options) {
18254            var obj = new GuideResultObject();
18255            // add the guideResultObject to options so that it can be passed to the success handler
18256            options.obj = obj;
18257
18258            if (!this._checkGuide(obj)) {
18259                return;
18260            }
18261
18262            var saveXfaXml = function (xfaResultObj) {
18263                if (!xfaResultObj.errors && xfaResultObj.completed) {
18264                    xfaState.currentContext = {'data' : xfaResultObj.data};
18265                }
18266            };
18267
18268            obj.data = {};
18269            var xfaState = null;
18270            if (this._isXfaGuide() && this._isValidXFAGuide()) {
18271                var xfaResultObject = null;
18272                if (options.reducedJSON) {
18273                    //If reduceJson is asked, then xfaState should also be reduced by passing the diff and bSubmit flag to true
18274                    xfaResultObject = window.formBridge.getFormState(true, true);
18275                } else {
18276                    xfaResultObject = window.formBridge.getFormState();
18277                }
18278                if (xfaResultObject.errors) {
18279                    guideBridge._guide.logger().log("Error in getting Xfa State:" + JSON.stringify(xfaResultObject.getNextMessage()));
18280                    alert(guidelib.util.GuideUtil.getLocalizedMessage("AF", guidelib.i18n.LogMessages["AEM-AF-901-001"]));
18281                }
18282                xfaState = xfaResultObject.data;
18283            }
18284
18285            var guideDom = guideBridge._getGuideDom(options);
18286
18287            //adding additionalSubmitInfo in the guideState.
18288            //additionalSubmitInfo contains the information about action fields.
18289            var additionalSubmitInfo = guideBridge._getAdditionalSubmitInfo();
18290            //set the updated file attachment map in the customPropertyMap
18291            guideBridge.customContextProperty("fileAttachmentMap", JSON.stringify(this.getFileAttachmentMap()));
18292            var guideState = {
18293                guideDom : guideDom,
18294                //save renderContext in guide state to enable deferred submit even if guide is not open
18295                guideContext : guideBridge._guide.runtime.guideContext,
18296                additionalSubmitInfo : additionalSubmitInfo
18297            };
18298
18299            if (guideBridge._guide.allLazyChildren.length > 0) {
18300                guideBridge._guide.internal.liveDataUtils.updateLiveData();
18301                var listOfDirtyPanels = guideBridge._guide.internal.GuideDirtyMarkerAndVisitor.flatten
18301DirtyPanelMapToCSV();
18302                if (listOfDirtyPanels.length > 0) {
18303                    this.afSubmissionInfo("afDraft", listOfDirtyPanels);
18304                }
18305                // save live xml & xfa state as xml for restoration of lazy model on 'restore'
18306                guideState.guideLiveData = guideBridge._guide.internal.liveDataUtils.getLiveDataStr();
18307                if (this._isXfaGuide() && this._isValidXFAGuide()) {
18308                    formBridge.getDataXML({"success" : saveXfaXml}); // currently xfa restore relies on formBridge.getDataXML being sync
18309                }
18310            }
18311            obj.data.guideState = guideState;
18312            if (xfaState) {
18313                obj.data.guideState.xfaState = xfaState;
18314            }
18315
18316        },
18317
18318        _updateAFSubmissionInfo : function (guide) {
18319            if (guideBridge.isGuideLoaded(true) && !guide) {
18320                var previousFocusSom = this._guideView._previousFocusItemSom;
18321                var previousItemModel = guideBridge.resolveNode(this._guideView._previousFocusItemSom);
18322                if (getOrElse(previousItemModel, "parent.className", undefined) === "guideToolbar") {
18323                    previousFocusSom = previousItemModel.parent.parent.somExpression;
18324                }
18325                this.afSubmissionInfo("lastFocusItem", this._guideView.getSomOnNavigableAncestor(previousFocusSom));
18326            }
18327            var newGuide = guide ? guide : guideBridge._guide;
18328            this.afSubmissionInfo("excludeFromDoR", newGuide._getExcludeFromDorMap());
18329            // send state override on in cases when we have dor
18330            var stateOverrides = {};
18331            if (newGuide.dorType && "none" !== newGuide.dorType) {
18332                stateOverrides = newGuide._getStateOverrideMap();
18333            }
18334            this.afSubmissionInfo("stateOverrides", stateOverrides);
18335            // Add signers to af submission info
18336            this.afSubmissionInfo("signers", newGuide._getSigners());
18337
18338        },
18339
18340        /**
18341         * Adaptive Form stores its state in the form of JSON. The Files attached in the component are uploaded
18342         * onto the server and their paths are returned in the JSON state except in certain conditions mentioned below.
18343         * The API is an asynchronous call which calls the success and error handlers with the data.
18344         *
18345         * In the below mentioned scenarios the file will not be uploaded
18346         * * User doesn't have **write permissions** on the _fileUploadPath_ provided
18347         * * The _fileUploadPath_ property doesn't point to a node of type _**sling:Folder**_
18348         *
18349         * @summary Retrieve the current state of Adaptive Form as json string
18350         * @param {object} options Input object containing the callbacks that will be invoked
18351         * to provide the result of the API
18352         * @param {function} [options.success] callback which receives the result of the API
18353         * in case of success.
18354         * {@link GuideResultObject#errors|errors} property as false.
18355         * @param {function} [options.error] callback which receives the result of the API in
18356         * case of failure.
18357         * {@link GuideResultObject#errors|errors} property as true.
18358         * @param {object} [options.context] _this_ object inside the _success_ and _error_ callback will point to this
18359         * object
18360         * @param {string} [options.fileUploadPath] controls whether the files in the File Attachment component have to be
18361         * uploaded or not. If _fileUploadPath_ is non null, only then file gets uploaded and the model's value is
18362         * updated with the file url
18363         *
18364         * @method
18365         * @memberof GuideBridge
18366         * @since 6.0
18367         * @instance
18368         */
18369        getGuideState : function (options) {
18370
18371            // walk through the model to get the list of file attachment components
18372            var fileAttachmentsList = this._getFileAttachmentsList();
18373            guideBridge._updateAFSubmissionInfo();
18374
18375            if (guideBridge.isGuideLoaded(true)) {
18376                this.customContextProperty("lastFocusItem", this._guideView.getSomOnNavigableAncestor(this._guideView._previousFocusItemSom));
18377            }
18378
18379            // Walk through the list of file Attachment components
18380            // and update the value of every item
18381            // Get the list of file Attachments
18382            if (options.fileUploadPath) {
18383                var optionArgument = {"options" : options,
18384                                       "fileAttachmentsList" : fileAttachmentsList,
18385                                       "fileUploadPath" : options.fileUploadPath,
18386                                        "callback" : window.guideBridge._collectFileUrls,
18387                                        "errorCallback" : window.guideBridge._fileUploadFailed};
18388
18389                this._getGuideAttachments(optionArgument);
18390            } else {
18391                this._createGuideStateAndLiveXml(options);
18392                if (options.success) {
18393                    options.success.call(options.context, options.obj);
18394                }
18395            }
18396
18397        },
18398
18399        /**
18400         * Validates the Adaptive Form or it's specific panel and return the validation status. The API also moves
18401         * focus to first invalid element
18402         * @summary validate the entire Form or a component in Adaptive Form
18403         * @param  {Field~ValidationError[]} errorList Input must be an empty array. The array will be filled with list
18404         * of Adaptive Form Components that failed validation.
18405         * @param  {string}
18405 [somExpression] SOM Expression of the Guide Node for which validation should be triggered.
18406         * If not provided, it would validate the entire Adaptive Form
18407         * @param {boolean} [setFocus=true] If true, set focus to the first invalid element.
18408         * @returns {boolean} true if the component/form was valid, false otherwise
18409         * @method
18410         * @memberof GuideBridge
18411         * @since 6.0
18412         * @instance
18413         * @see Field#validate
18414         * @see Panel#validate
18415         */
18416        validate : function (errorList, somExpression, setFocus, guide) {
18417            // guide parameter is not to be documented and it is meant for internal use only
18418            var guideNode = null,
18419                isFocusEnabled = _.isUndefined(setFocus) ? true : setFocus,
18420                ec = guidelib.util.ErrorConstants,
18421                validationContext,
18422                afContainer = guide ? guide : this._guide; // done, to keep this thread safe
18423            //  get Json of all the dirty , non visited (templateJson missing from cache)
18424            if (afContainer.allLazyChildren.length > 0) {
18425                afContainer.guideLazyUtil.putDirtyToTemplateCacheIfMissing(afContainer);
18426            }
18427            if (somExpression) {
18428                guideNode = this.resolveNode(somExpression);
18429                // how to know if the panel is navigable from the model. We do not bring the nonNavigable property ?
18430                if (guideNode instanceof guidelib.model.GuidePanel) {
18431                    validationContext = ec.CONTEXT_NAVIGATION;
18432                }
18433            } else {
18434                guideNode = afContainer;
18435                validationContext = ec.CONTEXT_SUBMISSION;
18436            }
18437            this.setValidationContext(validationContext);
18438            var status = false;
18439            if (!errorList) {
18440                errorList = [];
18441            }
18442            status = guideNode.validate(errorList);
18443
18444            try {
18445                // there can be errors in the user script, hence handling the exception gracefully, and resetting the global error state properly
18446                this._guide._triggerOnBridge("validationComplete", this._guide, status, "", errorList);
18447                if (!status && isFocusEnabled) {
18448                    var errorSom = errorList[0]["som"];
18449
18450                    guideBridge._guide.on(guidelib.event.GuideModelEvent.LAZY_LOADED, function () {
18451                        var errorField = guideBridge.resolveNode(errorSom);
18452                        if (errorField) {
18453                            errorField.validate();
18454                        }
18455                    }, {});
18456
18457                    this.setFocus(errorSom);
18458
18459                    guideBridge._guide.off(guidelib.event.GuideModelEvent.LAZY_LOADED);
18460                }
18461
18462            } catch (exception) {
18463                this._guide.logger().log(exception);
18464            } finally {
18465                // since the errors have been published reset the state back to normal
18466                //guidelib.runtime.errorManager.setGlobalError(false);
18467                this.unsetValidationContext(validationContext);
18468                return status;
18469            }
18470
18471        },
18472
18473        // todo: submit behaviour should make sure that if the value of file upload
18474        /**
18475         * Adaptive Form can be restore in three ways
18476         * * by passing the JSON data obtained from {@link GuideBridge#getGuideState}. This can be done by setting
18477         * _**data**_ property .
18478         * * by passing a URL pointing to a resource that returns JSON/XML data that should be used. This can be done by setting
18479         * _**dataRef**_ property. The data can be obtained by calling the
18480         * {@link GuideBridge#getData|getData} API.
18481         * * by passing a URL pointing to a resource that returns JSON data obtained from {@link GuideBridge#getGuideState}.
18482         * This can be done by setting _**guideStatePathRef**_ property .
18483         *
18484         * When restoring from dataRef, only values and other properties, that are dependant on value, are restored. For
18485         * example, If a Field was hidden based on the click of a Button then
18486         * when restoring from data XML/JSON the Field will not remain hidden.
18487         *
18488         * **NOTE:** The _data_, _dataRef_ and _guideStatePathRef_ must not be null simultaneously and only one property
18489         * must be specified. Specifying more than one can lead to undesired results.
18490         * @summary restore/prepopulate the state of Adaptive Form from an earlier saved state
18491         * @param {object}
18491 options object containing the callbacks to be invoked on
18492         * success/failure and data from where to restore the object.
18493         * @param {function} [options.success] callback which receives the result of the API
18494         * in case of success
18495         * {@link GuideResultObject#errors|errors} property as false.
18496         * @param {function} [options.error] callback which receives the result of the API in
18497         * case of failure.
18498         * {@link GuideResultObject#errors|errors} property as true.
18499         * @param {object} [options.context] _this_ object inside the _success_ and _error_ callback will point to this
18500         * object.
18501         * @param {object} [options.data] It must be the value of the {@link GuideResultObject#data|data} property passed to
18502         * the _success_ handler of {@link GuideBridge#getGuideState|getGuideState} API.
18503         * @param {string} [options.dataRef] URL pointing to the data XML/JSON.
18504         * @param {string} [options.guideStatePathRef] URL pointing to the JSON state of Adaptive Form.
18505         *
18506         * @method
18507         * @memberof GuideBridge
18508         * @since 6.0
18509         * @instance
18510         * @example <caption>Restoring from JSON data</caption>
18511         * var jsonData;
18512         * guideBridge.getGuideState({
18513         *      success : function (guideResultObj) {
18514         *          jsonData = guideResultObj.data;
18515         *      },
18516         *      error : function (guideResultObj) {
18517         *          // log error
18518         *      }
18519         * });
18520         *
18521         * // after some time or on click of a button or reloading the page
18522         * guideBridge.restoreGuideState({
18523         *      guideState : jsonData.guideState,
18524         *      error : function (guideResultObject) {
18525         *          // log the errors
18526         *      }
18527         * })
18528         *
18529         * @example <caption>Restoring from data XML/JSON</caption>
18530         * guideBridge.getData({
18531         *      success : function (guideResultObj) {
18532         *          var data = guideResultObj.data;
18533         *          //post the data to a server that saves it at say http://abc.com/my/data.xml
18534         *          //or http://abc.com/my/data.json
18535         *      },
18536         *      error : function (guideResultObj) {
18537         *          // log the errors
18538         *      }
18539         * });
18540         *
18541         * // after some time or on click of a button or reloading the page
18542         * guideBridge.restoreGuideState({
18543         *      dataRef : "http://abc.com/my/data.xml",
18544         *      error : function (guideResultObject) {
18545         *          // log the errors
18546         *      }
18547         * })
18548         *
18549         * @example <caption>Restoring from URL to a JSON</caption>
18550         * guideBridge.getGuideState({
18551         *      success : function (guideResultObj) {
18552         *          var json = guideResultObj.data;
18553         *          //post the JSON to a server that saves it at say http://abc.com/my/data.json
18554         *      },
18555         *      error : function (guideResultObj) {
18556         *          // log the errors
18557         *      }
18558         * });
18559         *
18560         * // after some time or on click of a button or reloading the page
18561         * guideBridge.restoreGuideState({
18562         *      guideStatePathRef : "http://abc.com/my/data.json",
18563         *      error : function (guideResultObject) {
18564         *          // log the errors
18565         *      }
18566         * })
18567         **/
18568        restoreGuideState : function (options) {
18569            var parameters,
18570                path;
18571            if (options && options.dataRef) {
18572                parameters = {"dataRef" : options.dataRef};
18573            } else if (options && options.guideStatePathRef) {
18574                parameters = {"guideStatePathRef" : options.guideStatePathRef};
18575            }
18576            // if parameters have DataRef or guideStatePathRef, a recursive call is made to restoreGuideState.
18577            if (parameters) {
18578                path = window.guideBridge.getGuidePath();
18579                path = path + ".guidejson";
18580                $.ajax({
18581                    url : path,
18582                    type : "GET",
18583                    async : false,
18584                    cache : false,
18585                    data : parameters,
18586                    success : function (response) {
18587                        //case where section information exist in guideState
18588                        if (response.guideState && response.guideState.guideContext
18589                            && response.guideState.guideContext.customPropertyMap
18590                            && response.guideState.guideContext.customPropertyMap.sections
18591                            && response.guideState.guideContext.customPropertyMap.sections.length > 0) {
18592                            // todo: add safe check for string vs array
18593                            window.guideBridge.customContextProperty.sections = response.guideState.guideContext.customPropertyMap.sections;
18594                        }
18595                        //passing the options again, but with DataRef or guideStatePathRef removed from it.
18596                        window.guideBridge.restoreGuideState(_.extend(
18597                            {},
18598                            options,
18599                            {
18600                                guideState : response.guideState,
18601                                dataRef : undefined,
18602                                guideStatePathRef : undefined
18603                            }
18604                        ));
18605                    },
18606                    error : function (response) {
18607                        window.guideBridge._guide.logger().log("Error: " + response);
18608                    }
18609                });
18610                return;
18611            }
18612
18613            /*
18614             * We have to merge the runtime guideContext with the guideContext passed in the guideState
18615             * so that no custom properties that were set in the guideState.guideContext are ignored.
18616             */
18617            guidelib.__runtime__.guideContext = guidelib.__runtime__.guideContext || {};
18618            if (guideBridge.isGuideLoaded()) {
18619                guideBridge._guide.runtime.guideContext = guideBridge._guide.runtime.guideContext || {};
18620            }
18621            var gc = getOrElse(options, "guideState.guideContext", undefined);
18622            if (!_.isUndefined(options.guideState.guideContext)) {
18623                /* Runtime custom property map is set by external application and hence, shallow copy will set the value
18624                 * as set externally. If no value was set, the guideState custom property map keys stay.
18625                 */
18626                _.extend(gc.customPropertyMap, guidelib.__runtime__.guideContext.customPropertyMap);
18627                if (guideBridge.isGuideLoaded()) {
18628                    _.extend(gc.customPropertyMap, guideBridge._guide.runtime.guideContext.customPropertyMap);
18629                }
18630            }
18631            // not setting at guidelib runtime, but honoring if anyone has set customPropertyMap
18632            // through guidelib.runtime.guideContext directly
18633            if (guideBridge.isGuideLoaded()) {
18634                _.extend(guideBridge._guide.runtime.guideContext, gc);
18635            }
18636
18637            if (!this._guide) {
18638                this.storage = {};
18639                this.storage.guideState = options.guideState;
18640                //NOCHECKMARX - This is error callback to be provided by the user of this API.
18641                this.storage.error = options.error;
18642                this.storage.success = options.success;
18643                this.storage.context = options.context;
18644            } else {
18645                this._playGuideJson(options);
18646                // Trigger the event
18647                // If guide has restore state, call sync guide node to html
18648                // Case 1: If this is called before view gets initialized, there would be no listener present, hence nothing would happen
18649                // Case 2: If it is called after view gets initialized(using restore guide state in mobile workspace), then the model would sync to view
18650                // using this event
18651                // If view is initialized, which means a listener would to MODEL_REFRESH would be set, hence just trigger the event for execution
18652                if (this._guideView) {
18653                    this._guide._triggerEvent(guidelib.event.GuideModelEvent.MODEL_REFRESH, "jsonModel", null, null);
18654                }
18655            }
18656
18657        },
18658
18659        /**
18660         * Adaptive Form can set data in three ways:
18661         * * by passing the JSON data obtained from {@link GuideBridge#getGuideState}. This can be done by setting
18662         * _**data**_ property .
18663         * * by passing a URL pointing to a resource that returns data JSON/XML that should be used. This can be done by setting
18664         * _**dataRef**_ property. The data can be obtained by calling the
18665         * {@link GuideBridge#getData|getData} API.
18666         * * by passing a URL pointing to a resource that returns JSON data obtained from {@link GuideBridge#getGuideState}.
18667         * This can be done by setting _**guideStatePathRef**_ property .
18668         *
18669         * When setting data from dataRef, only values and other properties, that are dependant on value, are set. For
18670         * example, If a Field was hidden based on the click of a Button in the data passed then
18671         * when setting data from XML/JSON the Field will not remain hidden.
18672         *
18673         * **NOTE:** The _data_, _dataRef_ and _guideStatePathRef_ must not be null simultaneously and only one property
18674         * must be specified. Specifying more than one can lead to undesired results.
18675         * @summary Populate the Adaptive Form from the data.
18676         * @param {object}
18676 options object containing the callbacks to be invoked on
18677         * success/failure and data from where to restore the object.
18678         * @param {function} [options.success] callback which receives the result of the API
18679         * in case of success
18680         * {@link GuideResultObject#errors|errors} property as false.
18681         * @param {function} [options.error] callback which receives the result of the API in
18682         * case of failure.
18683         * {@link GuideResultObject#errors|errors} property as true.
18684         * @param {object} [options.context] _this_ object inside the _success_ and _error_ callback will point to this
18685         * object.
18686         * @param {object} [options.data] It must be the value of the {@link GuideResultObject#data|data} property passed to
18687         * the _success_ handler of {@link GuideBridge#getGuideState|getGuideState} API.
18688         * @param {string} [options.dataRef] URL pointing to the data JSON/XML.
18689         * @param {string} [options.guideStatePathRef] URL pointing to the JSON state of Adaptive Form.
18690         *
18691         * @method
18692         * @memberof GuideBridge
18693         * @since 6.3
18694         * @instance
18695         * @example <caption>Setting data from JSON data</caption>
18696         * var jsonData;
18697         * guideBridge.getGuideState({
18698         *      success : function (guideResultObj) {
18699         *          jsonData = guideResultObj.data;
18700         *      },
18701         *      error : function (guideResultObj) {
18702         *       // log the errors
18703         *      }
18704         * });
18705         *
18706         * guideBridge.setData({
18707         *      guideState : jsonData,
18708         *      error : function (guideResultObject) {
18709         *          // log the errors
18710         *      }
18711         * })
18712         *
18713         * @example <caption>Setting data from XML/JSON</caption>
18714         * guideBridge.getData({
18715         *      success : function (guideResultObj) {
18716         *          var data = guideResultObj.data;
18717         *          //post the XML/JSON to a server that saves it at say http://abc.com/my/data.xml
18718         *          //or http://abc.com/my/data.json
18719         *      },
18720         *      error : function (guideResultObj) {
18721         *          // log the errors
18722         *      }
18723         * });
18724         *
18725         * guideBridge.setData({
18726         *      dataRef : "http://abc.com/my/data.xml",
18727         *      error : function (guideResultObject) {
18728         *          // log the errors
18729         *      }
18730         * })
18731         *
18732         * @example <caption>Setting data from URL to a JSON</caption>
18733         * guideBridge.getGuideState({
18734         *      success : function (guideResultObj) {
18735         *          var json = guideResultObj.data;
18736         *          //post the JSON to a server that saves it at say http://abc.com/my/data.json
18737         *      },
18738         *      error : function (guideResultObj) {
18739         *          // log the errors
18740         *      }
18741         * });
18742         *
18743         * guideBridge.setData({
18744         *      guideStatePathRef : "http://abc.com/my/data.json",
18745         *      error : function (guideResultObject) {
18746         *          // log the errors
18747         *      }
18748         * })
18749         **/
18750        setData : function (options) {
18751            guideBridge.restoreGuideState(options);
18752        },
18753
18754        /*
18755         * @private
18756         */
18757        _getStorage : function () {
18758            var storage = null;
18759            if (this.storage) {
18760                // Get the storage
18761                storage = this.storage;
18762                this.storage = null;
18763            }
18764            return storage;
18765        },
18766
18767        getGuideContext : function () {
18768            var obj = new GuideResultObject();
18769            obj.data = jQuery.extend(true, {}, (this._guide ? this._guide.runtime.guideContext : null));
18770            return obj;
18771        },
18772
18773        _getContextRoot : function () {
18774            return this.userConfig["contextPath"];
18775        },
18776
18777        _getEnableFocusOnFirstField : function () {
18778            var renderConfig = this.userConfig.renderConfig || {},
18779                enableFocusOnFirstField = renderConfig.enableFocusOnFirstField === undefined ? true : renderConfig.enableFocusOnFirstField,
18780                // convert "true"/"false" strings to boolean too
18781                enableFocusOnFirstFieldAsBoolean = enableFocusOnFirstField === 'true' || (enableFocusOnFirstField === 'false' ? false : enableFocusOnFirstField);
18782            // default value is true
18783            return enableFocusOnFirstFieldAsBoolean;
18784        },
18785
18786        _updateAjaxUrl : function (baseUrl) {
18787            if (this.hostName === "server") {
18788                $.ajaxPrefilter(function (options, originalOptions, jqXHR) {
18789                    // 'Rebase' the URL if required.
18790                    var thisUrl = options.url;
18791                    if ((thisUrl.lastIndexOf('http://', 0) !== 0) && (thisUrl.lastIndexOf('https://', 0) !== 0)) {
18792                        // thisUrl is relative.
18793                        // thisUrl may or may not begin with slash
18794                        // encoding taken care by the ajax call
18795                        if (thisUrl.indexOf("/") === 0) {
18796                            // if begins with slash
18797                            thisUrl = baseUrl + thisUrl;
18798                        } else {
18799                            thisUrl = baseUrl + "/" + thisUrl;
18800                        }
18801                        options.url = thisUrl;
18802                    }
18803                });
18804
18805                // Native XHR Wrapper
18806                var originalOpen = XMLHttpRequest.prototype.open;
18807                XMLHttpRequest.prototype.open = function(method, url) {
18808                    if ((url.lastIndexOf('http://', 0) !== 0) && (url.lastIndexOf('https://', 0) !== 0)) {
18809                        // url is relative
18810                        if (url.indexOf("/") === 0) {
18811                            url = baseUrl + url;
18812                        } else {
18813                            url = baseUrl + "/" + url;
18814                        }
18815                    }
18816                    originalOpen.apply(this, arguments);
18817                };
18818            }
18819        },
18820
18821        _getUrl : function (url) {
18822            var baseUrl = this.userConfig["baseUrl"],
18823                contextPath = this.userConfig["contextPath"];
18824            if (baseUrl) {
18825                return baseUrl + url;
18826            } else if (contextPath && contextPath !== "/" && url.indexOf(contextPath) !== 0 && (url.length === 0 || url.indexOf("/") === 0)) {
18827                //if url does not have contextPath and starts with /, pre-pend contextPath
18828                // Also url.length check because I need to pass "" to getUrl and get context path
18829                return contextPath + url;
18830            }
18831            return url;
18832        },
18833
18834        _getGuidePathUrl : function (urlSuffix, guidePath) {
18835            // guidePath here refers to the path got from json state of guide
18836            // we use this path, if there is no guidePath set in guidelib.runtime.guideContext, cases where guide is not initialized but
18837            // guideBridge is present
18838            var path = guidePath || this.getGuidePath(),
18839                url = path + (urlSuffix || "");
18840            return this._getUrl(url);
18841        },
18842
18843        /**
18844         * @summary Returns the path which refers to the location of
18845         * the content resource of adaptive form container
18846         * @returns {String} Path to the content resource of the adaptive form container
18847         * @method
18848         * @memberof GuideBridge
18849         * @since 6.5
18850         * @instance
18851         */
18852        getGuidePath : function () {
18853            var guideContext = this.getGuideContext().data;
18854            if (guideContext && guideContext.hasOwnProperty("guidePath")) {
18855                return guideContext["guidePath"];
18856            }
18857            return null;
18858        },
18859
18860        /**
18861         * @summary Given a somExpression, return the {@link GuideNode} having the same somExpression.
18862         * @param {string} somExpression somExpression of the Adaptive Form component
18863         * @returns {GuideNode} GuideNode matching the som expression or null if not found
18864         * @method
18865         * @memberof GuideBridge
18866         * @since 6.0
18867         * @instance
18868         * @see GuideNode#somExpression
18869         */
18870        resolveNode : function (somExpression) {
18871            return this._guide.resolveNode(somExpression);
18872        },
18873        /*
18874         * Internal API. Should be used carefully.
18875         */
18876        _resolveId : function (id) {
18877            var node = this._guide._modelTemplateCacheStore.getModel(id);
18878            return node;
18879        },
18880
18881        /**
18882         * Helper method for accesibility announcements
18883         * Is part of the fix for FORMS-7071 (CQ-4276669)
18884         */
18885        _ariaLiveAnnouncement : function (text) {
18886            var ariaLiveElement = $("#ariaLiveElement");
18887            setTimeout(function() {
18888                $(ariaLiveElement).text(text);
18889                return (setTimeout(function() {
18890                    $(ariaLiveElement).text("");
18891                }, 2000))
18892            }, 500);
18893        },
18894
18895        /**
18896         * Invokes {@link Field#resetData}
18896 API for all the Fields inside the Form to reset their values to default
18897         * @summary Reset the values of all the Fields to their default values.
18898         *
18899         * @method
18900         * @memberof GuideBridge
18901         * @instance
18902         * @since 6.0
18903         */
18904        reset : function () {
18905            if (window.xfalib && window.xfalib.runtime && window.xfalib.runtime.xfa) {
18906                var xfa = window.xfalib.runtime.xfa;
18907                xfa.host.resetData();
18908            }
18909            this._guide.resetData();
18910
18911            if (this._guide.internal.liveDataUtils.isLiveDataInitialized()) {
18912                this._guide.internal.liveDataUtils.updateLiveData();
18913            }
18914
18915            var guideDirtyMarkerAndVisitor = this._guide.internal.GuideDirtyMarkerAndVisitor;
18916            guideDirtyMarkerAndVisitor.visitMap = guidelib.model.util.CommonUtils.createMap(this._guide.allLazyChildren, 0);
18917
18918            this._ariaLiveAnnouncement(guidelib.i18n.strings["formHasBeenReset"]);
18919        },
18920
18921        _getPreviousFocus : function () {
18922            return this._guideView._previousFocusItemSom;
18923        },
18924
18925        /**
18926         * Returns the somExpression of the current {@link Panel} or current {@link Field} in Focus. The API can also
18927         * be used to get the somExpression of the Navigable Panel that contains the current Element in Focus.
18928         *
18929         * @summary return the somExpression of the {@link Panel} or {@link Field} that is currently in focus
18930         * @param {object} options configuration to be passed to the API to get the desired result
18931         * @param {?string} [options.focusOption] Currently the following value of this option are supported
18932         * * `navigablePanel`: if one wants to get the somExpression of the Navigable Panel
18933         * @returns {string} somExpression of Adaptive Form component representing the field or panel.
18934         * @method
18935         * @memberof GuideBridge
18936         * @instance
18937         * @since 6.0
18938         * @see {GuideNode#somExpression}
18939         * @example
18940         * guideBridge.getFocus({"focusOption": "navigablePanel"})
18941         */
18942        getFocus : function (options) {
18943            var focusOption;
18944            if (_.isUndefined(options)) {
18945                return this._guideView.currentFocusItemSom;
18946            }
18947            if ((focusOption = getOrElse(options, "focusOption", null)) === "navigablePanel") {
18948                return this._guideView._lastFocussedPanelForNonActionFields;
18949            }
18950            this._guide.logger().log("Invalid Focus option.", focusOption);
18951        },
18952
18953        /**
18954         * The API is equivalent to calling
18955         * `guideBridge.setFocus(options.somExpression, options.focusOption, options.runCompletionScript)`
18956         * @summary An alternate signature to the {@link GuideBridge#setFocus|setFocus} API
18957         * @method setFocus
18958         * @memberof GuideBridge
18959         * @instance
18960         * @since 6.1 FP1
18961         * @param {object} options options passed to the API
18962         * @param {string} options.somExpression somExpression to set the focus to
18963         * @param {string} options.focusOption item inside the Panel to focus to
18964         * @param {string} options.runCompletionScript whether to run the completion script or not.
18965         * @return {boolean} true if the focus was set successfully otherwise false.
18966         */
18967
18968        /**
18969         * In Adaptive Form one can focus a Field/Panel. Setting focus on a Panel means setting focus to its first
18970         * child. This can be controlled using the _focusOption_ provided in this API.
18971         *
18972         * The API provides two mechanism to focus a Field/Panel.
18973         * * **Direct** : By providing the somExpression of the Field/Panel. If the somExpression of Panel is provided,
18974         * then based on the focusOption one of its child (or their child) is set to Focus
18975         * * **Indirect** : By providing an item's relative position inside a Panel, first or last item inside of a
18976         * Panel, sibling of current focussed Item of a Panel, etc. If the item is a Panel then the First Item of
18977         * that Panel (if that is again a Panel, this process continues until a Field is found) is activated.
18978         *
18979         * The first way is trivial, by providing the _somExpression_ of a {@link Field} to the API, the focus will be
18980         * set to the Field.
18981         *
18982         * If that Field is inside a Panel that is not currently open because of tabbed/wizard navigation, then that tab
18983         * would be opened and focus would be set to the Field/Panel.
18984         *
18985         * The API can also execute the
18986         * [completion expression](https://helpx.adobe.com/aem-forms/6-1/adaptive-form-expressions.html#main-pars_header_8)
18987         * of the current Panel and only if the expression returns true set focus to the required element.
18988         *
18989         * **Note:**
18990         * * If _focusOption_ is either of nextItemDeep or prevItemDeep then _somExpression_ parameter must not be
18991         * passed. Otherwise the API will throw an exception
18992         * * If _somExpression_ points to a {@link Field} and _focusOption_ is not _nextItemDeep_ or _prevItemDeep_ then
18993         * _focusOption_ is ignored.
18994         *
18995         * @summary Sets focus to a {@link Field} or {@link Panel}
18996         * @param {?string} somExpression SOM Expression of the Adaptive Form Field or Panel which has to be activated.
18997         * @param {string} [focusOption=firstItem] The option provides the mechanism to focus onto an sibling of the
18998         * current active item.
18999         * * **_firstItem_** - Focuses to the first focusable item of the Panel whose _SOM Expression_ is provided
19000         * * **_lastItem_** - Focuses to the last focusable item of the Panel whose _SOM Expression_ is provided
19001         *
19002         * If either the _firstItem_ or _lastItem_ is a Panel, then the _firstItem_ of that Panel (until a Field is
19003         * found) is set to Focus.
19004         *
19005         * * **_nextItem_** - Next sibling component of the current active Item of the Panel whose _somExpression_ is
19006         * provided. It is equivalent to the result of `panel.navigationContext.nextItem` API.
19007         * * **prevItem** - Previous sibling component of the current active Item of the Panel show _somExpression_ is
19008         * provided. It is equivalent to the result of `panel.navigationContext.prevItem` API.
19009         *
19010         * * **_nextItemDeep_** - Focus is set to the next Navigable Panel of root Panel in DFS Order
19011         * * **_prevItemDeep_** - Focus is set to the next Navigable Panel of root Panel in DFS Order
19012         * @param {boolean} [runCompletionScript=false] indicating whether to execute the completion expression or not.
19013         * @returns {boolean} true if the focus was set to requested field successfully otherwise false
19014         * @method
19015         * @memberof GuideBridge
19016         * @since 6.0
19017         * @instance
19018         * @example
19019         * setFocus(somExpression); // Focus is set to the specified somExpression.
19020         * setFocus(this.panel.somExpression,'nextItem',true); // Focus is set to next item in the Panel.
19021         * setFocus(null,'nextItemDeep',true); // Focus is set to next navigable Panel in rootPanel
19022         */
19023        setFocus : function (somExpression, focusOption, runCompletionScript) {
19024            var options,
19025                focusDone,
19026                originalSkipFieldFocus;
19027            if (_.isObject(somExpression)) {
19028                options = somExpression;
19029            } else {
19030                options = {
19031                    somExpression : somExpression,
19032                    focusOption : focusOption,
19033                    runCompletionScript : runCompletionScript
19034                };
19035            }
19036            try {
19037                originalSkipFieldFocus = this._guideView.skipFieldFocus;
19038                /**
19039                 * Setting of this._guideView.skipFieldFocus was added for issue LC-3911361
19040                 * Here we set a skipFieldFocus property for gudeContainerView, which prevents
19041                 * actual 'input' / widget focus. This was done to prevent opening of keyboard or dropdown spinner
19042                 * or date picker.. in case of swipe and use of deep navigators in mobile view of Adaptive Form.
19043                 *
19044                 * when user validates Adaptive Form, skipFieldFocus is set to  options.skipFieldFocus based on somExpression
19045                 * which has default value of'undefined' else the skipFieldFocus set to the negated value of global variable
19046                 * enableFocusOnFirstField to enable/disable focus on first field of Adaptive Form.
19047                */
19048                var fallbackSkipFieldFocus = !this._guide.enableFocusOnFirstField;
19049                if (!fallbackSkipFieldFocus) {
19050                    fallbackSkipFieldFocus = !guideBridge._getEnableFocusOnFirstField();
19051                }
19052                this._guideView.skipFieldFocus = options.somExpression ? options.skipFieldFocus : fallbackSkipFieldFocus;
19053                focusDone = this._guideView.setFocus(options);
19054            } finally {
19055                this._guideView.skipFieldFocus = originalSkipFieldFocus; //moving back to original state
19056            }
19057            //TODO: need a more common place to do that.
19058            if (!this._guide._currentContext) {
19059                this._guide.runPendingExpressions();
19060            }
19061            return focusDone;
19062        },
19063
19064        /**
19065         * Loads the lazy fragment specified by somExpression
19066         * @param {string} somExpression somexpression of the lazy loaded fragment
19067         * @param {object} options options to control the behaviour of loadLazyFragment API.
19068         * @param {object} [options.async] options to control if the fragment is to be loaded lazily
19069         * @param {function} [options.error] callback which receives the result of the API in
19070         * case of failure.
19071         * @method
19072         * @memberof GuideBridge
19073         * @since 6.4
19074         * @instance
19075         * @example <caption>Loading a lazy loaded fragment with somexpression x[0].y[0].z[0]. If both y and z form objects are lazy loaded, this API
19076         * would load both</caption>
19077         * guideBridge.loadLazyFragment("x[0].y[0].z[0]");
19078         *
19079         */
19080        loadLazyFragment : function (somExpression, options) {
19081            options = options || {};
19082            if (!_.isUndefined(somExpression)) {
19083                var relativeSom = guidelib.util.GuideUtil.relativeSom(this._guide.rootPanel.somExpression, somExpression);
19084                if (relativeSom) {
19085                    var somTokens = relativeSom.split(".");
19086                    var currItem = this._guide.rootPanel;
19087                    _.each(somTokens, function (qName, index) {
19088                        if (currItem != null) {
19089                            var arr = currItem._findChildren(qName, false);
19090                            if (arr.length > 0) {
19091                                var node = arr[0];
19092                                if (node && node._lazyReference && !node._itemsLoaded) {
19093                                    this._guide.internal.liveDataUtils.updateLiveData();
19094                                    if (options.async) {
19095                                        var successFunc = (function () {
19096                                            return function (complete) {
19097                                                if (options.success) { // Check if success callback exists
19098                                                    options.success.call(this, {lazyLoadingComplete: complete});
19099                                                }
19100                                            }
19101                                        }(index === somTokens.length - 1))
19102                                    }
19103                                    node._loadLazyFragment(options);
19104                                }
19105                                currItem = options.async === true ? null : node;
19106                            } else {
19107                                currItem = null;
19108                            }
19109                        }
19110                    }, this);
19111                }
19112            }
19113        },
19114
19115        /**
19116         * Pre-loads models for all lazy loaded fragments without creating views or fetching HTML.
19117         * This allows existing user scripts to access lazy fragment fields immediately at form initialization
19118         * without waiting for user navigation. The actual view creation and HTML loading happens on-demand
19119         * when the user navigates to the lazy fragment, optimizing both initialization time and runtime performance.
19120         *
19121         * Note: This API should be called after the guide model is initialized but before view creation.
19122         * Use {@link GuideBridge#_modelConnect|_modelConnect} to ensure proper timing.
19123         *
19124         * IMPORTANT LIMITATION: Global bound fields in lazy fragments will NOT receive their prefilled values
19125         * when using this API, because it executes before prefill data is applied. If your lazy fragments contain
19126         * global bound fields that need prefill data, you have two options:
19127         * 1. Do not use this API and rely on on-demand lazy loading
19128         * 2. Manually apply prefill values to these fields after calling this API
19129         *
19130         * @summary Pre-loads lazy fragment models from cache to ensure script compatibility
19131         * @method
19132         * @memberof GuideBridge
19133         * @since 6.5
19134         * @instance
19135         * @param {Object} [options] - Optional configuration
19136         * @param {Function} [options.preFetch] - Callback invoked before loading models (e.g., show loading indicator). Registered for reuse during subsequent lazy loads.
19137         * @param {Function} [options.postFetch] - Callback invoked after loading models (e.g., hide loading indicator). Registered for reuse during subsequent lazy loads.
19138         * @example <caption>Pre-load all lazy fragment models during form initialization</caption>
19139         * window.guideBridge._modelConnect(function() {
19140         *     this.loadAllLazyFragmentModels();
19141         * });
19142         * @example <caption>Using bridgeInitializeStart event</caption>
19143         * window.addEventListener("bridgeInitializeStart", function(evnt) {
19144         *     var gb = evnt.detail.guideBridge;
19145         *     gb._modelConnect(function() {
19146         *         gb.loadAllLazyFragmentModels();
19147         *     });
19148         * });
19149         * @example <caption>With custom loading callbacks</caption>
19150         * window.guideBridge._modelConnect(function() {
19151         *     this.loadAllLazyFragmentModels({
19152         *         preFetch: function() { $("#customLoader").show(); },
19153         *         postFetch: function() { $("#customLoader").hide(); }
19154         *     });
19155         * });
19156         */
19157        loadAllLazyFragmentModels : function (options) {
19158            var guide = this._guide;
19159            options = options || {};
19160            
19161            if (!guide) {
19162                this.logger().error("AF", "Guide model is not initialized");
19163                return;
19164            }
19165
19166            // Default loading callbacks (same as used in _loadLazyFragment)
19167            var defaultPreFetch = function () {
19168                var loadingPage = document.getElementById("loadingPage");
19169                if (loadingPage) {
19170                    loadingPage.classList.add("guideLoading");
19171                }
19172            };
19173            var defaultPostFetch = function () {
19174                var loadingPage = document.getElementById("loadingPage");
19175                if (loadingPage) {
19176                    loadingPage.classList.remove("guideLoading");
19177                }
19178            };
19179
19180            // Register callbacks for reuse during subsequent lazy loads (handleVisibleChanged)
19181            // These callbacks will be invoked when lazy panels are auto-loaded on 
19181navigation
19182            // Use provided callbacks, or preserve existing, or fall back to defaults
19183            guide._lazyLoadCallbacks = {
19184                preFetch: options.preFetch || (guide._lazyLoadCallbacks && guide._lazyLoadCallbacks.preFetch) || defaultPreFetch,
19185                postFetch: options.postFetch || (guide._lazyLoadCallbacks && guide._lazyLoadCallbacks.postFetch) || defaultPostFetch
19186            };
19187
19188            // Invoke preFetch callback (e.g., show loading indicator)
19189            var preFetchCallback = options.preFetch || defaultPreFetch;
19190            if (typeof preFetchCallback === 'function') {
19191                preFetchCallback();
19192            }
19193
19194            try {
19195                // Mark dirty panels and ensure template cache is populated
19196                if (guide.allLazyChildren && guide.allLazyChildren.length > 0) {
19197                    window.guidelib.model.markDirtyPanels(guide.allLazyChildren, "", [], guide);
19198                    
19199                    if (guide.guideLazyUtil) {
19200                        guide.guideLazyUtil.putDirtyToTemplateCacheIfMissing(guide);
19201                    }
19202                }
19203
19204                // Visit all fields and pre-load lazy fragment models
19205                this.visit(function (field) {
19206                    // Check if this is a lazy reference that hasn't been loaded yet
19207                    if (field._lazyReference && 
19208                        window.guidelib.util.GuideUtil.isLazyJson(field.jsonModel) &&
19209                        (!field._children || field._children.length === 0)) {
19210                        
19211                        var modelTemplateCacheStore = guide._modelTemplateCacheStore,
19212                            templateJson,
19213                            templateId = field.templateId,
19214                            uniquePrefix;
19215                        
19216                        // Try to get JSON from cache
19217                        templateJson = modelTemplateCacheStore._getTemplate(templateId, true);
19218                        
19219                        if (templateJson && templateJson.items) {
19220                            // Generate unique prefix if parent is repeatable
19221                            if (field._ancestorRepeatable) {
19222                                uniquePrefix = window.guidelib.util.GuideUtil.generateUID();
19223                            }
19224                            
19225                            // Only embed model - no HTML, no view creation
19226                            // This allows user scripts to access fields immediately
19227                            // View and HTML will be loaded on-demand when user navigates to this panel
19228                            field._embedJson(templateJson.items, uniquePrefix);
19229                            
19230                            // Note: We intentionally do NOT call field.prepare() here
19231                            // prepare() executes initScript immediately, but initScript should run AFTER prefill data
19232                            // is applied (which happens later in the initialization sequence). Calling prepare() here
19233                            // would break the normal initialization order. The prepare() call will happen later in
19234                            // _postProcessLazyLoad when the fragment is actually loaded on-demand, maintaining the
19235                            // correct sequence: model creation -> prefill -> playLiveData -> prepare (with initScript).
19236                            
19237                            // Note: We intentionally do NOT set _itemsLoaded here
19238                            // _itemsLoaded indicates that BOTH model AND view are fully loaded
19239                            // Since we've only loaded the model, we leave it undefined
19240                            // This signals to _loadLazyFragment that HTML and view still need to be fetched
19241                        }
19242                    }
19243                });
19244            } catch (error) {
19245                // Log error but ensure postFetch callback is always invoked in finally block
19246                window.console && console.error("Error while loading lazy fragment models:", error);
19247            } finally {
19248                // Invoke postFetch callback (e.g., hide loading indicator)
19249                // This is in finally block to ensure it's always called, even if an error occurs above
19250                var postFetchCallback = options.postFetch || defaultPostFetch;
19251                if (typeof postFetchCallback === 'function') {
19252                    postFetchCallback();
19253                }
19254            }
19255        },
19256
19257        /*
19258         * Get the download link of signed document set by signing service.
19259         * @return: url from where the signed document can be accessed, empty in case its not set by signing service.
19260         */
19261        getSignedDocDownloadLink : function () {
19262            var url = "";
19263            if (!_.isUndefined(FD)
19264                && !_.isUndefined(FD.AFaddon)
19265                && !_.isUndefined(FD.AFaddon.Signing)
19266                && !_.isUndefined(FD.AFaddon.Signing.signedDocDownloadLink)) {
19267                url = FD.AFaddon.Signing.signedDocDownloadLink;
19268            }
19269            return url;
19270        },
19271
19272        /*
19273         If true is passed to the function then it checks for model and view both,
19274         if false or no parameter is passed, then it checks the model only.
19275         */
19276        isGuideLoaded : function (complete) {
19277            if (complete) {
19278                return !_.isEmpty(window.guideBridge._guide && window.guideBridge._guideView);
19279            }
19280            return !_.isEmpty(window.guideBridge._guide);
19281        },
19282
19283        _doInternalSubmit : function (options) {
19284            if (options.excludeFormState) {
19285                var submissionInfo = options.guideState.data.guideState.guideContext.afSubmissionInfo;
19286                if (submissionInfo && submissionInfo.hasOwnProperty('lastFocusItem')) {
19287                    submissionInfo.lastFocusItem = undefined;
19288                }
19289            }
19290            // Make a clone of options so that original options are not modified.
19291            // Remove additionalSubmitInfo from the guideState so that no extra information
19292            // is sent to the server.
19293            var clonedGuideState = JSON.parse(JSON.stringify(options.guideState));
19294            if (!_.isEmpty(clonedGuideState.data.guideState.additionalSubmitInfo)) {
19295                clonedGuideState.data.guideState.additionalSubmitInfo = {};
19296            }
19297            var guideState = clonedGuideState,
19298                strContent = this.getMultipartData({
19299                    guideState : JSON.stringify(guideState.data),
19300                    dorData : options.dorData || false,
19301                    _charset_ : "UTF-8"
19302                }),
19303            // check if guide state is present, if yes get guide path from guide state
19304            // Specifically written for mobile workspace to getDataXML from current json state
19305                guidePath = ((guideState && guideState.data) ? guideState.data.guideState.guideContext.guidePath : null);
19306
19307            $.ajax({
19308                url : this._getGuidePathUrl(".af.internalsubmit.jsp", guidePath),
19309                type : "POST",
19310                async : options.async || false,
19311                contentType : "multipart/form-data; charset=UTF-8; boundary=" + strContent[0],
19312                data : strContent[1],
19313                success : options.success,
19314                error : options.error
19315            });
19316        },
19317
19318        _submitInternal : function (options) {
19319            var self = this;
19320            options = options || {};
19321            if (!options.guideState) {
19322                this.getGuideState({
19323                    "diff" : "diff",
19324                    "fileUploadPath" : options.fileUploadPath,
19325                    "success" : function (guideState) {
19326                        self._doInternalSubmit({
19327                            guideState : guideState,
19328                            success : options.success,
19329                            error : options.error,
19330                            async : options.async,
19331                            excludeFormState : options.excludeFormState,
19332                            dorData : options.dorData
19333                        });
19334                    },
19335                    "error" : options.error,
19336                    reducedJSON : true
19337                });
19338            } else {
19339                this._doInternalSubmit({
19340                    guideState : options.guideState,
19341                    success : options.success,
19342                    error : options.error,
19343                    async : options.async,
19344                    excludeFormState : options.excludeFormState,
19345                    dorData : options.dorData
19346                });
19347            }
19348        },
19349
19350        getMultipartData : function (data) {
19351            //Start multipart formatting
19352            var initBoundary = this.randomString();
19353            var strBoundary = "--" + initBoundary;
19354            var strMultipartBody = "";
19355            var strCRLF = "\r\n";
19356
19357            //Create multipart for each element of the form
19358            for (var key in data) {
19359                if (data.hasOwnProperty(key)) {
19360                    var value = _.isObject(data[key]) ? JSON.stringify(data[key]) : data[key];
19361                    strMultipartBody +=
19362                        strBoundary +
19363                        strCRLF +
19364                        "Content-Disposition: form-data; name=\"" + key + "\"" +
19365                        strCRLF +
19366                        strCRLF +
19367                        value +
19368                        strCRLF;
19369                }
19370            }
19371            //End the body by delimiting it
19372            strMultipartBody += strBoundary + "--" + strCRLF;
19373            //Return boundary without -- and the multipart content
19374            return [initBoundary, strMultipartBody];
19375        },
19376
19377        randomString : function () {
19378            var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
19379            var string_length = 8;
19380            var randomstring = '';
19381            for (var i = 0; i < string_length; i++) {
19382                var rnum = Math.floor(Math.random() * chars.length);
19383                randomstring += chars.substring(rnum, rnum + 1);
19384            }
19385            return randomstring;
19386        },
19387
19388        /*
19389         * Get the file Attachment map that contains a mapping of som expression vs path when files have been uploaded
19390         * and som expression vs name when the files have not yet been uploaded .
19391         * @return: map of som expression and paths.
19392         * @private
19393         */
19394        getFileAttachmentMap : function () {
19395            var fileAttachmentMap = {},
19396                fileAttachmentsList = window.guideBridge._getFileAttachmentsList();
19397            for (var i = 0; i < fileAttachmentsList.length; i++) {
19398                var node = fileAttachmentsList[i];
19399                if (!_.isEmpty(node.fileAttachment.value)) {
19400                    fileAttachmentMap[node.somExpression] = node.fileAttachment.value;
19401                }
19402            }
19403
19404            var lazyAttachmentMap = this._guide.internal.liveDataUtils._getLazyAttachmentMap();
19405            _.each(lazyAttachmentMap, function (mapObject, key) {
19406                fileAttachmentMap[key] = mapObject.value;
19407            });
19408            return fileAttachmentMap;
19409        },
19410
19411        /*
19412         * sets the value of the file attachment component based on the map that is passed.
19413         * @private
19414         */
19415        putFileAttachmentMap : function (fileAttachmentMap) {
19416            _.each(fileAttachmentMap, function (value, som) {
19417                var node = guideBridge.resolveNode(som);
19418                node.fileAttachment.value = value;
19419            });
19420        },
19421
19422        _appendFileAttachmentsToFormData : function (dataForm, fileNameDomMap, fileAttachmentsList) {
19423            var fileNamesIndex,
19424                fileDoms = fileNameDomMap.fileDom,
19425                fileNames = fileNameDomMap.fileName,
19426                faPromise = {},
19427                rejectedFileNames = [],
19428                isIOS = guidelib.util.GuideUtil._isIOS(),
19429                createUnorderedList = function (list, bulletChar) {
19430                    var result = "";
19431                    for (var i = 0; i < list.length; ++i) {
19432                        result += bulletChar + " " + list[i] + "\n";
19433                    }
19434                    return "\n" + result;
19435                },
19436                throwException = function (fileNames) {
19437                    if (fileNames && fileNames.length > 0) {
19438                        throw guidelib.util.GuideUtil.getLocalizedMessage("AF", guidelib.i18n.LogMessages["AEM-AF-901-024"], [createUnorderedList(fileNames, "•")]);
19439                    }
19440                };
19441            for (fileNamesIndex = 0; fileNamesIndex < fileNames.length; fileNamesIndex++) {
19442                // multiple files inside one filedom element & draft save case is handled.
19443                var currentFileNames = fileNames[fileNamesIndex].split("\n");
19444                for (var fileIndex = 0; fileIndex < currentFileNames.length; fileIndex++) {
19445                    if (currentFileNames[fileIndex] && _.isString(fileDoms[fileNamesIndex])) {
19446                        //handle draft save scenario when fileDoms[fileNamesIndex] is string(URL) & currentFileNames[fileIndex] is a url
19447                        dataForm.append("_guideFileAttachment." + guideBridge._getRelativeFilePath(currentFileNames[fileIndex]), fileDoms[fileNamesIndex]);
19448                    }
19449                }
19450            }
19451            dataForm.append("_guideAttachments", fileNames.toString());
19452            if (isIOS) {
19453                var allFAPromises = [];
19454                _.each(fileAttachmentsList, function (fileAttachmentModel, index) {
19455                    var fileAttachmentWrapperPromises = fileAttachmentModel._fileAttachmentWrapperIOS;
19456                    if (fileAttachmentWrapperPromises) {
19457                        var submissionNames = fileAttachmentModel._getInputFileSubmissionNames();
19458                        _.each(fileAttachmentWrapperPromises, function (fileAttachmentWrapperPromise, wrapperIndex) {
19459                            allFAPromises.push(Promise.resolve(fileAttachmentWrapperPromise).then(function (fileAttachmentWrapper) {
19460                                return {
19461                                    wrapper : fileAttachmentWrapper,
19462                                    submissionName : submissionNames[wrapperIndex]
19463                                };
19464                            }));
19465                        });
19466                    }
19467                });
19468                faPromise = Promise.allSettled(allFAPromises).then(function (results) {
19469                    for (var pIndex = 0; pIndex < results.length; pIndex++) {
19470                        // if status rejected, fail submission
19471                        if (results[pIndex].status === "rejected") {
19472                            rejectedFileNames.push(results[pIndex].reason);
19473                        } else {
19474                            var resultValue = results[pIndex].value.wrapper;
19475                            var partFileName = results[pIndex].value.submissionName || resultValue.name;
19476                            var completeNameOfFile = resultValue.formElementName + "/" + partFileName;
19477                            dataForm.append(completeNameOfFile, resultValue.dataURLtoBlob(), resultValue.name);
19478                        }
19479                    }
19480                    // to fail this promise, throw an exception here
19481                    throwException(rejectedFileNames);
19482                    return dataForm;
19483                });
19484            } else {
19485                var allFileAccessPromise = [];
19486                for (fileNamesIndex = 0; fileNamesIndex < fileNames.length; fileNamesIndex++) {
19487                    // multiple files inside one filedom element & draft save case is handled.
19488                    var currentFileNames = fileNames[fileNamesIndex].split("\n");
19489                    for (var fileIndex = 0; fileIndex < currentFileNames.length; fileIndex++) {
19490                        // in case of IOS, file binary is from file object, we use the in-memory data
19491                        if (fileDoms[fileNamesIndex] && !_.isString(fileDoms[fileNamesIndex]) && fileDoms[fileNamesIndex].length > 0) {
19492                            // promise is not supported in IE11
19493                            // for IE11, we don't read file bytes
19494                            if (window.Promise) {
19495                                var fileAccessPromise = guidelib.util.GuideUtil._checkIfFileIsAccessible(currentFileNames[fileIndex], fileDoms[fileNamesIndex][0].files[fileIndex]);
19496                                allFileAccessPromise.push(fileAccessPromise);
19497                            } else {
19498                                // append each file of input file element to formdata
19499                                dataForm.append(currentFileNames[fileIndex], fileDoms[fileNamesIndex][0].files[fileIndex]);
19500                            }
19501
19502                        }
19503                    }
19504                }
19505                // promise is not supported in IE11
19506                if (window.Promise) {
19507                    faPromise = Promise.allSettled(allFileAccessPromise).then(function (results) {
19508                        for (var pIndex = 0; pIndex < results.length; pIndex++) {
19509                            // if status rejected, fail submission
19510                            if (results[pIndex].status === "rejected") {
19511                                rejectedFileNames.push(results[pIndex].reason);
19512                            } else {
19513                                var resultValue = results[pIndex].value;
19514                                dataForm.append(resultValue.fileName, resultValue.file);
19515                            }
19516                        }
19517                        throwException(rejectedFileNames);
19518                        return dataForm;
19519                    });
19520                } else {
19521                    faPromise = $.Deferred().resolve(dataForm);
19522                }
19523            }
19524            return faPromise;
19525        },
19526
19527        doAjaxSubmitWithFileAttachment : function (actionUrl, submitData, options, fileAttachmentsList) {
19528            var _options = options || {},
19529                self = this,
19530                dataForm = new FormData(),
19531                fileNameDomMap = this._juiceOutNameAndFileDomMap(fileAttachmentsList),
19532                faPromise = this._appendFileAttachmentsToFormData(dataForm, fileNameDomMap, fileAttachmentsList);
19533
19534            var _submitForm = function () {
19535                    $.ajax({
19536                        url : actionUrl,
19537                        type : "POST",
19538                        processData : false,
19539                        cache : false,
19540                        contentType : false,
19541                        dataType : 'json',
19542                        data : dataForm,
19543                        success : function (data) {
19544                            self.doAjaxSubmitSuccess(data, _options);
19545                        },
19546                        error : function (data) {
19547                            self.doAjaxSubmitError(data, _options);
19548                        }
19549                    });
19550                };
19551            faPromise.then(function (dataForm) {
19552                    $.each(submitData, function (key, val) {
19553                        if (typeof val == "object") {
19554                            val = JSON.stringify(val);
19555                        }
19556                        dataForm.append(key, val);
19557                    });
19558                    _submitForm();
19559                })
19560                .catch(function (e) {
19561                    // handle errors here
19562                    console.error(e);
19563                    if (typeof e === "string") {
19564                        guideBridge._handleSubmitError("", e);
19565                    } else {
19566                        guideBridge._handleSubmitError({
19567                            "status" : 400
19568                        });
19569                    }
19570
19571                });
19572        },
19573
19574        doAjaxSubmit : function (actionUrl, submitData, options) {
19575            var _options = options || {},
19576            self = this,
19577            asyncSubmit = _options.async !== false,
19578            strContent = this.getMultipartData(submitData);
19579            $.ajax({
19580                url : actionUrl,
19581                type : "POST",
19582                traditional : true,
19583                async : asyncSubmit,
19584                contentType : "multipart/form-data; charset=UTF-8; boundary=" + strContent[0],
19585                data : strContent[1],
19586                success : function (data) {
19587                    self.doAjaxSubmitSuccess(data, _options);
19588                },
19589                error : function (data) {
19590                    self.doAjaxSubmitError(data, _options);
19591                }
19592            });
19593        },
19594
19595        KEY_AF_SUCCESS_PAYLOAD : "afSuccessPayload",
19596        KEY_AF_SUCCESS_DOCUMENT_OF_RECORD : "afSuccessDocumentOfRecord",
19597
19598        doAjaxSubmitSuccess : function (data, options) {
19599            var guideResultObject = new GuideResultObject();
19600            guideResultObject.data = data;
19601            guideResultObject.completed = true;
19602            // remove the submitting message too after success of ajax submit
19603            guideBridge._showGuideLoading(false);
19604            if (_.isFunction(options.success)) {
19605                options.success.call(options.context, guideResultObject);
19606            } else {
19607                if (data.hasOwnProperty("signingURL")) {
19608                    // Adobe sign : FormFiller enabled case.
19609                    window.location.href = data.signingURL;
19610                } else {
19611                    var payload = {};
19612                    if (data.hasOwnProperty(guideBridge.KEY_AF_SUCCESS_PAYLOAD)) {
19613                        try {
19614                            payload = JSON.parse(data[guideBridge.KEY_AF_SUCCESS_PAYLOAD]);
19615                            payload.data = this._guide.internal.afdata;
19616                            if(data.hasOwnProperty(guideBridge.KEY_AF_SUCCESS_DOCUMENT_OF_RECORD)) {
19617                                payload.dorUri = data[guideBridge.KEY_AF_SUCCESS_DOCUMENT_OF_RECORD];
19618                            }
19619                            var schemaType = this._guide.runtime.guideContext.schemaType;
19620                            if (!schemaType) {
19621                                //TODO define a constant for schema Type.
19622                                schemaType = "xmlschema";
19623                            }
19624                            payload.contentType = schemaType;
19625                        } catch (e) {
19626                            guideBridge._guide.logger().log("Error while parsing AF Success Payload: " + e);
19627                        }
19628                    }
19629                    guideBridge._guide.executeExpression("submitSuccess", payload); // Executing Rule Editor code for submit success.
19630                    if (data.agreementId && guideBridge._guide._isFirstSignerFormFiller()) {
19631                        guidelib.util.GuideUtil.redirectWithDelay(data.afSuccessRedirectUrl, 3000);
19632                    }
19633                }
19634            }
19635        },
19636
19637        doAjaxSubmitError : function (data, options) {
19638            var guideResultObject = new GuideResultObject();
19639            guideResultObject.data = data;
19640            guideResultObject.completed = false;
19641            guideResultObject.addMessage(2, "Error in Async Submit", "");
19642            guideBridge._showGuideLoading(false);
19643            if (_.isFunction(options.error)) {
19644                options.error.call(options.context, guideResultObject);
19645            } else {
19646                var errorPayload = {};
19647                try {
19648                    errorPayload = JSON.parse(data.responseText);
19649                } catch (e) {
19650                    guideBridge._guide.logger().log("Error while parsing errorPayload." + e);
19651                }
19652                guideBridge._guide.executeExpression("submitError", errorPayload); //Executing Rule Editor code for submitError
19653            }
19654        },
19655
19656        handleUpload : function () {
19657            self = this.self;
19658            this.submitData['_guideAttachments'] = this.attachments.toString();
19659            _.each(this.attachments, function (att) {
19660                this.submitData["_guideFileAttachment." + att] = this.submitData['fileUrl'] + "/" + att;
19661            }, this);
19662            delete this.submitData['fileUrl'];
19663            self.doAjaxSubmit(this.actionUrl, this.submitData, this.options);
19664        },
19665
19666        _handleSubmitError : function (data, message) {
19667            // case: show message if it exists, for example, there could be client side errors during submit
19668            if (message) {
19669                alert(message);
19670            } else {
19671                // based on http status show error, these errors are based on server side http response codes
19672                var status = Number(data.status);
19673                switch (status) {
19674                    case 502:
19675                        alert(guidelib.util.GuideUtil.getLocalizedMessage("AF", guidelib.i18n.LogMessages["AEM-AF-901-003"]));
19676                        break;
19677                    case 400:
19678                        alert(guidelib.util.GuideUtil.getLocalizedMessage("AF", guidelib.i18n.LogMessages["AEM-AF-901-022"]));
19679                        break;
19680                    default:
19681                        alert(guidelib.util.GuideUtil.getLocalizedMessage("AF", guidelib.i18n.LogMessages["AEM-AF-901-004"]));
19682                        break;
19683                }
19684            }
19685            guideBridge._showGuideLoading(false);
19686        },
19687
19688        updateSubmitData : function (fileAttachmentsList, submitData, fileList) {
19689            var fileCount = 0,
19690                attachments = [],
19691                name;
19692            if (fileList.length === 0 && fileAttachmentsList.length > 0) {
19693                _.each(fileAttachmentsList, function (fileUploadComponentId, index) {
19694                    var currentCount = 0;
19695                    var componentInModel = window.guideBridge._resolveId(fileUploadComponentId);
19696                    var fileNameList = componentInModel["fileAttachment"].value;
19697                    if (fileNameList) {
19698                        var fileNames = fileNameList.split("\n");
19699                        _.each(fileNames, function (fileUrl, index) {
19700                            name = componentInModel.name + "/" + fileUrl.substring(fileUrl.lastIndexOf("/") + 1);
19701                            if (name) {
19702                                attachments[fileCount++] = name;
19703                                submitData["_guideFileAttachment." + name] = fileUrl;
19704                            }
19705                        }, this);
19706                    }
19707                }, this);
19708                submitData['_guideAttachments'] = attachments;
19709            } else if (fileList.length > 0) {
19710                _.each(fileList, function (file, index) {
19711                    name = guideBridge._getRelativeFilePath(file);
19712                    attachments[fileCount++] = name;
19713                    submitData["_guideFileAttachment." + name] = file;
19714                }, this);
19715                submitData['_guideAttachments'] = attachments;
19716            }
19717        },
19718
19719        _collectFileUrls : function (event) {
19720            var list = [],
19721                fileUploadError = false;
19722
19723            // Populate list to have path of all the uploaded files. The file Attachment component whose model was
19724            // loaded would have their fileNames first followed by the list of file names of unloaded file upload components.
19725            _.each(this.attachments, function (attachment) {
19726                _.each(attachment.split("\n"), function (att) {
19727                    // check if att is a url and hence push it directly to list
19728                    if (_.isString(att) && att.match(/\//g).length > 1) {
19729                        list.push(att);
19730                    } else {
19731                        list.push(this.fileUrl + "/" + att);
19732                    }
19733                }, this);
19734            }, this);
19735
19736            var options = {
19737                fileUrlList : list,
19738                fileUploadModelsList : this.fileAttachmentsList,
19739                lazyAttachmentMap : guideBridge._guide.internal.liveDataUtils._getLazyAttachmentMap()
19740            };
19741            guidelib.util.GuideUtil._updateFileModelsAndLazyMap(options);
19742
19743            var submitOptions = this.options.ajaxSubmitObject;
19744            if (submitOptions && submitOptions.ajaxSubmitDataHandler) {
19745                submitOptions.ajaxSubmitDataHandler.call(this.options.context, submitOptions.fileAttachmentsList, submitOptions.submitData, list);
19746                window.guideBridge.doAjaxSubmit(submitOptions.actionUrl, submitOptions.submitData, this.options);
19747            } else if (this.options.success) {
19748                //create the guideState now as the model has been updated with the latest values.
19749                //do this only during getGuideState and not on ajax submit
19750                guideBridge._createGuideStateAndLiveXml(this.options);
19751                this.options.success.call(this.options.context, this.options.obj);
19752            }
19753
19754        },
19755
19756        _fileUploadFailed : function (event) {
19757            $.proxy(guideBridge._handleSubmitError({
19758                        "status" : "500"
19759                    }), guideBridge);
19760        },
19761
19762        // This function extracts the form name from the guideContainerPath.
19763        _getFormName : function (guidePath) {
19764            var formName = "";
19765            if (guidePath) {
19766                var index = guidePath.indexOf("/jcr:content/guideContainer");
19767                guidePath = guidePath.substring(0, index);
19768                formName = guidePath.substring(guidePath.lastIndexOf("/") + 1);
19769            }
19770            return formName;
19771        },
19772
19773        /**
19774         * returns the form element to be used for submission in case of non-ajax
19775         * submit.
19776         * The function looks in the submitConfig for a form and if not present,
19777         * creates a new form
19778         * @returns {object} jQuery object for form element
19779         * @private
19780         */
19781        _getFormForSubmission : function () {
19782            var submitConfig = this.userConfig.submitConfig || {},
19783                form = submitConfig.form || $("<form method='post' enctype='multipart/form-data'></form>").appendTo($("body"));
19784            return $(form);
19785        },
19786
19787        _getThankYouPageFromConfig : function () {
19788            var submitConfig = this.userConfig.submitConfig || {};
19789            return submitConfig.thankyouPage;
19790        },
19791
19792        /**
19793         * This function prepare the guideValueMap and returns it.
19794         * @returns A map consisting of name and value for all the unbound components
19795         * @private
19796         */
19797        _prepareGuideValueMap : function () {
19798            var guideValueMap = {}, visitedMap = {};
19799            this.visit(function (node) {
19800                if (!node.bindRef && !visitedMap[node.somExpression]) {
19801                    if (node instanceof guidelib.model.Field && node.value) {
19802                        visitedMap[node.somExpression] = true;
19803                        guideValueMap[node.getAttribute("name")] = node.value;
19804                    } else if (node instanceof guidelib.model.GuideCompositeField) {
19805                        var obj = guideValueMap[node.getAttribute("name")] = {};
19806                        _.each(node.items, function (childNode, index) {
19807                            visitedMap[childNode.somExpression] = true;
19808                            if (childNode.value) {
19809                                obj[childNode.getAttribute("name")] = childNode.value;
19810                            }
19811                        }, this);
19812                    }
19813                }
19814            });
19815            return guideValueMap;
19816        },
19817
19818        _showGuideLoading : function (flag, msg) {
19819            if(!flag){
19820                if(_focusedSubmitButtonModel){
19821                    _focusedSubmitButtonModel.enabled = true;
19822                    _focusedSubmitButtonModel = null;
19823                }
19824            }
19825            var util = guidelib.util.GuideUtil;
19826            if (util) {
19827                util.showGuideLoading(flag);
19828                if (msg !== undefined) {
19829                    util.showMessages(msg);
19830                } else {
19831                    util.removeAllMessages();
19832                }
19833            }
19834        },
19835
19836        _submitAfterValidation : function (options, submitSuccess, submitError) {
19837            var self = this;
19838            if (guidelib.util.GuideUtil) {
19839                var msg = guidelib.i18n.strings.submittingForm;
19840                if (options && options.submissionSelector === 'agreement') {
19841                    msg = guidelib.i18n.strings.generatingSignAgreement;
19842                }
19843                guidelib.util.GuideUtil.showMessages(msg);
19844            }
19845            // Trigger submitStart before calling internal submit.
19846            if (guideBridge.isGuideLoaded() && self._guide._triggerOnBridge) {
19847                self._guide._triggerOnBridge("submitStart", "", "", "", "");
19848            }
19849            var excludeFormState = true;
19850            if (options && options.hasOwnProperty("excludeFormState")) {
19851                excludeFormState = options.excludeFormState;
19852            }
19853            try {
19854                var guideState = getOrElse(options, "guideState", null);
19855                if (guideState || guideBridge.isGuideLoaded()) {
19856                    var twoStepSubmission = getOrElse(options, "twoStepSubmission", false);
19857                    if (guideState || self._guide.xdpRef || twoStepSubmission) {
19858                        self._submitInternal({
19859                            guideState : guideState,
19860                            success : function () {
19861                                try {
19862                                    submitSuccess.apply(self, arguments);
19863                                } catch (e) {
19864                                    self._handleInternalSubmitError(submitError, self, arguments);
19865                                }
19866                            },
19867                            error : function () {
19868                                self._handleInternalSubmitError(submitError, self, arguments);
19869                            },
19870                            async : true,
19871                            excludeFormState : excludeFormState
19872                        });
19873                    } else {
19874                        self.getFormDataString({
19875                            success : function () {
19876                                try {
19877                                    submitSuccess.apply(self, arguments);
19878                                } catch (e) {
19879                                    self._handleInternalSubmitError(submitError, self, arguments);
19880                                }
19881                            }
19882                        });
19883                    }
19884                } else {
19885                    console.error("Form Submission failed as the form doesn't exist on the page");
19886                }
19887            } catch (e) {
19888                self._showGuideLoading(false);
19889                if (console && console.error) {
19890                    console.error(e);
19891                }
19892            }
19893        },
19894
19895        _handleCaptchaTimeout : function () {
19896            window.alert(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.LogMessages["AEM-AF-901-025"]));
19897            window.guideBridge.setEnabledAutoSave(_isAutoSaveEnabled);
19898            guideBridge._showGuideLoading(false);
19899            return;
19900        },
19901
19902        /**
19903         * Validate and submits the data of the Adaptive Form to the pre-configured submit action.
19904         *
19905         * The success handler provided in the argument is executed only if the Adaptive Form is configured to use AJAX
19906         * for submission using {@link GuideBridge#registerConfig|registerConfig} API
19907         * @summary submits the Adaptive Form
19908         * @param {object} options options to control the behaviour of submit API.
19909         * @param {string} [options.submissionSelector] url selector governs the submission behaviour at server
19910         * Default value is "submit", other options are "agreement", "signSubmit"
19911         * @param {function} [options.success] callback which receives the result of the API
19912         * in case of success.
19913         * {@link GuideResultObject#errors|errors} property as false.
19914         * @param {function} [options.error] callback which receives the result of the API in
19915         * case of failure.
19916         * {@link GuideResultObject#errors|errors} property as true.
19917         * @param {object} [options.context] _this_ object inside the _success_ and _error_ callback will point to this
19918         * object
19919         * @param {boolean} [options.validate=true] whether to validate the form before submission or not
19920         * @method
19921         * @memberof GuideBridge
19922         * @since 6.0
19923         * @instance
19924         * @example <caption>Submitting the form without validation</caption>
19925         * guideBridge.submit({
19926         *    validate: false,
19927         *    error : function (guideResultObject) {//log message}
19928         * });
19929         * @example <caption>Submitting the form and showing a success message</caption>
19930         * guideBridge.registerConfig("submitConfig" : {"useAjax" : true});
19931         * guideBridge.submit({
19932         *   validate: false,
19933         *   error : function (guideResultObject) {//log message}
19934         *   success : function (guideResultObject) {alert("data submitted successfully")
19935         * });
19936         */
19937
19938        submit : function (options) {
19939            // Disabling the submit button
19940            var focusedElementSOM = guideBridge.getFocus();
19941            if(focusedElementSOM){
19942                _focusedSubmitButtonModel = guideBridge.resolveNode(focusedElementSOM);
19943                _focusedSubmitButtonModel.enabled = false;
19944            }
19945            _isAutoSaveEnabled = window.guideBridge.getAutoSaveEnabledStatus();
19946            //Disable auto save till submission is not completed
19947            if (_isAutoSaveEnabled) {
19948                window.guideBridge.setEnabledAutoSave(false);
19949            }
19950            var self = this;
19951            var guideContextFromOptions,
19952                runtimeGuideContext = getOrElse(this._guide, "runtime.guideContext", {});
19953            if (getOrElse(options, "guideState", "")) {
19954                guideContextFromOptions = options.guideState.data.guideState.guideContext;
19955            }
19956            var localGuideContext = guideContextFromOptions || runtimeGuideContext;
19957            // to submit guideContainerForm  which will be stopped so that autocomplete values can be remembered
19958            $(".guideContainerFormSubmitButton").click();
19959
19960            window.guideBridge._populateBindRefToSomMap();
19961
19962            function submitError(data) {
19963                self._ariaLiveAnnouncement(guidelib.i18n.strings["formSubmitFail"]);
19964                if (options && options.error) {
19965                    options.error.call(options.context || this, data);
19966                } else {
19967                    $.proxy(guideBridge._handleSubmitError(data), guideBridge);
19968                }
19969            }
19970
19971            function submitSuccess(result) {
19972                var isAjaxSubmit = false;
19973
19974                if (options) {
19975                    isAjaxSubmit = options.success ? true : false;
19976                }
19977                options = options || {};
19978                options.success = options.success || (self.userConfig.submitConfig || {}).submitSuccessHandler;
19979                isAjaxSubmit = isAjaxSubmit || (self.userConfig.submitConfig || {useAjax : false}).useAjax || guideBridge._guide.enableAsyncSubmission;
19980                var submitData = {};
19981
19982                if (this.isGuideLoaded()) {
19983                    var guideCaptchaList = [];
19984                    this.visit(function (node) {
19985                        if (node.className === "guideCaptcha") {
19986                            guideCaptchaList.push(node);
19987                        }
19988                    });
19989                    var captchaModel = guideCaptchaList[0];
19990                    if (captchaModel) {
19991                        var captchaData = window.guideBridge._getCaptchaData(captchaModel);
19992                        submitData['captchaData'] = captchaData;
19993                    }
19994                }
19995
19996                // check if guide state is present, if yes get guide path from guide state
19997                var guidePath = getOrElse(options, "guideState.data.guideState.guideContext.guidePath", ""),
19998                    guideContainerPath = guidePath || window.guideBridge.getGuidePath(),
19999                    aemFormComponentPath = this.userConfig.submitConfig ? this.userConfig.submitConfig.aemFormComponentPath : "",
20000                    submissionSelector = options.submissionSelector || "submit",
20001                    actionUrl = window.guideBridge._getGuidePathUrl(".af." + submissionSelector + ".jsp", guideContainerPath);
20002
20003                submitData['guideContainerPath'] = guideContainerPath;
20004                submitData['aemFormComponentPath'] = aemFormComponentPath;
20005                submitData['_asyncSubmit'] = isAjaxSubmit;
20006                submitData['_charset_'] = "UTF-8";
20007                var customPropMap = localGuideContext.customPropertyMap || {};
20008                // need to remove lastFocusItem from being sent as a different property
20009                // as it being sent in xml and with afSubmissionInfo as well.
20010                var whiteListedProperties = ["lastFocusItem"];
20011                for (var prop in customPropMap) {
20012                    if (customPropMap.hasOwnProperty(prop) && whiteListedProperties.indexOf(prop) < 0) {
20013                        submitData[prop] = customPropMap[prop];
20014                    }
20015                }
20016                // todo: Have to remove the excludeFromDor map from the submission info, is this required ?
20017                if (this.isGuideLoaded()) {
20018                    submitData['afSubmissionInfo'] = this._guide.runtime.guideContext.afSubmissionInfo || {};
20019                }
20020                var resultJson = result,
20021                    guideJson,
20022                    data,
20023                    fileAttachmentsList,
20024                    attachments = [],
20025                    fileCount = 0;
20026                if (resultJson.hasOwnProperty("guideValue")) {
20027                    guideJson = resultJson.guideValue;
20028                } else if (!_.isUndefined(options.guideValueMap)) {
20029                    guideJson = options.guideValueMap;
20030                } else {
20031                    // todo: why is this required in client ?
20032                    guideJson = window.guideBridge._prepareGuideValueMap();
20033                }
20034                if (resultJson.hasOwnProperty("data")) {
20035                    data = resultJson["data"];
20036                }
20037
20038                if (resultJson.hasOwnProperty("fileAttachmentsList")) {
20039                    fileAttachmentsList = resultJson["fileAttachmentsList"];
20040                }
20041
20042                for (var key in guideJson) {
20043                    if (guideJson.hasOwnProperty(key)) {
20044                        submitData[key] = guideJson[key];
20045                    }
20046                }
20047
20048                if (data) {
20049                    submitData['jcr:data'] = data;
20050                    submitData['jcr:data@TypeHint'] = "Binary";
20051                    if (self.isGuideLoaded()) {
20052                        self._guide.internal.afdata = data;
20053                    }
20054                }
20055                if (!_.isUndefined(options.fileAttachmentMap)) {
20056                    submitData.fileAttachmentMap = options.fileAttachmentMap;
20057                } else {
20058                    //send the fileAttachmentMap through submit data to restore submission attachments for read only viewing
20059                    submitData.fileAttachmentMap = JSON.stringify(guideBridge._getFileAttachmentMapForSubmit());
20060                }
20061                // read the additional information from the guideState if it is passed in options
20062                // otherwise get the additional information from the DOM
20063                var additionalSubmitInfo = {};
20064                if (options.guideState && options.guideState.data.guideState.additionalSubmitInfo) {
20065                    additionalSubmitInfo = options.guideState.data.guideState.additionalSubmitInfo;
20066                } else {
20067                    additionalSubmitInfo = guideBridge._getAdditionalSubmitInfo();
20068                }
20069                // append additionalSubmitInfo to the submitData
20070                $.extend(true, submitData, additionalSubmitInfo);
20071
20072                if (isAjaxSubmit && isAjaxSubmit === true) {
20073                    // if the fileAttachmentMap is passed in the options, then we don't need to upload the files as the map contains the uploaded path only.
20074                    // we just update the submitData with the attachment information
20075                    if (options.fileAttachmentMap) {
20076                        var attachmentMap = JSON.parse(options.fileAttachmentMap);
20077                        var keys = _.keys(attachmentMap);
20078                        for (var i = 0; i < keys.length; i++) {
20079                            if (attachmentMap[keys[i]]) {
20080                                var fileNames = attachmentMap[keys[i]].split("\n");
20081                                for (var j = 0; j < fileNames.length; j++) {
20082                                    var name = guideBridge._getRelativeFilePath(fileNames[j]);
20083                                    attachments[fileCount++] = name;
20084                                    submitData["_guideFileAttachment." + name] = fileNames[j];
20085                                }
20086                            }
20087                        }
20088                        submitData['_guideAttachments'] = attachments;
20089                        self.doAjaxSubmit(actionUrl, submitData, options);
20090                    } else {
20091                        var attachedFilesList = [];
20092                        var currentCount = 0;
20093                        // need to check if the guide is loaded, as it is not available for mobile workspace app use case
20094                        if (guideBridge.isGuideLoaded()) {
20095                            attachedFilesList = window.guideBridge._getFileAttachmentsList();
20096                        }
20097                        _.each(attachedFilesList, function (object) {
20098                            var fileNameList = object["fileAttachment"].value;
20099                            if (fileNameList) {
20100                                currentCount++;
20101                            }
20102                        });
20103                        // If a file has been attached and isAjaxSubmit is true, then a UUID is generated and
20104                        // the files are uploaded at temp storage path.
20105                        // The submit data is updated with the attached files and then
20106                        // doAjaxSubmit is called.
20107                        if (currentCount > 0) {
20108                            self.doAjaxSubmitWithFileAttachment(actionUrl, submitData, options, attachedFilesList);
20109                        } else {
20110                            self.doAjaxSubmit(actionUrl, submitData, options);
20111                        }
20112                    }
20113                } else {
20114                    var $form = self._getFormForSubmission();
20115                    $form.attr('action', actionUrl);
20116                    $form.attr('data-name', 'afSubmissionForm');
20117                    for (var fields in submitData) {
20118                        if (submitData.hasOwnProperty(fields)) {
20119                            var value = submitData[fields];
20120                            $("<input>").attr("type", "hidden")
20121                                .attr("name", fields)
20122                                .val(_.isObject(value) ? JSON.stringify(value) : value)
20123                                .appendTo($form);
20124                        }
20125                    }
20126                    /*
20127                     * This means we did not do any preprocessing
20128                     * for file attachments so fileAttachment list won't be present
20129                     * so posting DOM for the files.
20130                     * */
20131                    var attachmentNameDomMap = guideBridge._getFileNameFileDomMap(),
20132                        fileNameList = [],
20133                        _guideAttachments = "";
20134                    // A string containing the names of all the files that are attached is stored in the variable _guideAttachments.
20135                    // For all the files that have been uploaded already and don't have a dom element are
20136                    // added to $form with prefix "_guideFileAttachment."
20137                    if (attachmentNameDomMap && attachmentNameDomMap.fileDom) {
20138                        fileNameList = attachmentNameDomMap.fileName;
20139                        _.each(attachmentNameDomMap.fileDom, function (file, index) {
20140                            if (!_.isString(file)) {
20141                                file.attr("name", fileNameList[index].split["\n"])
20142                                    .attr("class", "hidden")
20143                                    .appendTo($form);
20144                                _guideAttachments += fileNameList[index] + ",";
20145                            } else {
20146                                if (fileNameList[index]) {
20147                                    var name = guideBridge._getRelativeFilePath(fileNameList[index]);
20148                                    $("<input>").attr("type", "hidden")
20149                                        .attr("name", "_guideFileAttachment." + name)
20150                                        .attr("value", file)
20151                                        .appendTo($form);
20152                                    _guideAttachments += name + ",";
20153                                }
20154                            }
20155                        });
20156                    }
20157                    $("<input>").attr("type", "hidden")
20158                        .attr("name", "_guideAttachments")
20159                        .attr("value", _guideAttachments)
20160                        .appendTo($form);
20161
20162                    $form.submit();
20163                }
20164            }
20165
20166            self._showGuideLoading(true, guidelib.i18n.strings.val
20166idatingForm);
20167            // since validate is synchronous call, putting this in timeout
20168            // so that html changes can be display
20169            setTimeout(function () {
20170                // update the snapshot just before validating
20171                // so that we get true state of play before loading panels
20172                if (guideBridge.isGuideLoaded() && guideBridge._guide.allLazyChildren && guideBridge._guide.allLazyChildren.length > 0) {
20173                    self._guide.internal.liveDataUtils.updateLiveData();
20174                }
20175                var isValid = false;
20176                try {
20177                    isValid = self._performConditionalValidation(options);
20178                } catch (e) {
20179                    isValid = false;
20180                } finally {
20181                    self._showGuideLoading(true);
20182                }
20183                if (isValid) {
20184                    /* Handle Invisible Recaptcha on form submission */
20185                    var recaptchaInvisibleElement = $("#captchaInvisible");
20186                    if (recaptchaInvisibleElement != undefined && recaptchaInvisibleElement.attr("af-recaptcha-execute") == "") {
20187                        recaptchaInvisibleElement.trigger({
20188                            type: "recaptchaExecution",
20189                            submitParameters: {
20190                                options: options,
20191                                success: submitSuccess,
20192                                error: submitError
20193                            },
20194                            triggerPostSubmission: true
20195                        });
20196                        return;
20197                    }
20198                    guideBridge._submitAfterValidation(options, submitSuccess, submitError);
20199                } else {
20200                    window.guideBridge.setEnabledAutoSave(_isAutoSaveEnabled);
20201                    self._showGuideLoading(false);
20202                    return;
20203                }
20204            }, 1);
20205        },
20206
20207        /**
20208         * Save draft of the current adaptive form loaded
20209         * @param saveBtnConfig {object} Optional parameter for providing
20210         * @param options {object} Optional parameter options can consist of following -
20211         *  <ul>
20212         *     <li> success: {function}  Handler executed in case when the draft is successfully saved</li>
20213         *     <li> error: {function}  Handler  executed in case of draft failure</li>
20214         *     <li> context {object}  The context with which the success or error handler needs to be executed</li>
20215         * </ul>
20216         *
20217         */
20218        handleDraftSave : function (saveBtnConfig, custom_options) {
20219            custom_options = $.extend({
20220                success : $.noop,
20221                error : $.noop,
20222                context : this
20223            }, custom_options);
20224            // isAutoSaveTriggered is not a documented property.
20225            //handleDraftSave method is also called via auto save component,where we pass this value as true.
20226            // This flag is just set to understand if the call is triggered by auto save strategy or not
20227            custom_options.isAutoSaveTriggered = custom_options.isAutoSaveTriggered || false;
20228
20229            var options = {
20230                success : function (result) {
20231                    var draftId = result.data.draftId;
20232                    window.guideBridge.customContextProperty("draftId", draftId);
20233                    /** if (!isAutoSaveTriggered) {
20234                         $(".__FP_Saved_Message").show();
20235                         $(".__FP_Saved_Message").fadeOut(1600, "linear");
20236                     }**/
20237
20238                    window.guideBridge.trigger(
20239                        "saveCompleted",
20240                        window.guidelib.event.GuideModelEvent.createEvent("saveCompleted")
20241                    );
20242                    var payload = {};
20243                    payload.draftId = draftId;
20244                    payload.isAutoSaveTriggered = custom_options.isAutoSaveTriggered;
20245                    guideBridge._guide.executeExpression("saveSuccess", payload); // Executing Rule Editor code for save success.
20246                    // window.guideBridge._defaultSaveSuccessHandler();
20247                    custom_options.success.call(custom_options.context);
20248                },
20249                error : function (result) {
20250                    if (!custom_options.isAutoSaveTriggered) {
20251                        if (result.status == "503") {
20252                            alert(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.LogMessages["AEM-AF-901-008"]));
20253                        } else {
20254                            alert(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.LogMessages["AEM-AF-901-009"]));
20255                        }
20256                    }
20257                    var errorPayload = {};
20258                    errorPayload.result = result;
20259                    errorPayload.isAutoSaveTriggered = custom_options.isAutoSaveTriggered;
20260                    guideBridge._guide.executeExpression("saveError", errorPayload); //Executing Rule Editor code for saveError
20261                    custom_options.error.call(custom_options.context);
20262                }
20263            };
20264            var guidePath = window.guideBridge.getGuidePath();
20265            var draftId = window.guideBridge.customContextProperty("draftId") || "";
20266
20267            var contextPath = window.guideBridge._getUrl(guidePath);
20268            var self = this;
20269            guideBridge.getFormDataObject({
20270                "success" : function (resultObj) {
20271                    window.guideBridge.trigger(
20272                        "saveStarted",
20273                        window.guidelib.event.GuideModelEvent.createEvent("saveStarted")
20274                    );
20275                    var afFormData,
20276                        htmlFormData;
20277                    afFormData = resultObj.data;
20278                    htmlFormData = afFormData.toHTMLFormData();
20279                    htmlFormData.append('draftId', draftId);
20280                    self._doAjaxSubmitWithHTMLFormData(contextPath + ".af.save.jsp", htmlFormData, options);
20281                }
20282            });
20283        },
20284
20285        /**
20286         * @private
20287         */
20288        _doAjaxSubmitWithHTMLFormData : function (actionURL, htmlFormData, options) {
20289            var self = this;
20290            $.ajax({
20291                url : actionURL,
20292                type : "POST",
20293                processData : false,
20294                cache : false,
20295                contentType : false,
20296                dataType : 'json',
20297                data : htmlFormData,
20298                success : function (data) {
20299                    self.doAjaxSubmitSuccess(data, options);
20300                },
20301                error : function (data) {
20302                    self.doAjaxSubmitError(data, options);
20303                }
20304            });
20305        },
20306
20307        /**
20308         * @private
20309         */
20310        _handleInternalSubmitError : function (submitError, selfVar, args
20310) {
20311            try {
20312                submitError.apply(selfVar, args);
20313            } catch (e) {
20314                //ignoring the error
20315            } finally {
20316                guideBridge._showGuideLoading(false);
20317
20318            }
20319        },
20320        /**
20321         * @private
20322         */
20323        _getFileAttachmentMapForSubmit : function () {
20324            var fileAttachmentMap = {},
20325                fileAttachmentsList = window.guideBridge._getFileAttachmentsList();
20326            for (var i = 0; i < fileAttachmentsList.length; i++) {
20327                var node = fileAttachmentsList[i];
20328                if (!_.isUndefined(node.value) && node.value.length > 0) {
20329                    var attachmentList = node.value.split("\n");
20330                    for (var j = 0; j < attachmentList.length; j++) {
20331                        attachmentList[j] = node.name + "/" + attachmentList[j];
20332                    }
20333                    fileAttachmentMap[node.somExpression] = attachmentList.join('\n');
20334                }
20335            }
20336
20337            var lazyAttachmentMap = this._guide.internal.liveDataUtils._getLazyAttachmentMap();
20338            _.each(lazyAttachmentMap, function (mapObject, key) {
20339                var attachmentList = mapObject.value.split("\n");
20340                for (var j = 0; j < attachmentList.length; j++) {
20341                    attachmentList[j] = guidelib.util.GuideUtil.guideSomToComponentName(key) + "/" + attachmentList[j];
20342                }
20343                fileAttachmentMap[key] = attachmentList.join('\n');
20344            });
20345            return fileAttachmentMap;
20346        },
20347
20348        ERROR_CAUSED_BY : {
20349            CAPTCHA_VALIDATION : "CAPTCHA_VALIDATION",
20350            SERVER_SIDE_VALIDATION : "SERVER_SIDE_VALIDATION",
20351            FORM_SUBMISSION : "FORM_SUBMISSION",
20352            AGREEMENT_CREATION : "AGREEMENT_CREATION",
20353            SERVICE_INVOCATION_FAILURE: "SERVICE_INVOCATION_FAILURE"
20354        },
20355
20356        /**
20357         * This API displays validation error messages at the field level corresponding to the input errorJson object
20358         * @summary Displays validation error messages at field level
20359         * @memberof GuideBridge
20360         * @instance
20361         * @param {object} errorJson json object containing the error messages in the [standard format](https://helpx.adobe.com/experience-manager/6-5/forms/using/custom-validation-message-adaptive-forms.html)
20362         * @see {@link https://helpx.adobe.com/experience-manager/6-5/forms/using/custom-validation-message-adaptive-forms.html%7CCustom validation message in adaptive form}
20363         */
20364        handleServerValidationError : function (errorJson) {
20365            var self = this;
20366            if (errorJson) {
20367                var errors = errorJson.errors;
20368                if (errors && errors.length > 0) {
20369                    var firstFocusableSom;
20370                    _.each(errors, function (object, i) {
20371                        var errMsg;
20372                        if (object.errorMessages) {
20373                            errMsg = object.errorMessages.join("\n");
20374                        } else {
20375                            errMsg = object.errorMessage;
20376                        }
20377                        var som = (object.somExpression) ? object.somExpression : self._guide._bindRefMap[object.bindRef];
20378                        var node = self.resolveNode(som);
20379
20380                        if (node) {
20381                            if (!firstFocusableSom) {
20382                                firstFocusableSom = som;
20383                            }
20384                            node.markAsInvalid(errMsg);
20385                        }
20386                    });
20387                    // set focus to first invalid node
20388                    if (firstFocusableSom) {
20389                        self.setFocus(firstFocusableSom);
20390                    }
20391                }
20392            }
20393        },
20394
20395        /* Handle the server side validation failure in case of submission fails.
20396         * This function handles Captcha validation as well as server side validation.
20397         * @private
20398         */
20399        _handleServerValidationError : function (errorJson) {
20400            var self = this;
20401            window.guideBridge.setEnabledAutoSave(_isAutoSaveEnabled);
20402            if (errorJson) {
20403                if (errorJson.errorCausedBy && errorJson.errorCausedBy === this.ERROR_CAUSED_BY.CAPTCHA_VALIDATION) {
20404                    var errors = errorJson.errors,
20405                        firstFocusableSom = errors[0].somExpression;
20406                    _.each(errors, function (object, i) {
20407                        var somExpression = object.somExpression,
20408                            errorMessage = object.errorMessage,
20409                            guideCaptcha;
20410                        /*Setting focus to load captcha's view.
20411                         This is required when panel's children get loaded later.
20412                         Setting focus ensures that view is loaded properly so that model can throw
20413                         'guide.errorChanged' event and view can listen the same.
20414                         */
20415                        self.setFocus(somExpression);
20416                        guideCaptcha = self.resolveNode(somExpression);
20417                        if (guideCaptcha) {
20418                            guideCaptcha.showCaptchaError(errorMessage);
20419                        }
20420                    });
20421                    //Setting focus to the first captcha element.
20422                    self.setFocus(firstFocusableSom);
20423                } else if (errorJson.errorCausedBy && errorJson.errorCausedBy === this.ERROR_CAUSED_BY.FORM_SUBMISSION
20424                    || errorJson.errorCausedBy === this.ERROR_CAUSED_BY.AGREEMENT_CREATION) {
20425                    if (errorJson.errors && errorJson.errors.length > 0) {
20426                        window.guideBridge.handleServerValidationError(errorJson);
20427                    } else {
20428                        var statusCode = errorJson.originCode ? Number(errorJson.originCode) : 500,
20429                            errorMessage = statusCode === 400 ? (errorJson.errorMessage ? errorJson.errorMessage : "") : "";
20430                        // show the message returned by server only if if the HTTP status code is 400
20431                        // this is done so that users could act upon the error and re-submit the form
20432                        $.proxy(guideBridge._handleSubmitError({
20433                            "status" : statusCode
20434                        }, errorMessage), guideBridge);
20435                    }
20436                } else {
20437                    //Everything else is "SERVER_SIDE_VALIDATION". Calling this as it was being called.
20438                    window.guideBridge.handleServerValidationError(errorJson);
20439                }
20440            }
20441        },
20442
20443        /*
20444         * Populates bindRefToSomMap.
20445         * This function is called during submission and during unloading of a lazy fragment
20446         * @param {node} is equal to the lazy loaded fragment model if this is called during lazy fragment unloading
20447         * @private
20448         */
20449        _populateBindRefToSomMap : function (node) {
20450
20451            /*
20452             * While populating bindRefToSomMap we basically check if any panel is repeatable panel.
20453             * If a panel is repeatable, in that node and its descendant nodes we replace the bindRef
20454             * by corresponding json-pointer in the map.
20455             * parameter {jsonp} refers to the json-pointer of the parent node. It is valid if
20456             * some ancestor of current node in the hierarchy was a repeatable panel
20457             */
20458            var bindRefToSomMapper = function (node, map, jsonp) {
20459                var path, bindref;
20460                if (node.bindRef) {
20461                    if (node.repeatable) { // current node is a repeatable panel
20462                        if (jsonp) { // some ancestor panel in the hierarchy was a repeatable panel
20463                            path = jsonp + "/" + node.bindRef.split("/").slice(-1)[0] + "/" + node.index;
20464                            bindref = path;
20465                        } else { // current node is the first repeatable panel in the hierarchy
20466                            path = node.bindRef + "/" + node.index;
20467                            bindref = path;
20468                        }
20469                    } else {
20470                        if (jsonp) { // some panel in the upper level was a repeatable panel
20471                            path = jsonp + "/" + node.bindRef.split("/").slice(-1)[0];
20472                            bindref = path;
20473                        } else { // no repeatable panel till now
20474                            bindref = node.bindRef;
20475                        }
20476                    }
20477                    map[bindref] = node.somExpression;
20478                }
20479
20480                if (node._children) {
20481                    node._children.forEach(function (element) {
20482                        bindRefToSomMapper(element, map, path);
20483                    });
20484                }
20485            };
20486            var jsonp;
20487
20488            // since we support lazy-loading for a fragment upto only two level deep, the immediate parent panel
20489            // of a lazy-loaded fragment can atmost be a repeatable panel. so we only check the repeatability for the parent
20490            if (node && node.parent && node.parent.repeatable && node.parent.bindRef) {
20491                jsonp = node.parent.bindRef + "/" + node.parent.index;
20492            }
20493
20494            if (!node) {
20495                node = window.guideBridge._guide;
20496            }
20497
20498            if (window.guideBridge.isGuideLoaded()) {
20499                if (!window.guideBridge._guide._bindRefMap) {
20500                    window.guideBridge._guide._bindRefMap = {};
20501                }
20502                bindRefToSomMapper(node, window.guideBridge._guide._bindRefMap, jsonp);
20503            }
20504        },
20505
20506        SELECTOR_FORM_CONTAINER : "#guideContainerForm",
20507
20508        THANK_YOU_OPTION : {
20509            PAGE : "page",
20510            MESSAGE : "message"
20511        },
20512
20513        addDorDownloadLink: function (thankYouContent, dorUri) {
20514            var guidePath = window.guideBridge.getGuidePath();
20515            var contextPath = window.guideBridge._getUrl(guidePath);
20516            dorUri = contextPath + ".af.dor.pdf?submissionId="+dorUri;
20517            var dorVariable = "$%7BAF_DocumentOfRecord%7D";
20518            if (thankYouContent && thankYouContent.indexOf(dorVariable) !== -1) {
20519                var tempElement = document.createElement("div");
20520                tempElement.innerHTML = thankYouContent;
20521                var anchorTags = tempElement.querySelectorAll("a");
20522                for (var i=0; i<anchorTags.length; i++) {
20523                    var tag = anchorTags.item(i);
20524                    if(tag.getAttribute("href") == dorVariable) {
20525                        tag.setAttribute("href", dorUri);
20526                        tag.setAttribute("download", tag.getAttribute("title"));
20527                        thankYouContent = tempElement.innerHTML;
20528                    }
20529                }
20530            }
20531            return thankYouContent;
20532        },
20533        /*
20534         *  default Submit Success Handler.
20535         *  This function handles the Thank You Page/Message
20536         */
20537        _defaultSubmitSuccessHandler : function (successPayload) {
20538            if (successPayload) {
20539                if (successPayload.thankYouOption === this.THANK_YOU_OPTION.MESSAGE) {
20540                    successPayload.thankYouContent = this.addDorDownloadLink(successPayload.thankYouContent, successPayload.dorUri);
20541                    var tyMessage = $("<div class='tyMessage'>" + successPayload.thankYouContent + "</div>");
20542                    $(this.SELECTOR_FORM_CONTAINER).replaceWith(tyMessage);
20543                    tyMessage.attr({'tabindex': '-1',
20544                                   'role': 'alertdialog'});
20545                    tyMessage.focus();
20546                } else if (successPayload.thankYouOption === this.THANK_YOU_OPTION.PAGE) {
20547                    window.location.href = encodeURI(successPayload.thankYouContent);
20548                }
20549            }
20550        },
20551
20552        _defaultSaveSuccessHandler : function (successPayload) {
20553            alert(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings["formSavedMessage"]));
20554        },
20555
20556        _defaultSaveErrorHandler : function () {
20557            alert(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings["formSaveError"]));
20558        },
20559
20560        // This function gets the relative path of the file.
20561        // Suppose the component Name is attachment and the file name is a.jpg,
20562        // then it will return "attachment/a.jpg" as the path
20563        _getRelativeFilePath : function (fileName) {
20564            var relPath = fileName;
20565            if (fileName.indexOf("/") !== -1) {
20566                var splitPath = fileName.split("/");
20567                if (splitPath.length > 2) {
20568                    relPath = splitPath[splitPath.length - 2] + "/" + splitPath[splitPath.length - 1];
20569                }
20570            }
20571            return relPath;
20572        },
20573
20574        // We do not need to validate if options.validate = false.
20575        // This function makes sure that validations are not performed when validate flag is false.
20576        // Validation is performed in all the other cases.
20577        _performConditionalValidation : function (options) {
20578            if (getOrElse(options, "validate", true)) {
20579                return guideBridge.validate(null, null, true, false);
20580            }
20581            return true;
20582        },
20583
20584        /**
20585         * This API returns the HTML content of another Adaptive Form and optionally load the Form inside an HTML
20586         * element
20587         *
20588         * The {@link GuideResultObject#data|data} property of the result passed to success handler will contain the HTML of
20589         * the Form
20590         * @summary load an Adaptive Form given its path
20591         * @param {object} options object to pass to the API
20592         * @param {function} [options.success] callback which receives the result of the API
20593         * in case of success.
20594         * {@link GuideResultObject#errors|errors} property as false.
20595         * @param {function} [options.error] callback which receives the result of the API in
20596         * case of failure.
20597         * {@link GuideResultObject#errors|errors} property as true.
20598         * @param {object} [options.context] _this_ object inside the _success_ and _error_ callback will point to this
20599         * object
20600         * @param {string} options.path Path of the Adaptive Form whose HTML is required. If sever is running at a
20601         * context path, this parameter must have the context path
20602         * @param {string} [options.dataRef] URL of the resource that returns the XML. The protocol of the URL must
20603         * match the supported URL protocols
20604         * @param {string} [options.containerSelector] jquery Selector of the HTML element where to insert the HTML
20605         * of the form.
20606         * @method
20607         * @memberof GuideBridge
20608         * @since 6.1 FP1
20609         * @instance
20610         * @example
20611         * guideBridge.loadAdaptiveForm({
20612         *      success : function (guideResultObj) {console.log("html is " + guideResultObj.data)},
20613         *      error : function (guideResultObj) { //log errors},
20614         *      dataRef : "http://url/of/the/dataRef",
20615         *      path : "/contextpath/content/dam/formsanddocuments/form1"
20616         * })
20617         * @see {@link https://api.jquery.com/category/selectors/|jQuery selectors}
20618         * @see <a href="#guidebridge-api-usage" >GuideBridge API Usage</a>
20619         */
20620        loadAdaptiveForm : function (options) {
20621            if (options && options.path) {
20622                // Let's covert the adaptive form asset path or af path
20623                // @todo: add notion of channel type in the options to load adaptive form
20624                var path = options.path.replace(FM_DAM_ROOT, FM_AF_ROOT);
20625                path += "/jcr:content/guideContainer.html";
20626                $.ajax({
20627                    url : path,
20628                    type : "GET",
20629                    data : {
20630                        // lets set the wcmmode to disabled
20631                        wcmmode : "disabled",
20632                        // Set the data reference
20633                        "dataRef" : options.dataRef
20634                    },
20635                    async : false,
20636                    success : function (data) {
20637                        // Get the container selector and do a replaceWith HTML
20638                        // not using jquery since jquery create a separate array objects for script, link etc
20639                        if (options.containerSelector) {
20640                            //NOCHECKMARX - data is coming from serverside preventing Reflective XSS All Clients.
20641                            $(options.containerSelector).html(data);
20642                        }
20643                        var guideResultObject = new GuideResultObject();
20644                        // data would here be html
20645                        guideResultObject.data = data;
20646                        guideResultObject.completed = true;
20647                        if (options.success && _.isFunction(options.success)) {
20648                            options.success.call(options.context, guideResultObject);
20649                        }
20650                    },
20651                    error : function (data) {
20652                        var guideResultObject = new GuideResultObject();
20653                        // data is an object containing xhr request, status and error
20654                        guideResultObject.data = data;
20655                        guideResultObject.completed = false;
20656                        guideResultObject.addMessage(2, "Error in getting HTML of Adaptive Form: " + options.path, "");
20657                        if (options.error && _.isFunction(options.error)) {
20658                            options.error.call(options.context, guideResultObject);
20659                        }
20660                    }
20661                });
20662            } else {
20663                if (typeof(console) !== "undefined") {
20664                    console.log("Path of Adaptive Form not specified to loadAdaptiveForm API");
20665                }
20666            }
20667        },
20668
20669        /**
20670         * Unloads the Form loaded using the {@link GuideBridge#loadAdaptiveForm|loadAdaptiveForm} API
20671         * @summary Unloads an adaptive Form from the browser, removing all the existing event listeners, data, html.
20672         * @param containerSelector jQuery Selector of the container, which contains the HTML of the Adaptive Form
20673         * @method
20674         * @memberof GuideBridge
20675         * @since 6.1 FP1
20676         * @instance
20677         * @see {@link https://api.jquery.com/category/selectors/|jQuery selectors}
20678         */
20679        unloadAdaptiveForm : function (containerSelector) {
20680            guidelib.util.GuideUtil._unloadAdaptiveForm(containerSelector);
20681        },
20682
20683        /**
20684         * Disables all the fields and global toolbar
20685         * @private
20686         */
20687        _disableForm : function () {
20688            var rootPanel = guideBridge.resolveNode("guide[0].guide1[0].guideRootPanel[0]"),
20689                globalToolbar = guideBridge.resolveNode("guide[0].guide1[0].toolbar[0]");
20690
20691            // The following API disables the loaded fields
20692            rootPanel.disableAllFields();
20693            // The following API disables the form toolbar
20694            if (globalToolbar) {
20695                globalToolbar.disableAllFields();
20696            }
20697        },
20698
20699        /**
20700         * @summary Disables the adaptive form, i.e. it disables all the fields and buttons, including toolbar's button
20701         * @method
20702         * @memberof GuideBridge
20703         * @since 6.3
20704         */
20705        disableForm : function () {
20706            guideBridge._disableForm();
20707            //Listening on guideBridge for "elementLazyLoaded" event to disable lazily loaded fields
20708            guideBridge.on("elementLazyLoaded", guideBridge._disableForm);
20709        },
20710
20711        _playGuideJson : function (options) {
20712            this._guide.setGuideState(guidelib.model.GuideSchema.prototype.GuideStateConstants.GUIDE_STATE_MERGE_PROGRESS);
20713            /*
20714             * no need to check here since merged json will not have xfaState if
20715             * xdp is invalid
20716             */
20717            if (this._isXfaGuide() && options.guideState.xfaState && options.guideState.xfaState.xfaDom) {
20718                var that = this;
20719                window.formBridge.restoreFormState({
20720                    formState : options.guideState.xfaState,
20721                    context : this,
20722                    //NOCHECKMARX - This is error callback to be provided by the user of this API.
20723                    error : options.error || defaultErrorHandler,
20724                    success : function () {
20725                        that._playNonXfaJson(options);
20726                    }
20727                });
20728            } else {
20729                this._playNonXfaJson(options);
20730            }
20731        },
20732
20733        _playNonXfaJson : function (options) {
20734            // try to  get xml-s from restore state 1st as they will be more relevant than the prefill state
20735            var xmlStr = getOrElse(options, "guideState.guideLiveData", null)
20736                    || getOrElse(options, "guideState.guidePrefillXml", null),
20737                xfaXmlStr = getOrElse(options, "guideState.xfaState.currentContext.data", null)
20738                    || JSON.parse(getOrElse(options, "guideState.xfaState.xfaRenderContext", "{}")).data,
20739                jsonStr = getOrElse(options, "guideState.guidePrefillJson", null);
20740            if (xmlStr || xfaXmlStr) {
20741                this._guide.internal.liveDataUtils.initLiveData(xmlStr, xfaXmlStr,
20742                    _.isString(this._guide.xdpRef), _.isString(this._guide.xsdRef),
20743                    this._guide.getAttribute("xsdRootElement"));
20744                this._guide.internal.liveModel.prefillCrossFragFields(this._guide);
20745                this._guide.internal.liveDataUtils.dropXfaXml();
20746            } else if (jsonStr) {
20747                this._guide.internal.liveDataUtils.initLiveData(jsonStr, this._guide.runtime.guideContext);
20748            } else {
20749                this._guide.internal.liveDataUtils.initLiveData(null, null,
20750                    _.isString(this._guide.xdpRef), _.isString(this._guide.xsdRef),
20751                    this._guide.getAttribute("xsdRootElement"));
20752            }
20753
20754            // If the restore state is not stored in local storage,then use it from the json passed from the server
20755            if (options.guideState.guideDom) {
20756                this._guide.playJson(options.guideState.guideDom, options.attachments);
20757            }
20758            if (options.guideState.unboundDataMap && options.guideState.unboundDataMap.data) {
20759                this.visit(function (node) {
20760                    // Fileupload value should not be set again, as it replaces the url with the file name
20761                    if (!(node instanceof guidelib.model.GuideFileUpload) && (node instanceof guidelib.model.Field || node instanceof guidelib.model.GuideCompositeField)
20762                        && !node.getAttribute("bindRef") && options.guideState.unboundDataMap.data[node.name]) {
20763                        var nodeValue = options.guideState.unboundDataMap.data[node.name];
20764                        //If the xml had empty tag, an empty object will come in the map, so set to null.
20765                        if (_.isObject(nodeValue) && _.isEmpty(nodeValue)) {
20766                            node._setGuideValue(null);
20767                        } else {
20768                            node._setGuideValue(nodeValue);
20769                        }
20770
20771                        if (node.className === "guideRadioButton") {
20772                            node.prevOnItem = node.getSelectedIndex(node.jsonModel._value);
20773                        }
20774                    }
20775                });
20776            }
20777            this._guide.setGuideState(guidelib.model.GuideSchema.prototype.GuideStateConstants.GUIDE_STATE_MERGE_COMPLETE);
20778            this._guide.prepare();
20779
20780            if (options.success) {
20781                options.success.call(this);
20782            }
20783        },
20784
20785        _postExternalMessage : function (message) {
20786            if (this.userConfig["postExternalMessageConfig"] && _.isFunction(this.userConfig["postExternalMessageConfig"]["postExternalHandler"])) {
20787                var externalHandler = this.userConfig["postExternalMessageConfig"]["postExternalHandler"];
20788                externalHandler(message);
20789            }
20790        },
20791
20792        _isXfaGuide : function () {
20793            if (this._guide.xdpRef) {
20794                return true;
20795            } else {
20796                return false;
20797            }
20798        },
20799        _readRuntimeLocale : function (runtimeLocale) {
20800            return this.customContextProperty("runtimeLocale", runtimeLocale);
20801
20802        },
20803
20804        /*
20805         * checks whether xdp present in Adaptive Form is valid or not
20806         * This is verified by checking the xdpRef property in guideContext
20807         */
20808        _isValidXFAGuide : function () {
20809            return !_.isUndefined(this._guide.runtime.guideContext.xdpRef);
20810        },
20811
20812        _isEditDesignMode : function () {
20813            if (window.CQ && window.CQ.WCM && (window.CQ.WCM.isEditMode() || window.CQ.WCM.isDesignMode())) {
20814                return true;
20815            } else {
20816                return false;
20817            }
20818        },
20819
20820        /**
20821         * @private
20822         */
20823        _getUUID : function () {
20824            if (this._formInstanceUUID) {
20825                return this._formInstanceUUID;
20826            }
20827            //Generate the UUID for the form instance on client side
20828            this._formInstanceUUID = guideBridge._produceUUID();
20829            return this._formInstanceUUID;
20830        },
20831
20832        /**
20833         * This will produce new UUID
20834         * @returns {string}
20835         * @private
20836         */
20837        _produceUUID : function () {
20838            var uuid = $('div.guideContainerWrapperNode').data("tmproot"),
20839                uuidSuffix = Math.floor((Math.random() * 10000) + 1),
20840                uuidCurrentTime = new Date().getTime();
20841            return uuid + "_" + uuidCurrentTime + uuidSuffix;
20842        },
20843
20844        /**
20845         * Signature of the callback for the GuideBridgeEvent Listener. It must be passed as handler in the
20846         * {@link GuideBridge#on|on} API.
20847         * @callback GuideBridge~GuideBridgeEventCallback
20848         * @param {jQuery.Event} event jQuery Event Object with target property being the instance of GuideBridge
20849         * @param {Object} payload Payload containing extra information in the API
20850         * @see {@link http://api.jquery.com/category/events/event-object/|jQuery.Event}
20851         * @since 6.0
20852         */
20853        /**
20854         * The API can be used to add an event listener for events triggered by GuideBridge object
20855         *
20856         * @summary add a listener on a GuideBridge Event.
20857         * @param eventName {string} name of the event for which listener has to be added. It must be one of the
20858         * following events
20859         * * bridgeInitializeComplete
20860         * * elementEnableChanged
20861         * * elementFocusChanged
20862         * * elementHelpShown
20863         * * elementLazyLoaded
20864         * * elementNavigationChanged
20865         * * elementValidationStatusChanged
20866         * * elementValueChanged
20867         * * elementVisibleChanged:
20868         * * guideAutoSaveStart
20869         * * submitStart
20870         * * validationComplete
20871         * @param {function} handler callback to be invoked whenever the event is triggered. The signature of the
20872         * callback is {@link GuideBridge~GuideBridgeEventCallback|GuideBridgeEventCallback}
20873         * @param {object} [context] The _this_ object in the _handler_ will point to _context_
20874         *
20875         * @method on
20876         * @memberof GuideBridge
20877         * @instance
20878         * @since 6.0
20879         */
20880        on : function (eventName, handler, context) {
20881            this._$target.on(eventName, handler, context);
20882        },
20883
20884        /**
20885         * Unregister the event registered using the {@link GuideBridge#on|on} function
20886         *
20887         * @param eventName {string} name of the event to un-register.
20888         * @param [selector] {string} selector which should match the one originally passed to guideBridge's on() while registering handlers
20889         * @param [handler] {function} handler which needs to un-registered. If not provided all the event listeners
20890         * will be unregistered
20891         *
20892         * @method off
20893         * @memberof GuideBridge
20894         * @instance
20895         * @since 6.0
20896         */
20897
20898        off : function (eventName, selector, handler) {
20899            this._$target.off(eventName, selector, handler);
20900        },
20901
20902        /**
20903         * Internal API
20904         * @param extraParamerts
20905         * @param eventName
20906         * @private
20907         */
20908        trigger : function (eventName, extraParamerts) {
20909            this._$target.trigger(eventName, extraParamerts);
20910        },
20911
20912        /**
20913         * If the name of the file attachments have to be made unique then the
20914         * vaule of this function would be true else false
20915         * @returns {*}
20916         * @private
20917         */
20918        _makeFileNameUnique : function () {
20919            if (this._guide && this._guide.runtime && this._guide.runtime.guideContext) {
20920                return this._guide.runtime.guideContext.makeFileNameUnique;
20921            }
20922        },
20923        /*this function is used to mince out
20924         * file attachmenemts name and dom in case of
20925         * anonymous user
20926         * */
20927        _getFileNameFileDomMap : function () {
20928            var fileAttachmentsList = this._getFileAttachmentsList();
20929            return this._juiceOutNameAndFileDomMap(fileAttachmentsList);
20930        },
20931
20932        /**
20933         * Returns a list of file attachment wrapper object represeting all file binaries
20934         * @returns reference of {@link guidelib.model.FileAttachmentWrapper}
20935         * @method
20936         * @memberof GuideBridge
20937         * @since FaaCS
20938         * @instance
20939         */
20940        getFileAttachmentWrapper : function () {
20941            var fileNameDomBindRefMap = this._getFileNameFileDomMap(),
20942                attachments = [],
20943                fileDoms = fileNameDomBindRefMap.fileDom,
20944                fileNames = fileNameDomBindRefMap.fileName,
20945                bindRefs = fileNameDomBindRefMap.fileBindRef,
20946                contentTypes = fileNameDomBindRefMap.fileContentType,
20947                _getFileName = function (fileName, componentName) {
20948                    // if file name contains component name
20949                    if (fileName.indexOf(componentName) !== -1) {
20950                        return fileName.replace(componentName + "/", "");
20951                    } else if (fileName.indexOf("/") !== -1) {
20952                        // if file name is a URL
20953                        return fileName.substring(fileName.lastIndexOf('/') + 1);
20954                    }
20955                };
20956
20957            var fileNamesIndex;
20958            for (fileNamesIndex = 0; fileNamesIndex < fileNames.length; fileNamesIndex++) {
20959                // multiple files inside one filedom element & draft save case is handled.
20960                var currentFileNames = fileNames[fileNamesIndex].split("\n");
20961                for (var fileIndex = 0; fileIndex < currentFileNames.length; fileIndex++) {
20962                    if (fileDoms[fileNamesIndex] && !_.isString(fileDoms[fileNamesIndex]) && fileDoms[fileNamesIndex].length > 0) {
20963                        // append each file of input file element
20964                        attachments.push(new guidelib.model.FileAttachmentWrapper({
20965                            name : _getFileName(currentFileNames[fileIndex], bindRefs[fileNamesIndex]),
20966                            data : fileDoms[fileNamesIndex][0].files[fileIndex],
20967                            contentType : fileDoms[fileNamesIndex][0].files[fileIndex].type,
20968                            bindRef : bindRefs[fileNamesIndex]
20969                        }));
20970                    } else if (currentFileNames[fileIndex]) {
20971                        //handle draft save scenario when fileDoms[fileNamesIndex] is null & currentFileNames[fileIndex] is a url
20972                        attachments.push(new guidelib.model.FileAttachmentWrapper({
20973                            name : _getFileName(guideBridge._getRelativeFilePath(currentFileNames[fileIndex]), bindRefs[fileNamesIndex]),
20974                            data : fileDoms[fileNamesIndex],
20975                            contentType : contentTypes[fileNamesIndex],
20976                            bindRef : bindRefs[fileNamesIndex]
20977                        }));
20978
20979                    }
20980                }
20981            }
20982            return attachments;
20983        },
20984
20985        /**
20986         * Returns the file attachment name and dom (input type=file) element
20987         * The returned object contains a list of file Doms and a list of corresponding file Names.
20988         * If the file is already uploaded, then the file DOM is null and file Name contains the URL.
20989         * @param fileAttachmentsList object list of file attachment models
20990         * @returns {{fileName: Array, fileDom: Array}}
20991         * @private
20992         */
20993        _juiceOutNameAndFileDomMap : function (fileAttachmentsList) {
20994            var fileDoms = [],
20995                fullFileNames = [],
20996                fullContentTypes = [],
20997                fileBindRefs = [],
20998                fileContentTypes = [],
20999                fileCount = 0,
21000                loadedFileDoms = [],
21001                loadedBindRefs = [],
21002                loadedContentTypes = [],
21003                loadedFileNames = [];
21004
21005            _.each(fileAttachmentsList, function (fileAttachmentModel, index) {
21006                var fileName = fileAttachmentModel._getFileAttachmentNames(),
21007                    fileAttachmentModelValue = fileAttachmentModel.value,
21008                    effectiveBindRef = fileAttachmentModel._getEffectiveBindRef(),
21009                    fileNameList = fileName; // even in case of makeFileNameUnique context set, fileName has the correct unique value
21010                if (fileNameList) {
21011                    var fileNames = fileNameList.split("\n");
21012                    var fileList = $.extend(true, [], fileAttachmentModel.fileList);
21013                    var fileNamesIndex = 0;
21014
21015                    _.each(fileList, function (inputFileDOM, currIndex) {
21016                        var fileNamesOfFileDom = null;
21017
21018                        // case: if there is a file dom
21019                        if (!_.isString(inputFileDOM)) {
21020                            _.each(inputFileDOM[0].files, function (file) {
21021                                var fileName = fileNames[fileNamesIndex++];
21022                                if (fileName) {
21023                                    if (fileNamesOfFileDom) {
21024                                        fileNamesOfFileDom += "\n" + fileAttachmentModel.name + "/" + fileName;
21025                                    } else {
21026                                        fileNamesOfFileDom = fileAttachmentModel.name + "/" + fileName;
21027                                    }
21028                                }
21029                            });
21030                            if (fileNamesOfFileDom != null) {
21031                                // Check if the value exist in the file, this is done because in IE9 and IE10 the list
21032                                // will have an extra empty dom
21033                                if ($(inputFileDOM).val().length > 0) {
21034                                    $(inputFileDOM).attr('name', fileNamesOfFileDom);
21035                                    loadedFileNames[fileCount] = fileNamesOfFileDom;
21036                                    loadedBindRefs[fileCount] = effectiveBindRef;
21037                                    // since the api is internal, we are not setting this
21038                                    loadedContentTypes[fileCount] = null; // we don't set "\n" separated content type here
21039                                    loadedFileDoms[fileCount++] = $(inputFileDOM);
21040                                }
21041                            }
21042                        } else {
21043                            // these values are nothing but field present as part of guidelib.model.FileAttachmentWrapper
21044                            // @note: to minimize the refactoring, not reusing the same model
21045                            // since there is no file dom in case of draft reload, make it null
21046                            loadedFileNames[fileCount] = fileAttachmentModel.name + "/" + fileNames[currIndex];
21047                            loadedBindRefs[fileCount] = effectiveBindRef;  // we add effective bindRef here
21048                            loadedContentTypes[fileCount] = fileAttachmentModel._getContentType(fileList[currIndex]);  // we add effective bindRef here
21049                            loadedFileDoms[fileCount++] = fileList[currIndex]; // we add the file URL in fileDom
21050                            fileNamesIndex++;
21051                        }
21052                    }, this);
21053
21054                }
21055            }, this);
21056
21057            // create the dom and name map for lazy file upload components as well
21058            var lazyFileMap = this._guide.internal.liveDataUtils._getLazyAttachmentMap(),
21059                lazyFileDom = [],
21060                lazyFileBindRef = [],
21061                lazyFileContentType = [],
21062                lazyFileName = [];
21063            _.each(lazyFileMap, function (mapObject, key) {
21064                var fileList = mapObject.fileList;
21065                var fileUploadValue = mapObject.value.split("\n");
21066                var fileUploadBindRef = mapObject.bindRef;
21067                var fileNames = mapObject.fileNames.split("\n");
21068                var fileNamesIndex = 0;
21069                _.each(fileList, function (value) {
21070                    if (!_.isString(value)) {
21071                        var fileNamesOfFileDom = null;
21072                        _.each(value[0].files, function (file) {
21073                            var fileName = fileUploadValue[fileNamesIndex++];
21074                            if (fileName) {
21075                                var fullName = guidelib.util.GuideUtil.guideSomToComponentName(key) + "/" + fileName;
21076                                if (fileNamesOfFileDom) {
21077                                    fileNamesOfFileDom += "\n" + fullName;
21078                                } else {
21079                                    fileNamesOfFileDom = fullName;
21080                                }
21081                            }
21082                        });
21083
21084                        lazyFileDom.push(value);
21085                        lazyFileName.push(fileNamesOfFileDom);
21086                    } else {
21087                        var fullName = guidelib.util.GuideUtil.guideSomToComponentName(key) + "/" + fileNames[fileNamesIndex];
21088                        lazyFileDom.push(value);
21089                        lazyFileName.push(fullName);
21090                        fileNamesIndex++;
21091                    }
21092                    lazyFileBindRef.push(fileUploadBindRef);
21093                    lazyFileContentType.push(null); // todo: check if this use-case would ever hit
21094                });
21095            });
21096
21097            // concatenate the arrays for loaded and unloaded file doms and names
21098            fileDoms = loadedFileDoms.concat(lazyFileDom);
21099            fullFileNames = loadedFileNames.concat(lazyFileName);
21100            fileBindRefs = loadedBindRefs.concat(lazyFileBindRef);
21101            fileContentTypes = loadedContentTypes.concat(lazyFileContentType);
21102
21103            return {
21104                "fileName" : fullFileNames,
21105                "fileDom" : fileDoms,
21106                "fileBindRef" : fileBindRefs,
21107                "fileContentType" : fileContentTypes
21108            };
21109        },
21110
21111        setValidationContext : function (context) {
21112            var ec = guidelib.util.ErrorConstants;
21113            if (typeof ec[context] === "number") {
21114                var nContext = ec[context];
21115                if (nValidationContext < nContext) {
21116                    nValidationContext = nContext;
21117                    sValidationContext = context;
21118                }
21119            }
21120        },
21121
21122        unsetValidationContext : function (context) {
21123            if (context === sValidationContext) {
21124                nValidationContext = 0;
21125                sValidationContext = "";
21126            }
21127        },
21128
21129        getValidationContext : function () {
21130            return sValidationContext;
21131        },
21132
21133        /**
21134         * @summary Enable/Disable the swipe gesture for navigation on touch devices.
21135         * @param swiptLeft boolean flag to enable(true)/disable(false) the swipe left gesture to perform next item navigation
21136         * @param swipeRight boolean flag to enable(true)/disable(false) the swipe right gesture to perform previous item navigation
21137         * @method
21138         * @memberof GuideBridge
21139         * @instance
21140         * @since 6.3
21141         */
21142        enableSwipeGesture : function (swiptLeft, swipeRight) {
21143            $guideWrapperNode = $('.guideContainerWrapperNode');
21144            $guideWrapperNode.off('swipeleft', window.guideBridge._performItemDeepNavigationNext);
21145            $guideWrapperNode.off('swiperight', window.guideBridge._performItemDeepNavigationPrevious);
21146            if (swiptLeft) {
21147                $guideWrapperNode.on('swipeleft', window.guideBridge._performItemDeepNavigationNext);
21148            }
21149            if (swipeRight) {
21150                $guideWrapperNode.on('swiperight', window.guideBridge._performItemDeepNavigationPrevious);
21151            }
21152        },
21153
21154        /**
21155         * Enable the next item navigation (deep) using swipe left gesture
21156         * @private
21157         */
21158        _performItemDeepNavigationNext : function () {
21159            window.guideBridge.setFocus({
21160                somExpression : null,
21161                focusOption : 'nextItemDeep',
21162                runCompletionScript : true,
21163                skipFieldFocus : true
21164            });
21165        },
21166
21167        /**
21168         * Enable the previous item navigation (deep) using swipe right gesture
21169         * @private
21170         */
21171        _performItemDeepNavigationPrevious : function () {
21172            window.guideBridge.setFocus({
21173                somExpression : null,
21174                focusOption : 'prevItemDeep',
21175                runCompletionScript : true,
21176                skipFieldFocus : true
21177            });
21178        },
21179
21180        /**
21181         * Update the model popup that appears at click of file attachment listing button
21182         * This function is currently run of the clickExp of fileAttachmentListingButton
21183         * @param node
21184         * @private
21185         */
21186        _updateFileListing : function (node) {
21187            var somExpression = node.somExpression,
21188                viewOfListingButton = guideBridge._guideView.getView(somExpression);
21189            viewOfListingButton._clearFileListing();
21190            guideBridge.visit($.proxy(viewOfListingButton._updateFileListing, viewOfListingButton));
21191
21192        },
21193
21194        registerPanelProvider : function (panelProvider) {
21195            var resultObj = new GuideResultObject();
21196            if (this.panelProvider == null) {
21197                resultObj.data = panelProvider;
21198                this.panelProvider = panelProvider;
21199                return resultObj;
21200            }
21201            resultObj.addMessage(2, "registrationError: PanelProvider already registered", "");
21202            return resultObj;
21203        }
21204    });
21205
21206    window.guideBridge = new GuideBridge();
21207    window.guideBridge._$target = $(window.guideBridge);
21208    window.guideBridge.on("af.invisibleMandatoryRecaptchaInitialization", function (event, data) {
21209        var model = data.jsonModel.target.jsonModel;
21210        var formContainerSelector = FD.isToggleEnabled("FT_FORMS-11858") ? guidelib.util.GuideUtil.GUIDE_CONTAINER_FORM_CLASS : ".guideContainer,.aemformcontainer";
21211        $(formContainerSelector).append('<div id="captchaInvisible"></div>');
21212        var captchaInvisibleElement = $("#captchaInvisible"), captchaElement = $("[data-captchaservice]");
21213
21214        captchaInvisibleElement.attr({
21215            "modelId" : model.id || model.templateId,
21216            "af-recaptcha-execute" : "",
21217            "data-locale" : captchaElement.attr("data-locale")
21218        });
21219
21220        if (model.captchaService === 'turnstile') {
21221            captchaInvisibleElement.on("recaptchaExecution", guidelib.util.CaptchaUtil.captchaExecution);
21222            var turnstileParameters = {
21223                'sitekey' : model.siteKey,
21224                'theme' : model.theme || 'light',
21225                'size' : model.size,
21226                'language' : captchaElement.attr('data-locale'),
21227                'execution' : 'execute'
21228            };
21229            guidelib.util.CaptchaUtil.renderCaptcha(captchaInvisibleElement, model,
21230                model.clientJsUrl, 'cf-turnstile-response', turnstileParameters);
21231        } else if (model.captchaService === 'hcaptcha') {
21232            captchaInvisibleElement.on("recaptchaExecution", guidelib.util.CaptchaUtil.captchaExecution);
21233            var hcaptchaParameters = {
21234                'sitekey' : model.siteKey,
21235                'theme' : model.theme || 'light',
21236                'size' : model.size,
21237            };
21238            guidelib.util.CaptchaUtil.renderCaptcha(captchaInvisibleElement, model,
21239                model.clientJsUrl, 'h-captcha-response', hcaptchaParameters);
21240        } else {
21241            captchaInvisibleElement.attr({
21242                "data-externaldomain" : captchaElement.attr("data-externaldomain")
21243            });
21244            captchaInvisibleElement.on("recaptchaExecution", guidelib.util.RecaptchaUtil.recaptchaExecution);
21245            guidelib.util.RecaptchaUtil.renderRecaptcha(captchaInvisibleElement, model);
21246        }
21247    });
21248
21249    try {
21250        var evnt = document.createEvent("CustomEvent");
21251        evnt.initCustomEvent("bridgeInitializeStart", true, true, {"guideBridge" : window.guideBridge});
21252        window.dispatchEvent(evnt);
21253    } catch (exception) {
21254        // written for env rhino to execute(for server side validation)
21255        // todo: once env rhino implements CustomEvent and initCustomEvent remove this
21256        // this._guide.logger().log(exception);
21257    }
21258
21259    if (!window.guideBridge.userConfig["postExternalMessageConfig"]) {
21260        if (window !== window.parent) {
21261            try {
21262                window.parent.document.getElementById(window.name);
21263                //We are here means no cross domain issue. So if user has not defined custom postExternalMessageConfig and
21264                // then we'll create one which would just send event on parent.
21265                window.guideBridge.registerConfig("postExternalMessageConfig", {
21266                    "postExternalHandler" : function (message) {
21267                        try {
21268                            var tmpEvent = document.createEvent("CustomEvent");
21269                            tmpEvent.initCustomEvent(message.name, true, true, message.data);
21270                            window.parent.dispatchEvent(tmpEvent);
21271                        } catch (exception) {
21272                            // written for env rhino to execute
21273                            //this._guide.logger().log(exception);
21274                        }
21275                    }
21276                });
21277            } catch (e) {
21278                //ignore the error
21279            }
21280        }
21281    }
21282
21283    window.guideBridge._postExternalMessage({
21284        name : "bridgeInitializeStart",
21285        data : {
21286            "guideBridge" : window.guideBridge
21287        }
21288    });
21289})($, _);
21290
21291/**
21292 * @package guidelib.model.DataNode
21293 * @version 0.0.1
21294 */
21295
21296(function ($, _, guideBridge, guidelib, formBridge, xfalib) {
21297
21298    var LiveDataUtils = guidelib.model.LiveDataUtils = xfalib.ut.Class.extend({
21299
21300        constants : {
21301            SKELETON_XML : '<afData><afUnboundData><data/></afUnboundData><afBoundData><data xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/"/></afBoundData></afData>',
21302            SKELETON_JSON : '{"afData":{"afUnboundData":{"data":{}},"afBoundData":{"data":{}}}}',
21303            UNBOUND_SKELETON : '<unBound></unBound>',
21304            UNBOUND_JSON_SKELETON : '{"afUnboundData":{}}',
21305            INDEXED_XPATH_PAT : new RegExp(/\/[^\/]+\[\d+\]/),
21306            INDEXED_XPATH_PAT_JSON : new RegExp(/\/[^\/]+\/\d+/),
21307            XFA_DATA_NODE_ATTR_NAME : "xfa:dataNode",
21308            XFA_DATA_NODE_ATTR_VALUE : "dataGroup",
21309            UNKNOWN_XSD_ROOT_ELEMENT : "?",
21310            AF_ROOT_TAG : "afData",
21311            BOUND_TAG : "afBoundData",
21312            UNBOUND_TAG : "afUnboundData",
21313            XFA_TAG : "xfa",
21314            DATA_TAG : "data",
21315            BOUND_DATA_XPATH : "afBoundData/data",
21316            UNBOUND_DATA_XPATH : "afUnboundData/data",
21317            AF_DRAFT_TAG : "afSubmissionInfo/afDraft"
21318        },
21319
21320        initialize : function () {
21321            LiveDataUtils._super.initialize.call(this);
21322            this._boundDataRoot = null;
21323            this._unboundDataRoot = null;
21324            this._xfaDataRoot = null;
21325            this._fetchingClientSideData = false; // this state indicates that we are fetching client side data, its not use-case to fetch lazy data
21326            this.lazyAttachmentMap = {};
21327            this.attachments = [];
21328        },
21329
21330        /**
21331         * This function updates the lazy attachment Map from
21332         * the map passed
21333         * @param fileAttachmentMap
21334         * @private
21335         */
21336        _updateLazyAttachmentMap : function(fileAttachmentMap) {
21337            _.each(fileAttachmentMap, function (value, key) {
21338                this.lazyAttachmentMap[key] = {};
21339                this.lazyAttachmentMap[key].fileList = value.split("\n");
21340                this.lazyAttachmentMap[key].value = value;
21341            }, this);
21342        },
21343
21344        /**
21345         * This function updates the lazy attachment Map from the model.
21346         * It gets the value and fileList from the model and updates the map.
21347         * If the fileUpload component is not in a lazy panel then it removes
21348         * its entry form the map(if the entry is already there).
21349         * @param model
21350         * @private
21351         */
21352        _updateLazyAttachmentMapFromModel : function (model) {
21353            // add the component in the map only when its in a lazy panel
21354            // add the entry in map only when its not not empty
21355            if (model.parent._selfOrAncestorIsLazyReference && model.value && model.fileList && !this._fetchingClientSideData) {
21356                this.lazyAttachmentMap[model.somExpression] = {
21357                    value : model.value,
21358                    fileList : model.fileList,
21359                    bindRef : model._getEffectiveBindRef(),
21360                    fileNames : model._getFileAttachmentNames()
21361                };
21362            } else {
21363                if (this.lazyAttachmentMap[model.somExpression]) {
21364                    delete this.lazyAttachmentMap[model.somExpression];
21365                }
21366            }
21367        },
21368
21369        /**
21370         * This function returns the value in the lazy attachment map for the model.
21371         * It removes the entry from the map as well. This is required so that the map gets
21372         * updated with the new values when the panel unloads.
21373         * @param model
21374         * @returns {*}
21375         * @private
21376         */
21377        _getAttachmentDataForModel : function (model) {
21378            var effectiveBindRef = model._getEffectiveBindRef();
21379            if (model.somExpression && !_.isEmpty(this.lazyAttachmentMap)) {
21380                var data = this.lazyAttachmentMap[model.somExpression];
21381                delete this.lazyAttachmentMap[model.somExpression];
21382                return data;
21383            }
21384            if (effectiveBindRef && !_.isEmpty(this.attachments)) {
21385                var data = model._getCurrentFileAttachmentWrapper(this.attachments);
21386                return data;
21387            }
21388        },
21389
21390        _getLazyAttachmentMap : function () {
21391            return this.lazyAttachmentMap;
21392        },
21393
21394        dropXfaXml : function () {
21395            this._xfaDataRoot = null;
21396        },
21397
21398        // only called from test framework
21399        destroy : function () {
21400            this._liveDataDoc = null;
21401            this._boundDataRoot = null;
21402            this._unboundDataRoot = null;
21403            this._xfaDataRoot = null;
21404        },
21405
21406        initLiveData : function (prefillDataStr, xfaPrefillDataStr, isXdp, isXsd, xsdRootElement, attachments) {
21407            this.attachments = attachments;
21408        },
21409
21410        isLiveDataInitialized : function () {
21411        },
21412
21413        getLiveDataStr : function () {
21414        },
21415
21416        getLiveDataDoc : function () {
21417            return this._liveDataDoc;
21418        },
21419
21420        _isNonNaked : function () {
21421        },
21422
21423        _getNameAndIndex : function (xpathPart) {
21424        },
21425
21426        isIndexedPath : function (xpath) {
21427        },
21428
21429        _createElements : function (contextNode, xpathParts) {
21430        },
21431
21432        _createRepeatedElements : function (contextNode, xpathParts) {
21433        },
21434
21435        _createChildElement : function (parentElement, elemName) {
21436        },
21437
21438        _createAttributeNode : function (parentElement, attrName) {
21439        },
21440
21441        getContextNode : function (schemaPath, dataSection, createMissingNodes, lastNodeValue) {
21442        },
21443
21444        addIndexToPath : function (path, index) {
21445        },
21446
21447        _getElement : function (node, xpath, options) {},
21448
21449        hasChildNodes : function (node) {
21450        },
21451
21452        /**
21453         * Removes a child node from its parent
21454         * @param parentNode {Node} Parent Node from which to remove the child node
21455         * @param targetNode {String} Node name of the child to remove
21456         * @param index Index of the child node to remove
21457         */
21458        removeChild : function (parentNode, targetNodeName, index) {
21459        },
21460
21461        insertNode : function (parentNode, childNodeName, index) {
21462        },
21463
21464        _getDataContext : function (model, bound_indexedXpathSoFar, unBound_indexedXpathSoFar) {
21465            var bindRef = model.bindRef,
21466                liveDataUtils = this,
21467                xmlSec,
21468                indexedXpath;
21469
21470            if (model._isXfaNode()) {
21471                xmlSec = liveDataUtils.constants.XFA_TAG;
21472                indexedXpath = xfalib.ut.XMLUtils.dataSom2xpath(model.dataSom);
21473            } else if (_.isEmpty(bindRef)) {
21474                xmlSec = liveDataUtils.constants.UNBOUND_TAG;
21475                indexedXpath = unBound_indexedXpathSoFar + '/' + model.getAttribute("name").replace(/\s+/g, '');
21476                // use attr 'name' here, as schema might have an elem called 'name'
21477            } else {
21478                xmlSec = liveDataUtils.constants.BOUND_TAG;
21479
21480                var xpathMatch = liveDataUtils.getMatchingXpathHierarchy(bou
21480nd_indexedXpathSoFar, bindRef);
21481                if (xpathMatch.isCrossHierarchy) {
21482                    indexedXpath = bindRef;
21483                } else {
21484                    indexedXpath = bound_indexedXpathSoFar;
21485                    if (!_.isEmpty(xpathMatch.suffixParts)) {
21486                        indexedXpath += '/' + xpathMatch.suffixParts.join('/');
21487                    }
21488                }
21489            }
21490
21491            return {
21492                'xmlSec' : xmlSec,
21493                'indexedXpath' : indexedXpath
21494            };
21495        },
21496
21497        /**
21498         * return true if both xpath parts have same element name and indices
21499         * absence of index in the templateName is ignored
21500         * @param indexedName
21501         * @param templateName
21502         * @returns {boolean}
21503         * @private
21504         * @memberof LiveDataUtils
21505         */
21506        _cmpXpathParts : function (indexedName, templateName) {
21507          },
21508
21509        /**
21510         * get a partition of the matching xpath part hierarchy
21511         * the matching parts have same element names and agreeable indices
21512         * @param parentXpath
21513         * @param currentXpath
21514         * @returns {{prefixParts: Array, suffixParts: (*|Array.<T>|list), isCrossHierarchy: boolean}}
21515         * @memberof LiveDataUtils
21516         */
21517        getMatchingXpathHierarchy : function (parentXpath, currentXpath) {
21518            var isCrossHierarchy = false,
21519                prefixParts = [],
21520                suffixParts = this._sanitizedXpathParts(currentXpath);
21521
21522            _.find(this._sanitizedXpathParts(parentXpath), function (parentPart) {
21523                if (this._cmpXpathParts(parentPart, suffixParts[0])) {
21524                    prefixParts.push(parentPart);
21525                    suffixParts.shift();
21526                } else {
21527                    isCrossHierarchy = true;
21528                    return true;
21529                }
21530            }, this);
21531
21532            return {
21533                'prefixParts' : prefixParts,
21534                'suffixParts' : suffixParts,
21535                'isCrossHierarchy' : isCrossHierarchy
21536            };
21537        },
21538
21539        _getXpathContext : function (targetPanel) {
21540            var boundXpath = '',
21541                unBoundXpath = '',
21542                ancestors = [],
21543                panel = targetPanel.parent;
21544
21545            while (panel instanceof guidelib.model.GuidePanel) {
21546                if (panel._preserveLazyValue()) {
21547                    ancestors.unshift(panel);
21548                }
21549                panel = panel.parent;
21550            }
21551
21552            _.each(ancestors, function (ancestor) {
21553                var xmlContext = ancestor._syncModelAndData(boundXpath, unBoundXpath);
21554                boundXpath = xmlContext.bound;
21555                unBoundXpath = xmlContext.unBound;
21556            });
21557
21558            return {
21559                'bound' : boundXpath,
21560                'unBound' : unBoundXpath
21561            };
21562        },
21563
21564        _applyOnLiveData : function (action, targetPanel) {
21565            if (_.isString(targetPanel)) {
21566                targetPanel = guideBridge.resolveNode(targetPanel);
21567            }
21568
21569            if (targetPanel instanceof guidelib.model.GuidePanel) {
21570                var indexedXpathsFromRoot = targetPanel._guide().internal.liveDataUtils._getXpathContext(targetPanel);
21571                targetPanel[action](indexedXpathsFromRoot.bound, indexedXpathsFromRoot.unBound);
21572            } else {
21573                guideBridge._guide.rootPanel[action]('', '');
21574            }
21575        },
21576
21577        /**
21578         * will capture the currently loaded model hierarchy in a xml doc to be referred to later by lazily loaded panels
21579         * @private
21580         * @memberof LiveDataUtils
21581         */
21582        updateLiveData : function (targetPanel, fetchingClientSideData) {
21583            this._fetchingClientSideData = !_.isUndefined(fetchingClientSideData);
21584            this._applyOnLiveData('_updateLiveData', targetPanel);
21585            this._fetchingClientSideData = false;
21586        },
21587
21588        /**
21589         * will replay the model hierarchy from the live xml, for the supplied panel
21590         * @param targetPanel
21591         * @private
21592         * @memberof LiveDataUtils
21593         */
21594        playLiveData : function (targetPanel) {
21595            this._applyOnLiveData('_playLiveData', targetPanel);
21596        },
21597
21598        getListOfDirtyPanels : function (dataString) {
21599            return [];
21600        },
21601
21602        addDataNodeInfo : function (contextNode) {
21603        },
21604
21605        /**
21606         * Set the value of the node referred by xpath in the bounded/unbounded
21607         * section as specified by section. This optionally creates the data nodes
21608         * if they are not present
21609         * @param xpath
21610         * @param section
21611         * @param createMissingNodes
21612         * @param value
21613         */
21614        setDataValue : function (xpath, section, createMissingNodes, value) {
21615        },
21616
21617        /**
21618         * Set the rich text(html) value of the node referred by xpath in the bounded/unbounded
21619         * section as specified by section. This optionally creates the data nodes
21620         * if they are not present
21621         * @param xpath
21622         * @param xmlSection
21623         * @param createMissingNodes
21624         * @param value
21625         */
21626        setRichTextValue : function (xpath, xmlSection, createMissingNodes, value) {
21627            this.setDataValue(xpath, xmlSection, createMissingNodes, value);
21628        },
21629
21630        /**
21631         * Returns the value of the node referred by xpath in the bounded/unbounded
21632         * section as specified by section. It returns undefined if the node doesn't
21633         * exist
21634         * @param xpath
21635         * @param section
21636         */
21637        getDataValue : function (xpath, section) {
21638        },
21639
21640        _convertModelIndexToDataIndex : function (index) {
21641        },
21642
21643        getParentRef : function (path) {
21644        },
21645
21646        /**
21647         * returns the parent data node for the context specified by dataNodeContext
21648         * @param dataNodeContext {object} containing xpath and section
21649         * @param createIfMissing
21650         * @returns {*}
21651         * @param parentNodeValue
21652         */
21653        getParentDataNode : function (dataNodeContext, createIfMissing, parentNodeValue) {
21654            var parentRef = this.getParentRef(dataNodeContext.indexedXpath),
21655                parentNode;
21656            if (_.isEmpty(parentRef)) {
21657                parentNode = this.getContextNode("", dataNodeContext.xmlSec, false);
21658            } else {
21659                parentNode = this.getContextNode(parentRef, dataNodeContext.xmlSec, createIfMissing, parentNodeValue);
21660            }
21661            return parentNode;
21662        },
21663
21664
21665        /**
21666         * Insert submission Info in the data
21667         * @param submissionInfo {object} object containing the properties to be added as submission info in data
21668         */
21669        insertSubmissionInfo : function (submissionInfo) {
21670
21671        }
21672
21673    });
21674
21675}($, _, window.guideBridge, window.guidelib, window.formBridge, window.xfalib));
21676
21677/**
21678 * @package guidelib.model.DataNode
21679 * @version 0.0.1
21680 */
21681
21682(function ($, _, guideBridge, guidelib, formBridge, xfalib) {
21683    var getOrElse = xfalib.ut.XfaUtil.prototype.getOrElse;
21684
21685    var LiveJsonUtils = guidelib.model.LiveJsonUtils = guidelib.model.LiveDataUtils.extend({
21686
21687        initialize : function () {
21688            LiveJsonUtils._super.initialize.call(this);
21689            this._liveDataDoc = null;
21690        },
21691
21692        initLiveData : function (prefillDataStr, guideContext) {
21693            LiveJsonUtils._super.initLiveData.apply(this, arguments);
21694            prefillDataStr = prefillDataStr || getOrElse(guideContext, "guidePrefillJson", null);
21695
21696            if (_.isString(prefillDataStr) && prefillDataStr.length > 0) {
21697                var prefillDataDoc = JSON.parse(prefillDataStr);
21698
21699                if (this._isNonNaked(prefillDataDoc)) {
21700                    // non naked json, assuming full hierarchy afdata/afbounddata/data
21701                    this._liveDataDoc = prefillDataDoc;
21702                    this._boundDataRoot = this._getElement(this._liveDataDoc.afData, this.constants.BOUND_DATA_XPATH);
21703                    this._unboundDataRoot = this._getElement(this._liveDataDoc.afData, this.constants.UNBOUND_DATA_XPATH);
21704
21705                } else {
21706                    // naked json start from prefill data root
21707                    this._boundDataRoot = prefillDataDoc;
21708                    this._unboundDataRoot = JSON.parse(this.constants.UNBOUND_JSON_SKELETON)[this.constants.UNBOUND_TAG];  // need this for unbound data fill across lazy
21709                    this._liveDataDoc = prefillDataDoc;
21710                }
21711            } else {
21712                // init default skeleton for no prefill cases
21713                this._liveDataDoc = JSON.parse(this.constants.SKELETON_JSON);
21714                this._boundDataRoot = this._getElement(this._liveDataDoc.afData, this.constants.BOUND_DATA_XPATH);
21715                this._unboundDataRoot = this._getElement(this._liveDataDoc.afData, this.constants.UNBOUND_DATA_XPATH);
21716            }
21717            if (this._boundDataRoot == null && this._isNonNaked(prefillDataDoc)) {
21718                this._liveDataDoc.afData.afBoundData = this._liveDataDoc.afData.afBoundData || {};
21719                this._liveDataDoc.afData.afBoundData.data = this._liveDataDoc.afData.afBoundData.data || {};
21720                this._boundDataRoot = this._liveDataDoc.afData.afBoundData.data;
21721            }
21722        },
21723
21724        /*
21725         * This API gets the element w.r.t to the node.
21726         * Eg - path is a/b/c, then it converts the path to a.b.c and then searches for c.
21727         */
21728        _getElement : function (node, path, options) {
21729            if (!(node instanceof Object)) {
21730                return null;
21731            }
21732
21733            if (_.isEmpty(path) || !_.isString(path)) {
21734                return node;
21735            }
21736            options = options || {};
21737            var index = options.index;
21738            var convertedPath = path.split('/').join('.');
21739            if (!(_.isUndefined(index) || _.isNull(index))) {
21740                convertedPath = convertedPath + "." + index;
21741            }
21742            return getOrElse(node, convertedPath, null);
21743        },
21744
21745        /**
21746         * This function checks if the data contains naked or non naked json
21747         * @returns {boolean} returns true if there exists a afData node inside data
21748         * @private
21749         * @memberof LiveJsonUtils
21750         * @param prefillData
21751         */
21752        _isNonNaked : function (prefillData) {
21753            prefillData = prefillData || this.getLiveDataDoc();
21754            if (prefillData) {
21755                return prefillData.hasOwnProperty("afData");
21756            } else {
21757                return false;
21758            }
21759        },
21760
21761        isLiveDataInitialized : function () {
21762            return (this.getLiveDataDoc() instanceof Object);
21763        },
21764
21765        getLiveDataStr : function () {
21766            if (this.isLiveDataInitialized()) {
21767                return JSON.stringify(this.getLiveDataDoc());
21768            } else {
21769                return '';
21770            }
21771        },
21772
21773        /*
21774         * This API will remove the spaces,"\" from the path.
21775         * It will return an array after splitting the path.
21776         * Eg - for a/0/b/c, it will return ["a/0","b","c"]
21777         */
21778        _sanitizedXpathParts : function (path) {
21779            var pathParts = (path || '').replace(/^\//, '').replace(/\s+/g, '');
21780            pathParts = this._splitForIndex(pathParts);
21781
21782            return _.filter(pathParts, function (xpathPart) {
21783                return this._getNameAndIndex(xpathPart) !== null;
21784            }, this);
21785        },
21786
21787        _splitForIndex : function (path) {
21788            var pathArray = [];
21789            var pathParts = path.split('/');
21790            for (var i = 0; i < pathParts.length; i++) {
21791                var str = pathParts[i];
21792                if ((i + 1) < pathParts.length && !isNaN(pathParts[i + 1]) && !_.isEmpty(pathParts[i + 1])) {
21793                    str = str + "/" + pathParts[i + 1];
21794                    i = i + 1;
21795                }
21796                pathArray.push(str);
21797            }
21798            return pathArray;
21799        },
21800
21801        /**
21802         * Returns the index associated with the pathPart.
21803         * Eg - if pathPart is 'a/1', then it returns {name : a, index : 1}
21804         * @param pathPart
21805         * @returns {*}
21806         * @private
21807         */
21808        _getNameAndIndex : function (pathPart) {
21809            if (pathPart) {
21810                var elName = pathPart.match(/^([^\s\/]+)(?:\/(\d+))?$/);  // match the whole string
21811                if (elName !== null) {
21812                    return {
21813                        name : elName[1],
21814                        index : elName[2] ? parseInt(elName[2]) : -1
21815                        // -1 index for depicting non repeatable element
21816                    };
21817                }
21818            }
21819            return null;
21820        },
21821
21822        _cmpXpathParts : function (indexedName, templateName) {
21823            if (indexedName && templateName) {
21824                var match1 = this._getNameAndIndex(indexedName),
21825                    match2 = this._getNameAndIndex(templateName);
21826                return !_.isEmpty(match1 && match2)
21827                    && match1.name === match2.name
21828                    && (match2.index === -1 || match1.index === match2.index);
21829            }
21830            return false;
21831        },
21832
21833        /**
21834         * This function gets or creates the node if its not there. The node can be any valid JSON Value
21835         * null, string, object, array, number, boolean.
21836         * @param schemaPath
21837         * @param dataSection
21838         * @param createMissingNodes
21839         * @param lastNodeValue
21840         * @returns {*}
21841         */
21842        getContextNode : function (schemaPath, dataSection, createMissingNodes, lastNodeValue) {
21843            var contextNode,
21844                baseContextNode,
21845                basePath = "",
21846                pathParts = this._sanitizedXpathParts(schemaPath);
21847            if (dataSection == this.constants.BOUND_TAG) {
21848                baseContextNode = this._boundDataRoot;
21849                if (this._isNonNaked(this._liveDataDoc)) {
21850                    basePath = "afData/" + this.constants.BOUND_DATA_XPATH + "/";
21851                }
21852            } else if (dataSection === this.constants.UNBOUND_TAG) {
21853                baseContextNode = this._unboundDataRoot;
21854                if (this._isNonNaked(this._liveDataDoc)) {
21855                    basePath = "afData/" + this.constants.UNBOUND_DATA_XPATH + "/";
21856                }
21857            }
21858            if (!_.isEmpty(pathParts)) {
21859                var path = (basePath + pathParts.join('/'));
21860
21861                // return baseContextNode for naked json. path can be "" only for naked json.
21862                if (path == "" && !this._isNonNaked(this._liveDataDoc)) {
21863                    return baseContextNode;
21864                }
21865
21866                contextNode = this._getElement(this._liveDataDoc, path);
21867                if (!contextNode && createMissingNodes) {
21868                    contextNode = this._createElements(baseContextNode, pathParts, lastNodeValue);
21869                }
21870            } else {
21871                contextNode = baseContextNode;
21872            }
21873            return contextNode;
21874        },
21875
21876        /**
21877         * This function creates the node at the path.
21878         *
21879         * @param contextNode
21880         * @param pathParts
21881         * @returns {*}
21882         * @private
21883         * @param lastNodeValue
21884         */
21885        _createElements : function (contextNode, pathParts, lastNodeValue) {
21886            if (!(contextNode instanceof Object)) {
21887                return null;
21888            }
21889
21890            if (_.isEmpty(pathParts)) {
21891                return contextNode;
21892            }
21893
21894            // recurse and create one level of tags at a time
21895            contextNode = this._createRepeatedElements(contextNode, pathParts, lastNodeValue);
21896            return contextNode;
21897        },
21898
21899        // it will always return the parent node after checking the last token
21900        _createRepeatedElements : function (contextNode, pathParts, lastNodeValue) {
21901            var childContextNode = contextNode,
21902                xpathPart = this._getNameAndIndex(pathParts[0]),
21903                elemName = xpathPart.name,
21904                index = xpathPart.index || 0,
21905                i,
21906                isLastToken = (pathParts.length == 1),
21907                elementNode = contextNode[elemName];
21908            // -1 signifies non repeating element
21909            if (index === -1) {
21910                if (elementNode == null) {
21911                    childContextNode = this._createChildElement(contextNode, elemName, isLastToken, lastNodeValue);
21912                } else {
21913                    childContextNode = elementNode;
21914                }
21915                // if its the last token, then stop recursion here and return the created node
21916                if (isLastToken) {
21917                    return childContextNode;
21918                }
21919            } else {
21920                if (elementNode != null) {
21921                    var numOfChildren = elementNode.length;
21922                    if (numOfChildren < index + 1) {
21923                        // create immediate 'extra' children
21924                        for (i = numOfChildren; i < index + 1; ++i) {
21925                            childContextNode = {};
21926                            contextNode[elemName].push(childContextNode);
21927                        }
21928                    } else {
21929                        childContextNode = elementNode[index];
21930                    }
21931                } else {
21932                    contextNode[elemName] = [];
21933                    for (i = 0; i < index + 1; ++i) {
21934                        childContextNode = {};
21935                        contextNode[elemName].push(childContextNode);
21936                    }
21937                }
21938            }
21939            // recursively create descendants
21940            return this._createElements(childContextNode, pathParts.slice(1), lastNodeValue);
21941        },
21942
21943        _createChildElement : function (parentElement, elemName, isLastToken, nodeValue) {
21944            if (parentElement instanceof Object) {
21945                if (isLastToken) {
21946                    parentElement[elemName] = nodeValue;
21947                } else {
21948                    parentElement[elemName] = {};
21949                }
21950                return parentElement[elemName];
21951            }
21952        },
21953
21954        isIndexedPath : function (xpath) {
21955            return (xpath || "").match(this.constants.INDEXED_XPATH_PAT_JSON) !== null;
21956        },
21957
21958        /**
21959         * This function sets the value of the field in the live data document.
21960         * @param xpath
21961         * @param xmlSection
21962         * @private
21963         * @param createMissingNodes
21964         * @param value
21965         */
21966        setDataValue : function (xpath, xmlSection, createMissingNodes, value) {
21967            var lastSlash = xpath.lastIndexOf("/"),
21968                parentPath = xpath.substring(0, lastSlash),
21969                name = xpath.substring(lastSlash + 1),
21970                parent = this.getContextNode(parentPath, xmlSection, createMissingNodes, {});
21971            if (parent instanceof Object) {
21972                if (createMissingNodes || parent.hasOwnProperty(name)) {
21973                    parent[name] = value;
21974                }
21975            }
21976        },
21977
21978        /**
21979         * This function sets the value in the model from the live data document.
21980         * @param node
21981         * @param field
21982         * @private
21983         */
21984        getDataValue : function (xpath, xmlSection) {
21985            var lastSlash = xpath.lastIndexOf("/"),
21986                parentPath = xpath.substring(0, lastSlash),
21987                name = xpath.substring(lastSlash + 1),
21988                parent = this.getContextNode(parentPath, xmlSection, false);
21989            if (parent instanceof Object) {
21990                return parent[name] === undefined ? null : parent[name];
21991            }
21992            return null;
21993        },
21994
21995        getRichTextValue : function (xpath, xmlSection) {
21996            return this.getDataValue(xpath, xmlSection);
21997        },
21998
21999        addIndexToPath : function (path, index) {
22000            if (path.match(/\/\d+$/) === null) { // only add repeat index if it doesn't already end in one
22001                path += '/' + (index);
22002            } else {
22003                this.logger().debug("AF", "Tried to add index to already indexed JSON path :" + path);
22004            }
22005            return path;
22006        },
22007
22008        hasChildNodes : function (node) {
22009            return !_.isEmpty(node);
22010        },
22011
22012        removeChild : function (parentNode, targetNodeName, index) {
22013            parentNode[targetNodeName].splice(index, 1);
22014        },
22015
22016        insertNode : function (parentNode, childNodeName, index) {
22017            if (parentNode[childNodeName] == null) {
22018                parentNode[childNodeName] = [];
22019            }
22020            for (var i = 0; i < index; i++) {
22021                if (parentNode[childNodeName][i] == null) {
22022                    parentNode[childNodeName][i] = {};
22023                }
22024            }
22025            parentNode[childNodeName].splice(index, 0, {});
22026            return parentNode[childNodeName][index];
22027        },
22028
22029        getDataInstances : function (dataContext, dataNodeName) {
22030            return this.getContextNode(dataContext.indexedXpath, dataContext.xmlSec);
22031        },
22032
22033        _convertModelIndexToDataIndex : function (index) {
22034            if (index < 0) {
22035                return 0;
22036            }
22037            return index;
22038        },
22039
22040        getParentRef : function (path) {
22041            return path.replace(/\/[^\/]+(?:\/\d+)?$/, "");
22042        },
22043
22044        insertSubmissionInfo : function (submissionInfo, rootNode) {
22045            if (this._isNonNaked()) {
22046                var node = rootNode,
22047                    self = this,
22048                    finalValue, insert, keyNode;
22049                if (node == null) {
22050                    node = this._liveDataDoc.afData.afSubmissionInfo;
22051                }
22052                if (node == null && this._liveDataDoc.afData.afSubmissionInfo == null) {
22053                    node = {};
22054                    this._liveDataDoc.afData.afSubmissionInfo = node;
22055                }
22056                _.each(submissionInfo, function (value, key) {
22057                    if (value instanceof Array) {
22058                        // we only support string items in json array
22059                        finalValue = [];
22060                        insert = true;
22061                        _.each(value, function (arrItem, index) {
22062                            if (typeof arrItem === "string") {
22063                                finalValue.push(arrItem);
22064                            } else {
22065                                //ignore this. we currently do not support anything other than string
22066                            }
22067                        });
22068                        if (insert) {
22069                            node[key] = finalValue.join(',');
22070                        }
22071                    } else if (typeof (value) === "object" && value != null) {
22072                        keyNode = node[key];
22073                        if (keyNode == null) {
22074                            keyNode = {};
22075                            node[key] = keyNode;
22076                        }
22077                        self.insertSubmissionInfo(value, keyNode);
22078                    } else {
22079                        node[key] = value;
22080                    }
22081                });
22082            }
22083        }
22084
22085    });
22086
22087}($, _, window.guideBridge, window.guidelib, window.formBridge, window.xfalib));
22088
22089/**
22090 * @package guidelib.model.DataNode
22091 * @version 0.0.1
22092 */
22093
22094(function ($, _, guideBridge, guidelib, formBridge, xfalib) {
22095    var isXdp, isXsd, isNone;
22096
22097    var LiveXmlUtils = guidelib.model.LiveXmlUtils = guidelib.model.LiveDataUtils.extend({
22098
22099        initialize : function () {
22100            LiveXmlUtils._super.initialize.call(this);
22101
22102            if (_.isUndefined(document.evaluate)) {
22103                wgxpath.install();
22104            }
22105            this._liveDataDoc = null;
22106        },
22107
22108        initLiveData : function (prefillXmlStr, xfaPrefillXmlStr, isXdp, isXsd, xsdRootElement) {
22109            LiveXmlUtils._super.initLiveData.apply(this, arguments);
22110            isXdp = isXdp || false;
22111            isXsd = isXsd || false;
22112            isNone = !(isXdp || isXsd);
22113            this.xsdRootElement = xsdRootElement;
22114            // init default skeleton for no pefill cases
22115            this._liveDataDoc = $.parseXML(this.constants.SKELETON_XML);
22116            this._boundDataRoot = this._getElement(this._liveDataDoc.documentElement, this.constants.BOUND_DATA_XPATH);
22117            this._unboundDataRoot = this._getElement(this._liveDataDoc.documentElement, this.constants.UNBOUND_DATA_XPATH);
22118
22119            if (_.isString(prefillXmlStr) && prefillXmlStr.length > 0) {
22120                var prefillXmlDoc = $.parseXML(prefillXmlStr);
22121
22122                // find data root
22123                if (this._isNonNaked(prefillXmlDoc)) {
22124                    // non naked xml, assuming full hierarchy afdata/afbounddata/data
22125
22126                    var prefillBoundDataRoot,
22127                        prefillUnBoundDataRoot,
22128                        newDataNode;
22129
22130                    if (!isXdp) { //capture bound data from prefill, for both none(may contain bound form/frag) and xsd
22131                        prefillBoundDataRoot = this._getElement(prefillXmlDoc.documentElement, this.constants.BOUND_DATA_XPATH);
22132                        if (null == prefillBoundDataRoot) {
22133                            prefillBoundDataRoot = this._getElement(prefillXmlDoc.documentElement, this.constants.BOUND_TAG +
22134                                                                        "/" + guideBridge._guide.jsonModel.xsdRootElement);
22135                        }
22136                        if (prefillBoundDataRoot) {
22137                            newDataNode = this._liveDataDoc.importNode(prefillBoundDataRoot, true);
22138                            this._boundDataRoot.parentNode.replaceChild(newDataNode, this._boundDataRoot);
22139                            this._boundDataRoot = newDataNode;
22140                        }
22141                    }
22142
22143                    prefillUnBoundDataRoot = this._getElement(prefillXmlDoc.documentElement, this.constants.UNBOUND_DATA_XPATH);
22144                    if (prefillUnBoundDataRoot) {
22145                        newDataNode = this._liveDataDoc.importNode(prefillUnBoundDataRoot, true);
22146                        this._unboundDataRoot.parentNode.replaceChild(newDataNode, this._unboundDataRoot);
22147                        this._unboundDataRoot = newDataNode;
22148                    }
22149
22150                } else {
22151                    // naked xml start from prefill data root
22152
22153                    if (isNone) {
22154                        this._unboundDataRoot = prefillXmlDoc.documentElement;
22155                        this._boundDataRoot = null;
22156                    } else {
22157                        if (isXsd) {
22158                            this._boundDataRoot = prefillXmlDoc.documentElement;
22159                        }
22160
22161                        var unBoundXmlDoc = $.parseXML(this.constants.UNBOUND_SKELETON);
22162                        this._unboundDataRoot = unBoundXmlDoc.documentElement;  // need this for unbound data fill across lazy
22163                    }
22164                    this._liveDataDoc = prefillXmlDoc;
22165                }
22166            }
22167
22168            if (isXdp) { // don't need the bound data sec, model is always loaded & server will fill during submission
22169                if (_.isString(xfaPrefillXmlStr) && xfaPrefillXmlStr.length > 0) {
22170                    this._xfaDataRoot = xfalib.ut.XMLUtils.getXFARootFormElementFromXML($.parseXML(xfaPrefillXmlStr));
22171                }
22172                this._boundDataRoot.parentNode.parentNode.removeChild(this._boundDataRoot.parentNode);
22173                this._boundDataRoot = null;
22174            }
22175        },
22176
22177        isLiveDataInitialized : function () {
22178            return (this.getLiveDataDoc() instanceof Node);
22179        },
22180
22181        getLiveDataStr : function () {
22182            if (this.isLiveDataInitialized()) {
22183                return (new XMLSerializer()).serializeToString(this.getLiveDataDoc());
22184            } else {
22185                return '';
22186            }
22187        },
22188
22189        _ignoreXpathRoot : function (xpathRoot) {
22190            return this.xsdRootElement === this.cons
22190tants.UNKNOWN_XSD_ROOT_ELEMENT
22191                || this.xsdRootElement === xpathRoot;
22192        },
22193
22194        /**
22195         * will return the apt node, in the AF xml, based on the xml context passed in.
22196         * Will create nodes if it doesn't exist and createMissingNodes is passed as true
22197         * @param schemaPath
22198         * @param dataSection
22199         * @param createMissingNodes
22200         * @returns {*}
22201         * @memberof LiveXmlUtils
22202         */
22203        getContextNode : function (schemaPath, dataSection, createMissingNodes) {
22204            var contextNode,
22205                baseContextNode,
22206                xpathParts = this._sanitizedXpathParts(schemaPath);
22207            if (dataSection === this.constants.BOUND_TAG) {
22208                baseContextNode = this._boundDataRoot;
22209            } else if (dataSection === this.constants.UNBOUND_TAG) {
22210                baseContextNode = this._unboundDataRoot;
22211            } else if (dataSection === this.constants.XFA_TAG) {
22212                baseContextNode = this._xfaDataRoot;
22213            }
22214            if (!_.isEmpty(xpathParts)) {
22215                if (dataSection === this.constants.BOUND_TAG) {
22216                    if (this._ignoreXpathRoot(xpathParts[0])) {
22217                        xpathParts = xpathParts.slice(1);   // discard xsd schema root
22218                        if (xpathParts.length === 0) {
22219                            return baseContextNode;
22220                        }
22221                    }
22222                }
22223
22224                contextNode = this._getElement(baseContextNode, xpathParts.join('/'));
22225
22226                if (!contextNode && createMissingNodes) {
22227                    contextNode = this._createElements(baseContextNode, xpathParts);
22228                }
22229            } else if (_.isEmpty(schemaPath)) {
22230                contextNode = baseContextNode;
22231            }
22232            return contextNode;
22233        },
22234
22235        addIndexToPath : function (path, index) {
22236            if (path.match(/\[\d+\]$/) === null) { // only add repeat index if it doesn't already end in one
22237                path += '[' + (index + 1) + ']'; // indices in xpath 1 based}
22238            } else {
22239                this.logger().debug("AF", "Tried to add index to already indexed xpath :" + path);
22240            }
22241            return path;
22242        },
22243
22244        getDataInstances : function (dataContext, dataNodeName) {
22245            var node = this.getContextNode(dataContext.indexedXpath, dataContext.xmlSec);
22246            if (node != null) {
22247                return _.filter(node.parentNode.childNodes, function (child) {
22248                    return (child instanceof Element) && child.nodeName === dataNodeName;
22249                }, this);
22250            }
22251            return null;
22252        },
22253
22254        _findLastDataNode : function (parentContextNode, dataNodeName) {
22255            var xmlUtils = xfalib.ut.XMLUtils,
22256                iterator = xmlUtils.evaluateXPath(dataNodeName, parentContextNode, null, null, null),
22257                result = xmlUtils.iteratorToArray(iterator);
22258            if (result.length > 0) {
22259                return result[result.length - 1];
22260            }
22261            return null;
22262        },
22263
22264        hasChildNodes : function (node) {
22265            return node.hasChildNodes();
22266        },
22267
22268        removeChild : function (parentNode, targetNodeName, index) {
22269            var childNode = this._getElement(parentNode, targetNodeName + "[" + (index + 1) + "]", null);
22270            if (childNode) {
22271                parentNode.removeChild(childNode);
22272            }
22273        },
22274
22275        insertNode : function (parentNode, childNodeName, index) {
22276            var childNode = this._getElement(parentNode, childNodeName + "[" + (index + 1) + "]", null),
22277                node = parentNode.ownerDocument.createElement(childNodeName);
22278            if (childNode) {
22279                parentNode.insertBefore(node, childNode);
22280            } else {
22281                var lastNode = this._findLastDataNode(parentNode, childNodeName);
22282                if (lastNode && lastNode.nextSibling) {
22283                    parentNode.insertBefore(node, lastNode.nextSibling);
22284                } else if (lastNode && !lastNode.nextSibling) {
22285                    // for the case when the last node is there but there is no next sibling.
22286                    // we don't need to create all the nodes for this scenario.
22287                    parentNode.appendChild(node);
22288                } else {
22289                    // we need to create all the nodes till the count reaches the index.
22290                    for (var i = 0; i <= index; i++) {
22291                        var newNode = parentNode.ownerDocument.createElement(childNodeName);
22292                        parentNode.appendChild(newNode);
22293                    }
22294                }
22295            }
22296            return node;
22297        },
22298
22299        /**
22300         * Form an xpath part returns the index as well as the tagName.
22301         * Index returned is 0 if not present
22302         * @param xpathName
22303         * @returns {*}
22304         * @private
22305         * @memberof LiveXmlUtils
22306         */
22307        _getNameAndIndex : function (xpathPart) {
22308            if (xpathPart) {
22309                var elName = xpathPart.match(/^([^[\s\/]+)(?:\[(\d+)\])?$/);  // match the whole string
22310                if (elName !== null) {
22311                    return {
22312                        name : elName[1],
22313                        index : elName[2] ? parseInt(elName[2]) : 0
22314                    };
22315                }
22316            }
22317            return null;
22318        },
22319
22320        _cmpXpathParts : function (indexedName, templateName) {
22321            if (indexedName && templateName) {
22322                var match1 = this._getNameAndIndex(indexedName),
22323                    match2 = this._getNameAndIndex(templateName);
22324                return !_.isEmpty(match1 && match2)
22325                    && match1.name === match2.name
22326                    && (match2.index === 0 || match1.index === match2.index);
22327            }
22328            return false;
22329        },
22330
22331        /**
22332         * Will split an xpath string into an array containing one xml element/node per part
22333         * This expects only the simple xpath syntax allowed in bindRefs of xsd bound fields
22334         * of the form /a/b/c/@d
22335         * @param xpath
22336         * @returns {*|Array.<T>|list}
22337         * @private
22338         * @memberof LiveXmlUtils
22339         */
22340        _sanitizedXpathParts : function (xpath) {
22341            var xpathParts = (xpath || '').replace(/^\//, '').replace(/\s+/g, '').split('/');
22342
22343            if (_.last(xpathParts) === "text()") { // ignore "/text()" appended to bindRef for SimpleType schema element
22344                xpathParts.splice(-1, 1); // drop last element
22345            }
22346
22347            return _.filter(xpathParts, function (xpathPart) {
22348                return this._getNameAndIndex(xpathPart) !== null;
22349            }, this);
22350        },
22351
22352        /**
22353         * returns true if the xpath uses indices
22354         * @param xpath
22355         * @returns {boolean}
22356         * @memberof LiveXmlUtils
22357         */
22358        isIndexedPath : function (xpath) {
22359            return (xpath || "").match(this.constants.INDEXED_XPATH_PAT) !== null;
22360        },
22361
22362        _createElements : function (contextNode, xpathParts) {
22363            if (!(contextNode instanceof Node)) {
22364                return null;
22365            }
22366
22367            if (_.isEmpty(xpathParts)) {
22368                return contextNode;
22369            }
22370
22371            if (xpathParts[0][0] === '@') { // xpath parts having '@' as 1st char must be and attr
22372                var attrName = xpathParts[0].slice(1);
22373                // in bindrefs attributes are the last xpath part, so no need to recurse
22374                contextNode = this._createAttributeNode(contextNode, attrName);
22375            } else {
22376                // recurse and create one level of tags at a time
22377                contextNode = this._createRepeatedElements(contextNode, xpathParts);
22378            }
22379
22380            return contextNode;
22381        },
22382
22383        /**
22384         * This will update the xml with the required tags,
22385         * and return the context node matching the xpath query.
22386         * Further if xml has lesser number of tags than the index in each part,
22387         * it'll fill those gaps with empty tags.
22388         * @param contextNode node beneath which tags are to be created
22389         * @param xpathParts
22390         * @returns {*}
22391         * @private
22392         * @memberof LiveXmlUtils
22393         */
22394        _createRepeatedElements : function (contextNode, xpathParts) {
22395            var childContextNode = contextNode,
22396                xpathPart = this._getNameAndIndex(xpathParts[0]),
22397                elemName = xpathPart.name,
22398                index = xpathPart.index || 1,
22399                i,
22400                children = _.filter(contextNode.childNodes, function (child) {
22401                    return (child instanceof Element) && child.nodeName === elemName;
22402                });
22403
22404            if (children.length < index) {
22405                // create immediate 'extra' children
22406                for (i = children.length; i < index; ++i) {
22407                    childContextNode = this._createChildElement(contextNode, elemName);
22408                }
22409            } else {
22410                childContextNode = children[index - 1]; // indices are 1 based in xml
22411            }
22412            // recursively create descendants
22413            return this._createElements(childContextNode, xpathParts.slice(1));
22414        },
22415
22416        _createChildElement : function (parentElement, elemName) {
22417            if (parentElement instanceof Element) {
22418                var childElem = parentElement.ownerDocument.createElement(elemName);
22419                parentElement.appendChild(childElem);
22420                return childElem;
22421            }
22422        },
22423
22424        _createAttributeNode : function (parentElement, attrName) {
22425            if (parentElement instanceof Element) {
22426                var attrNode = parentElement.ownerDocument.createAttribute(attrName);
22427                parentElement.setAttributeNode(attrNode);
22428                return attrNode;
22429            }
22430        },
22431
22432        /**
22433         * finds xml node/element based on current context node and xpath
22434         * @param node
22435         * @param xpath
22436         * @param options
22437         * @returns {*}
22438         * @private
22439         * @memberof LiveXmlUtils
22440         */
22441        _getElement : function (node, xpath, options) {
22442            if (!(node instanceof Node)) {
22443                return null;
22444            }
22445
22446            if (_.isEmpty(xpath) || !_.isString(xpath)) {
22447                return node;
22448            }
22449            options = options || {};
22450            var nsResolver = options.nsResolver;
22451            var index = options.index;
22452            // in IE singleNodeValue maybe null for attribute queries,
22453            // so find parent element of attribute, and then explicitly check for attribute node's presence
22454
22455            var xpathParts = xpath.split('/@'),
22456                checkAttr = false,
22457                attributeName;
22458
22459            if (xpathParts.length > 2) { // more than 1 attr unsupported
22460                xfalib.ut.XfaUtil.prototype.getLogger().error("BindRefs must be Xpaths ending in atmost one attribute"); // TODO localize
22461                return null;
22462            } else if (xpathParts.length === 2) {
22463                xpath = xpathParts[0]; // find parent el and seek attribute there
22464                attributeName = xpathParts[1]; // attr can only be in the last part
22465                checkAttr = true;
22466            }
22467            if (!(_.isUndefined(index) || _.isNull(index))) {
22468                xpath = xpath + "[" + index + "]";
22469            }
22470            if (!window.XPathResult) {
22471                document.evaluate = undefined;
22472                wgxpath.install(window, true);
22473            }
22474            var result = xfalib.ut.XMLUtils.evaluateXPath(xpath, node, nsResolver, XPathResult.FIRST_ORDERED_NODE_TYPE, null),
22475                el;
22476
22477            if (result && result.resultType === XPathResult.FIRST_ORDERED_NODE_TYPE) {
22478                el = result.singleNodeValue;
22479                if (el instanceof Node) {
22480                    if (!checkAttr) {
22481                        return el;
22482                    } else if (el.hasAttribute(attributeName)) {
22483                        el = el.getAttributeNode(attributeName);
22484                        if (el instanceof Node) {
22485                            return el;
22486                        }
22487                    }
22488                }
22489            }
22490        },
22491
22492        /**
22493         * This function checks if the document was naked or non naked xml
22494         * @param doc
22495         * @returns {boolean} returns true if there exists a afData node inside data false otherwise
22496         * @private
22497         * @memberof LiveXmlUtils
22498         */
22499        _isNonNaked : function (doc) {
22500            doc = doc || this.getLiveDataDoc();
22501            if (doc) {
22502                return doc.documentElement.tagName === this.constants.AF_ROOT_TAG;
22503            } else {
22504                return false;
22505            }
22506        },
22507
22508        /**
22509         * Returns list of panels touched by the end user before saving the draft
22510         * @param dataString
22511         */
22512        getListOfDirtyPanels : function (dataString) {
22513            if (dataString == null || dataString === "") {
22514                return [];
22515            }
22516            var livePrefillXmlDoc = $.parseXML(dataString),
22517                draftDoc = this._getElement(livePrefillXmlDoc.documentElement, this.constants.AF_DRAFT_TAG);
22518            if (_.isUndefined(draftDoc) || draftDoc.childNodes.length === 0) {
22519                return [];
22520            }
22521            var draftStr = draftDoc.firstChild.textContent.replace(/\"/g, ""),
22522                retVal = [];
22523            // not using filter here explicitly, due to ES4 syntax
22524            if (draftStr) {
22525                retVal = draftStr.split(",");
22526            }
22527            return retVal;
22528        },
22529
22530        /**
22531         * This function sets the rich text value of the field in the live data.
22532         * @param xpath
22533         * @param xmlSection
22534         * @param createMissingNodes
22535         * @param value
22536         * @private
22537         */
22538        setRichTextValue : function (xpath, xmlSection, createMissingNodes, value) {
22539            var node = this.getContextNode(xpath, xmlSection, createMissingNodes);
22540            if (node instanceof Node) {
22541                var richTextNode = $.parseXML(value);
22542                // clear the text content before appending child
22543                node.textContent = "";
22544                node.appendChild(richTextNode.documentElement);
22545            }
22546        },
22547
22548        setDataValue : function (xpath, xmlSection, createMissingNodes, value) {
22549            var node = this.getContextNode(xpath, xmlSection, createMissingNodes);
22550            if (node instanceof Node) {
22551                node.textContent = value;
22552            }
22553        },
22554
22555        getDataValue : function (xpath, xmlSection) {
22556            var node = this.getContextNode(xpath, xmlSection, false);
22557            if (node instanceof Node) {
22558                return node.textContent || null;
22559            }
22560            return undefined;
22561        },
22562
22563        getRichTextValue : function (xpath, xmlSection) {
22564            var node = this.getContextNode(xpath, xmlSection, false);
22565            if (node instanceof Node) {
22566                return node.innerHTML.trim();
22567            }
22568            return undefined;
22569        },
22570
22571        _convertModelIndexToDataIndex : function (index) {
22572            if (index < 0) {
22573                return 1;
22574            }
22575            return index + 1;
22576        },
22577
22578        getParentRef : function (path) {
22579            return path.substring(0, path.lastIndexOf("/"));
22580        },
22581
22582        insertSubmissionInfo : function (submissionInfo, rootNode) {
22583            if (this._isNonNaked()) {
22584                var xmlutils = xfalib.ut.XMLUtils,
22585                    node = rootNode === undefined
22586                        ? xmlutils.findOrCreateElement("afSubmissionInfo", this._liveDataDoc.documentElement)
22587                        : rootNode,
22588                    self = this;
22589                _.each(submissionInfo, function (value, key) {
22590                    var keyNode;
22591                    if (value instanceof Array) {
22592                        // we only support string items in json array
22593                        var finalValue = [], insert = true;
22594                        _.each(value, function (arrItem, index) {
22595                            if (typeof arrItem === "string") {
22596                                finalValue.push(arrItem);
22597                            } else if (arrItem instanceof Object && arrItem != null) {
22598                                insert = false;
22599                                var el = node.ownerDocument.createElement(key);
22600                                node.appendChild(el);
22601                                self.insertSubmissionInfo(arrItem, el);
22602                            }
22603                        });
22604                        if (insert) {
22605                            keyNode = xmlutils.findOrCreateElement(key, node);
22606                            keyNode.textContent = finalValue.join(',');
22607                            node.appendChild(keyNode);
22608                        }
22609                    } else if (typeof (value) === "object" && value != null) {
22610                        keyNode = xmlutils.findOrCreateElement(key, node);
22611                        self.insertSubmissionInfo(value, keyNode);
22612                        if (keyNode) {
22613                            node.appendChild(keyNode);
22614                        }
22615                    } else {
22616                        keyNode = xmlutils.findOrCreateElement(key, node);
22617                        if (keyNode) {
22618                            keyNode.textContent = value;
22619                            node.appendChild(keyNode);
22620                        }
22621                    }
22622                });
22623            }
22624        }
22625    });
22626
22627}($, _, window.guideBridge, window.guidelib, window.formBridge, window.xfalib));
22628
22629/*
22630 * ***********************************************************************
22631 * ADOBE CONFIDENTIAL
22632 * __________________
22633 *
22634 * Copyright 2015 Adobe Systems Incorporated
22635 * All Rights Reserved.
22636 *
22637 * NOTICE:  All information contained herein is, and remains
22638 * the property of Adobe Systems Incorporated and its suppliers,
22639 * if any.  The intellectual and technical concepts contained
22640 * herein are proprietary to Adobe Systems Incorporated and its
22641 * suppliers and may be covered by U.S. and Foreign Patents,
22642 * patents in process, and are protected by trade secret or copyright law.
22643 * Dissemination of this information or reproduction of this material
22644 * is strictly forbidden unless prior written permission is obtained
22645 * from Adobe Systems Incorporated.
22646 * ***********************************************************************
22647 */
22648
22649/**
22650 * @package guidelib.model.LiveModel
22651 * @version 0.0.1
22652 */
22653
22654(function ($, _, guideBridge, guidelib) {
22655    var LiveModel = guidelib.model.LiveModel = xfalib.ut.Class.extend({
22656        initialize : function () {
22657            LiveModel._super.initialize.call(this);
22658            this._crossFragmentFields = {}; // 2 level map: name => { bindRef => abstract model }
22659            this._dataNodes = {};
22660        },
22661
22662        // only called from test framework
22663        destroy : function () {
22664            this._crossFragmentFields = {};
22665            this._dataNodes = {};
22666        },
22667
22668        getCrossFragmentFields : function () {
22669            return this._crossFragmentFields;
22670        },
22671
22672        add : function (key, model) {
22673            if (key) {
22674                var dn = this._dataNodes[key] || new guidelib.model.DataNode();
22675                dn.addField(model);
22676                this._dataNodes[key] = dn;
22677            }
22678        },
22679
22680        isLive : function (key) {
22681            return _.isString(key) && _.has(this._dataNodes, key);
22682        },
22683
22684        remove : function (key, model) {
22685            if (this.isLive(key)) {
22686                var dn = this._dataNodes[key];
22687                dn.removeField(model);
22688            }
22689        },
22690
22691        getAllFieldModels : function (keys) {
22692            return _.flatten(_.map(keys, function (key) {
22693                var result,
22694                    dataNode = this._dataNodes[key];
22695                if (dataNode) {
22696                    result = dataNode.getFieldModels();
22697                }
22698                return result;
22699            }, this));
22700        },
22701
22702        getAllAbstractFieldModels : function (keys) {
22703            return _.flatten(_.map(keys, function (key) {
22704                return this._dataNodes[key].getAbstractFieldModels();
22705            }, this));
22706        },
22707
22708        resetData : function () {
22709            // all loaded models in data nodes dataNodes will be reset by the respective fields
22710            // just need to reset the abstract cross frag fields
22711            _.each(this._crossFragmentFields, function (fields) {
22712                _.each(fields, function (abstractField) {
22713                    abstractField.resetData();
22714                });
22715            });
22716        },
22717
22718        createDataNodes : function (duplicateBindRefs) {
22719            _.each(duplicateBindRefs, function (bindRef) {
22720                this.add(bindRef);
22721            }, this);
22722        },
22723
22724        createCrossFragFields : function (crossFragFields, guide) {
22725            _.each(crossFragFields, function (field) {
22726                var effectiveBindRef = field.bindRef || field.name,
22727                    value = field._value || null,// default value, keep null because js is quirky with operations on undefined
22728                    absModel = new guidelib.model.AbstractField({
22729                        'name' : field.name,
22730                        'className' : field.guideNodeClass,
22731                        'bindRef' : field.bindRef,
22732                        'dataSom' : field.dataSom,
22733                        'afDataSom' : field.afDataSom,
22734                        'jsonModel' : {
22735                            '_value' : value,
22736                            "{default}" : value
22737                        },
22738                        '_guideContainer' : guide
22739                    });
22740
22741                if (_.isEmpty(this._crossFragmentFields[field.name])) {
22742                    this._crossFragmentFields[field.name] = {};
22743                }
22744                this._crossFragmentFields[field.name][effectiveBindRef] = absMo
22744del;
22745
22746                this.add(effectiveBindRef, absModel); // unbound globals with same name linked together
22747
22748            }, this);
22749        },
22750
22751        prefillCrossFragFields : function (guide) {
22752            var dataUtils = guide.internal.liveDataUtils;
22753            if (dataUtils.isLiveDataInitialized()) {
22754                _.each(this._crossFragmentFields, function (fields, name) {
22755                    _.each(fields, function (absModel, bindRef) {
22756                        var dataContext = dataUtils._getDataContext(absModel, '', '');
22757                        // fill value from prefill data or saved lazy live data
22758                        absModel.value = dataUtils.getDataValue(dataContext.indexedXpath, dataContext.xmlSec);
22759                    }, this);
22760                }, this);
22761            }
22762        }
22763    });
22764}($, _, window.guideBridge, window.guidelib));
22765
22766/**
22767 * @package guidelib.model.FormData
22768 * @version 0.0.1
22769 */
22770
22771(function ($, _, guidelib) {
22772
22773    /**
22774     * JavaScript class to represent form data
22775     * @class FormData
22776     * @since Forms As A Cloud service (FaaCS)
22777     */
22778    var AfFormData = guidelib.model.FormData = xfalib.ut.Class.extend({
22779
22780        initialize : function () {
22781            AfFormData._super.initialize.call(this);
22782        },
22783
22784        toJsObject : function() {
22785            return {
22786                "data" : this.data,
22787                "contentType" : this.contentType,
22788                "attachments" : this.attachments
22789            }
22790        },
22791
22792        /**
22793         * This returns the html form data representation of adaptive form data. This could be used to submit the adaptive form data to
22794         * external end point from the client. The HTML form data contains the following the key / value pairs:
22795         * 1. data -> contains form data represented as string
22796         * 2. contentType -> contains content type of form data (it would be application/xml or application/json)
22797         * 2. fileAttachments -> list of blobs containing the file (in case of fileUrl's the type of blob would be application/json)
22798         * 3. fileAttachmentBindRefs -> list of string containing file bindRef's, this has one to one mapping with fileAttachments
22799         * @returns {*}
22800         */
22801        toHTMLFormData : function() {
22802            // using native formData class
22803            var formData = new FormData();
22804            // appending data of adaptive form in data key
22805            // data could be JSON or XML
22806            if (this.contentType) {
22807                formData.append("contentType", this.contentType);
22808            }
22809            formData.append("data", this.data);
22810            for (var index = 0; index < this.attachments.length; index++) {
22811                var fileAttachmentWrapper = this.attachments[index];
22812                // 2nd parameter should be of blob type, hence adding an explicit check here
22813                // we could have created dataURL for all the files in the client, but this would cause the browser
22814                // to slow down since it would serialize the binary, hence following the below approach
22815                if (fileAttachmentWrapper.isFile()) {
22816                    formData.append("fileAttachments", fileAttachmentWrapper.data, fileAttachmentWrapper.name);
22817                } else {
22818                    // blob is supported on all major browsers
22819                    var urlBlob = new Blob([
22820                        JSON.stringify({
22821                            "data" : fileAttachmentWrapper.data,
22822                            "name" : fileAttachmentWrapper.name,
22823                            "contentType" : fileAttachmentWrapper.contentType
22824                        })
22825                    ], { type: 'application/json' });
22826                    formData.append("fileAttachments", urlBlob);
22827                }
22828                formData.append("fileAttachmentBindRefs", fileAttachmentWrapper.bindRef);
22829            }
22830            return formData;
22831        }
22832    });
22833
22834    AfFormData.defineProps({
22835        /**
22836         * Actual form data (could be JSON or xml)
22837         */
22838        data : {
22839            get : function () {
22840                return this.options.data;
22841            }
22842        },
22843
22844        /**
22845         * List of {FileAttachmentWrapper} {@link FileAttachmentWrapper}
22846         */
22847        attachments : {
22848            get : function () {
22849                return this.options.attachments;
22850            }
22851        },
22852
22853        /**
22854         * Content type of form data (it could be application/xml or application/json)
22855         */
22856        contentType : {
22857            get : function () {
22858                return this.options.contentType;
22859            }
22860        }
22861    });
22862
22863
22864}($, _, window.guidelib));
22865
22866/**
22867 * @package guidelib.model.FileAttachmentWrapper
22868 * @version 0.0.1
22869 */
22870
22871(function ($, _, guidelib) {
22872
22873    /**
22874     * JavaScript class to represent the each file data present in the form.
22875     * Data could be URI (URI could be a file URL or dataURL)
22876     * @class FileAttachmentWrapper
22877     * @since Forms As A Cloud service (FaaCS)
22878     */
22879    var FileAttachmentWrapper = guidelib.model.FileAttachmentWrapper = xfalib.ut.Class.extend({
22880
22881        initialize : function () {
22882            FileAttachmentWrapper._super.initialize.call(this);
22883        },
22884
22885        /**
22886         * Converts file attachment wrapper to a javascript object
22887         * @returns {{name: *, contentType: *, bindRef: *, data: *}}
22888         */
22889        toJsObject : function () {
22890            return {
22891                name : this.name,
22892                contentType : this.contentType,
22893                bindRef : this.bindRef,
22894                data : this.data
22895            }
22896        },
22897
22898        /**
22899         * Checks if the file data is native JS File object
22900         * @returns {boolean}
22901         */
22902        isFile : function() {
22903            return this.data instanceof File;
22904        },
22905
22906
22907        /**
22908         * Returns blob for the data URL present in data
22909         * @returns {*}
22910         */
22911        dataURLtoBlob : function() {
22912            var dataurl = this.data, // data should be a data url
22913                arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
22914                bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
22915            while(n--){
22916                u8arr[n] = bstr.charCodeAt(n);
22917            }
22918            return new Blob([u8arr], {type: mime});
22919        }
22920    });
22921
22922    FileAttachmentWrapper.defineProps({
22923        /**
22924         * Actual name of the file associated with data
22925         */
22926        name : {
22927            get : function () {
22928                return this.options.name;
22929            }
22930        },
22931
22932        /**
22933         * Content type of file
22934         */
22935        contentType : {
22936            get : function () {
22937                return this.options.contentType;
22938            }
22939        },
22940
22941        /**
22942         * This would be effective bindRef meaning bindRef in case of data model or component name in case of unbound data
22943         */
22944        bindRef : {
22945            get : function () {
22946                return this.options.bindRef;
22947            }
22948        },
22949
22950        /**
22951         * This would represent the name of the form element to which the file binary is associated.
22952         * In case of unbound form, bindRef and component name would be the same
22953         */
22954        formElementName : {
22955            get : function () {
22956                return this.options.formElementName || this.options.bindRef;
22957            }
22958        },
22959
22960        /**
22961         * Data could be URI (URI could be file URL or dataURL) or native JavaScript File object
22962         */
22963        data : {
22964            get : function () {
22965                return this.options.data;
22966            }
22967        }
22968    });
22969
22970
22971}($, _, window.guidelib));
22972
22973/*************************************************************************
22974 *
22975 * ADOBE CONFIDENTIAL
22976 * __________________
22977 *
22978 *  Copyright 2014 Adobe Systems Incorporated
22979 *  All Rights Reserved.
22980 *
22981 * NOTICE:  All information contained herein is, and remains
22982 * the property of Adobe Systems Incorporated and its suppliers,
22983 * if any.  The intellectual and technical concepts contained
22984 * herein are proprietary to Adobe Systems Incorporated and its
22985 * suppliers and may be covered by U.S. and Foreign Patents,
22986 * patents in process, and are protected by trade secret or copyright law.
22987 * Dissemination of this information or reproduction of this material
22988 * is strictly forbidden unless prior written permission is obtained
22989 * from Adobe Systems Incorporated.
22990 **************************************************************************/
22991
22992
22993(function (_, $) {
22994    "use strict";
22995
22996    
22997    var isBrowserIE = xfalib.ut.XfaUtil.prototype.detectIE();
22998
22999    var _defaults = {
23000        'showLink' : false,
23001        'scrollMode' : 'vertical',
23002        textAreaClass : ".guide-tnc-content",
23003        checkBoxClass : ".guide-tnc-checkbox",
23004        checkBoxDisableClass : ".guide-tnc-checkbox-disabled",
23005        checkBoxReviewedClass : ".guide-tnc-checkbox-reviewed",
23006        linkClass     : ".guide-tnc-link",
23007        documentVisitedClass : ".guide-tnc-document-visited",
23008        documentUnVisitedClass : ".guide-tnc-document-unvisited"
23009    };
23010
23011    var _reviewStatusMap = {
23012        REVIEWED : "reviewed",
23013        UNREVIEWD : "unreviewed",
23014        AGREE : "agree"
23015    };
23016
23017    var AfTnc = function (element, options) {
23018        this.options = options;
23019        this.$element = $(element);
23020
23021        
23022        this.enters = this.leaves = 0;
23023        this.inside = false;
23024
23025        
23026        this.reviewdoc = this.status = _reviewStatusMap.UNREVIEWD;
23027
23028        
23029        this.$elementCheckBox = this.$element.find(this.options.checkBoxClass || _defaults.checkBoxClass);
23030        
23031        this.$elementTextArea = $(this.textArea());
23032        
23033        this.$elementLink =  $(this.link());
23034
23035        this.isTextContentVisible = false;
23036
23037        if (this.options.showLink) {
23038            
23039            this.$elementLink.find('a').click($.proxy(this.handleReviewStatusChange, this));
23040        } else {
23041            var setCheckBoxState = function () {
23042                if (this.hasScrollBar(this.$elementTextArea.parent().get(0))) {
23043                    
23044                    
23045                    this.$elementTextArea.parent().scroll($.proxy(this.handleReviewStatusChange, this));
23046                } else {
23047                    
23048                    if (this.$elementTextArea.css('display') !== 'none') {
23049                        this.status = _reviewStatusMap.REVIEWED;
23050                        this.isTextContentVisible = true;
23051                        
23052                        if (!this.options.showAsPopUp) {
23053                            this.enableCheckBox();
23054                        }
23055                        this.reviewDoc = this.$elementTextArea.text();
23056                    }
23057                }
23058            };
23059            
23060            
23061            if (document.readyState === "complete") { 
23062                setCheckBoxState.call(this);          
23063            } else {
23064                
23065                
23066                $($.proxy(setCheckBoxState, this));
23067            }
23068        }
23069
23070        
23071        if (this.options.showAsPopUp) {
23072            var unvisitedClass = this.options.documentUnVisitedClass || _defaults.documentUnVisitedClass,
23073                visitedClass = this.options.documentVisitedClass || _defaults.documentVisitedClass;
23074            var _self = this,
23075                dialogId = this.$elementCheckBox.find('a')
23076                .keydown(function (e) {
23077                    if (e.keyCode === 13 || e.which == 13 || e.charCode === 32) {
23078                        $(this).click();
23079                        return false;
23080                    }
23081                })
23082                .click(function (event) {
23083                    if ($(this).hasClass(unvisitedClass.substring(1))) {
23084                        $(this).toggleClass(visitedClass.substring(1) + " " + unvisitedClass.substring(1));
23085                    }
23086                    
23087                    
23088                    if (isBrowserIE || _self.isTextContentVisible) {
23089                        _self.enableCheckBox();
23090                    }
23091                }).attr("href");
23092            
23093            $(dialogId).on('hidden.bs.modal', function (e) {
23094                _self.$elementCheckBox.find('input').focus();
23095            });
23096        } else {
23097            
23098            this._updateScreenReaderText();
23099        }
23100
23101        
23102        this.$elementCheckBox.find('input').change($.proxy(this.handleCheckBoxChange, this));
23103    };
23104
23105    AfTnc.prototype = {
23106
23107        clear : function () {
23108            this.$element.val('');
23109        },
23110
23111        destroy : function () {
23112            this.$element.val('');
23113            this.$element.empty();
23114        },
23115
23116        _updateScreenReaderText : function () {
23117            if (!this.options.showAsPopUp) {
23118                var _self = this;
23119                
23120                this.$element.find(".guide-tnc-sr-only").each(function (i, obj) {
23121                    $(this).html(_self.options.screenReaderText);
23122                });
23123            }
23124        },
23125
23126        _restoreClickState : function (value) {
23127            if (this.options.showLink) {
23128                var arr = value.split("\n"),
23129                    linkState = [];
23130                
23131                _.each(arr, function (linkText, index) {
23132                    
23133                    linkState.push(_.last(linkText.split('=')));
23134                });
23135                var unvisitedClass = this.options.documentUnVisitedClass || _defaults.documentUnVisitedClass,
23136                    visitedClass = this.options.documentVisitedClass || _defaults.documentVisitedClass;
23137                this.$elementLink.find('a').each(function (index) {
23138                    $(this).data("clicked", linkState[index]);
23139                    if (linkState[index] === "1") {
23140                        $(this).addClass(visitedClass.substring(1));
23141                    } else {
23142                        $(this).addClass(unvisitedClass.substring(1));
23143                    }
23144                });
23145            }
23146        },
23147
23148        value : function (value) {
23149            if (value) {
23150                
23151                if (this.options.showLink) {
23152                    this._restoreClickState(value);
23153                }
23154                this.reviewDoc = value;
23155            } else {
23156                return this.reviewDoc;
23157            }
23158
23159        },
23160
23161        reviewStatus : function (value) {
23162            var val = this.getClickState();
23163            if (!_.isUndefined(value)) {
23164                if (value == "true") {
23165                    this.enableCheckBox();
23166                    this.$elementCheckBox.find('input').attr("checked", "checked");
23167                    this.$elementCheckBox.find('input').prop("checked", true);
23168                } else if (value == null || value == "false") {
23169                    
23170                    this.$elementCheckBox.find('input').removeAttr("checked");
23171                    this.$elementCheckBox.find('input').removeProp("checked");
23172                }
23173                this.approvalStatus = value;
23174            } else {
23175                if (this.status == _reviewStatusMap.REVIEWED || this.status == _reviewStatusMap.UNREVIEWD) {
23176                    return null;
23177                } else if (this.status == _reviewStatusMap.AGREE) {
23178                    return true;
23179                }
23180            }
23181        },
23182
23183        clickStatus : function (value) {
23184            if (value) {
23185                if (value === _reviewStatusMap.REVIEWED) {
23186                    var arr = this.getClickState();
23187                    if (_.isArray(arr) && arr.length > 0) {
23188                        arr = arr.join("\n");
23189                        this._restoreClickState(arr);
23190                    }
23191                    this.enableCheckBox();
23192                }
23193                this.status = value;
23194            } else {
23195                return this.status;
23196            }
23197        },
23198
23199        showLink : function (value) {
23200            if (value !== undefined) {
23201                this.options.showLink = value;
23202            } else {
23203                return this.options.showLink;
23204            }
23205        },
23206
23207        access : function (value) {
23208            this.accessOption = value;
23209            if (value == "readOnly") {
23210                this.disableCheckBox();
23211                if (this.options.showLink) {
23212                    this.$elementLink.find('a').each(function (index, elem) {
23213                        $(elem).css('pointer-events', 'none');
23214                        
23215                        $(elem).attr('disabled', 'disabled');
23216                    });
23217                }
23218            } else if (value == "open") {
23219                
23220                
23221                if ((this.status == _reviewStatusMap.REVIEWED || this.status == _reviewStatusMap.AGREE) && !this.options.showAsPopUp) {
23222                    this.enableCheckBox();
23223                }
23224                if (this.options.showLink) {
23225                    this.$element.find('a').each(function (index, elem) {
23226                        $(elem).css('pointer-events', '');
23227                        $(elem).removeAttr('disabled');
23228                    });
23229                }
23230            }
23231        },
23232
23233        link : function () {
23234            return this.$element.find(this.options.linkClass || _defaults.linkClass);
23235        },
23236
23237        textArea : function () {
23238            return this.$element.find(this.options.textAreaClass || _defaults.textAreaClass);
23239        },
23240
23241        getClickState : function () {
23242            if (this.options.showLink) {
23243                var arr = [];
23244                this.$elementLink.find('a').each(function (index) {
23245                    arr.push({
23246                        'displayText' : $(this).text(),
23247                        'linkText' : $(this).attr('href'),
23248                        'clicked' : $(this).data("clicked")
23249                    });
23250                });
23251                return arr;
23252            }
23253        },
23254
23255        enableCheckBox : function () {
23256            if (this.accessOption !== "readOnly") {
23257                this.$elementCheckBox.find('input').removeAttr("disabled");
23258                this.$elementCheckBox.removeClass(this.options.checkBoxDisableClass.substring(1));
23259            }
23260        },
23261
23262        disableCheckBox : function () {
23263            this.$elementCheckBox.find('input').attr('disabled', 'disabled');
23264            this.$elementCheckBox.addClass(this.options.checkBoxDisableClass.substring(1));
23265        },
23266
23267        handleReviewStatusChange : function (event) {
23268            var arr = [],
23269                visitedClass = this.options.documentVisitedClass || _defaults.documentVisitedClass;
23270            if (this.options.showLink) {
23271                this.status = _reviewStatusMap.REVIEWED;
23272                
23273                $(event.target).data("clicked", 1);
23274                $(event.target).addClass(visitedClass.substring(1));
23275                this.linkStateMap = this.getClickState();
23276                _.each(this.linkStateMap, function (element, index) {
23277                    if (!element.clicked) {
23278                        this.status = _reviewStatusMap.UNREVIEWD;
23279                    }
23280                    
23281                    arr.push(element.displayText + "=" + element.linkText + "=" + (_.isUndefined(element.clicked) ? "0" : "1"));
23282                }, this);
23283                if (arr.length > 0) {
23284                    this.reviewDoc = arr.join("\n");
23285                }
23286
23287                if (this.status == _reviewStatusMap.REVIEWED) {
23288                    this.enableCheckBox();
23289                }
23290
23291                
23292                this.$element.trigger('reviewComplete.tnc');
23293
23294            } else {
23295                
23296                var position = this.getScroll(this.$elementTextArea.parent().get(0)),
23297                    xy = position[this.options.scrollMode == 'vertical' ? 'y' : 'x'];
23298                var isScrolledToEnd = this.getScrollSize(this.$elementTextArea.parent().get(0)).y <=  (this.getSize(this.$elementTextArea.parent().get(0)).y + xy);
23299                
23300                this.reviewDoc = this.$elementTextArea.text();
23301
23302                
23303                if (isScrolledToEnd) {
23304                    
23305                    if (!this.inside) {
23306                        
23307                        this.inside = true;
23308                        this.enters++;
23309                        
23310                        this.status = _reviewStatusMap.REVIEWED;
23311                        if (!this.approvalStatus) {
23312                            this.enableCheckBox();
23313                            
23314                            this.$element.trigger('reviewComplete.tnc', [position,this.enters,event]);
23315                        }
23316                    }
23317                }
23318                
23319                else if (this.inside) {
23320                    this.inside = false;
23321                    this.leaves++;
23322
23323                }
23324            }
23325
23326        },
23327
23328        handleCheckBoxChange : function (event) {
23329            if ($(event.target).is(':checked')) {
23330                this.status = _reviewStatusMap.AGREE;
23331                this.$elementCheckBox.addClass(this.options.checkBoxReviewedClass.substring(1));
23332            } else {
23333                this.status = _reviewStatusMap.UNREVIEWD;
23334                this.$elementCheckBox.removeClass(this.options.checkBoxReviewedClass.substring(1));
23335            }
23336            this.$element.trigger('checkboxStateChange.tnc');
23337        },
23338
23339        getScrollSize : function (elem) {
23340            return {x : elem.scrollWidth, y : elem.scrollHeight};
23341        },
23342
23343        getScroll : function (elem) {
23344            return {x : elem.scrollLeft, y : elem.scrollTop};
23345        },
23346
23347        getSize : function (elem) {
23348            return {x : elem.offsetWidth, y : elem.offsetHeight};
23349        },
23350
23351        hasScrollBar : function (container) {
23352            
23353            if (isBrowserIE) {
23354                
23355                return ((container.scrollHeight - 2) > container.clientHeight) || ((container.scrollWidth - 2) > container.clientWidth);
23356            } else {
23357                return container.scrollHeight > container.clientHeight || container.scrollWidth > container.clientWidth;
23358            }
23359        }
23360    };
23361
23362    $.fn.afTnc = function (option, value) {
23363        var get = '',
23364            element = this.each(function () {
23365
23366                var $this = $(this),
23367                    data = $this.data('AfTnc'),
23368                    options = $.extend({}, _defaults, typeof option === 'object' && option);
23369
23370                
23371                if (!data) {
23372                    $this.data('AfTnc', (data = new AfTnc(this, options)));
23373                }
23374
23375                
23376                if (typeof option === 'string') {
23377                    get = data[option](value);
23378                }
23379            });
23380
23381        if (typeof get !== undefined) {
23382            return get;
23383        } else {
23384            return element;
23385        }
23386    };
23387
23388})(_, $);
23389(function ($) {
23390    var xfaUtil = xfalib.ut.XfaUtil.prototype;
23391    $.widget("xfaWidget.tnc", $.xfaWidget.abstractWidget, {
23392
23393        _widgetName : "tnc",
23394        _superPrototype : $.xfaWidget.abstractWidget.prototype,
23395        getOptionsMap : function () {
23396            var parentOptionsMap = this._superPrototype.getOptionsMap.apply(this, arguments),
23397                newMap = $.extend({}, parentOptionsMap, $.extend({}, this.options, {
23398                    "value" : function (value) {
23399                        this.$userControl.afTnc("value", value);
23400                    },
23401                    "reviewStatus" : function (value) {
23402                        this.$userControl.afTnc("reviewStatus", value);
23403                    },
23404
23405                    "clickStatus" : function (value) {
23406                        this.$userControl.afTnc("clickStatus", value);
23407                    },
23408                    
23409                    "access" : function (value) {
23410                        this.$userControl.afTnc("access", value);
23411                    }
23412                }));
23413            return newMap;
23414        },
23415
23416        _getReviewStatus : function () {
23417            return $(this.element).afTnc("reviewStatus");
23418        },
23419
23420        _getClickStatus : function () {
23421            return $(this.element).afTnc("clickStatus");
23422        },
23423
23424        getEventMap : function () {
23425            var parentEventMap = this._superPrototype.getEventMap.apply(this, arguments),
23426                newMap = $.extend({}, parentEventMap,
23427                    {
23428                        "change" : null,
23429                        "reviewComplete.tnc" : xfaUtil.XFA_CHANGE_EVENT,
23430                        "checkboxStateChange.tnc" : xfaUtil.XFA_CHANGE_EVENT
23431                    });
23432            return newMap;
23433        },
23434        render : function () {
23435            this._superPrototype.render.apply(this, arguments);
23436            $(this.element).afTnc(this.getOptionsMap());
23437            return $(this.element);
23438        },
23439        showDisplayValue : function () {
23440            
23441        },
23442        showValue : function () {
23443            
23444        },
23445        getCommitValue : function () {
23446            this.options.reviewStatus = this._getReviewStatus();
23447            this.options.clickStatus = this._getClickStatus();
23448            return $(this.element).afTnc("value");
23449        }
23450    });
23451})($);
23452
23453(function (_, guidelib) {
23454    var orderGetAttribute = {
23455        "Guide" : "XFA",
23456        "XFA" : "Guide"
23457    },
23458    
23459    newlyAddedProperties = ["enabled", "visible"];
23460    
23461    var GuideNode = guidelib.model.GuideNode = xfalib.ut.EventClass.extend({
23462        msClassName : "guideNode",
23463        guideUtil : guidelib.util.GuideUtil,
23464
23465        initialize : function () {
23466            
23467            
23468            this.className = this.jsonModel.guideNodeClass || this.msClassName;
23469            this.parent = null;
23470            this._isItem = false;
23471            this._index = 0;
23472        },
23473
23474        _postInitialize : function () {
23475            
23476        },
23477
23478        _triggerOnBridge : function (eventName, target, property, oldVal, newVal) {
23479            if (window.guideBridge) {
23480                window.guideBridge.trigger(eventName,
23481                    guidelib.event.GuideModelEvent.createEvent(eventName, target, property,
23482                                                           oldVal, newVal));
23483            }
23484        },
23485
23486        _getEffectiveBindRef : function() {
23487            return this.bindRef || this.getAttribute("name");
23488        },
23489
23490        validate : function (errorList) {
23491
23492        },
23493
23494        
23495        
23496        _getXFAOptionStringFromGuideItems : function (guideItems) {
23497            var optionsStr = "", indexOfSeparator = 0;
23498            if (!_.isEmpty(guideItems) && !_.isArray(guideItems)) {
23499                guideItems = [guideItems];
23500            }
23501            _.each(guideItems, function (item, index, list) {
23502                if(item.indexOf(",") > -1){
23503                    item = item.replace(/,/g, "\\,");
23504                }
23505                indexOfSeparator = item.indexOf('=');
23506                
23507                
23508                if (indexOfSeparator > -1) {
23509                    optionsStr += item.substring(indexOfSeparator + 1) + "," + item.substring(0, indexOfSeparator);
23510                } else {
23511                    optionsStr += item + "," + item;
23512                }
23513                if (index < guideItems.length - 1) {
23514                    optionsStr += ",";
23515                }
23516            });
23517            return optionsStr;
23518        },
23519
23520        _compareXFAItemsWithGuideItems : function (xfaItems, guideItems) {
23521            var match = true;
23522            if (xfaItems.length !== guideItems.length) {
23523                match = false;
23524            }
23525            if (match) {
23526                var bndNode = this.bindNode;
23527                _.each(guideItems, function (item, index, list) {
23528                    if (item.indexOf('=') > -1) {
23529                        if ((bndNode.getSaveItem(index) + "=" + bndNode.getDisplayItem(index)) == item) {
23530                            match = false;
23531                        }
23532                    } else {
23533                        if ((bndNode.getSaveItem(index) + "=" + bndNode.getDisplayItem(index)) == (item + "=" + item)) {
23534                            match = false;
23535                        }
23536                    }
23537                });
23538            }
23539            return match;
23540        },
23541
23542        
23543        syncXFAProps : function () {
23544            if (this.bindNode) {
23545                _.each(this._guide()._guideSchema.getAttributes(this.className),
23546                    function (attr, attrName) {
23547                        var xfaProp = attr.xfaProp,
23548                            propChain = (xfaProp || "").split("."),
23549                            xfaAttr = propChain.length > 0 ? propChain[propChain.length - 1]
23550                                                           : undefined;
23551                        
23552                        
23553                        
23554                        
23555                        
23556                        
23557                        if (!xfaAttr || (newlyAddedProperties.indexOf(attrName) != -1 && _.isUndefined(this.jsonModel[attrName]))) {
23558                            return;
23559                        }
23560                        var objChain = propChain.splice(0, propChain.length - 1),
23561                            obj = _.reduce(objChain,
23562                                function (obj, prop) {
23563                                    if (_.isObject(obj)) {
23564                                        return obj[prop];
23565                                    }
23566                                    return undefined;
23567                                }, this.bindNode),
23568                            val = this.getGuideProp(attrName, attr),
23569                            convertor = this._guide()._guideSchema.getConvertor(attrName),
23570                            cVal = convertor ? convertor.guideToXfa.apply(this, [val]) : val,
23571                            xfaVal;
23572                        try {
23573                            if (obj) {
23574                                xfaVal = obj[xfaAttr];
23575                                if (cVal !== undefined) {
23576                                    if (xfaAttr === "items") {
23577                                        var match = this._compareXFAItemsWithGuideItems(obj, cVal);
23578                                        var SET_ITEMS_INSERT_MODE_PAIR = 2;
23579                                        if (!match) {
23580                                            var optionsStr = this._getXFAOptionStringFromGuideItems(cVal);
23581                                            if (optionsStr !== "") {
23582                                                obj.setItems(optionsStr, SET_ITEMS_INSERT_MODE_PAIR);
23583                                            } else {
23584                                                obj.clearItems();
23585                                            }
23586                                        }
23587                                    } else if (cVal !== xfaVal) {
23588                                        obj[xfaAttr] = cVal;
23589                                    }
23590                                }
23591                            }
23592                        } catch (e) {
23593                            this.logger().error("AF", "setting {0}(guide {1}) for {2} is not supported in xfa",
23594                                [xfaProp, attrName, this.bindNode.somExpression]);
23595                            if (e.stack) {
23596                                this.logger().error("AF", e.stack);
23597                            }
23598                        }
23599                    }, this);
23600            }
23601        },
23602
23603        
23604        prepare : function () {
23605
23606        },
23607
23608        
23609        nakedChildReferences : function (nIndex, obj) {
23610            return;
23611        },
23612
23613        
23614        getNaked : function (nIndex, container, scope) {
23615            var nodeName = this.getAttribute("name"),
23616                oldReference = container._private["_" + nodeName + "_"],
23617                canOverride = (container._isOverriden && !container._isOverriden["_" + nodeName + "_"]),
23618                isGlobalFieldRef = this.isGlobal && (container === guidelib.__runtime__ || container === this._guide().runtime) 
23619                    && (container[nodeName] instanceof guidelib.model.AbstractField);
23620
23621            if ((scope && scope._nameArray[nodeName] === 1) || (nIndex === this.index)) {
23622                if (oldReference === null || oldReference === undefined || canOverride || isGlobalFieldRef) {
23623                    guidelib.util.GuideUtil._createGetterSetter(container, nodeName, this);
23624                    if (canOverride === true) {
23625                        container._isOverriden["_" + nodeName + "_"] = true;
23626                    }
23627                }
23628            }
23629        },
23630
23631        _getReducedJSON : function () {
23632            var whitelistedProperties = ["name", "templateId", "_value", "guideNodeClass"],
23633                reducedJsonObject = {};
23634            guidelib.model.util.CommonUtils.returnMinimalJSON(whitelistedProperties, reducedJsonObject, this);
23635            return reducedJsonObject;
23636        },
23637
23638        _getNakedThis : function () {
23639            return this;
23640        },
23641
23642        _xfa : function () {
23643            if (window.xfalib) {
23644                return window.xfalib.runtime.xfa;
23645            }
23646            return null;
23647        },
23648
23649        _guide : function () {
23650            return this.options._guideContainer;
23651        },
23652
23653        
23654        playJson : function (pJsonModel) {
23655
23656        },
23657
23658        
23659        
23660        visit : function (callback, context) {
23661            callback.apply(context, [this]);
23662        },
23663
23664        _collectValues : function (keyValue) {
23665
23666        },
23667
23668        _setParentAccess : function (value) {
23669            
23670        },
23671
23672        _unloadModel : function () {
23673            this.trigger(guidelib.event.GuideModelEvent.OBJECT_DESTROYED,
23674                guidelib.event.GuideModelEvent.createEvent(
23675                    guidelib.event.GuideModelEvent.OBJECT_DESTROYED,
23676                    this,
23677                    "destroy",
23678                    null,
23679                    this
23680                )
23681            );
23682            this._guide()._modelTemplateCacheStore.removeModel(this.id);
23683            this.off();
23684
23685            if (_.isObject(guidelib.__runtime__[this.name]) && (guidelib.__runtime__[this.name] === this || guidelib.__runtime__[this.name].somExpression === this.somExpression)) {
23686                guidelib.__runtime__[this.name] = undefined;
23687                if (_.isObject(guidelib.__runtime__._private['_' + this.name + '_'])) {
23688                    guidelib.__runtime__._private['_' + this.name + '_'] = undefined;
23689                }
23690            }
23691
23692            if (_.isObject(this._guide().runtime[this.name]) && (this._guide().runtime[this.name] === this || this._guide().runtime[this.name].somExpression === this.somExpression)) {
23693                this._guide().runtime[this.name] = undefined;
23694                if (_.isObject(this._guide().runtime._private['_' + this.name + '_'])) {
23695                    this._guide().runtime._private['_' + this.name + '_'] = undefined;
23696                }
23697            }
23698        },
23699
23700        _triggerEvent : function (event, propName, prevText, newText) {
23701            this.trigger(event,
23702                guidelib.event.GuideModelEvent.createEvent(event, this, propName,
23703                                                           prevText, newText));
23704        },
23705
23706        
23707        dispatchEvent : function (eventName, payload) {
23708            this._triggerEvent(eventName, payload);
23709            if(this.parent !== null){
23710                this.parent.dispatchEvent(eventName, payload);
23711            }
23712        },
23713
23714        
23715        setAttribute : function (value, attrName) {
23716            if (this.jsonModel[attrName] !== value) { 
23717                var oldValue = this.jsonModel[attrName];
23718                this.jsonModel[attrName] = value;
23719                this._triggerEvent(guidelib.event.GuideModelEvent.MODEL_CHANGED, attrName, oldValue, value);
23720            }
23721        },
23722
23723        _getSomExpression : function () {
23724            if (this.parent == null) {
23725                return "guide[0]." + this._escapeQualifiedName();
23726            } else {
23727                return this.parent.somExpression + "." + this._escapeQualifiedName();
23728            }
23729        },
23730
23731        _escapeQualifiedName : function () {
23732            var name = this.getAttribute("name");
23733            var index = this._index;
23734            var qname = name + "[" + index + "]";
23735            return qname.replace(/\./, "\\.");
23736        },
23737
23738        
23739        getGuideProp : function (attrName, attr) {
23740            var val = this.getOrElse(this.jsonModel, attrName, attr["default"]);
23741            if (val === undefined) {
23742                return undefined;
23743            }
23744            return guidelib.model.GuideSchema.prototype.getTypedValue(attr.type, val);
23745            
23746        },
23747
23748        
23749        getXFAProp : function (attrName, attr) {
23750            var xfaName = attr.xfaProp,
23751                convertor = guidelib.model.GuideSchema.prototype.getConvertor(attrName),
23752                val;
23753            if (this.bindNode && xfaName !== undefined) {
23754                val = this.bindNode.getOrElse(this.bindNode, xfaName, undefined);
23755                if (convertor) {
23756                    val = convertor.xfaToGuide.apply(this, [val]);
23757                }
23758                if (val !== undefined) {
23759                    return val;
23760                }
23761            }
23762            return undefined;
23763        },
23764
23765        
23766        getAttribute : function (attrName) {
23767            var attr = guidelib.model.GuideSchema.prototype.getAttributeProps(this.className, attrName),
23768                priority = attr.priority || (attr.xfaProp !== undefined ? "XFA" : "Guide"), 
23769                                                  
23770                val = this["get" + priority + "Prop"].apply(this, [attrName, attr]); 
23771            
23772            if (val === undefined) {
23773                
23774                val = this["get" + orderGetAttribute[priority] + "Prop"].apply(this, [attrName, attr]);
23775            }
23776            return val;
23777        },
23778
23779        
23780        resetData : function () {
23781
23782        }
23783    });
23784
23785    GuideNode.defineProps({
23786
23787        
23788        "name" : {
23789            get : function () {
23790                return (this.getAttribute("name") || "").replace(/\s+/g, '');
23791            }
23792        },
23793
23794        "templateId" : {
23795            get : function () {
23796                return this.getAttribute("templateId");
23797            }
23798        },
23799
23800        
23801        "id" : {
23802            get : function () {
23803                return this.getAttribute("id") || this.templateId;
23804            }
23805        },
23806
23807        
23808        somExpression : {
23809            get : function () {
23810                return this._getSomExpression();
23811            }
23812        },
23813
23814        
23815        "title" : {
23816            get : function () {
23817                return this.getAttribute("jcr:title");
23818            }
23819        },
23820
23821        
23822        "nonLocalizedTitle" : {
23823            get : function () {
23824                return this.getAttribute("nonLocalizedTitle");
23825            }
23826        },
23827
23828        
23829        panel : {
23830            get : function () {
23831                return this.parent.panel;
23832            }
23833        },
23834
23835        viewVisited : {
23836            get : function () {
23837                return this.getAttribute("viewVisited");
23838            },
23839            set : function (visit) {
23840                this.setAttribute(visit, "viewVisited");
23841            }
23842        },
23843
23844        
23845        index : {
23846            get : function () {
23847                return this._index;
23848            }
23849        },
23850
23851        
23852        visible : {
23853            get : function () {
23854                return true;
23855            },
23856            set : function (value) {
23857                
23858            }
23859        },
23860
23861        
23862        enabled : {
23863            get : function () {
23864                return true;
23865            },
23866            set : function (value) {
23867                
23868            }
23869        },
23870
23871        
23872        cssClassName : {
23873            get : function () {
23874                return this.getAttribute("css");
23875            }
23876        },
23877
23878        enableLayoutOptimization : {
23879            get : function () {
23880                return false;
23881            }
23882        },
23883
23884        jcrPath : {
23885            get : function () {
23886                return this.jsonModel["jcr:path"];
23887            }
23888        },
23889
23890        
23891        targetVersion : {
23892            get : function () {
23893                return this.getAttribute("fd:targetVersion");
23894            }
23895        }
23896    });
23897}(_, guidelib));
23898(function (_, guidelib, $) {
23899    var Verify = guidelib.model.Verify = guidelib.model.GuideNode.extend({
23900        msClassName : "verify",
23901
23902        initialize : function () {
23903            Verify._super.initialize.call(this);
23904            this.validationStatus = true;
23905        },
23906
23907        validate : function (errorList) {
23908            
23909
23910            var iframeFormBridge = null, validationStatus = true;
23911
23912            if (this.jsonModel.interactive !== undefined && this.jsonModel.interactive === "true") {
23913                
23914                
23915                
23916                
23917                
23918                if (guideBridge.hostName === "client") {
23919                    iframeFormBridge = $('#verifiable_form').get(0).contentWindow.formBridge;
23920                }
23921                
23922                
23923                if (iframeFormBridge !== undefined && iframeFormBridge !== null) {
23924                    validationStatus = iframeFormBridge.validateForm();
23925                    if (!validationStatus) {
23926                        errorList.push({som : this.somExpression, errorText : "XFA validation errors."});
23927                    }
23928                    this.validationStatus = validationStatus;
23929                }
23930            }
23931
23932            return validationStatus;
23933        }
23934    });
23935    Verify.defineProps({
23936        forceElementFocusChange : {
23937            get : function () {
23938                return true;
23939            }
23940        }
23941    });
23942})(_, guidelib, $);
23943(function (_, guidelib) {
23944    var Esign = guidelib.model.Esign = guidelib.model.GuideNode.extend({
23945        msClassName : "esign",
23946
23947        initialize : function () {
23948            Esign._super.initialize.call(this);
23949            this.validationStatus = true;
23950        },
23951
23952        validate : function (errorList) {
23953            
23954            
23955            var validationStatus =  true;
23956            if (!_.isUndefined(FD) &&
23957                !_.isUndefined(FD.AFaddon) &&
23958                FD.AFaddon.Signing) {
23959                validationStatus = FD.AFaddon.Signing.isDocumentSigned(this.jsonModel.signingService);
23960                if (!validationStatus) {
23961                    errorList.push({som : this.somExpression, errorText : "Signing not complete."});
23962                }
23963            }
23964            this.validationStatus = validationStatus;
23965            return validationStatus;
23966        }
23967    });
23968    Esign.defineProps({
23969        forceElementFocusChange : {
23970            get : function () {
23971                return true;
23972            }
23973        }
23974    });
23975})(_, guidelib);
23976(function (_, xfalib, guidelib) {
23977    
23978    var expressionContent = "with(this) {" +
23979                        "\n\t with(guidelib.__runtime__) {" +
23980                        "\n\t with(this._guide().runtime) {" +
23981                        "\n\t\t var _guide_result = this[${affectedProp}] = eval(\"${expression}\");" +
23982                        "\n\t\t return _guide_result ;" +
23983                        "\n\t }" +
23984                        "\n}};",
23985        scriptContent = "with(this) {" +
23986                        "\n\t with(guidelib.__runtime__) {" +
23987                        "\n\t with(this._guide().runtime) {" +
23988                        "\n\t var result = eval(\"${expression}\");" +
23989                        "\n\t\t return result; " +
23990                        "\n\t }" +
23991                        "\n}}";
23992    
23993    var Scriptable = guidelib.model.Scriptable = guidelib.model.GuideNode.extend({
23994        msClassName : "scriptable",
23995
23996        initialize : function () {
23997            Scriptable._super.initialize.call(this);
23998            
23999            this.className = this.jsonModel.guideNodeClass || this.msClassName;
24000            this._compiledExpressions = {};
24001            this._compiledScripts = {};
24002            this.mActiveEvents = [];
24003            this.dependants = [];
24004            
24005            if (this.initScript) {
24006                this._isInitScriptExecuted = false;
24007            }
24008            this._collectExpressions();
24009        },
24010
24011        _postInitialize : function () {
24012            
24013            if (this._isXfaNode()) {
24014                this.bindNode = this.options.bindNode || this._getBindNode();
24015                if (this.bindNode) {
24016                    this.bindNode.on(xfalib.script.XfaModelEvent.FORM_MODEL_CHANGED, this);
24017                }
24018            }
24019            
24020            this._parentAccess = this.getOrElse(this, "parent.enabled", true);
24021        },
24022
24023        _unloadModel : function () {
24024            if (this._isXfaNode && this._isXfaNode()) {
24025                if (this.bindNode) {
24026                    this.bindNode.off(xfalib.script.XfaModelEvent.FORM_MODEL_CHANGED, this);
24027                }
24028            }
24029
24030            Scriptable._super._unloadModel.call(this);
24031        },
24032
24033        _collectExpressions : function () {
24034            if (this.visibleExp) {
24035                this._compiledExpressions["visibleExp"] = this._compileExpression(this.visibleExp, "visible");
24036            }
24037            if (this.enabledExp) {
24038                this._compiledExpressions["enabledExp"] = this._compileExpression(this.enabledExp, "enabled");
24039            }
24040            
24041            if (this.initScript) {
24042                this._compiledScripts.initScript = this._compileExpression(this.initScript, null);
24043            }
24044        },
24045
24046        _compileExpression : function (expression, affectedProp) {
24047            if (expression) {
24048                try {
24049                    
24050                    var content = affectedProp ? expressionContent.replace(/\${affectedProp}/g, '"' + affectedProp + '"')
24051                                                                  .replace(/\${expression}/g, expression.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/(?:\r\n|\r|\n)/g, " "))
24052                                               : scriptContent.replace(/\${expression}/g,
24053                                                                        expression.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/(?:\r\n|\r|\n)/g, " "));
24054
24055                    return new Function(content);
24056                } catch (exception) {
24057                    this.logger().error("AF", "Error in compiling expression:" + expression);
24058                }
24059            }
24060            return null;
24061        },
24062
24063        _isXfaNode : function () {
24064            return (this._xfa() && this.getOrElse(this, "jsonModel.bindRef", "").indexOf("xfa[0].form[0].") === 0);
24065        },
24066
24067        _xfa : function () {
24068            return this.getOrElse(window, "xfalib.runtime.xfa", null);
24069        },
24070
24071        prepare : function () {
24072            Scriptable._super.prepare.apply(this);
24073            
24074            
24075            
24076            
24077            
24078            if (this.initScript && !this._isInitScriptExecuted) {
24079                this.executeExpression("initScript");
24080                this._isInitScriptExecuted = true;
24081            }
24082            var expressionTypes = _.keys(this._compiledExpressions);
24083            this._guide().queueExpressions(this, expressionTypes);
24084        },
24085
24086        
24087        handleEvent : function (evnt) {
24088            if (evnt instanceof xfalib.script.XfaModelEvent) {  
24089                switch (evnt.name) {
24090                    case xfalib.script.XfaModelEvent.FORM_MODEL_CHANGED:
24091                        this._handleXfaModelChanged(evnt);
24092                        break;
24093                    default:
24094                    
24095                }
24096            } else if (evnt instanceof guidelib.event.GuideModelEvent) {
24097                this.handleGuideEvent(evnt);
24098            }
24099        },
24100
24101        handleGuideEvent : function (evnt) {
24102        },
24103
24104        
24105        executeExpression : function (eventName, detail) {
24106            var guideContainerNode = this._guide();
24107            if (this._isXfaNode() && this.bindNode instanceof xfalib.script.EventContainerNode) {
24108                if (guidelib.util.GuideUtil.xfaExprMap[eventName] !== null) {
24109                    this.bindNode.execEvent(guidelib.util.GuideUtil.xfaExprMap[eventName] || eventName, detail);
24110                }
24111            }
24112            if (_.isUndefined(this._compiledExpressions[eventName]) && _.isUndefined(this._compiledScripts[eventName])) {
24113                if (!guideContainerNode._currentContext) {
24114                    guideContainerNode.runPendingExpressions();
24115                } else {
24116                    this.logger().log("AF", "executeExpression called withing from another executeExpression. Should NEVER happen ");
24117                }
24118                return true;
24119            }
24120
24121            if (this.mActiveEvents[eventName]) {
24122                return;
24123            }
24124            this.mActiveEvents[eventName] = true;
24125            var managedExp = this._compiledExpressions[eventName] ? true : false,
24126                oldContext = guideContainerNode._currentContext;
24127            
24128            guideContainerNode._currentContext = {contextNode: this, expression: eventName, managedExp: managedExp};
24129            this._setExpressionContext(this, this.index);
24130            var $event = {
24131                name: eventName,
24132                target: this,
24133                data: detail
24134            };
24135            guideContainerNode.runtime.$event = $event;
24136            var expResult = this._expressionHandler(eventName);
24137            this.mActiveEvents[eventName] = false;
24138            
24139            
24140            guideContainerNode._currentContext = oldContext;
24141            if (oldContext && oldContext.contextNode) {
24142                oldContext.contextNode._setExpressionContext(oldContext.contextNode, oldContext.contextNode.index);
24143            }
24144            guideContainerNode.runtime.$event = null;
24145            guideContainerNode.runPendingExpressions();
24146            return expResult;
24147        },
24148
24149        _setExpressionContext : function (startNode, currentIndex) {
24150            
24151            var currentSom = this.somExpression;
24152            function somCommonPrefixLen(field) {
24153                return guidelib.util.GuideUtil.commonPrefixLen(currentSom, field.somExpression);
24154            }
24155
24156            if (this._guide().internal.liveModel) {
24157                _.each(this._guide().internal.liveModel.getCrossFragmentFields(), function (fields, name) {
24158                    var loadedFields,
24159                        nearestField;
24160
24161                    
24162                    loadedFields = this._guide().internal.liveModel.getAllFieldModels(_.keys(fields));
24163
24164                    
24165                    if (!_.isEmpty(loadedFields)) {
24166                        nearestField = _.max(loadedFields, somCommonPrefixLen);
24167                    }
24168
24169                    
24170                    
24171
24172                    
24173                    guidelib.util.GuideUtil._createGetterSetter(guidelib.__runtime__, name, nearestField || fields[_.keys(fields)[0]]);
24174                    guidelib.util.GuideUtil._createGetterSetter(this._guide().runtime, name, nearestField || fields[_.keys(fields)[0]]);
24175                }, this);
24176            }
24177
24178            
24179            this._guide().runtime._isOverriden = {};
24180            guidelib.__runtime__._isOverriden = {};
24181            while (startNode) {
24182                
24183                startNode.nakedChildReferences(currentIndex, guidelib.__runtime__);
24184                startNode.nakedChildReferences(currentIndex, this._guide().runtime);
24185                currentIndex = startNode.index;
24186                startNode = startNode.parent;
24187            }
24188        },
24189
24190        _expressionHandler : function (expressionName) {
24191            var expFn, returnValue;
24192            if (this._compiledExpressions[expressionName]) {
24193                expFn = this._compiledExpressions[expressionName];
24194                try {
24195                    returnValue = expFn.apply(this);
24196                } catch (exception) {
24197                    
24198                    this.logger().error("AF", "Error in compiling expression:" + this.name + ":" + expressionName + ":" + exception.stack);
24199                }
24200            } else if (this._compiledScripts[expressionName]) {
24201                expFn = this._compiledScripts[expressionName];
24202                try {
24203                    return expFn.apply(this);
24204                } catch (scriptException) {
24205                    
24206                    this.logger().error("AF", "Error in compiling expression:" + this.name + ":" + expressionName + ":" + scriptException.stack);
24207                }
24208            }
24209            return returnValue;
24210        },
24211
24212        _handleXfaModelChanged : function (event) {
24213            if (event._property == "presence") {
24214                
24215                var newText = !(event.newText != "visible");
24216                this._triggerEvent(guidelib.event.GuideModelEvent.MODEL_CHANGED, "visible", event.prevText, newText);
24217            } else if (event._property == "access") {
24218                this.trigger(guidelib.event.GuideModelEvent.MODEL_CHANGED,
24219                    guidelib.event.GuideModelEvent.createEvent(
24220                        guidelib.event.GuideModelEvent.MODEL_CHANGED,
24221                        this,
24222                        "enabled",
24223                        event.prevText == "open",
24224                        event.newText == "open"
24225                    )
24226                );
24227            }
24228        },
24229
24230        _getScreenReaderText : function (index) {
24231            var screenReaderText, assistPriority = this._getAssistPriority();
24232            if (assistPriority == "custom") {
24233                screenReaderText = this._getCustomAssist(index) || this._getToolTip(index) || this._getCaption(index) || this._getName(index);
24234            } else if (assistPriority == "shortDescription") {
24235                screenReaderText = this._getToolTip(index) || this._getCaption(index) || this._getName(index);
24236            } else if (assistPriority == "label") {
24237                screenReaderText = this._getCaption(index) || this._getName(index);
24238            } else if (assistPriority == "name") {
24239                screenReaderText = this._getName(index);
24240            }
24241            return screenReaderText;
24242        },
24243
24244        _getAssistPriority : function () {
24245            
24246            return this.getAttribute("assistPriority") || "custom";
24247        },
24248
24249        _getCustomAssist : function () {
24250            var customAssist;
24251            if (this.bindNode && this.bindNode.assist && this.bindNode.assist.speak && this.bindNode.assist.speak.value) {
24252                customAssist = this.bindNode.assist.speak.value;
24253            } else if (this.jsonModel.custom) {
24254                customAssist = this.jsonModel.custom;
24255            }
24256            return customAssist;
24257        },
24258
24259        _getToolTip : function () {
24260            return this.shortDescription;
24261        },
24262
24263        _getCaption : function () {
24264            return this.getAttribute("jcr:title");
24265        },
24266
24267        _getName : function (index) {
24268            return this.getAttribute("name");
24269        },
24270
24271        _getBindNode : function () {
24272            var bindRef = this.getAttribute("bindRef");
24273            if (!bindRef) {
24274                return null;
24275            }
24276            var bindNode = null;
24277            var bindParent = this.parent ? this.parent._bindParent() : null;
24278            if (bindParent) {
24279                var bindParentRef = bindParent.getAttribute("bindRef");
24280                if (bindRef.substring(0, bindParentRef.length) == bindParentRef) {
24281                    
24282                    
24283                    var relativeBindRef = bindRef.substring(bindParentRef.length + 1); 
24284                    bindNode = bindParent.bindNode.resolveNode(relativeBindRef);
24285                }
24286            }
24287            if (!bindNode && this._isXfaNode()) {
24288                bindNode = this._xfa().resolveNode(bindRef);
24289            }
24290            return bindNode;
24291        },
24292
24293        _bindParent : function () {
24294            if (this.bindNode) {
24295                return this;
24296            } else if (this.parent) {
24297                return this.parent._bindParent();
24298            }
24299            return null;
24300        },
24301
24302        
24303        _getEnabled : function () {
24304            if (this.bindNode) {
24305                return this.bindNode.access == "open";
24306            } else {
24307                return this.getAttribute("enabled") && this._parentAccess;
24308            }
24309        },
24310
24311        
24312        _setEnabled : function (value) {
24313            if (!this.bindNode) {
24314                if (this.getAttribute("enabled") !== value) {
24315                    var oldEnabled = this.getAttribute("enabled");
24316                    this.setAttribute(value, "enabled");
24317                    this.trigger(guidelib.event.GuideModelEvent.MODEL_CHANGED,
24318                        guidelib.event.GuideModelEvent.createEvent(
24319                            guidelib.event.GuideModelEvent.MODEL_CHANGED,
24320                            this,
24321                            "enabled",
24322                            oldEnabled,
24323                            this.jsonModel.enabled
24324                        )
24325                    );
24326                    this._triggerOnBridge("elementEnableChanged", this, "enablement", oldEnabled, this.jsonModel.enabled);
24327                }
24328
24329            } else {
24330                var convertor = this._guide()._guideSchema.getConvertor("enabled");
24331                if (convertor) {
24332                    this.bindNode.access =  convertor.guideToXfa.apply(this, [value]);
24333                }
24334            }
24335        },
24336
24337        
24338        _setParentAccess : function (value) {
24339            var oldValue = this._parentAccess;
24340            this._parentAccess = value;
24341            this.trigger(guidelib.event.GuideModelEvent.MODEL_CHANGED,
24342                guidelib.event.GuideModelEvent.createEvent(
24343                    guidelib.event.GuideModelEvent.MODEL_CHANGED,
24344                    this,
24345                    "enabled",
24346                    oldValue,
24347                    this.enabled
24348                )
24349            );
24350        },
24351
24352        
24353        _addStateOverride : function (key, values) {
24354            if (key !== null && _.isString(key) && values !== null) {
24355                var somExpr = this.somExpression;
24356                somExpr = somExpr.substring(this._guide().somExpression.length + 1);
24357                this.jsonModel.stateOverrides = this.jsonModel.stateOverrides || {"somExpr" : somExpr};
24358                this.jsonModel.stateOverrides[key] = values;
24359                this._guide()._addToStateOverrideMap(this.id + this.name, this.jsonModel.stateOverrides);
24360            }
24361        }
24362    });
24363
24364    Scriptable.defineProps({
24365        
24366        shortDescription : {
24367            get : function () {
24368               return this.getAttribute("shortDescription");
24369           }
24370        },
24371
24372        
24373        longDescription : {
24374            get : function () {
24375                return this.getAttribute("longDescription");
24376            }
24377        },
24378
24379        visibleExp : {
24380            get : function () {
24381                return this.getAttribute("visibleExp");
24382            }
24383        },
24384
24385        initScript : {
24386            get : function () {
24387                return this.jsonModel.initScript;
24388            }
24389        },
24390
24391        enabledExp : {
24392            get : function () {
24393                return this.getAttribute("enabledExp");
24394            }
24395        },
24396
24397        
24398        visible : {
24399            get : function () {
24400                return this.getAttribute("visible");
24401            },
24402
24403            set : function (value) {
24404                if (!this.bindNode) {
24405                    if (this.getAttribute("visible") !== value) {
24406                        var oldVisible = this.getAttribute("visible"),
24407                            dorExclusionFlag;
24408                        this.setAttribute(value, "visible");
24409                        
24410                        
24411                        
24412                        if (this.getAttribute("dorExclusion") !== null) {
24413                            if ((this._guide().getAttribute("excludeFromDoRIfHidden") === "true") 
24414                                || (this._guide().print
24415                                && this._guide().print["excludeFromDoRIfHidden"] === "true")) {
24416                                dorExclusionFlag = !value;
24417                                
24418                                
24419                                this.dorExclusion = dorExclusionFlag;
24420                            }
24421                        }
24422                        this.trigger(guidelib.event.GuideModelEvent.MODEL_CHANGED,
24423                            guidelib.event.GuideModelEvent.createEvent(
24424                                guidelib.event.GuideModelEvent.MODEL_CHANGED,
24425                                this,
24426                                "visible",
24427                                oldVisible,
24428                                this.jsonModel.visible
24429                            )
24430                        );
24431                        this._triggerOnBridge("elementVisibleChanged", this, "visible", oldVisible, this.jsonModel.visible);
24432                    }
24433                } else {
24434                    if (value == true) {
24435                        this.bindNode.presence = "visible";
24436                    } else {
24437                        this.bindNode.presence = "hidden";
24438                    }
24439                }
24440            }
24441        },
24442
24443        
24444        dorExclusion : {
24445            get : function () {
24446                
24447                if (this.jsonModel.dorExclusion != null) {
24448                    if (_.isString(this.jsonModel.dorExclusion)) {
24449                        
24450                        return this.jsonModel.dorExclusion === "true";
24451                    } else {
24452                        return this.jsonModel.dorExclusion;
24453                    }
24454                }
24455                
24456                else if ((this._guide().getAttribute("excludeFromDoRIfHidden") === "true") 
24457                    || (this._guide().print
24458                    && this._guide().print["excludeFromDoRIfHidden"] === "true")) {
24459                    return !this.visible;
24460                } else {
24461                    
24462                    return false;
24463                }
24464            },
24465
24466            set : function (value) {
24467                
24468                
24469                
24470                var somExpr = this.somExpression;
24471                somExpr = somExpr.substring(this._guide().somExpression.length + 1);
24472                this._guide()._addToExcludeFromDorMap(somExpr, value);
24473                this.jsonModel.dorExclusion = value;
24474            }
24475        },
24476
24477        
24478        stateOverrides : {
24479            get : function () {
24480                return this.jsonModel.stateOverrides;
24481            }
24482        },
24483
24484        
24485        enabled : {
24486            get : function () {
24487                return this._getEnabled();
24488            },
24489
24490            set : function (value) {
24491                
24492                this._setEnabled(!!value);
24493            }
24494        },
24495
24496        
24497        bindRef : {
24498            get : function () {
24499                return (this.getAttribute("bindRef") || "").replace(/\s+/g, '');
24500            }
24501        },
24502
24503        
24504        isXsd : {
24505            
24506            get : function () {
24507                return _.isString(guideBridge._guide.xsdRef) && !_.isEmpty(this.bindRef) && this.bindRef[0] === '/';
24508            }
24509        }
24510    });
24511})(_, window.xfalib, guidelib);
24512(function (_, guidelib) {
24513    var GuideImage = guidelib.model.GuideImage = guidelib.model.Scriptable.extend({
24514        msClassName : "guideImage"
24515    });
24516
24517    GuideImage.defineProps({
24518        value : {
24519            get : function () {
24520                if (this.bindNode) {
24521                    return this.bindNode.rawValue;
24522                } else {
24523                    return null;
24524                }
24525            }
24526        }
24527    });
24528})(_, guidelib);
24529(function (_, guidelib) {
24530    var GuideAdModule = guidelib.model.GuideAdModule = guidelib.model.Scriptable.extend({
24531        msClassName : "guideAdModule",
24532
24533        initialize : function () {
24534            GuideAdModule._super.initialize.call(this);
24535            this.jsonModel["{default}"] = this.getOrElse(this.jsonModel, "{default}", this.jsonModel._value);
24536            this.layoutConfigs = [];
24537            
24538            if (typeof this.jsonModel.layoutConfig === "string") {
24539                this.layoutConfigs.push(JSON.parse(this.jsonModel.layoutConfig));
24540            } else {
24541                _.each(this.jsonModel.layoutConfig, function (layoutConfig) {
24542                    this.layoutConfigs.push(JSON.parse(layoutConfig));
24543                }, this);
24544            }
24545        },
24546
24547        _getTypedValue : function (value) {
24548            if (_.isUndefined(value) || value === null || value === "") {
24549                return null;
24550            }
24551            return value + "";
24552        },
24553
24554        playJson : function (pJsonModel) {
24555            var olval = this.jsonModel._value;
24556            this.jsonModel._value = pJsonModel._value;
24557            this._triggerOnBridge("elementValueChanged", this, "value", olval, this.jsonModel._value);
24558        }
24559    });
24560
24561    GuideAdModule.defineProps({
24562        
24563        value : {
24564            get : function () {
24565                return this._getTypedValue(this.jsonModel._value);
24566            },
24567            set : function (newValue) {
24568                var oldValue = this._getTypedValue(this.jsonModel._value),
24569                    newTypedValue = this._getTypedValue(newValue);
24570                
24571                if (newTypedValue !== undefined && (newTypedValue !== oldValue)) {
24572                    if (this.jsonModel._value !== newValue) {
24573                        this.jsonModel._value = newTypedValue || "";
24574                    }
24575                    this._triggerOnBridge("elementValueChanged", this, "value", oldValue, newTypedValue);
24576                }
24577            }
24578        }
24579    });
24580}(_, guidelib));
24581(function (_, $) {
24582
24583    var Responsive = {
24584        breakpoints : [],
24585        controlRowDefaults : {}
24586    },
24587    isPad = navigator.userAgent.match(/iPad/i) !== null,
24588    isIphone = (navigator.userAgent.match(/iPhone/i) !== null) || (navigator.userAgent.match(/iPod/i) !== null),
24589    isIphoneOrIpad = isPad || isIphone;
24590    
24591    Responsive.breakpoints = [
24592        {
24593            name : 'desktop',
24594            width : Infinity
24595        },
24596        {
24597            name : 'tablet-landscape',
24598            width : 1024
24599        },
24600        {
24601            name : 'tablet-potrait',
24602            width : 768
24603        },
24604        {
24605            name : 'mobile-landscape',
24606            width : 480
24607        },
24608        {
24609            name : 'mobile-potrait',
24610            width : 320
24611        }
24612    ];
24613
24614    
24615    Responsive.controlRowDefaults = {
24616        
24617        breakpoints : Responsive.breakpoints,
24618
24619        
24620        controlRowDetails : {
24621            renderer : function (tablePlugin, row) {
24622                var cells = null;
24623                if (tablePlugin.options.bControlRowHiddenCells) {
24624                    cells = row.$tableRowElement.find("td:hidden");
24625                } else {
24626                    cells = row.$tableRowElement.find("td");
24627                    
24628                    if (tablePlugin.options.bDisableControlRowCells) {
24629                        
24630                        row.$tableRowElement.find("input, select, textarea, button").attr("disabled", "disabled");
24631                    }
24632                }
24633                var data = cells.map(function (index, cell) {
24634                    var $cell = $(cell),
24635                        header = tablePlugin.header($cell),
24636                        $clickedTableRow = row.$tableRowElement,
24637                        cellIdx = null,
24638                        cellData = null;
24639                    cellIdx = {
24640                        
24641                        row : $clickedTableRow.index(),
24642                        column : $cell.index()
24643                    };
24644
24645                    cellData = tablePlugin._getCellData(cellIdx);
24646                    return $("<li></li>").attr("data-rtp-index", cellIdx.column).addClass("clearfix").append(
24647                        $("<div></div>").addClass("rtp-title").text($.trim(header.text()))
24648                    ).append(
24649                        $("<div></div>").addClass("rtp-data").append(cellData)
24650                    );
24651                });
24652
24653                return $('<ul data-rtp-index="' + row.index + '"></ul>').append(data.get());
24654            },
24655
24656            target : 0,
24657
24658            type : 'inline'
24659        }
24660    };
24661    
24662    var ResponsiveTablePlugin = function (element, options) {
24663        this.options = options;
24664        this.$element = $(element);
24665        this.columns = [];
24666    };
24667
24668    
24669    var TableColumn = function ($tableElement, colIdx, bIsResize) {
24670        var $colHeaderElement = $tableElement.find("th").eq(colIdx);
24671        
24672        this.minWidth =  (bIsResize ? (parseInt($colHeaderElement.css("min-width"), 10)) : $colHeaderElement.outerWidth());
24673        this.header = $colHeaderElement;
24674        this.colIndex = colIdx;
24675        this.$tableElement = $tableElement;
24676    };
24677
24678    
24679    TableColumn.prototype = {
24680        
24681        cells : function () {
24682            
24683            var headerValue = this.header.attr("id");
24684            return this.$tableElement.find("tr td").filter(function () {
24685                var id = $(this).attr("headers");
24686                if (id) {
24687                    if (id.indexOf(headerValue) > -1) {
24688                        return $(this);
24689                    }
24690                }
24691            });
24692        },
24693        
24694        visible : function (bFlag) {
24695            var cells = this.cells();
24696            this.isVisible = bFlag;
24697            if (bFlag ===  true) {
24698                cells.show();
24699                this.header.show();
24700            } else {
24701                this.header.hide();
24702                
24703                var headers = this.header.prevAll().filter(":visible"),
24704                    headerLen = headers.length;
24705                
24706                $.each(cells, function () {
24707                    if (!$(this).data("shown")) {
24708                        $(this).hide();
24709                    }
24710                    var colSpan = $(this).data("colspan") || $(this).attr("colspan");
24711                    
24712                    if (colSpan > 1) {
24713                        var totalColSpan = 0;
24714                        $(this).prevAll().each(function () {
24715                            totalColSpan += (+($(this).data("colspan") || $(this).attr("colspan")));
24716                        });
24717                        
24718                        if (totalColSpan == 0) {
24719                            $(this).show();
24720                            $(this).data("shown", true);
24721                            
24722                            if ($(this).data("colspan") == null) {
24723                                $(this).data("colspan", $(this).attr("colspan"));
24724                            }
24725                            $(this).attr("colspan", headerLen);
24726                        }
24727                        
24728                        else if (totalColSpan < headerLen) {
24729                            $(this).show();
24730                            $(this).data("shown", true);
24731                            if ($(this).data("colspan") == null) {
24732                                $(this).data("colspan", $(this).attr("colspan"));
24733                            }
24734                            $(this).attr("colspan", (headerLen - totalColSpan));
24735                        }
24736                    }
24737                });
24738            }
24739        }
24740    };
24741
24742    
24743    var TableRow = function ($tableRowElement) {
24744        this.$tableRowElement = $tableRowElement;
24745        this.index = $tableRowElement.index();
24746        
24747        this.child = {
24748            $element : null,
24749            isShown : false
24750        };
24751        $tableRowElement.data("tableRow", this);
24752    };
24753
24754    TableRow.prototype = {
24755
24756        updateChild : function (info, colSpan) {
24757            
24758            if (this.child.$element && this.child.$element.length > 0) {
24759                this.child.$element.empty();
24760                this.child.$element.append($("<td></td>").addClass(ResponsiveTablePlugin.prototype.defaults.CONTROL_ROW_CLASS).attr("colspan", colSpan).append($(info)));
24761            } else if (this.$tableRowElement.next(ResponsiveTablePlugin.prototype.defaults.CONTROL_ROW_SELECTOR).length > 0) {
24762                this.child.$element = this.$tableRowElement.next();
24763                this.child.$element.append($("<td></td>").addClass(ResponsiveTablePlugin.prototype.defaults.CONTROL_ROW_CLASS).attr("colspan", colSpan).append($(info)));
24764            } else {
24765                
24766                this.child.$element = $("<tr></tr>").addClass(ResponsiveTablePlugin.prototype.defaults.CONTROL_ROW_CLASS).append($("<td></td>").addClass(ResponsiveTablePlugin.prototype.defaults.CONTROL_ROW_CLASS).attr("colspan", colSpan).append($(info)));
24767                
24768                this.$tableRowElement.after(this.child.$element);
24769            }
24770
24771        },
24772
24773        showChild : function () {
24774            
24775            this.child.$element.get(0).style.display = "";
24776            this.child.isShown = true;
24777        },
24778
24779        hideChild : function () {
24780            this.child.$element.hide();
24781            this.child.isShown = false;
24782        }
24783    };
24784
24785    ResponsiveTablePlugin.prototype = {
24786        
24787        _getCellData : function (index) {
24788            
24789            var tableRow = this.$element.find("tbody tr").eq(index.row),
24790                tableCell =   tableRow.find("td").eq(index.column);
24791            
24792            if (this.options.viewCallback) {
24793                
24794                var id = tableCell.find(ResponsiveTablePlugin.prototype.defaults.GUIDE_ID_SELECTOR).attr("id");
24795                
24796                return this.options.viewCallback(id);
24797            } else {
24798                return tableCell.html();
24799            }
24800        },
24801
24802        
24803        header : function (cell) {
24804            
24805            
24806            var id = cell.attr("headers").split(" ")[0];
24807            
24808            return this.$element.find("#" + id);
24809        },
24810
24811        initializeColumns : function (bIsResize) {
24812            var columns = [];
24813            
24814            
24815            
24816            this.colLength = this.$element.find("th").length;
24817            for (var colIdx = 0; colIdx < this.colLength; colIdx++) {
24818                
24819                
24820                columns.push(new TableColumn(this.$element, colIdx, bIsResize));
24821            }
24822            return columns;
24823        },
24824
24825        
24826        _initializeColumnWidth : function () {
24827            
24828            
24829            
24830            var display = this._getColumnsVisibility(),
24831                
24832                visibleColumns = _.filter(display, function (item) {
24833                    return item == true;
24834                }).length,
24835                $allTableHeaders = this.$element.find("th"),
24836                $tableHeader = null,
24837                width = null,
24838                sum = 0;
24839            if (!this.options.bAutoWidth) {
24840                
24841                
24842                for (var i = 0; i < visibleColumns; i++) {
24843                    sum += parseInt(this.options.aWidth[i], 10);
24844                }
24845            } else {
24846                sum = visibleColumns;
24847            }
24848
24849            if (display.length == this.colLength) {
24850                for (var i = 0; i < visibleColumns; i++) {
24851                    if (this.options.aWidth) {
24852                        
24853                        width = ((Math.floor((this.options.aWidth[i] * 100) / sum)) + "%");
24854                    } else {
24855                        width = ((Math.floor((1 * 100) / sum)) + "%");
24856                    }
24857                    $tableHeader = $allTableHeaders.eq(i);
24858                    
24859                    
24860                    $tableHeader[0].style.width = width;
24861                }
24862            }
24863        },
24864
24865        _constructor : function () {
24866            var that = this;
24867            
24868            this.controlRow = $.extend(true, {}, Responsive.controlRowDefaults);
24869            this.columns = this.initializeColumns();
24870            
24871            $(window).on("resize orientationchange", function (event) {
24872                that._initializeColumnVisibility(event);
24873            });
24874
24875            
24876            
24877            this.controlRow.breakpoints.sort(function (a, b) {
24878                return a.width < b.width ? 1 :
24879                    a.width > b.width ? -1 : 0;
24880            });
24881            this._initializeColumnVisibility();
24882            
24883            this._controlRowInitialization();
24884        },
24885
24886        _initializeColumnVisibility : function (event) {
24887            var that = this;
24888            
24889            if (event) {
24890                
24891                
24892                this.$element.find("td").each(function () {
24893                    $(this).removeData("shown");
24894                    
24895                    if ($(this).data("colspan") != null) {
24896                        
24897                        $(this).attr("colspan", $(this).data("colspan"));
24898                    }
24899                });
24900                
24901                
24902                
24903                this.columns = this.initializeColumns(event);
24904            }
24905            
24906            
24907            
24908            
24909            this._initializeColumnWidth();
24910            this.display = this._resize();
24911            
24912            
24913            this.$element.find("tbody tr:not(.child)").each(function () {
24914                if ($(this).next(ResponsiveTablePlugin.prototype.defaults.CONTROL_ROW_SELECTOR).length == 0) {
24915                    $(this).after($("<tr></tr>").addClass(ResponsiveTablePlugin.prototype.defaults.CONTROL_ROW_CLASS).hide());
24916                }
24917            });
24918
24919            
24920            var details = this.controlRow.controlRowDetails;
24921            
24922            if (details.type) {
24923                
24924                this._controlRowVisibility(event);
24925                
24926                
24927                this.$element.on(ResponsiveTablePlugin.prototype.defaults.EVENT_COLUMN_VISIBILITY, function () {
24928                    that._controlRowVisibility();
24929                });
24930
24931                this.$element.addClass('rtp-' + details.type);
24932            }
24933            
24934            if (this.options.fixTableControls) {
24935                
24936                
24937                
24938                if (_.isUndefined(event) || event.type === "orientationchange" || (event.type === "resize" && !isIphoneOrIpad)) {
24939                    
24940                    this.options.fixTableControls(event);
24941                }
24942            }
24943        },
24944
24945        
24946        _fixControlRows : function () {
24947            this.$element.find(ResponsiveTablePlugin.prototype.defaults.CONTROL_ROW_SELECTOR).remove();
24948        },
24949
24950        
24951        isColumnHidden : function () {
24952            return this.bColumnHidden || false;
24953        },
24954
24955        
24956        _rearrangeTableRuntimeControls : function (lastVisibleColumn, event) {
24957            
24958            
24959            var $runtimeAddControls = this.$element.find(".guideTableRuntimeControls .guideTableRuntimeAddControl"),
24960                runtimeControlIndex = 0,
24961                that = this,
24962                index = null;
24963            $runtimeAddControls.each(function () {
24964                
24965                if ($(this).is(":visible")) {
24966                    runtimeControlIndex = $(this).closest("td").index();
24967                    return false;
24968                }
24969            });
24970            
24971            if ((runtimeControlIndex <= lastVisibleColumn)) {
24972                
24973                
24974                $runtimeAddControls.each(function () {
24975                    
24976                    
24977                    var $runtimeControl = $(this).closest(".guideTableRuntimeControls"),
24978                        $runtimeControlTableRow = $(this).closest("tr");
24979                    if ($runtimeControl.hasClass("guideTableRuntimeRightControls")) {
24980                        
24981                        $runtimeControl.appendTo($runtimeControlTableRow.find("td").eq(lastVisibleColumn));
24982                        if (runtimeControlIndex !== lastVisibleColumn) {
24983                            var $component = $runtimeControl.prev();
24984                            $component.css("display", "block");
24985                            $component.css("float", "none");
24986                        }
24987                    }
24988
24989                });
24990            }
24991        },
24992
24993        
24994        _controlRowVisibility : function (event) {
24995            var that = this,
24996                
24997                hiddenColumns = _.filter(this.columns, function (element) {
24998                    return (element.isVisible) !== true;
24999                }),
25000                lastVisibleColumn = this.columns.length - hiddenColumns.length;
25001            
25002            
25003            this._rearrangeTableRuntimeControls(lastVisibleColumn - 1, event);
25004            
25005            if (hiddenColumns && hiddenColumns.length > 0) {
25006                
25007                this.$element.addClass('collapsed');
25008                
25009            this.bColumnHidden = true;            } else {
25010                
25011                this.$element.removeClass('collapsed');
25012                
25013                this.bColumnHidden = false;
25014            }
25015        },
25016
25017        
25018        _controlRowInitialization : function () {
25019            var that    = this;
25020            var details = this.controlRow.controlRowDetails;
25021
25022            
25023            if (details.type === 'inline') {
25024                
25025                details.target = ("." +  (this.options.tableRuntimeEditControlClass || "tableRuntimeEditControl"));
25026            }
25027
25028            
25029            
25030            
25031            var target   = details.target;
25032            var selector = typeof target === 'string' ? target : 'td';
25033
25034            
25035            this.$element.on('click keypress', selector, function (e) {
25036                
25037                
25038                if ((e.type == "keypress" && e.keyCode == 13) || e.type == "click") {
25039                    
25040                    if (!that.$element.hasClass('collapsed')) {
25041                        return;
25042                    }
25043                    
25044                    var $row = $(this).closest('tr'),
25045                        rowData = $row.data("tableRow"),
25046                        row = rowData;
25047                    
25048                    
25049                    
25050                    if (row == null || row.child.$element.parent().length === 0) {
25051                        row = new TableRow($row);
25052                        $row.data("tableRow", row);
25053                    }
25054                    if (row.child.isShown) {
25055                        row.hideChild();
25056                        row.$tableRowElement.removeClass('parent');
25057                    } else {
25058                        var info = that.controlRow.controlRowDetails.renderer(that, row);
25059                        row.updateChild(info, that.colLength);
25060                        row.showChild();
25061                        row.$tableRowElement.addClass('parent');
25062                        
25063                        row.child.$element.find("input, select, textarea, button").eq(0).focus();
25064                    }
25065                }
25066            });
25067        },
25068
25069        
25070        _resize : function () {
25071            var width = $(window).width();
25072            var breakpoints = this.controlRow.breakpoints;
25073            var breakpoint = breakpoints[0].name;
25074
25075            
25076            for (var i = breakpoints.length - 1 ; i >= 0 ; i--) {
25077                if (width <= breakpoints[i].width) {
25078                    breakpoint = breakpoints[i].name;
25079                    break;
25080                }
25081            }
25082
25083            
25084            var display = this._getColumnsVisibility(breakpoint);
25085
25086            _.each(this.columns, function (item, index) {
25087                item.visible(display[index]);
25088            });
25089
25090            return display;
25091        },
25092
25093        
25094        _getColumnsVisibility : function (breakpoint) {
25095            var columns = this.columns,
25096                i,
25097                len = this.$element.find("th"),
25098                display = [];
25099
25100            
25101            var widthAvailable = this.$element.parent().outerWidth();
25102            var usedWidth = widthAvailable;
25103
25104            
25105            
25106            display = _.map(columns, function (item) {
25107                usedWidth -= item.minWidth;
25108                return ((usedWidth < 0) ? false : true);
25109            });
25110
25111            
25112            display[0] = true;
25113            return display;
25114        }
25115
25116    };
25117
25118    $.fn.responsiveTablePlugin = function (option, value) {
25119        var get = '',
25120            element = this.each(function () {
25121                
25122                if ($(this).is('table') === true) {
25123                    var $this = $(this),
25124                        data = $this.data('responsiveTablePlugin'),
25125                        options = $.extend({}, ResponsiveTablePlugin.prototype.defaults, typeof option === 'object' && option);
25126
25127                    
25128                    if (!data) {
25129                        $this.data('responsiveTablePlugin', (data = new ResponsiveTablePlugin(this, options)));
25130                        data._constructor();
25131                    }
25132
25133                    
25134                    if (typeof option === 'string') {
25135                        get = data[option](value);
25136                    }
25137                }
25138            });
25139
25140        if (get != "") {
25141            return get;
25142        } else {
25143            return element;
25144        }
25145    };
25146
25147    ResponsiveTablePlugin.prototype.defaults = {
25148        
25149        EVENT_COLUMN_VISIBILITY : "responsiveTablePlugin.columnVisibility",
25150        GUIDE_ID_SELECTOR : "div[data-guide-view-bind]",
25151        CONTROL_ROW_CLASS : "child",
25152        CONTROL_ROW_SELECTOR : "tr.child"
25153    };
25154
25155})(_, $);
25156(function ($, _, guidelib) {
25157
25158    
25159    var getPanelsWithNumericFields = function (panels, fieldName) {
25160            if (_.isUndefined(panels) || panels === null) {
25161                return [];
25162            }
25163            if (!_.isArray(panels)) {
25164                panels = [panels];
25165            }
25166            return _.filter(panels, function (panel) {
25167                return panel instanceof guidelib.model.GuidePanel
25168                    && panel[fieldName] instanceof guidelib.model.GuideNumericBox;
25169            });
25170        },
25171        
25172        sum = function (numPanels, fieldName) {
25173            return _.reduce(numPanels,
25174                function (memo, currentItem) {
25175                    var curValue = parseFloat(currentItem.getOrElse(currentItem, fieldName + ".value", 0));
25176                    if (isNaN(curValue)) {
25177                        curValue = 0;
25178                    }
25179                    return memo + curValue;
25180                }, 0);
25181        };
25182
25183    
25184    guidelib.__runtime__.af.sum = function (panels, fieldName) {
25185        return sum(getPanelsWithNumericFields(panels, fieldName), fieldName);
25186    };
25187
25188    
25189    guidelib.__runtime__.af.avg = function (panels, fieldName) {
25190        var n_panels = getPanelsWithNumericFields(panels, fieldName),
25191            total = sum(n_panels, fieldName);
25192        if (n_panels.length === 0) {
25193            return 0;
25194        }
25195        return total / n_panels.length;
25196    };
25197
25198    
25199    guidelib.__runtime__.af.max = function (panels, fieldName) {
25200        var panel = _.max(getPanelsWithNumericFields(panels, fieldName), function (panel) {
25201            return panel.getOrElse(panel, fieldName + ".value", Number.NEGATIVE_INFINITY);
25202        });
25203        if (panel instanceof guidelib.model.GuidePanel) {
25204            return panel[fieldName];
25205        }
25206        return null;
25207    };
25208
25209    
25210    guidelib.__runtime__.af.min = function (panels, fieldName) {
25211        var panel =  _.min(getPanelsWithNumericFields(panels, fieldName), function (panel) {
25212            return panel.getOrElse(panel, fieldName + ".value", Number.POSITIVE_INFINITY);
25213        });
25214        if (panel instanceof guidelib.model.GuidePanel) {
25215            return panel[fieldName];
25216        }
25217        return null;
25218    };
25219
25220}($, _, guidelib));
25221(function ($, _, guidelib) {
25222
25223    
25224    
25225    guidelib.__runtime__.af.reduce = function (panels, fieldName, iterator, memo, context) {
25226        if (!_.isArray(panels)) {
25227            panels = [panels];
25228        }
25229        return _.reduce(panels, function (memo, panel) {
25230            if (panel instanceof guidelib.model.GuidePanel && !_.isUndefined(panel[fieldName])) {
25231                if (_.isFunction(iterator)) {
25232                    return iterator.apply(context, [memo, panel, panel[fieldName]]);
25233                }
25234            }
25235            return memo;
25236        }, memo);
25237    };
25238
25239    
25240    
25241    guidelib.__runtime__.af.filter = function (panels, fieldName, predicate, context) {
25242        if (!_.isArray(panels)) {
25243            panels = [panels];
25244        }
25245        return _.map(
25246            _.filter(panels, function (panel) {
25247                if (panel instanceof guidelib.model.GuidePanel && !_.isUndefined(panel[fieldName])) {
25248                    if (_.isFunction(predicate)) {
25249                        return predicate.apply(context, [panel, panel[fieldName]]);
25250                    }
25251                    return false;
25252                }
25253            }),
25254            function (panel) {
25255                return panel[fieldName];
25256            }
25257        );
25258    };
25259    
25260    guidelib.__runtime__.af.formatDateToISOString = function (dateObject) {
25261        var day, month, year;
25262        if (!_.isUndefined(dateObject) && _.isObject(dateObject)) {
25263            day = dateObject.getDate().toString();
25264            
25265            month = (dateObject.getMonth() + 1).toString();
25266            year = dateObject.getFullYear().toString();
25267            if (month.length === 1) {
25268                month = "0" + month.toString();
25269            }
25270            
25271            return year + "-" + month + "-" + day;
25272
25273        }
25274    };
25275}($, _, guidelib));
25276(function (_, guidelib) {
25277    
25278    var GuideNavigationContext = guidelib.model.util.GuideNavigationContext = xfalib.ut.Class.extend({
25279        msClassName : "guideNavigationContext",
25280        initialize : function () {
25281            GuideNavigationContext._super.initialize.call(this);
25282            this._currentItem = this.options.currentItem;
25283            this._parentPanel = this.options.parentPanel;
25284            this.guideUtil = guidelib.util.GuideUtil;
25285        },
25286
25287        getQualifiedNamedItem : function (qName) {
25288            var navItems = this._getNavigableItems();
25289            var qItem = _.find(navItems, function (item) {
25290                return (item._escapeQualifiedName() == qName);
25291            }, this);
25292            return qItem;
25293        },
25294
25295        getItemForNav : function (navToken) {
25296            if (navToken == "prevItem" || navToken == "nextItem" || navToken == "firstItem" || navToken == "lastItem") {
25297                return this[navToken];
25298            } else {
25299                return this.getQualifiedNamedItem(navToken);
25300            }
25301        },
25302
25303        
25304        _isNavigableItem : function (item) {
25305            return item.visible;
25306        },
25307
25308        
25309        _isNavigablePanel : function (item) {
25310            if (item && item instanceof guidelib.model.GuidePanel) {
25311                return item.visible && item.isNavigable;
25312            }
25313        },
25314
25315        _getNavigableItems : function () {
25316            var navItems = _.filter(this._parentPanel.items, function (item) {
25317                return this._isNavigableItem(item);
25318            }, this);
25319            return navItems;
25320        },
25321        
25322        _getNavigableDescendant : function (navigableAncestor) {
25323            
25324            
25325            if (navigableAncestor && navigableAncestor != this._parentPanel) {
25326                var currentItem = navigableAncestor.parent._navigationContext.currentItem,
25327                    deepItem = null;
25328                while (currentItem instanceof guidelib.model.GuidePanel) {
25329                    deepItem = currentItem;
25330                    currentItem = currentItem._navigationContext.currentItem;
25331                }
25332                return deepItem;
25333            }
25334            return null;
25335        },
25336
25337        
25338        _getSomOnNavigableAncestor : function (somExpression) {
25339            if (_.isEmpty(somExpression)) {
25340                return null;
25341            }
25342
25343            var index = somExpression.lastIndexOf("."),
25344                parentModel,
25345                parentSom,
25346                isNavigable,
25347                guideModel = this._parentPanel._guide();
25348
25349            if (index !== -1) {
25350                parentSom = somExpression.substring(0, index);
25351                parentModel = guideModel.resolveNode(parentSom);
25352                if (parentModel) {
25353                    isNavigable = this._isNavigablePanel(parentModel);
25354                }
25355                if (isNavigable) {  
25356                    return somExpression;
25357                }
25358                return this._getSomOnNavigableAncestor(parentSom);
25359            }
25360            
25361            return guideModel.rootPanel.somExpression;
25362        },
25363
25364        
25365        _getNavigableAncestor : function (navOrder) {
25366            
25367            
25368            
25369            var guideModel = this._parentPanel._guide(),
25370                navigableAncestorSom = this._getSomOnNavigableAncestor(guideModel._currentNavigablePanelSom),
25371                navigableAncestorItem = guideModel.resolveNode(navigableAncestorSom);
25372            
25373            while (navigableAncestorItem
25374                && navigableAncestorItem != this._parentPanel && !navigableAncestorItem.parent._navigationContext[navOrder]
25375                && this.guideUtil.isChildPartOfContainer(this._parentPanel, navigableAncestorItem)) {
25376                
25377                var navigableParentItemSom = this._getSomOnNavigableAncestor(navigableAncestorItem.parent.somExpression);
25378                navigableAncestorItem = guideModel.resolveNode(navigableParentItemSom);
25379            }
25380            return navigableAncestorItem;
25381        },
25382
25383        _getNakedThis : function () {
25384            return this;
25385        }
25386    });
25387
25388    GuideNavigationContext.defineProps({
25389        
25390        currentItem : {
25391            get : function () {
25392                if (this._currentItem) {
25393                    return this._currentItem;
25394                } else {
25395                    return this.firstItem;
25396                }
25397            },
25398            set : function (value) {
25399                this._currentItem = value;
25400            }
25401        },
25402        
25403        prevItem : {
25404            get : function () {
25405                var navItems = this._getNavigableItems();
25406                var item = this.currentItem;
25407                if (navItems.indexOf(item) > 0) {
25408                    return navItems[navItems.indexOf(item) - 1];
25409                } else {
25410                    return null;
25411                }
25412            }
25413        },
25414        
25415        nextItem : {
25416            get : function () {
25417                var navItems = this._getNavigableItems();
25418                var item = this.currentItem;
25419                if (navItems.indexOf(item) < (navItems.length - 1)) {
25420                    return navItems[navItems.indexOf(item) + 1];
25421                } else {
25422                    return null;
25423                }
25424            }
25425        },
25426        
25427        nextNavigablePanel : {
25428            get : function () {
25429                var navigableAncestor = this._getNavigableAncestor("nextItem"),
25430                
25431                    navigableDescendant = this._getNavigableDescendant(navigableAncestor);
25432                return navigableDescendant;
25433            }
25434        },
25435
25436        
25437        prevNavigablePanel : {
25438            get : function () {
25439                var navigableAncestor = this._getNavigableAncestor("prevItem"),
25440                
25441                    navigableDescendant = this._getNavigableDescendant(navigableAncestor);
25442                return navigableDescendant;
25443            }
25444        },
25445
25446        
25447        firstItem : {
25448            get : function () {
25449                var navItems = this._getNavigableItems();
25450                return navItems[0] || null;
25451            }
25452        },
25453        
25454        lastItem : {
25455            get : function () {
25456                var navItems = this._getNavigableItems();
25457                if (navItems.length) {
25458                    return navItems[navItems.length - 1];
25459                } else {
25460                    return null;
25461                }
25462            }
25463        },
25464        
25465        hasNextItem : {
25466            get : function () {
25467                return this.nextItem != null;
25468            }
25469        },
25470        
25471        hasPrevItem : {
25472            get : function () {
25473                return this.prevItem != null;
25474            }
25475        },
25476
25477        
25478        hasNextNavigablePanel : {
25479            get : function () {
25480                return this.nextNavigablePanel != null;
25481            }
25482        },
25483
25484        
25485        hasPrevNavigablePanel : {
25486            get : function () {
25487                return this.prevNavigablePanel != null;
25488            }
25489        },
25490
25491        
25492        isFirstItem : {
25493            get : function () {
25494                return this.currentItem == this.firstItem;
25495            }
25496        },
25497        
25498        isLastItem : {
25499            get : function () {
25500                return this.currentItem == this.lastItem;
25501            }
25502        }
25503    });
25504
25505})(_, guidelib);
25506(function (_, guidelib) {
25507
25508    
25509    var GuideModelEvent = guidelib.event.GuideModelEvent = xfalib.ut.Class.extend({
25510        msClassName : "guideModelEvent"
25511    });
25512
25513    GuideModelEvent.defineProps({
25514        
25515        "prevText" : {
25516            get : function () {
25517                return this.jsonModel.prevText;
25518            }
25519        },
25520        
25521        "newText" : {
25522            get : function () {
25523                return this.jsonModel.newText;
25524            }
25525        },
25526        
25527        "name" : {
25528            get : function () {
25529                return this.jsonModel.name;
25530            }
25531        },
25532        "keyDown" : {
25533            get : function () {
25534                return this.jsonModel.keyDown;
25535            }
25536        },
25537        "modifier" : {
25538            get : function () {
25539                return this.jsonModel.modifier;
25540            }
25541        },
25542        
25543        "target" : {
25544            get : function () {
25545                return this.jsonModel.target;
25546            }
25547        },
25548        "shift" : {
25549            get : function () {
25550                return this.jsonModel.shift;
25551            }
25552        },
25553        "change" : {
25554            get : function () {
25555                return this.jsonModel.change;
25556            },
25557            set : function (value) {
25558                this.jsonModel.change = value;
25559            }
25560        },
25561        
25562        "_property" : {
25563            get : function () {
25564                return this.jsonModel._property;
25565            }
25566        }
25567    });
25568
25569    GuideModelEvent.createEvent = function (nm, tgt, prop, oldVal, newVal) {
25570        var evnt = {
25571            name : nm,
25572            target : tgt,
25573            _property : prop,
25574            prevText : oldVal,
25575            newText : newVal
25576        };
25577        return new GuideModelEvent({"jsonModel" : evnt});
25578    };
25579
25580    GuideModelEvent.MODEL_REFRESH = "guide.modelRefresh";
25581    GuideModelEvent.CHILD_CHANGED = "guide.childChanged";
25582    GuideModelEvent.MULTIPLE_CHILD_ADDED = "guide.multipleChildAdded";
25583    GuideModelEvent.MODEL_CHANGED = "guide.modelChanged";
25584    GuideModelEvent.VALUE_CHANGED = "guide.valueChanged";
25585    GuideModelEvent.ERROR_CHANGED = "guide.errorChanged";
25586    GuideModelEvent.ERROR_RESET = "guide.errorReset";
25587    GuideModelEvent.VISIBLE_CHANGED = "guide.visibleChanged";
25588    GuideModelEvent.ENABLED_CHANGED = "guide.enabledChanged";
25589    GuideModelEvent.ITEMS_CHANGED   = "guide.itemsChanged";
25590    GuideModelEvent.OBJECT_DESTROYED = "guide.objectDestroyed";
25591    GuideModelEvent.NAVIGATE_SECTION = "guide.navigateSection";
25592    GuideModelEvent.LAZY_LOADED = "guide.lazyLoaded";
25593}(_, guidelib));
25594(function ($, _, guidelib) {
25595    var GuideViewRegistry = guidelib.view.GuideViewRegistry = xfalib.ut.Class.extend({
25596
25597        
25598        _findWidget : function (config, name, className) {
25599            var result = _.find(config, function (widgetName, identifier) {
25600                return name === identifier;
25601            });
25602            if (result === undefined) {
25603                result = _.find(config, function (widgetName, identifier) {
25604                    return className === identifier;
25605                });
25606            }
25607            return result;
25608        },
25609
25610        
25611        _findWidgetNameFromCSS : function (cssClasses) {
25612            var result = null;
25613            if (_.isString(cssClasses)) {
25614                _.find(cssClasses.split(" "),
25615                    function (cssClass, index) {
25616                        var match = cssClass.match(/^widget_([\w\W]+)$/);
25617                        if (match && match.length === 2) {
25618                            result = match[1];
25619                            return true;
25620                        }
25621                        return false;
25622                    });
25623            }
25624            return result;
25625        },
25626
25627        createView : function (element, parentView) {
25628            var $element = $(element);
25629            var options = {
25630                    'element' : $element.get(0),
25631                    'widgetName' : $element.data("guideViewWidget"),
25632                    'parentView' : parentView
25633                };
25634            var guideViewBind = $element.data("guideViewBind");
25635            var model = window.guideBridge._resolveId(guideViewBind);
25636            
25637            
25638            if (model) {
25639                options.model = model;
25640                var clsName = model.className;
25641                var nodeClass = clsName.charAt(0).toUpperCase() + clsName.substr(1) + "View";
25642                var viewClass = guidelib.view[nodeClass],
25643                    widgetConfig = window.guideBridge.userConfig.widgetConfig;
25644                if (model instanceof guidelib.model.Field || model instanceof guidelib.model.GuideCompositeField) {
25645                    options.widgetName = this._findWidgetNameFromCSS(model.cssClassName)
25646                        || this._findWidget(widgetConfig, model.name, model.className);
25647                }
25648                if (!viewClass && model instanceof guidelib.model.GuideContainerNode) {
25649                    viewClass = guidelib.view.GuideContainerView;
25650                }
25651                if (!viewClass && model instanceof guidelib.model.Field) {
25652                    viewClass = guidelib.view.GuideFieldView;
25653                }
25654                if (!viewClass && model instanceof guidelib.model.GuidePanel) {
25655                    viewClass = guidelib.view.GuidePanelView;
25656                }
25657                if (!viewClass && model instanceof guidelib.model.GuideItemsContainer) {
25658                    viewClass = guidelib.view.GuideItemsView;
25659                }
25660                if (!viewClass) {
25661                    viewClass = guidelib.view.GuideBaseView;
25662                }
25663                
25664                var bindView = new viewClass(options);
25665                return bindView;
25666            }
25667        }
25668    });
25669
25670})($, _, guidelib);
25671(function (_, guidelib, xfalib) {
25672    var DataNode = guidelib.model.DataNode = xfalib.ut.Class.extend({
25673        initialize : function () {
25674            this.linkedFields = [];
25675            this.isUpdateInProgress = false;
25676        },
25677
25678        addField : function (model) {
25679            if (!_.isEmpty(model) && !_.contains(this.linkedFields, model)) {
25680                this.linkedFields.push(model);
25681                model.on(guidelib.event.GuideModelEvent.VALUE_CHANGED, this);
25682            }
25683        },
25684
25685        removeField : function (model) {
25686            if (!_.isEmpty(model)) {
25687                model.off(guidelib.event.GuideModelEvent.VALUE_CHANGED, this);
25688                this.linkedFields = _.without(this.linkedFields, model);
25689            }
25690        },
25691
25692        getFieldModels : function () {
25693            return _.filter(this.linkedFields, function (field) {
25694                return (field instanceof guidelib.model.Field);
25695            });
25696        },
25697
25698        getAbstractFieldModels : function () {
25699            return _.filter(this.linkedFields, function (field) {
25700                return (field instanceof guidelib.model.AbstractField);
25701            });
25702        },
25703
25704        handleEvent : function (event) {
25705            switch (event.name) {
25706            case guidelib.event.GuideModelEvent.VALUE_CHANGED:
25707                if (!_.contains(['guideButton', 'guideTextDraw', 'guideAdobeSignBlock'], event.target.className)) {
25708                    this.updateLinkedFieldsValue(event);
25709                }
25710                break;
25711            default:
25712                event.target.logger().warn("AF", "Unexpected Event type on Data Node", event);
25713            }
25714        },
25715
25716        updateLinkedFieldsValue : function (event) {
25717            if (this.isUpdateInProgress) {
25718                return;
25719            }
25720
25721            this.isUpdateInProgress = true;
25722            var newValue = event.target._getValue();
25723
25724            try {
25725                _.each(this.linkedFields, function (field) {
25726                    if (field !== event.target) {
25727                        field.value = newValue;
25728                    }
25729                }, this);
25730            } catch (ex) {
25731                event.target.logger().error("AF", "Unable to set Linked Field value" + ex);
25732            } finally {
25733                this.isUpdateInProgress = false;
25734            }
25735        }
25736    });
25737
25738}(_, guidelib, xfalib));
25739
25740
25741(function (guidelib, $) {
25742
25743    var VERSION_AEM_61 = "AEM6.1",
25744        VERSION_AEM_62 = "AEM6.2",
25745        VERSION_AEM_63 = "AEM6.3",
25746        VERSION_AEM_65 = "AEM6.5",
25747        flagsStatus = {},
25748        getMinorMajor = function (version) {
25749            var match = version.match(/AEM(\d+)(?:\.(\d+))?/);
25750            if (match == null) {
25751                return null;
25752            }
25753            return {
25754                major : match[1],
25755                minor : match[2] === undefined ? "0" : match[2]
25756            };
25757        },
25758        compareNumbers = function (num1, num2) {
25759            return (num1 - num2);
25760        },
25761        compareVersions = function (version1, version2) {
25762            if (typeof version1 !== "string" || typeof version2 !== "string") {
25763                throw "Comparing Invalid Versions";
25764            }
25765            var v1 = getMinorMajor(version1),
25766                v2 = getMinorMajor(version2);
25767            if (v1 == null || v2 == null) {
25768                throw "Comparing Invalid Versions";
25769            }
25770            var c = compareNumbers(+v1.major, +v2.major);
25771            return c !== 0 ? c : compareNumbers(+v1.minor, +v2.minor);
25772        },
25773        Version = guidelib.util.Version = xfalib.ut.Class.extend({
25774            initialize : function (options) {
25775                flagsStatus = {};
25776                var compat = options.scriptingBehaviourVersion;
25777                if (compat === "None") {
25778                    compat = this.current();
25779                }
25780                this.scriptingBehaviourVersion = compat || VERSION_AEM_65;
25781                var majorMinor = getMinorMajor(this.scriptingBehaviourVersion);
25782                if (majorMinor == null) {
25783                    throw "Invalid Version number";
25784                }
25785                this.major = majorMinor.major;
25786                this.minor = majorMinor.minor;
25787            },
25788
25789            current : function () {
25790                return VERSION_AEM_65;
25791            },
25792
25793            compatibleVersion : function () {
25794                return this.scriptingBehaviourVersion;
25795            },
25796
25797            isPrevious : function (version) {
25798                return compareVersions(this.scriptingBehaviourVersion, version) < 0;
25799            },
25800
25801            isPreviousOrSame : function (version) {
25802                var c = compareVersions(this.scriptingBehaviourVersion, version);
25803                return c < 0 || c == 0;
25804            },
25805
25806            isAfter : function (version) {
25807                return compareVersions(this.scriptingBehaviourVersion, version) > 0;
25808            },
25809
25810            isAfterOrSame : function (version) {
25811                var c = compareVersions(this.scriptingBehaviourVersion, version);
25812                return c > 0 || c == 0;
25813            },
25814
25815            isSame : function (version) {
25816                return compareVersions(this.scriptingBehaviourVersion, version) == 0;
25817            },
25818
25819            isOn : function (flag) {
25820                switch (flag) {
25821                    case this.Flags.RUN_VALUE_COMMMIT_ON_SCRIPT_CHANGE:
25822                        if (flagsStatus[flag] == undefined) {
25823                            flagsStatus[flag] = this.isAfter(this.AEM_61);
25824                        }
25825                        return flagsStatus[flag];
25826                    case this.Flags.RUN_VALUE_COMMMIT_ON_PREFILL:
25827                        if (flagsStatus[flag] == undefined) {
25828                            flagsStatus[flag] = this.isAfter(this.AEM_63);
25829                        }
25830                        return flagsStatus[flag];
25831                }
25832                throw "Invalid Flag";
25833            }
25834        });
25835
25836    Version.prototype.Flags = {};
25837    Object.defineProperties(Version.prototype.Flags, {
25838        RUN_VALUE_COMMMIT_ON_SCRIPT_CHANGE : {
25839            value : "manageValueCommit",
25840            writable : false
25841        },
25842        RUN_VALUE_COMMMIT_ON_PREFILL : {
25843            value : "manageValueCommitOnPrefill",
25844            writable : false
25845        }
25846    });
25847    Version.defineProps({
25848        AEM_61 : {
25849            value : VERSION_AEM_61,
25850            writable : false
25851        },
25852
25853        AEM_62 : {
25854            value : VERSION_AEM_62,
25855            writable : false
25856        },
25857
25858        AEM_63 : {
25859            value : VERSION_AEM_63,
25860            writable : false
25861        },
25862
25863        AEM_65 : {
25864            value : VERSION_AEM_65,
25865            writable : false
25866        }
25867    });
25868}(guidelib, $));
25869(function ($, guidelib, _) {
25870    var GuideBaseView = guidelib.view.GuideBaseView = xfalib.ut.Class.extend({
25871        guideUtil : guidelib.util.GuideUtil,
25872        _triggerOnBridge : function (eventName, target, property, oldVal, newVal) {
25873            var evnt = guidelib.event.GuideModelEvent.createEvent(eventName, target,
25874                                                    property, oldVal, newVal);
25875            window.guideBridge.trigger(eventName, evnt);
25876        },
25877
25878        initialize : function () {
25879            GuideBaseView._super.initialize.call(this);
25880            this.$element = $(this.options.element);
25881            this.id = this.$element.attr("id");
25882            this._model = this.options.model;
25883            this.parentView = this.options.parentView;
25884            this.$element.data("guideView", this);
25885            this._$item = null;
25886            this._$itemNav = null;
25887            if (this._model && this._model != null) {
25888                this._model.on(guidelib.event.GuideModelEvent.MODEL_CHANGED, this.handleModelChanged, this);
25889            }
25890            this._syncPending = true; 
25891            this._visibleHelpElement = "none";
25892            this._polyfills();
25893        },
25894
25895        _polyfills: function () {
25896            var IEpolyfillForObjectDotEntries = function() {
25897                if(!Object.entries) {
25898                    Object.entries = function (obj) {
25899                        var ownProps = Object.keys(obj),
25900                            i = ownProps.length,
25901                            resArray = new Array(i); 
25902                        while (i--)
25903                            resArray[i] = [ownProps[i], obj[ownProps[i]]];
25904
25905                        return resArray;
25906                    };
25907                }
25908            };
25909
25910            var polyfills = [IEpolyfillForObjectDotEntries];
25911
25912            for (var i = 0; i < polyfills.length; ++i) {
25913                polyfills[i](); 
25914            }
25915        },
25916
25917        postInitialize : function () {
25918        },
25919
25920        _unloadView : function () {
25921            
25922            this._model.off(guidelib.event.GuideModelEvent.MODEL_CHANGED, this.handleModelChanged, this);
25923            
25924            this.$element = null;
25925            this.$widget = null;
25926            this._model = null;
25927            this._$item = null;
25928            this._$itemNav = null;
25929            this.parentView = null;
25930        },
25931
25932        handleVisibleChanged : function (event) {
25933            
25934            
25935            if (!event.newText) {
25936                this.$item.addClass("hidden");
25937                this.$itemNav.addClass("hidden");
25938                if (this.parentView.currentActiveItemView == this) {
25939                    this.parentView.setActive("nextItem");
25940                }
25941                if (event.prevText) {
25942                    this.announceVisibilityChanged("HIDDEN");
25943                }
25944            }   else {
25945                
25946                this.$item.removeClass("hidden");
25947                this.$itemNav.removeClass("hidden");
25948                if (!event.prevText) {
25949                    this.announceVisibilityChanged("VISIBLE");
25950                }
25951            }
25952        },
25953
25954        announceVisibilityChanged : function (visible) {
25955            var $statusAnnounceElement = this.parentView.$element.find('.guideGridFluidLayout2ContainerStatus');
25956            var $elementLabel = this.$item.find('.guideFieldLabel label');
25957            if ($statusAnnounceElement && $elementLabel) {
25958                var newStatus = visible === "VISIBLE" ? 
25959                    this.guideUtil.getLocalizedMessage("", guidelib.i18n.strings.showingField, [$elementLabel.text()])
25960                    :
25961                    this.guideUtil.getLocalizedMessage("", guidelib.i18n.strings.hidingField, [$elementLabel.text()]);
25962                $statusAnnounceElement.attr('aria-label', newStatus);
25963            }
25964        },
25965
25966        handleModelChanged : function (event) {
25967            switch (event._property) {
25968                case "viewVisited":
25969                    if (event.newText) {
25970                        this.$item.addClass("stepped");
25971                        this.$itemNav.addClass("stepped");
25972                    }else {
25973                        this.$item.removeClass("stepped");
25974                        this.$itemNav.removeClass("stepped");
25975                    }
25976                    break;
25977
25978                case "visible":
25979                    
25980                    this.handleVisibleChanged(event);
25981                    break;
25982            }
25983        },
25984
25985        setActive : function (activeItemToken, focus, muteScripts) {
25986            if (focus && (this._model.className === "guideNode" || this._model.forceElementFocusChange)) {
25987                if (this.$element !== null && typeof this.$element.focus === "function" && !this._guideView.skipFieldFocus) {
25988                    
25989                    this.$element.focus();
25990                    
25991                    this._guideView.currentFocusItemSom = this._model.somExpression;
25992                }
25993
25994            }
25995            return true;
25996        },
25997
25998        focusable : function () {
25999            return this._model.visible;
26000        },
26001
26002        _find : function (selector) {
26003            return this._guideView.$element.find(selector);
26004        },
26005
26006        _syncGuideNodeToHtml : function (deepSync) {
26007            this._syncPending = false;
26008            
26009            
26010            this.handleVisibleChanged(guidelib.event.GuideModelEvent.createEvent(
26011                guidelib.event.GuideModelEvent.MODEL_CHANGED,
26012                this,
26013                "visible",
26014                this._model.visible,
26015                this._model.visible
26016            ), {skipLazyAutoLoad: true});  
26017        },
26018
26019        _updateIds : function ($el, oldId, newId) {
26020            if (oldId == newId) {
26021                return;
26022            }
26023            
26024            var idSelector = "#" + oldId,
26025                modelBindSelector = this.guideUtil.modelElSelector(oldId),
26026                attrSelector = '[id^="' + oldId + '"]',
26027                longDescriptionSelector = '[data-guide-longDescription^="' + oldId + '"]',
26028                labelSelector = 'label[for^="' + oldId + '"]',
26029                targetIdSelector = "[data-guide-id^='" + oldId + "']",
26030                $elById = $el.find(idSelector).addBack(idSelector),
26031                selectorAttrObject  = {
26032                    "id" : attrSelector ,
26033                    "for" : labelSelector,
26034                    "data-guide-longDescription" : longDescriptionSelector,
26035                    "data-guide-id" : targetIdSelector
26036                };
26037            
26038            
26039            
26040            if ($elById.attr(guidelib.util.GuideUtil.DATA_GUIDE_ITEM_CONTAINER) !== undefined) {
26041                $elById.attr(guidelib.util.GuideUtil.DATA_GUIDE_ITEM_CONTAINER, newId + guidelib.util.GuideUtil.GUIDE_ITEM_CONTAINER_SUFFIX);
26042            }
26043            
26044            if ($elById.attr(guidelib.util.GuideUtil.DATA_GUIDE_ITEM) !== undefined) {
26045                $elById.attr(guidelib.util.GuideUtil.DATA_GUIDE_ITEM, newId + guidelib.util.GuideUtil.GUIDE_ITEM_SUFFIX);
26046            }
26047            $elById.attr("id", newId);
26048            $el.find(modelBindSelector).addBack(modelBindSelector).attr(this.guideUtil.GUIDE_VIEW_BIND_ATTR, newId);
26049            
26050            _.each(_.keys(selectorAttrObject), function (item, index) {
26051                var selector = selectorAttrObject[item];
26052                $el.find(selector).addBack(selector).each(function () {
26053                    
26054                    var $this = $(this),
26055                        prevId = $this.attr(item),
26056                        nextId = newId + prevId.substring(oldId.length);
26057                    $this.attr(item, nextId);
26058                });
26059            }, this);
26060        },
26061
26062        getSiblingItemView : function (siblingType) {
26063            if (this.parentView instanceof guidelib.view.GuidePanelView) {
26064                var siblingItem = this.parentView._model.navigationContext.getItemForNav(siblingType);
26065                if (siblingItem) {
26066                    return this.parentView.getQualifiedNamedView(siblingItem._escapeQualifiedName());
26067                }
26068            }
26069            return null;
26070        }
26071    });
26072
26073    GuideBaseView.defineProps({
26074        _guideView : {
26075            get : function () {
26076                return window.guideBridge._guideView;
26077            }
26078        },
26079
26080        _guide : {
26081            get : function () {
26082                return window.guideBridge._guide;
26083            }
26084        },
26085
26086        $item : {
26087            get : function () {
26088                if (!this._$item || this._$item.length == 0) {
26089                    var itemSelector = this.guideUtil.itemSelector(this._model.id, this._model);
26090                    this._$item = this._find(itemSelector);
26091                    
26092                    
26093                    if (this._$item && this._$item.length == 0) {
26094                        return this.$element;
26095                    }
26096                }
26097                return this._$item;
26098            }
26099        },
26100
26101        $itemNav : {
26102            get : function () {
26103                if (!this._$itemNav) {
26104                    var itemNavSelector = this.guideUtil.itemNavSelector(this._model.id);
26105                    this._$itemNav = this._find(itemNavSelector);
26106                }
26107                return this._$itemNav;
26108            }
26109        },
26110        visibleHelpElement :  {
26111            get : function () {
26112                return this._visibleHelpElement;
26113            },
26114            set : function (helpType) {
26115                this._visibleHelpElement = helpType;
26116            }
26117        },
26118
26119        
26120        isItem : {
26121            get : function () {
26122                return this._model._isItem;
26123            }
26124        },
26125
26126        qualifiedName : {
26127            get : function () {
26128                return this._model._escapeQualifiedName();
26129            }
26130        }
26131
26132    });
26133}($, guidelib, _));
26134(function ($, guidelib, _) {
26135
26136    var xfaUtil = xfalib.ut.XfaUtil.prototype,
26137        GuideFieldView = guidelib.view.GuideFieldView = guidelib.view.GuideBaseView.extend({
26138            _defaultWidgetName : "defaultWidget",
26139
26140            
26141            autofillFieldKeywordToName  : {
26142                "name" : "name",
26143                "given-name" : "fname",
26144                "additional-name" : "mname",
26145                "family-name" : "lname",
26146                "email" : "email",
26147                "street-address" : "address",
26148                "address-line1" : "address",
26149                "address-line2" : "address",
26150                "address-level1" : "state",
26151                "address-level2" : "city",
26152                "postal-code" : "zip",
26153                "country" : "country",
26154                "tel" : "phone",
26155                "cc-name" : "ccname",
26156                "cc-number" : "cardnumber",
26157                "cc-csc" : "cvc",
26158                "cc-exp-month" : "ccmonth",
26159                "cc-exp-year" : "ccyear",
26160                "cc-exp" : "exp-date",
26161                "cc-type" : "card-type"
26162            },
26163
26164            initialize : function () {
26165                GuideFieldView._super.initialize.call(this);
26166                this._initializeWidget();
26167                this._defineModelEvents();
26168                this._markMandatory();
26169                this._updateEmptyStatus();
26170                this.oldValue = null;
26171            },
26172
26173            postInitialize : function () {
26174                this._syncGuideNodeToHtml(true);
26175            },
26176
26177            createWidgetOptions : function () {
26178                return {
26179                    name : this._model.getAttribute("autocomplete") ? this.autofillFieldKeywordToName[this._model.getAttribute("autofillFieldKeyword")] : this._model.id + "_jqName",
26180                    value : this._model.value,
26181                    displayValue : this._model.formattedValue,
26182                    commitEvent : this.getCommitEvent(),
26183                    access : this._model.enabled ? "open" : "readOnly",
26184                    screenReaderText : this._model._getScreenReaderText(),
26185                    mandatory : this._model.mandatory
26186                };
26187            },
26188
26189            getCommitEvent : function () {
26190                return xfalib.ut.XfaUtil.prototype.XFA_EXIT_EVENT;
26191            },
26192
26193            getWidgetName : function () {
26194                var widgetName;
26195                if (this.$widget) {
26196                    var $elem = this.$widget.find('[data-af-widgetname]').addBack('[data-af-widgetname]');
26197                    
26198                    if ($elem && $elem.length > 0) {
26199                        widgetName = $elem.attr("data-af-widgetname");
26200                    }
26201                }
26202                if (!widgetName) {
26203                    this.logger().warn("AF", "widget name is not specified for field " + this._model.somExpression +
26204                        ", falling back to other widget");
26205                }
26206                return widgetName || this.options.widgetName || this._defaultWidgetName;
26207            },
26208
26209            _unloadView : function () {
26210                if (this._model) {
26211                    this._model.off(guidelib.event.GuideModelEvent.VALUE_CHANGED, this.handleValueChanged, this);
26212                    this._model.off(guidelib.event.GuideModelEvent.ERROR_CHANGED, this.handleErrorChanged, this);
26213                    this._model.off(guidelib.event.GuideModelEvent.ERROR_RESET, this.handleErrorReset, this);
26214                }
26215                
26216                this.jqwidget = null;
26217                GuideFieldView._super._unloadView.apply(this, arguments);
26218            },
26219
26220            _initializeWidget : function () {
26221                if (this.$element.find('div.guideFieldWidget').length) {
26222                    this.$widget = this.$element.find('div.guideFieldWidget');
26223                } else {
26224                    this.$widget = null;
26225                }
26226
26227                
26228                if (this.$widget) {
26229                    $(this.$widget).on(this.getCommitEvent(), $.proxy(this.handleCommit, this))
26230                        .on(xfaUtil.XFA_CLICK_EVENT, $.proxy(this.handleClick, this))
26231                        .on(xfaUtil.XFA_EXIT_EVENT, $.proxy(this.handleFocusOut, this))
26232                        .on(xfaUtil.XFA_ENTER_EVENT, $.proxy(this.handleEnter, this));
26233                }
26234            },
26235
26236            _defineModelEvents : function () {
26237                if (this._model) {
26238                    
26239                    
26240                    this._model.on(guidelib.event.GuideModelEvent.VALUE_CHANGED, this.handleValueChanged, this);
26241                    
26242                    this._model.on(guidelib.event.GuideModelEvent.ERROR_CHANGED, this.handleErrorChanged, this);
26243                    this._model.on(guidelib.event.GuideModelEvent.ERROR_RESET, this.handleErrorReset, this);
26244
26245                }
26246            },
26247
26248            _syncGuideNodeToHtml : function (deepSync) {
26249                GuideFieldView._super._syncGuideNodeToHtml.apply(this, arguments);
26250                if (this._model) {
26251                    var propsToSync = {                  
26252                        "visible" : this._model.visible, 
26253                        "jcr:title" : this._model.title
26254                    };
26255                    _.each(propsToSync, function (value, key, list) {
26256                        this.handleModelChanged(guidelib.event.GuideModelEvent.createEvent(
26257                            guidelib.event.GuideModelEvent.MODEL_CHANGED, this, key, value, value
26258                        ));
26259                    }, this);
26260                    this.$element.attr("data-disabled", !this._model.enabled + "");
26261                }
26262                if (this.$widget) {
26263                    var widgetOptions = this.createWidgetOptions();
26264                    if (!this.jqwidget) {
26265                        this.createWidget(this.getWidgetName(), widgetOptions);
26266                    } else {
26267                        this.setWidgetOptions(widgetOptions);
26268                    }
26269                }
26270                
26271                if (this._model.forceErrorShow && this._model._errorText) {
26272                    this.handleErrorChanged({prevText : this._model.validationState, newText : this._model._errorText});
26273                }
26274
26275                
26276                
26277                
26278                
26279                if (this._guide.jsonModel.textReplacementMap) {
26280                    var footnoteArr = Object.entries(this._guide.jsonModel.textReplacementMap);
26281                    var tempArray = [];
26282                    for (var i = 0; i < footnoteArr.length; i++) {
26283                        
26284                        
26285                        
26286                        if(!tempArray[footnoteArr[i][1]]){
26287                            tempArray[footnoteArr[i][1]] = footnoteArr[i][0];
26288                        }
26289                        var selector = $("span[data-af-footnote-id=" + "\"" + footnoteArr[i][0] + "\"]");
26290                        for (var j = 0; j < $(selector).length; j++) {
26291                            var supTag = document.createElement("sup");
26292                            var anchorTag = document.createElement("a");
26293                            anchorTag.setAttribute("href", "#" + tempArray[footnoteArr[i][1]] + "_ftn");
26294                            anchorTag.setAttribute("data-footnote-id", tempArray[footnoteArr[i][1]]);
26295                            anchorTag.setAttribute("title", $('#' + tempArray[footnoteArr[i][1]]).text());
26296                            anchorTag.innerHTML = footnoteArr[i][1];
26297                            supTag.appendChild(anchorTag);
26298                            $($(selector)[j]).html(supTag.outerHTML);
26299                        }
26300                    }
26301                }
26302            },
26303
26304            setWidgetOptions : function (widgetOptions) {
26305                this.jqwidget.option(widgetOptions);
26306
26307            },
26308
26309            
26310            _markMandatory : function (value) {
26311                if (this._model.mandatory && this.$element) {
26312                    this.$element.attr("data-mandatory", "true");
26313                } else {
26314                    this.$element.removeAttr("data-mandatory");
26315                    
26316                    if (this._model._failedTest === this.guideUtil.MANDATORY_TEST) {
26317                        this._model._guide().runtime.errorManager.unMarkError(this.$element, this._model.somExpression);
26318                    }
26319                }
26320                if (this.jqwidget) {
26321                    this.setWidgetOptions({
26322                        "mandatory" : value
26323                    });
26324                }
26325            },
26326
26327            
26328            _updateEmptyStatus : function (event) {
26329                var val = event ? event.newText : this._model.value;
26330                if (val == null || typeof val === 'string' && val.length == 0) {
26331                    this.$element.removeClass("af-field-filled").addClass("af-field-empty");
26332                } else {
26333                    this.$element.removeClass("af-field-empty").addClass("af-field-filled");
26334                }
26335            },
26336
26337            handleValueChanged : function (event) {
26338                switch (event._property) {
26339                case "value":
26340                    this.jqwidget.option("value", event.prevText);
26341                    this.jqwidget.option("displayValue", event.newText);
26342                    break;
26343                }
26344                this._updateEmptyStatus(event);
26345            },
26346
26347            handleErrorChanged : function (event) {
26348                var value = event.prevText,
26349                    errorMessage = event.newText;
26350                if (value === true) {
26351                    this._model._guide().runtime.errorManager.unMarkError(this.$element, this._model.somExpression);
26352                    this.$element.addClass("validation-success").removeClass("validation-failure");
26353                    this.updateWidgetOption("isValid", true);
26354                } else {
26355                    this._model._guide().runtime.errorManager.markError(errorMessage, this.$element, this._model.somExpression,
26356                        guideBridge.getValidationContext());
26357                    this.$element.addClass("validation-failure").removeClass("validation-success");
26358                    this.updateWidgetOption("isValid", false);
26359                }
26360            },
26361
26362            handleErrorReset : function (event) {
26363                this._model._guide().runtime.errorManager.unMarkError(this.$element, this._model.somExpression);
26364                this.$element.removeClass("validation-failure").removeClass("validation-success");
26365                this.updateWidgetOption("isValid", undefined);
26366            },
26367
26368            handleCommit : function () {
26369                if (this._model.enabled) {
26370                    this.commitValue(this.jqwidget.option("value"));
26371                }
26372            },
26373
26374            handleClick : function (event) {
26375                window.guideBridge.clickedOnWindow = false;
26376            },
26377
26378            handleFocusOut : function (event) {
26379                var gb = window.guideBridge;
26380
26381                if (this.getCommitEvent() !== xfaUtil.XFA_EXIT_EVENT) {
26382                    this._model.executeExpression("exit");
26383                }
26384                if (gb && gb.clickedOnWindow) {
26385                    this._guideView.currentFocusItemSom = null;
26386                }
26387                gb.clickedOnWindow = false;
26388                if (!(this._model.className === 'guideRadioButton'  || this._model.className === 'guideCheckBox' || this._model.className === 'guideButton')) {
26389                    this._triggerOnBridge("elementFocusOut", "", "", "", "");
26390                }
26391                
26392                if ((this.oldValue !== this._model.value) && this._model._errorText) {
26393                    this.handleErrorChanged({prevText : this._model.validationState, newText : this._model._errorText});
26394                }
26395                this.$element.removeClass('guideActiveField');
26396            },
26397
26398            handleModelChanged : function (event) {
26399                switch (event._property) {
26400                    case "enabled":
26401                        
26402                        
26403                        var prop = event.newText ? "open" : "readOnly";
26404                        if (this.jqwidget) {
26405                            this.jqwidget.option("access", prop);
26406                        }
26407                        this.$element.attr("data-disabled", !event.newText + "");
26408                        break;
26409                    case "mandatory":
26410                        
26411                        this._markMandatory(this._model.mandatory);
26412                        break;
26413                    case "validateExpMessage":
26414                        var newText = event.jsonModel.newText;
26415                        this._changeValidationMessage(newText);
26416                        break;
26417                    case "jcr:title":
26418                        
26419                        var newText = event.jsonModel.newText;
26420                        this._changeTitle(newText);
26421                        break;
26422                    default:
26423                        GuideFieldView._super.handleModelChanged.apply(this, arguments);
26424                }
26425            },
26426
26427            
26428            _changeTitle : function (newText) {
26429                var $field = $("#" + this.id),
26430                    $guideFieldLabelDiv = $field.children(".guideFieldLabel"),
26431                    $labelDiv = $guideFieldLabelDiv.children("label");
26432                if ($labelDiv) {
26433                    newText =  DOMPurify.sanitize(newText);
26434                    $labelDiv.html(newText);
26435                }
26436            },
26437
26438            
26439            _changeValidationMessage : function (newText) {
26440                var $fieldNode = $("#" + this.id),
26441                    $errorDiv = $fieldNode.children(".guideFieldError");
26442                $errorDiv.html(newText);
26443            },
26444
26445            
26446            commitValue : function (value) {
26447                this._model.value = value;
26448                var _version = this._model._guide().version;
26449                if (!(_version.isOn(_version.Flags.RUN_VALUE_COMMMIT_ON_SCRIPT_CHANGE))) {
26450                    this._model.executeExpression("valueCommitScript");
26451                }
26452                
26453                
26454                if (this.getCommitEvent() === xfaUtil.XFA_CHANGE_EVENT) {
26455                    this._model.executeExpression("change");
26456                } else {
26457                    this._model.executeExpression("exit");
26458                }
26459            },
26460
26461            
26462            tempXfaFixes : function () {
26463                
26464                
26465                
26466                if (this.$element) {
26467                    this.$element.find("input").css("position", "relative");
26468                }
26469                this.handleAccessibility();
26470            },
26471
26472            handleAccessibility : function () {
26473                
26474                if (this._model.mandatory) {
26475                    this.$widget.find("input,textarea,select,button").attr("aria-required", true);
26476                }
26477                if(this._model._getToolTip())  {
26478                    this.$element.find("input,textarea,select,button").attr("aria-labelledby",this._model.id + "_widget" + " " + this._model.id + "_guideFieldShortDescription");
26479                }
26480                if (this._model._getScreenReaderText() === this._model._getToolTip()) {
26481                    this.$element.find("input,textarea,select,button").removeAttr("aria-label");
26482                    this.$element.find("input,textarea,select,button").attr("aria-labelledby",this._model.id + "_guideFieldShortDescription");
26483                }
26484            },
26485
26486            
26487            _getWidgetInitialOptions : function ($widget) {
26488                var $elem = $widget.find('[data-af-widgetname]').addBack('[data-af-widgetname]');
26489                if ($elem.length > 0) {
26490                    this.logger().info("AF", "Getting widget options for " + this._model.somExpression);
26491                    var optionsMap = $elem.data('af-widgetoptions') || {};
26492                    _.each($elem[0].attributes, function (attr) {
26493                        var nm = attr.name.match(/data-af-widgetoption-([^-]+)$/);
26494                        if (nm != null && nm.length > 1) {
26495                            this.logger().info("AF", "adding option " + nm[1] + " with value " + " ");
26496                            optionsMap[nm[1]] = attr.value;
26497                        }
26498                    }, this);
26499                    return optionsMap;
26500                }
26501                return {};
26502            },
26503
26504            _newWidget : function (widgetname, options, $widgetElem) {
26505                var jqwidget = null,
26506                    fixesRequired = widgetname == this._defaultWidget
26506Name;
26507                try {
26508                    
26509                    $widgetElem[widgetname](options);
26510                    
26511                    
26512                    jqwidget = $widgetElem.data(widgetname) || $widgetElem.data('xfaWidget-' + widgetname);
26513                } catch (e) {
26514                    this.logger().error("AF", "widget " + widgetname + " doesn't exists. Falling back to default widget");
26515                    fixesRequired = true;
26516                    jqwidget = $widgetElem[this._defaultWidgetName](options).data('xfaWidget-' + widgetname);
26517                }
26518                
26519                if (fixesRequired) {
26520                    this.tempXfaFixes();
26521                }
26522                return jqwidget;
26523            },
26524
26525            createWidget : function (widgetname, options) {
26526                var initialOptions = this._getWidgetInitialOptions(this.$widget);
26527                var _options = $.extend({}, options, initialOptions);
26528                this.jqwidget = this._newWidget(widgetname, _options, this.$widget);
26529            },
26530
26531            handleEnter : function () {
26532                this._guideView.currentFocusItemSom = this._model.somExpression;
26533                var gb = window.guideBridge;
26534                if (gb) {
26535                    gb.clickedOnWindow = false;
26536                }
26537                if (!(this._model.className === 'guideRadioButton' || this._model.className === 'guideCheckBox' || this._model.className === 'guideButton')) {
26538                    this._triggerOnBridge("elementFocus", "", "", "", "");
26539                }
26540                this.oldValue = this._model.value;
26541                this.$element.addClass('guideActiveField');
26542            },
26543
26544            handleChange : function () {
26545
26546            },
26547
26548            setActive : function (activeItemToken, focus, muteScripts) {
26549                GuideFieldView._super.setActive.call(this, activeItemToken, focus, muteScripts);
26550                if (focus) {
26551                    
26552                    if (!this._guideView.skipFieldFocus && this.jqwidget && this.jqwidget.focus) {
26553                        this.jqwidget.focus();
26554                        this._guideView.currentFocusItemSom = this._model.somExpression;
26555                    }
26556
26557                }
26558                return true;
26559            },
26560
26561            updateWidgetOption : function (optionName, optionValue) {
26562                
26563                if (this.jqwidget) {
26564                    this.jqwidget.option(optionName, optionValue);
26565                }
26566            }
26567
26568        });
26569}($, guidelib, _));
26570(function ($, guidelib) {
26571    var GuideCaptchaView = guidelib.view.GuideCaptchaView = guidelib.view.GuideFieldView.extend({
26572        
26573        _defaultWidgetName : "afcaptcha",
26574
26575        syncGuideNodeToHtml : true,
26576
26577        initialize : function () {
26578            
26579            if (this.options.model.isWidgetRecaptcha) {
26580                if ((this.options.model.captchaEnterprise && !this.options.model.checkBoxkey) ||
26581                    (this.options.model.captchaInvisible && this.options.model.mandatory)) {
26582                    this._model = this.options.model;
26583                    this.syncGuideNodeToHtml = false;
26584                    return;
26585                } else if (this.options.model.captchaInvisible) {
26586                    this.options.element.classList.add("af-hideRecaptchaView");
26587                    this.options.model.captchaValidate = false;
26588                }
26589            } else if ((this.options.model.isWidgetTurnstile || this.options.model.isWidgetHcaptcha) && this.options.model.captchaInvisible) {
26590                this._model = this.options.model;
26591                this.syncGuideNodeToHtml = false;
26592                return;
26593            }
26594            GuideCaptchaView._super.initialize.apply(this, arguments);
26595            if (this._model.captchaWidget) {
26596                
26597                this._defaultWidgetName = this._model.captchaWidget;
26598            }
26599        },
26600
26601        _initializeWidget : function () {
26602            GuideCaptchaView._super._initializeWidget.apply(this, arguments);
26603            if (this.$widget.length > 0) {
26604                this.$widget.on("tokenChange.captcha", $.proxy(this.handleTokenChange, this));
26605            }
26606        },
26607
26608        _syncGuideNodeToHtml : function (deepSync) {
26609            if(!this.syncGuideNodeToHtml)
26610                return;
26611            GuideCaptchaView._super._syncGuideNodeToHtml.call(this, deepSync);
26612        },
26613
26614        handleTokenChange : function (event) {
26615            this._model.value = event.token;
26616        },
26617
26618        createWidgetOptions : function () {
26619            var options = GuideCaptchaView._super.createWidgetOptions.apply(this, arguments);
26620            return $.extend({}, options, {
26621                "captchaConfigData" : this.options.model.jsonModel
26622            });
26623        },
26624
26625        handleErrorChanged : function (event) {
26626                var value = event.prevText,
26627                    errorMessage = event.newText;
26628                if (value === false) {
26629                    this._model._guide().runtime.errorManager.markError(errorMessage, this.$element, this._model.somExpression,
26630                    guideBridge.getValidationContext());
26631                    this.$element.addClass("validation-failure").removeClass("validation-success");
26632                } else {
26633                    this.$element.addClass("validation-success").removeClass("validation-failure");
26634                }
26635            }
26636    });
26637}($, guidelib));
26638(function ($, guidelib, _) {
26639    var xfaUtil = xfalib.ut.XfaUtil.prototype,
26640        GuideCompositeFieldView = guidelib.view.GuideCompositeFieldView = guidelib.view.GuideFieldView.extend({
26641            _defaultWidgetName : "defaultField",
26642
26643            
26644            getModelNameOptionsMap : function () {
26645                return {};
26646            },
26647
26648            initialize : function () {
26649                GuideCompositeFieldView._super.initialize.call(this);
26650                this._defineChildModelEvents();
26651            },
26652
26653            postInitialize : function () {
26654                GuideCompositeFieldView._super.postInitialize.call(this);
26655                var _self = this;
26656                if (this.getModelNameOptionsMap()) {
26657                    _.each(this.getModelNameOptionsMap(), function (value, modelName) {
26658                        var childModel = _self._model[modelName];
26659                        if (childModel._errorText) {
26660                            childModel._triggerEvent(guidelib.event.GuideModelEvent.ERROR_CHANGED,
26661                                "validationStatus", childModel.validationState, childModel._errorText);
26662                        }
26663                    });
26664                }
26665            },
26666
26667            _unloadView : function () {
26668                var _self = this;
26669                if (this.getModelNameOptionsMap()) {
26670                    _.each(this.getModelNameOptionsMap(), function (value, modelName) {
26671                        var obj = _self._model[modelName];
26672                        
26673                        obj.off(guidelib.event.GuideModelEvent.VALUE_CHANGED, _self.handleValueChanged, _self);
26674                        if (obj.mandatory || obj.validateExp) {
26675                            obj.off(guidelib.event.GuideModelEvent.ERROR_CHANGED, _self.handleErrorChanged, _self);
26676                            obj.off(guidelib.event.GuideModelEvent.ERROR_RESET, _self.handleErrorReset, _self);
26677                        }
26678                    });
26679
26680                }
26681                GuideCompositeFieldView._super._unloadView.call(_self);
26682            },
26683
26684            _defineChildModelEvents : function () {
26685                var _self = this;
26686                if (this.getModelNameOptionsMap()) {
26687                    _.each(this.getModelNameOptionsMap(), function (value, modelName) {
26688                        var obj = _self._model[modelName];
26689                        
26690                        obj.on(guidelib.event.GuideModelEvent.VALUE_CHANGED, _self.handleValueChanged, _self);
26691                        
26692                        
26693                        if (obj.mandatory || obj.validateExp) {
26694                            obj.on(guidelib.event.GuideModelEvent.ERROR_CHANGED, _self.handleErrorChanged, _self);
26695                            obj.on(guidelib.event.GuideModelEvent.ERROR_RESET, _self.handleErrorReset, _self);
26696                        }
26697                    });
26698
26699                }
26700            },
26701
26702            handleCommit : function () {
26703                var _self = this;
26704                if (!_.isEmpty(this.getModelNameOptionsMap())) {
26705                    _.each(this.getModelNameOptionsMap(), function (value, modelName) {
26706                        var obj = _self._model[modelName];
26707                        if (!_.isUndefined(obj)) {
26708                            var val = _self.jqwidget.option(value);
26709                            if (_.isArray(val)) {
26710                                val = val.join("\n");
26711                            }
26712                            obj.value = val;
26713                        }
26714                    });
26715                } else {
26716                    this._model.value = this.jqwidget.option("value");
26717                }
26718                this._model.executeExpression("valueCommitScript");
26719                this.execCommitExpression();
26720            },
26721
26722            handleValueChanged : function (event) {
26723                
26724                
26725                switch (event._property) {
26726                    case "value":
26727                        var map = this.getModelNameOptionsMap();
26728                        this.jqwidget.option(map[event.target.name], event.prevText);
26729                        break;
26730                }
26731            },
26732
26733            execCommitExpression : function () {
26734                
26735                if (this.getCommitEvent() == xfaUtil.XFA_CHANGE_EVENT) {
26736                    this._model.executeExpression("change");
26737                } else {
26738                    this._model.executeExpression("exit");
26739                }
26740            }
26741        });
26742}($, guidelib, _));
26743(function ($, guidelib) {
26744    var GuideFileUploadView = guidelib.view.GuideFileUploadView = guidelib.view.GuideCompositeFieldView.extend({
26745        _defaultWidgetName : "fileUpload",
26746
26747        initialize : function () {
26748            GuideFileUploadView._super.initialize.call(this);
26749            
26750            this._blockDoubleExtensions = this._readDoubleExtensionConfig();
26751        },
26752
26753        
26754        _readDoubleExtensionConfig: function () {
26755            var $widget = this.$element.hasClass('afFileUpload') ? this.$element : this.$element.find('.afFileUpload');
26756            var disableDoubleExtension = $widget.data('disableDoubleExtensionFiles');
26757            return disableDoubleExtension === true || disableDoubleExtension === "true";
26758        },
26759
26760        getModelNameOptionsMap : function () {
26761            var map = GuideFileUploadView._super.getModelNameOptionsMap.apply(this, arguments);
26762            return $.extend({}, map, {
26763                "fileAttachment" : "value",
26764                "comment" : "comment"
26765            });
26766        },
26767
26768        createWidgetOptions : function () {
26769            var options = GuideFileUploadView._super.createWidgetOptions.apply(this, arguments),
26770                fileNamesStr = this._model._getFileAttachmentNames(),
26771                fileNamesArr = [];
26772            if (fileNamesStr) {
26773                fileNamesArr = fileNamesStr.split("\n");
26774            }
26775            return $.extend({}, options, {
26776                fileList : this._model.fileList,
26777                buttonText  : this._model.buttonText,
26778                multiSelect : this._model.multiSelection,
26779                fileSizeLimit : this._model.fileSizeLimit,
26780                mimeType : this._model.getOrElse(this._model.jsonModel, "mimeType", ""),
26781                buttonClass : "button.guide-fu-attach-button",
26782                fileItemListClass : "ul.guide-fu-fileItemList",
26783                iframeContainer : "div.guideContainerWrapperNode",
26784                showComment :  this._model.showComment,
26785                value : this._model.fileAttachment.value,
26786                fileNames : fileNamesArr,
26787                comment : this._model.comment.value,
26788                _uuidGenerator : function () { return guideBridge._getUUID.apply(this); }, 
26789                _filePath : "/tmp/fd/af",           
26790                _getUrl : guideBridge._getUrl(""),  
26791                disablePreview : false, 
26792                uploaderPluginName : guideBridge.userConfig.uploaderPluginName || "adobeFileUploader"
26793            });
26794        },
26795
26796        handleCommit : function () {
26797            
26798            
26799            
26800            if (!this._blockDoubleExtensions) {
26801                this._model.fileList = this.jqwidget.option("fileList");
26802                GuideFileUploadView._super.handleCommit.apply(this, arguments);
26803            } else {
26804                var fileList = this.jqwidget.option("fileList") || [];     
26805                var filtered = this._filterFileList(fileList);
26806                var validFiles = filtered.validFiles;
26807                var invalidFiles = filtered.invalidFiles;
26808
26809                if (invalidFiles.length > 0) {
26810                    alert("Files with multiple extensions are not allowed:\n" + invalidFiles.join("\n"));
26811                }
26812                this._updateFileList(validFiles);
26813
26814                this._model.fileAttachment.value = (this._model.fileList || [])
26815                    .map(this._extractFileName.bind(this))
26816                    .filter(Boolean)
26817                    .join("\n");
26818            }
26819        },
26820
26821        
26822        _extractFileName: function (fileItem) {
26823            if (typeof fileItem === "string") {
26824                return fileItem;
26825            } else if (fileItem && fileItem.name) {
26826                return fileItem.name;
26827            } else if (fileItem && fileItem[0] && fileItem[0].files && fileItem[0].files.length > 0) {
26828                return fileItem[0].files[0].name;
26829            }
26830            return "";
26831        },
26832
26833        
26834        _renderFileListUI: function () {
26835            var self = this;
26836            var $ul = this.$element.find("ul.guide-fu-fileItemList");
26837            $ul.empty();
26838
26839            (this._model.fileList || []).forEach(function(fileItem) {
26840                var name = self._extractFileName(fileItem);
26841                if (name) {
26842                    $ul.append("<li class='guide-fu-fileItem'>" + name + "</li>");
26843                }
26844            });
26845        },
26846
26847        
26848        _updateFileList: function (fileList) {
26849            this._model.fileList = fileList;
26850            this.jqwidget.option("fileList", fileList);
26851            this._renderFileListUI();
26852        },
26853
26854        
26855        _filterFileList: function (fileList) {
26856            var self = this;
26857            var invalidFiles = [];
26858            var validFiles = [];
26859
26860            if (!fileList || !fileList.length) return { invalidFiles: invalidFiles, validFiles: validFiles };
26861
26862            for (var i = 0; i < fileList.length; i++) {
26863                var fileItem = fileList[i];
26864                
26865                if (fileItem && fileItem[0] && fileItem[0].files) {
26866                    var hasInvalidFile = false;
26867                    for (var j = 0; j < fileItem[0].files.length; j++) {
26868                        var file = fileItem[0].files[j];
26869                        if (this._hasDoubleExtension(file.name)) {
26870                            invalidFiles.push(file.name);
26871                            hasInvalidFile = true;
26872                        }
26873                    }
26874                    if (!hasInvalidFile) {
26875                        validFiles.push(fileItem); 
26876                    }
26877                } else {
26878                    
26879                    var fileName = this._extractFileName(fileItem);
26880                    if (fileName) {
26881                        if (this._hasDoubleExtension(fileName)) {
26882                            invalidFiles.push(fileName);
26883                        } else {
26884                            validFiles.push(fileItem);
26885                        }
26886                    }
26887                }
26888            }
26889            return { invalidFiles: invalidFiles, validFiles: validFiles };
26890        },
26891
26892        
26893        _hasDoubleExtension: function (fileName) {
26894            return fileName && fileName.split('.').length > 2;
26895        },
26896
26897        handleModelChanged : function (event) {
26898            switch (event._property) {
26899                case "fileList":
26900                    if (this._blockDoubleExtensions) {
26901                        this.jqwidget.option("fileList", this._model.fileList || []);
26902                        this._renderFileListUI();
26903                    } else {
26904                        this.jqwidget.option("fileList", event.prevText);
26905                    }
26906                    break;
26907                default:
26908                    GuideFileUploadView._super.handleModelChanged.apply(this, arguments);
26909                    break;
26910            }
26911        },
26912
26913        handleAccessibility : function () {
26914            
26915            
26916            var isBrowserIE9OrIE10 = ($.browser.msie && ($.browser.version === '9.0' || $.browser.version === '10.0'));
26917            if (isBrowserIE9OrIE10) {
26918                if (this._model.mandatory) {
26919                    this.$widget.attr("aria-required", true);
26920                }
26921                if (this._model._getScreenReaderText() === this._model._getToolTip()) {
26922                    this.$widget.removeAttr("aria-label");
26923                    this.$widget.attr("aria-labelledby", this._model.id + "_guideFieldShortDescription");
26924                }
26925            } else {
26926                GuideFileUploadView._super.handleAccessibility.apply(this, arguments);
26927            }
26928        },
26929
26930        setActive : function (activeItemToken, focus, muteScripts) {
26931            guidelib.view.GuideFieldView._super.setActive.call(this, activeItemToken, focus, muteScripts);
26932            if (focus) {
26933                this._guideView.currentFocusItemSom = this._model.somExpression;
26934                this.$element.find("button").focus();
26935            }
26936            return true;
26937        },
26938
26939        
26940        
26941        tempXfaFixes : function () {
26942            
26943            this.handleAccessibility();
26944        },
26945
26946        getCommitEvent : function () {
26947            return xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT;
26948        }
26949    });
26950}($, guidelib));
26951(function ($, guidelib) {
26952    var GuideTermsAndConditionsView = guidelib.view.GuideTermsAndConditionsView = guidelib.view.GuideCompositeFieldView.extend({
26953        _defaultWidgetName : "tnc",
26954
26955        getModelNameOptionsMap : function () {
26956            var map = GuideTermsAndConditionsView._super.getModelNameOptionsMap.apply(this, arguments);
26957            return $.extend({}, map, {
26958                "reviewDocument" : "value",
26959                "reviewStatus" : "reviewStatus"
26960            });
26961        },
26962
26963        createWidgetOptions : function () {
26964            var options = GuideTermsAndConditionsView._super.createWidgetOptions.apply(this, arguments);
26965            return $.extend({}, options, {
26966                textAreaClass : ".guide-tnc-content",
26967                checkBoxClass : ".guide-tnc-checkbox",
26968                linkClass     : ".guide-tnc-link",
26969                checkBoxDisableClass : ".guide-tnc-checkbox-disabled",
26970                checkBoxReviewedClass : ".guide-tnc-checkbox-reviewed",
26971                showLink      :  this._model.showLink,
26972                showAsPopUp   :  this._model.showAsPopUp,
26973                value : this._model.reviewDocument.value,
26974                reviewStatus : this._model.reviewStatus.value,
26975                clickStatus  : this._model.clickStatus
26976            });
26977        },
26978
26979        
26980        tempXfaFixes : function () {
26981            
26982            
26983            
26984            if (this.$widget) {
26985                this.$widget.css("position", "relative");
26986            }
26987
26988        },
26989
26990        handleCommit : function (event) {
26991            
26992            this._model.clickStatus = this.jqwidget.option("clickStatus");
26993            
26994            GuideTermsAndConditionsView._super.handleCommit.apply(this, arguments);
26995        },
26996
26997        handleModelChanged : function (event) {
26998            
26999            
27000            switch (event._property) {
27001                case "clickStatus":
27002                    this.jqwidget.option("clickStatus", event.prevText);
27003                    break;
27004                default:
27005                    GuideTermsAndConditionsView._super.handleModelChanged.apply(this, arguments);
27006                    break;
27007            }
27008        },
27009
27010        getCommitEvent : function () {
27011            return xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT;
27012        }
27013    });
27014}($, guidelib));
27015(function ($, guidelib) {
27016    var GuideTelephoneView = guidelib.view.GuideTelephoneView = guidelib.view.GuideFieldView.extend({
27017        
27018        _defaultWidgetName : "telephoneWidget",
27019
27020        createWidgetOptions : function () {
27021            var options = GuideTelephoneView._super.createWidgetOptions.apply(this, arguments);
27022            return $.extend({}, options, {
27023                placeholder : this._model.placeholderText
27024            });
27025        }
27026
27027    });
27028}($, guidelib));
27029
27030(function ($, guidelib) {
27031    var GuideTextDrawView = guidelib.view.GuideTextDrawView = guidelib.view.GuideFieldView.extend({
27032        _defaultWidgetName : "abstractWidget",
27033
27034        initialize : function () {
27035            GuideTextDrawView._super.initialize.call(this);
27036            if (this.$element && this.$element.length > 0) {
27037                $(this.$element)
27038                    .on("focus.guideTextDraw", $.proxy(this.handleEnter, this))
27039                    .on("click.guideTextDraw", $.proxy(this.handleClick, this));
27040            }
27041        },
27042
27043        _syncGuideNodeToHtml : function (deepSync) {
27044            GuideTextDrawView._super._syncGuideNodeToHtml.call(this, deepSync);
27045            
27046            
27047            var isFloatingField = this._model._isFloatingField();
27048            var isParentLazy = guidelib.util.GuideUtil._checkIfAncestorIsALazyReference(this);
27049            if (!isParentLazy && this._model.value === this._model.jsonModel._value && this.$element.html() !== this._model.value && !isFloatingField) {
27050                
27051                
27052            } else {
27053                this.handleValueChanged({
27054                    _property : "value",
27055                    newText : this._model.value ? this._model.value : ""
27056                });
27057            }
27058        },
27059
27060        handleValueChanged : function (event) {
27061            switch (event._property) {
27062                case "value":
27063                    this.$element.html(event.newText);
27064                    break;
27065            }
27066        },
27067
27068        setActive : function (activeItemToken, focus, muteScripts) {
27069            guidelib.view.GuideFieldView._super.setActive.call(this, activeItemToken, focus, muteScripts);
27070            if (focus && !this._guideView.skipFieldFocus) {
27071                if (this.$element) {
27072                    this.$element.focus();
27073                }
27074                this._guideView.currentFocusItemSom = this._model.somExpression;
27075            }
27076            return true;
27077        }
27078    });
27079}($, guidelib));
27080
27081
27082(function ($, guidelib) {
27083    var GuideAdobeSignBlockView = guidelib.view.GuideAdobeSignBlockView = guidelib.view.GuideTextDrawView.extend({
27084    });
27085}($, guidelib));
27086(function ($, guidelib) {
27087    var GuideButtonView = guidelib.view.GuideButtonView = guidelib.view.GuideFieldView.extend({
27088        _defaultWidgetName : "xfaButton",
27089
27090        handleClick : function (event) {
27091            this._triggerOnBridge("elementButtonClicked", this._model, "click", "", "");
27092            this._model.executeExpression("clickExp");
27093            GuideButtonView._super.handleClick.call(this);
27094        },
27095
27096        _changeTitle : function (newText) {
27097            var $fieldTitleSpan = $("#" + this.id + "_widget");
27098            var $buttonLabel = $fieldTitleSpan.children("[data-guide-button-label]");
27099            newText =  DOMPurify.sanitize(xfalib.ut.XfaUtil.prototype.encodeScriptableTags(newText));
27100            $buttonLabel.html(newText);
27101        },
27102
27103        tempXfaFixes : function () {
27104            
27105            
27106            
27107            if (this.$element) {
27108                this.$element.find("button").css("position", "relative");
27109            }
27110            this.handleAccessibility();
27111        }
27112
27113    });
27114}($, guidelib));
27115(function ($, guidelib, _) {
27116    var fileInputIdCounter = 0;
27117    var GuideListFileAttachmentButtonView = guidelib.view.GuideListFileAttachmentButtonView = guidelib.view.GuideButtonView.extend({
27118        
27119        _clearFileListing : function () {
27120            $('#fileAttachment .modal-list', window.document).children().remove();
27121            _.each(this._fileListViews, function (childView) {
27122                childView._unloadView();
27123            }, this);
27124            this._fileListViews = [];
27125            fileInputIdCounter = 0;
27126        },
27127        _updateFileListing : function (fileAttachmentModel) {
27128            if (fileAttachmentModel.className == "guideFileUpload") {
27129                var $htmlTemplate = this._guideView.$element.find("#" + fileAttachmentModel.id),
27130                    inputFileSelector = "#" + fileAttachmentModel.id + "_widget",
27131                
27132                
27133                
27134                
27135                
27136                    $cloneHtmlTemplate = $htmlTemplate.clone();
27137                
27138                $cloneHtmlTemplate.find(inputFileSelector).attr("id", fileAttachmentModel.id + "_widget" + (++fileInputIdCounter));
27139                this._addSuffixToHelpIds($cloneHtmlTemplate, fileInputIdCounter);
27140                var $fluidDesign = $('<div></div>').addClass("row").append('<div class="col-md-12"></div>');
27141                $('#fileAttachment .modal-list', window.document).append($cloneHtmlTemplate.appendTo($fluidDesign));
27142                var view = guidelib.view.GuideViewRegistry.prototype.createView($cloneHtmlTemplate, this);
27143                this._fileListViews.push(view);
27144                view.postInitialize();
27145
27146            }
27147        },
27148        _addSuffixToHelpIds : function ($html, suffix) {
27149            var $questionMarkElement = $html.find("[data-guide-longDescription]"),
27150                $shortHelpElement;
27151            if ($questionMarkElement.length > 0) {
27152                var idForLongHelp = $questionMarkElement.attr("data-guide-longDescription"),
27153                    $longHelpElement = $(".guideFieldDescription.long", $html);
27154                idForLongHelp = idForLongHelp + suffix;
27155                $longHelpElement.attr("id", idForLongHelp);
27156                $questionMarkElement.attr("data-guide-longDescription", idForLongHelp);
27157            }
27158            
27159
27160        },
27161
27162        
27163        _markFileListing : function () {
27164            if (this.$element) {
27165                this.$element.find("button").attr("data-guide-fileListing", true);
27166            }
27167        },
27168
27169        initialize : function () {
27170            GuideListFileAttachmentButtonView._super.initialize.apply(this, arguments);
27171            this._markFileListing();
27172            
27173            
27174            this._fileListViews = [];
27175        }
27176    });
27177}($, guidelib, _));
27178(function ($, guidelib, _) {
27179    var xfaUtil = xfalib.ut.XfaUtil.prototype,
27180        GuideDropDownListView = guidelib.view.GuideDropDownListView = guidelib.view.GuideFieldView.extend({
27181
27182            _defaultWidgetName : "dropDownList",
27183
27184            initialize : function () {
27185                GuideDropDownListView._super.initialize.apply(this, arguments);
27186                if (this._model.multiSelect) {
27187                    this._defaultWidgetName = "listBox";
27188                }
27189            },
27190
27191            _valueToArray : function (value) {
27192                var valueArray;
27193                if (value !== null && !_.isUndefined(value)) {
27194                    if (_.isString(value)) {
27195                        valueArray = value.split("\n");
27196                    } else if (_.isNumber(value)) {
27197                        valueArray = [value.toString()];
27198                    }
27199                } else {
27200                    valueArray = [null];
27201                }
27202                return valueArray;
27203            },
27204
27205            createWidgetOptions : function () {
27206                var options = GuideDropDownListView._super.createWidgetOptions.apply(this, arguments);
27207                
27208                
27209                return $.extend({}, options, {
27210                    multiSelect : this._model.multiSelect,
27211                    editable : false,
27212                    items : this._model._getOptionsArray("save", "display"),
27213                    value : this._valueToArray(this._model.value),
27214                    placeholder : this._model.placeholderText
27215                });
27216            },
27217
27218            
27219            handleCommit : function () {
27220                var val = this.jqwidget.option("value");
27221                if (_.isArray(val)) {
27222                    val = val.join("\n");
27223                }
27224                
27225                this.commitValue(val);
27226            },
27227
27228            
27229            commitValue : function (value) {
27230                var oldValue = this._model.value;
27231                this._model.value = value;
27232                
27233                
27234                
27235                var _version = this._model._guide().version;
27236                if (!(_version.isOn(_version.Flags.RUN_VALUE_COMMMIT_ON_SCRIPT_CHANGE))) {
27237                    this._model.executeExpression("valueCommitScript");
27238                }
27239                if (this.getCommitEvent() === xfaUtil.XFA_CHANGE_EVENT) {
27240                    
27241                    
27242                    
27243                    
27244                    
27245                    this._model.executeExpression("change", {
27246                        "prevText" : oldValue,
27247                        "newText" : this._model.value
27248                    });
27249                } else {
27250                    
27251                    this._model.executeExpression("exit");
27252                }
27253            },
27254
27255            handleValueChanged : function (event) {
27256                this.jqwidget.option("value", this._valueToArray(event.prevText));
27257                this.jqwidget.option("displayValue", this._valueToArray(event.
27257newText));
27258                this._updateEmptyStatus(event);
27259            },
27260
27261            getCommitEvent : function () {
27262                return xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT;
27263            },
27264
27265            handleModelChanged : function (event) {
27266                if (event._property === "addItem") {
27267                    this._handleAddItem(event);
27268                }
27269                if (event._property === "clearItems") {
27270                    this._handleClearItems(event);
27271                }
27272                if (event._property === "deleteItem") {
27273                    this._handleDeleteItem(event);
27274                } else {
27275                    GuideDropDownListView._super.handleModelChanged.apply(this, arguments);
27276                }
27277            },
27278
27279            _handleAddItem : function (event) {
27280                var itemValues = {
27281                    sDisplayVal : event.newText,
27282                    sSaveVal : event.prevText
27283                };
27284                this.jqwidget.addItem(itemValues);
27285            },
27286
27287            _handleClearItems : function (event) {
27288                this.jqwidget.clearItems();
27289            },
27290
27291            _handleDeleteItem : function (event) {
27292                this.jqwidget.deleteItem(event.newText);
27293            },
27294
27295            handleItemsChanged : function (event) {
27296                var items = this._model._getOptionsArray("save", "display");
27297                this.jqwidget.option("items", items);
27298                this.jqwidget.option("value", this._valueToArray(this._model.jsonModel._value));
27299                this.jqwidget.option("displayValue", this._valueToArray(this._model.formattedValue));
27300            },
27301
27302            _defineModelEvents : function () {
27303                GuideDropDownListView._super._defineModelEvents.apply(this, arguments);
27304                if (this._model) {
27305                    
27306                    this._model.on(guidelib.event.GuideModelEvent.ITEMS_CHANGED, this.handleItemsChanged, this);
27307                }
27308            },
27309
27310            
27311            tempXfaFixes : function () {
27312                
27313                
27314                if (this.$element) {
27315                    if (!this._model.multiSelect) {
27316                        this.$element.find("select")
27317                            .css("position", "relative")
27318                            .attr("id", this._model.id + "_widget")
27319                            .attr("aria-describedby", this._model.id + "_widget_desc");
27320                    } else {
27321                        
27322                        if (this._model.height) {
27323                            this.$element.find("ol").css("max-height", "none");
27324                        }
27325                        this.$element.find("ol")
27326                            .css("position", "relative")
27327                            .attr("id", this._model.id + "_widget");
27328                    }
27329                }
27330                this.handleAccessibility();
27331            }
27332        });
27333
27334}($, guidelib, _));
27335(function ($, guidelib, _) {
27336    var GuideCheckBoxView = guidelib.view.GuideCheckBoxView = guidelib.view.GuideFieldView.extend({
27337        _defaultWidgetName : "XfaCheckBox",
27338        initialize : function () {
27339            GuideCheckBoxView._super.initialize.apply(this, arguments);
27340            this._setListenersForLabelClick();
27341            this._setListenersForRadioButtonKeyPress();
27342        },
27343        
27344        _setListenersForLabelClick : function () {
27345            var self = this;
27346            this.$element
27347                .find(".guideWidgetLabel")
27348                .each(function (index, item) {
27349                    $(item).click(
27350                        (function (index) {
27351                            return function () {
27352                                
27353                                if (self._model.enabled) {
27354                                    self.jqwidget[self.getJQWidgetIdentifier(index)].click();
27355                                }
27356                            };
27357                        }(index))
27358                    );
27359                });
27360        },
27361
27362        _setListenersForRadioButtonKeyPress : function () {
27363            var self = this;
27364            this.$element
27365                .find(".guideRadioButtonItem")
27366                .each(function (index, item) {
27367                    $(item).keypress(function (e){
27368                        if(e.keyCode == "13" || e.keyCode == "32"){
27369                            e.preventDefault();
27370                            if (self._model.enabled) {
27371                                self.jqwidget[self.getJQWidgetIdentifier(index)].click();
27372                            }
27373                        }
27374                    });
27375                });
27376        },
27377        _syncGuideNodeToHtml : function (deepSync) {
27378            if (this._model._isStateOverridden("options")) {
27379                this._replaceGroupItemsWithNewOptions(this._model._getOptionsArray(), this._model.getAttribute("alignment"));
27380                
27381                
27382                
27383                
27384                this.jqwidget = null; 
27385
27386            }
27387            GuideCheckBoxView._super._syncGuideNodeToHtml.apply(this, arguments);
27388        },
27389        getJQWidgetIdentifier : function (index) {
27390            return index;
27391        },
27392
27393        createWidgetOptions : function () {
27394            var options = GuideCheckBoxView._super.createWidgetOptions.apply(this, arguments);
27395
27396            return $.extend({}, options, {
27397                states : 2
27398            });
27399        },
27400
27401        getCommitEvent : function () {
27402            return xfalib.ut.XfaUtil.prototype.XFA_CHANGE_EVENT;
27403        },
27404
27405        getStateFromValue : function (value, items) {
27406            if (value === null) {
27407                return 1;
27408            }
27409            var valuesArray = null;
27410            if (value && value.indexOf && value.indexOf("\\,") > -1) {
27411                valuesArray = this.splitOnNonEscapedCommas(value);
27412            } else {
27413                valuesArray = (value + "").split(",");
27414            }
27415            if (valuesArray && valuesArray.indexOf(items[0] + "") !== -1)  {
27416                return 0;
27417            }
27418            return 1;
27419        },
27420
27421        getOnOffValueFromModelValue : function (val, items) {
27422            return items[this.getStateFromValue(val, items)];
27423        },
27424
27425        splitOnNonEscapedCommas : function (string) {
27426            var splitArray = [];
27427            var currentSubstring = '';
27428            var escaped = false;
27429
27430            for (var i = 0; i < string.length; i++) {
27431                var char = string[i];
27432
27433                if (char === ',' && !escaped) {
27434                    splitArray.push(currentSubstring.trim());
27435                    currentSubstring = '';
27436                } else {
27437                    currentSubstring += char;
27438                    escaped = (char === '\\' && !escaped);
27439                }
27440            }
27441            splitArray.push(currentSubstring.trim()); 
27442            return splitArray;
27443        },
27444
27445        handleValueChanged : function (event) {
27446            _.each(this.jqwidget, function (jqwidget) {
27447                var setVal = this.getOnOffValueFromModelValue(event.prevText, this._escapeCommas(jqwidget.option("values")));
27448                setVal = this._unescapeCommas(setVal);
27449                jqwidget.option("value", setVal);
27450                jqwidget.option("displayValue", setVal);
27451            }, this);
27452            this.$widget.find("[checked!=checked]").parents(".guideCheckBoxItem").removeClass('guideItemSelected');
27453            this.$widget.find("[checked=checked]").parents(".guideCheckBoxItem").addClass('guideItemSelected');
27454        },
27455
27456        _escapeCommas : function (items) {
27457            var temp = _.clone(items);
27458            if(temp[0] && temp[0].indexOf && temp[0].indexOf(',') > -1 && temp[0].indexOf('\\,') === -1) {
27459                temp[0] = temp[0].replace(/,/g, "\\,"); 
27460            }
27461            return temp;
27462        },
27463
27464        _unescapeCommas : function (value) {
27465            if(value && value.indexOf && value.indexOf('\\,') > -1) {
27466                value = value.replace(/\\,/g, ','); 
27467            }
27468            return value;
27469        },
27470
27471        handleCommit : function () {
27472            var temp = "";
27473            _.each(this.jqwidget, function (jqwidget, index) {
27474                var items = this._escapeCommas(jqwidget.option("values"));
27475                if (jqwidget.option("state") === 0) {
27476                    
27477                    temp = temp + items[0] + ",";
27478                }
27479            }, this);
27480            temp = temp.substring(0, temp.length - 1);
27481            this.commitValue(this._unescapeCommas(temp));
27482        },
27483
27484        handleEnabledChanged : function (event) {
27485            
27486            if (!this.$element.hasClass("dontSyncEnabled")) {
27487                var prop = event.newText ? "open" : "readOnly";
27488                _.each(this.jqwidget, function (jqwidget) {
27489                    jqwidget.option("access", prop);
27490                });
27491            }
27492
27493            this.$element.attr("data-disabled", !this._model.enabled);
27494        },
27495
27496        handleModelChanged : function (evnt) {
27497            switch (evnt._property) {
27498            case "enabled":
27499                this.handleEnabledChanged(evnt);
27500                break;
27501            default:
27502                GuideCheckBoxView._super.handleModelChanged.apply(this, arguments);
27503            }
27504        },
27505
27506        handleItemsChanged : function (event) {
27507            this._replaceGroupItemsWithNewOptions(this._model._getOptionsArray(), this._model.jsonModel.alignment);
27508            this.createWidget(this.getWidgetName(), this.createWidgetOptions());
27509        },
27510
27511        _getGroupItemIdentifier : function () {
27512            return '.guideCheckBoxGroupItems';
27513        },
27514
27515        _getWidgetType : function () {
27516            return 'checkbox';
27517        },
27518
27519        _getItemName : function () {
27520            return "CheckBoxItem";
27521        },
27522
27523        _getItemSkeleton : function () {
27524            var guideWidgetItemName = "guide" + this._getItemName(); 
27525            var afWidgetItemName = "af" + this._getItemName(); 
27526            return '<div class="' + guideWidgetItemName + ' ' + afWidgetItemName + ' {NAME_PLACEHOLDER} {CSS_PLACEHOLDER}" data-original-title="" title="">\n' +
27527                '            <div class="guideFieldWidget left XfaCheckBox" data-id="{COUNTER_PLACEHOLDER}" data-original-title="" title="">\n' +
27528                '                <input type="' + this._getWidgetType() + '" id="{TEMPLATE_ID_PLACEHOLDER}_{COUNTER_PLACEHOLDER}_widget" name="{TEMPLATE_ID_PLACEHOLDER}_jqName" value="-100" tabindex="0" placeholder="" style="position: relative;">\n' +
27529                '            </div>\n' +
27530                '            <div class="guideWidgetLabel right">\n' +
27531                '                <label>{LABEL_PLACEHOLDER}</label>\n' +
27532                '            </div>\n' +
27533                '        </div>';
27534        },
27535
27536        _renderGroupItem : function (options) {
27537            var itemSkeleton = this._getItemSkeleton(),
27538                namePlaceHolder = "{NAME_PLACEHOLDER}",
27539                cssPlaceHolder = "{CSS_PLACEHOLDER}",
27540                counterPlaceHolder = "{COUNTER_PLACEHOLDER}" ,
27541                templateIDPlaceHolder = "{TEMPLATE_ID_PLACEHOLDER}",
27542                labelPlaceHolder = "{LABEL_PLACEHOLDER}",
27543                guideUtil = guidelib.util.GuideUtil;
27544            itemSkeleton = guideUtil.replaceAll(itemSkeleton, namePlaceHolder, options.modelName);
27545            itemSkeleton = guideUtil.replaceAll(itemSkeleton, templateIDPlaceHolder, options.modelTemplateId);
27546            itemSkeleton = guideUtil.replaceAll(itemSkeleton, cssPlaceHolder, options.cssValue);
27547            itemSkeleton = guideUtil.replaceAll(itemSkeleton, counterPlaceHolder, options.itemIndex);
27548            itemSkeleton = guideUtil.replaceAll(itemSkeleton, labelPlaceHolder, options.displayValue);
27549            return itemSkeleton;
27550        },
27551
27552        _replaceGroupItemsWithNewOptions : function (items, cssValue) {
27553            var groupItem = this.$element.find(this._getGroupItemIdentifier()),
27554                options = {},
27555                widgetName = this.getWidgetName(),
27556                self = this;
27557
27558            
27559            groupItem.empty();
27560            options.widgetType = this._getWidgetType();
27561            options.modelName = this._model.name;
27562            options.modelTemplateId = this._model.id;
27563
27564            if (this._model.css !== null && !_.isUndefined(this._model.css)) {
27565                cssValue +=  " " + this._model.css;
27566            }
27567            options.cssValue = cssValue;
27568
27569            _.each(items, function (value, index) {
27570                options.itemIndex = index;
27571                options.displayValue = value.displayValue;
27572                options.saveValue = value.saveValue;
27573                groupItem.append(self._renderGroupItem(options));
27574            });
27575            this._initializeWidget();
27576            this._setListenersForLabelClick();
27577        },
27578
27579        _replaceAll : function (stringToReplaceIn, textToReplace, replacementString) {
27580            return stringToReplaceIn.split(textToReplace).join(replacementString);
27581        },
27582
27583        _defineModelEvents : function () {
27584            GuideCheckBoxView._super._defineModelEvents.apply(this, arguments);
27585            if (this._model) {
27586                
27587                this._model.on(guidelib.event.GuideModelEvent.ITEMS_CHANGED, this.handleItemsChanged, this);
27588            }
27589        },
27590
27591        setWidgetOptions : function (options) {
27592            var index = 0;
27593            _.each(this.jqwidget, function (jqwidget, id) {
27594                this._initOrUpdateWidget(id, this._getOptions(options, index++));
27595            }, this);
27596        },
27597
27598        _getOptions : function (options, index) {
27599            var items = this._model.getOnOffValues(index),
27600                val = this.getOnOffValueFromModelValue(this._model.value, items),
27601                optionsCopy = _.extend(options, {
27602                    value : val,
27603                    displayValue : val,
27604                    values : items,
27605                    state : this.getStateFromValue(this._model.value, items),
27606                    screenReaderText : this._model._getScreenReaderText(index)
27607                });
27608            return optionsCopy;
27609        },
27610
27611        _initOrUpdateWidget : function (id, options, widgetname, $widget, initialOptions) {
27612            if (this.jqwidget[id]) {
27613                this.jqwidget[id].option(options);
27614            } else {
27615                var _options = $.extend({}, options, initialOptions);
27616                this.jqwidget[id] = this._newWidget(widgetname, _options, $widget);
27617            }
27618            this.$widget.find("[checked!=checked]").parents(".guideCheckBoxItem").removeClass('guideItemSelected');
27619            this.$widget.find("[checked=checked]").parents(".guideCheckBoxItem").addClass('guideItemSelected');
27620        },
27621
27622        initializeJqWidget : function () {
27623            this.jqwidget = [];
27624        },
27625
27626        createWidget : function (widgetname, options) {
27627            var self = this;
27628            this.initializeJqWidget();
27629            if (this.$widget) {
27630                this.$widget.each(function (index, widget) {
27631                    self._initOrUpdateWidget(self.getJQWidgetIdentifier(index),
27632                        self._getOptions(options, index),
27633                        widgetname,
27634                        $(widget),
27635                        self._getWidgetInitialOptions($(widget)));
27636                });
27637                this.tempXfaFixes();
27638            }
27639        },
27640
27641        setActive : function (activeItemToken, focus, muteScripts) {
27642            guidelib.view.GuideFieldView._super.setActive.call(this, activeItemToken, focus, muteScripts);
27643            if (focus && !this._guideView.skipFieldFocus) {
27644                if (this.jqwidget && this.jqwidget[this.getJQWidgetIdentifier(0)]) {
27645                    this.jqwidget[this.getJQWidgetIdentifier(0)].focus();
27646                }
27647                this._guideView.currentFocusItemSom = this._model.somExpression;
27648            }
27649            return true;
27650        },
27651
27652        updateWidgetOption : function (optionName, optionValue) {
27653            _.each(this.jqwidget, function (jqwidget, index) {
27654                if (optionName == "isValid") {
27655                    jqwidget.option(optionName, optionValue);
27656                }
27657            }, this);
27658        },
27659
27660        handleAccessibility : function () {
27661            GuideCheckBoxView._super.handleAccessibility.apply(this, arguments);
27662            this.$element.attr("role", "group");
27663            if (this._model.jsonModel.assistPriority && this._model.jsonModel.custom && this._model.jsonModel.assistPriority === "custom"){
27664                this.$element.attr("aria-label", this._model.jsonModel.custom[0]);
27665            } else {
27666                var $label = this.$element.find(".guideFieldLabel label"),
27667                    label = $label.get(0);
27668                if (label && label.id) {
27669                    this.$element.attr("aria-labelledby", label.id);
27670                }
27671            }
27672        }
27673
27674    });
27675}($, guidelib, window._));
27676
27677(function ($, guidelib, _) {
27678    var GuideRadioButtonView = guidelib.view.GuideRadioButtonView = guidelib.view.GuideCheckBoxView.extend({
27679
27680        _defaultWidgetName : "XfaCheckBox",
27681
27682        _prevOnWidget : null,
27683
27684        _getWidgetType : function () {
27685            return 'radio';
27686        },
27687
27688        _getItemName : function () {
27689            return "RadioButtonItem";
27690        },
27691
27692        _getGroupItemIdentifier : function () {
27693            return '.guideRadioButtonGroupItems';
27694        },
27695
27696        getJQWidgetIdentifier : function (index) {
27697            return this._model.getItemIdentifier(index);
27698        },
27699
27700        handleValueChanged : function (event) {
27701            var somExpression = event.prevText;
27702            if (this.jqwidget[somExpression]) {
27703                this.jqwidget[somExpression].option("value", event.newText);
27704                this.jqwidget[somExpression].option("displayValue", event.newText);
27705                if (event.newText === null) {
27706                    this._prevOnWidget = null;
27707                } else {
27708                    this._prevOnWidget = this.jqwidget[somExpression];
27709                }
27710            }
27711            this.$widget.find("[checked!=checked]").parents(".guideRadioButtonItem").removeClass('guideItemSelected').attr("aria-checked", false);
27712            this.$widget.find("[checked=checked]").parents(".guideRadioButtonItem").addClass('guideItemSelected').attr("aria-checked", true);
27713            this._updateEmptyStatus();
27714        },
27715
27716        handleCommit : function () {
27717            var jqwidgettochange = _.find(this.jqwidget, function (jqwidget) {
27718                    return jqwidget.option("state") === 0 && jqwidget !== this._prevOnWidget;
27719                }, this);
27720            this.commitValue(jqwidgettochange.option("value"));
27721            this._prevOnWidget = jqwidgettochange;
27722        },
27723
27724        _initOrUpdateWidget : function (id, options, widgetname, widget) {
27725            GuideRadioButtonView._super._initOrUpdateWidget.apply(this, arguments);
27726            if (options.state === 0) {
27727                this._prevOnWidget = this.jqwidget[id];
27728            }
27729            this.$widget.find("[checked!=checked]").parents(".guideRadioButtonItem").removeClass('guideItemSelected');
27730            this.$widget.find("[checked=checked]").parents(".guideRadioButtonItem").addClass('guideItemSelected');
27731        },
27732
27733        initializeJqWidget : function () {
27734            this.jqwidget = {};
27735            
27736            
27737            
27738            this.$widget.find("[checked]").removeAttr("checked");
27739            this.$widget.find("[checked=checked]").removeAttr("checked"); 
27740
27741        },
27742
27743        handleAccessibility : function () {
27744            GuideRadioButtonView._super.handleAccessibility.apply(this, arguments);
27745            this.$element.attr("role", "radiogroup");
27746        }
27747    });
27748}($, guidelib, _));
27749(function ($, guidelib, _) {
27750    var GuideSwitchView = guidelib.view.GuideSwitchView = guidelib.view.GuideCheckBoxView.extend({
27751        _defaultWidgetName : "guideSwitch",
27752
27753        createWidgetOptions : function () {
27754            var options = GuideSwitchView._super.createWidgetOptions.apply(this, arguments),
27755                items = this._model.jsonModel.options, checkedLabel, uncheckedLabel;
27756            
27757            if (Array.isArray(items) && items.length > 0) {
27758                checkedLabel = items[0];
27759            } else if (!_.isUndefined(items) && items.length > 0) {
27760                checkedLabel = items;
27761            } else {
27762                checkedLabel = " ";
27763            }
27764            if (Array.isArray(items) && items.length > 1) {
27765                uncheckedLabel = items[1];
27766            } else {
27767                uncheckedLabel = "    ";
27768            }
27769            return $.extend({}, options, {
27770                checkedLabel : checkedLabel.substring(checkedLabel.indexOf("=") + 1),
27771                uncheckedLabel : uncheckedLabel.substring(uncheckedLabel.indexOf("=") + 1)
27772            });
27773        },
27774
27775        handleValueChanged : function (event) {
27776            
27777            var jqwidget = this.jqwidget[0],
27778                jqwidgetOptions = jqwidget.options;
27779            var setVal = this.getOnOffValueFromModelValue(event.prevText, jqwidget.option("values"));
27780            if (jqwidgetOptions.value !== setVal) {
27781                jqwidget.option("value", setVal);
27782                
27783                var userControl = jqwidget.$userControl;
27784                var checked = jqwidgetOptions.value === jqwidgetOptions.values[0];
27785                userControl.prop("checked", checked);
27786                userControl.parent().toggleClass('ui-state-active', checked);
27787                userControl.change();
27788            }
27789        },
27790
27791        handleCommit : function () {
27792            var jqwidget = this.jqwidget[0],
27793                items = jqwidget.option("values"),
27794                state = jqwidget.option("state");
27795            this.commitValue(items[state]);
27796        }
27797    });
27798}($, guidelib, _));
27799
27800(function ($, guidelib) {
27801    var GuideNumericBoxView = guidelib.view.GuideNumericBoxView = guidelib.view.GuideFieldView.extend({
27802        _defaultWidgetName : "numericInput",
27803        createWidgetOptions : function () {
27804            var options = GuideNumericBoxView._super.createWidgetOptions.apply(this, arguments);
27805            return $.extend({}, options, {
27806                dataType : this._model.dataType,
27807                leadDigits : this._model.leadDigits,
27808                fracDigits : this._model.fracDigits,
27809                
27810                zero : guidelib.i18n.numberSymbols.zero,
27811                decimal : guidelib.i18n.numberSymbols.decimal,
27812                commitEvent : this.getCommitEvent(),
27813                placeholder : this._model.placeholderText
27814            });
27815        }
27816    });
27817
27818}($, guidelib));
27819(function ($, guidelib) {
27820    var GuidePasswordBoxView = guidelib.view.GuidePasswordBoxView = guidelib.view.GuideFieldView.extend({
27821        _defaultWidgetName : "defaultWidget",
27822
27823        createWidgetOptions : function () {
27824            var options = GuidePasswordBoxView._super.createWidgetOptions.apply(this, arguments);
27825
27826            return $.extend({}, options, {
27827                 placeholder : this._model.placeholderText
27828             });
27829        }
27830    });
27831}($, guidelib));
27832(function ($, guidelib) {
27833    var GuideDatePickerView = guidelib.view.GuideDatePickerView = guidelib.view.GuideFieldView.extend({
27834        _defaultWidgetName : "dateTimeEdit",
27835
27836        createWidgetOptions : function () {
27837            var options = GuideDatePickerView._super.createWidgetOptions.apply(this, arguments),
27838                useNativeWidget = (this._model.displayPictureClause === null && this._model.editPictureClause == null);
27839
27840            return $.extend({}, options, {
27841                days : guidelib.i18n.calendarSymbols.abbrdayNames,
27842                months : guidelib.i18n.calendarSymbols.monthNames,
27843                zero : guidelib.i18n.numberSymbols.zero,
27844                clearText : xfalib.locale.Strings.clearText,
27845                useNativeWidget : useNativeWidget,
27846                showCalendarIcon : true,
27847                editPattern : this._model.editPictureClause,
27848                placeholder : this._model.placeholderText,
27849                minValidDate : this._model.minimum,
27850                maxValidDate : this._model.maximum,
27851                exclMaxDate :  this._model.exclusiveMaximum,
27852                exclMinDate : this._model.exclusiveMinimum,
27853                allowNonIsoValue : true
27854            });
27855        },
27856
27857        
27858        tempXfaFixes : function () {
27859            GuideDatePickerView._super.tempXfaFixes.apply(this, arguments);
27860            
27861            if (this.$widget) {
27862                this.$widget.children("not:input[type=date]").height("100%"); 
27863            }
27864        },
27865
27866        handleAccessibility : function () {
27867            GuideDatePickerView._super.handleAccessibility.apply(this, arguments);
27868            this.$widget.children("div[tabIndex]").removeAttr("tabIndex");
27869            if (this.$widget) {
27870                var $icon = this.$widget.find('.datepicker-calendar-icon');
27871                if ($icon && $icon.length) {
27872                    var localizedLabel = (guidelib && guidelib.i18n && guidelib.i18n.strings && guidelib.i18n.strings.showDatePicker)
27873                        ? guidelib.i18n.strings.showDatePicker
27874                        : 'Show date picker';
27875                    $icon.attr('role', 'button')
27876                        .attr('tabindex', '0')
27877                        .attr('aria-haspopup', 'dialog')
27878                        .attr('aria-label', localizedLabel)
27879                        .attr('title', localizedLabel);
27880                }
27881            }
27882        }
27883    });
27884}($, guidelib));
27885
27886 (function ($, guidelib) {
27887    var GuideFootnotePlaceHolderView = guidelib.view.GuideFootnotePlaceHolderView = guidelib.view.GuideTextDrawView.extend({
27888        _defaultWidgetName : "abstractWidget",
27889
27890        initialize : function () {
27891            GuideFootnotePlaceHolderView._super.initialize.call(this);
27892            var that = this;
27893            $(function () {
27894                that._renderFootnotes();
27895            })
27896            guideBridge.on("elementNavigationChanged", function(event, payload) {
27897                that._renderFootnotes();
27898            })
27899            $(window.document).on('click.guidetab.data-api', '[data-guide-toggle$="accordion-tab"]',
27900                function(e) {
27901                    that._renderFootnotes();
27902                })
27903
27904        },
27905
27906       _renderFootnotes: function () {
27907           
27908           
27909           if(!this.$element.is(":visible")) {
27910               this._model.value = "";
27911               return;
27912           }
27913
27914           var footnoteMap = this._model.footnoteMap;
27915           var footnoteArr = Object.entries(footnoteMap);
27916           if (footnoteArr.length > 0) {
27917               var value = '<div>';
27918               var nodes = new Map();
27919               for (footnoteID in footnoteMap) {
27920                   var selector = "a[data-footnote-id=\"" + footnoteID + "\"]";
27921                   var mapKey = $(selector)[0].innerHTML;
27922                   if (!nodes.has(mapKey)) {
27923                       nodes.set(mapKey, footnoteMap[footnoteID]);
27924                   }
27925               };
27926               var tupleArray = [];
27927               nodes.forEach(function(value, key) {
27928                   tupleArray.push([key, value]);
27929               });
27930               tupleArray.sort(function(a, b) {
27931                   return a[0] - b[0];
27932               });
27933               tupleArray.forEach(function(el) {
27934                   value += el[1];
27935               });
27936               value += '</div>';
27937               this._model.value = value;
27938           }
27939       },
27940
27941               setActive: function () {
27942                   this._renderFootnotes();
27943               }
27944    });
27945}($, guidelib));
27946
27947
27948
27949
27950(function ($, guidelib) {
27951    var GuideScribbleView = guidelib.view.GuideScribbleView = guidelib.view.GuideFieldView.extend({
27952        _defaultWidgetName : "ScribbleImageField",
27953
27954        createWidgetOptions : function () {
27955            var options = GuideScribbleView._super.createWidgetOptions.apply(this, arguments);
27956            return $.extend({}, options, {
27957                commitProperty : "src",
27958                geoLocMandatoryOnIpad : "false",
27959                aspectRatio : this._valueOfAspectRatioToBeUsed()
27960            });
27961        },
27962
27963        _valueOfAspectRatioToBeUsed : function () {
27964            var aspectRatio ;
27965            if (this._model.jsonModel.aspectRatio) {
27966                aspectRatio = this._model.jsonModel.aspectRatio;
27967            } else {
27968                
27969                if (!this._presenceOfHeight()) {
27970                    aspectRatio = "6.8888";
27971                }
27972            }
27973            return aspectRatio ;
27974        },
27975
27976        _presenceOfHeight : function () {
27977            return (this._model.jsonModel.hasOwnProperty('height') && this._model.jsonModel.height.toString().length > 0);
27978        },
27979
27980        postInitialize : function () {
27981            GuideScribbleView._super.postInitialize.call(this);
27982            var that = this;
27983            
27984            if (!this._presenceOfHeight()) {
27985                setTimeout(function () {guidelib.util.GuideUtil._computeHeightAndWidthForScribble(that.$widget);}, guidelib.util.GuideUtil.SCRIBBLE_RESIZE_TIME_INTERVAL);
27986                $(window).off("resize", guidelib.util.GuideUtil._resizeScribbleField);
27987                $(window).on("resize", guidelib.util.GuideUtil._resizeScribbleField);
27988            }
27989        },
27990
27991        handleAccessibility : function () {
27992            
27993            if (this._model.mandatory) {
27994                this.$widget.find("img").attr("aria-required", true);
27995            }
27996            if (this._model._getScreenReaderText() === this._model._getToolTip()) {
27997                this.$element.find("img").removeAttr("aria-label");
27998                this.$element.find("img").attr("aria-labelledby", this._model.id + "_guideFieldShortDescription");
27999            } else if (this._model._getAssistPriority() === "none") {
28000                this.$element.find("img").attr("aria-label", " ");
28001            }
28002        },
28003
28004        
28005        tempXfaFixes : function () {
28006            if (this.$widget) {
28007                this.$widget.css("position", "relative").find("img").css("position", "relative");
28008            }
28009            this.handleAccessibility();
28010        }
28011    });
28012}($, guidelib));
28013(function ($, guidelib) {
28014    var GuideTextBoxView = guidelib.view.GuideTextBoxView = guidelib.view.GuideFieldView.extend({
28015        _defaultWidgetName : "textField",
28016
28017        initialize : function () {
28018            GuideTextBoxView._super.initialize.apply(this, arguments);
28019            if (this._model.allowRichText) {
28020                this._defaultWidgetName = "richTextField";
28021            }
28022        },
28023
28024        createWidgetOptions : function () {
28025            var options = GuideTextBoxView._super.createWidgetOptions.apply(this, arguments),
28026                html5Type = this._model.getAttribute("html5Type");
28027            return $.extend({}, options, {
28028                multiLine : this._model.multiLine,
28029                minLength : this._model.allowRichText ? null : this._model.minLength,
28030                length : this._model.allowRichText ? null : this._model.length,
28031                maxChars : this._model.allowRichText ? null : this._model.maxChars,
28032                required : this._model.mandatory,
28033                
28034                html5Type : html5Type ? html5Type : "",
28035                totalLengthMessage : this.guideUtil.getLocalizedMessage("", guidelib.i18n.strings.totalLengthMessage, [this._model.length]),
28036                minimumLengthMessage : this.guideUtil.getLocalizedMessage("", guidelib.i18n.strings.minimumLengthMessage, [this._model.minLength]),
28037                allowRichText : this._model.allowRichText,
28038                placeholder : this._model.placeholderText
28039            });
28040        },
28041
28042        
28043        
28044        
28045        tempXfaFixes : function () {
28046            if (this._model.jsonModel.multiLine) {
28047                this.$element.find("textarea").css("position", "relative");
28048                this.handleAccessibility();
28049            } else {
28050                GuideTextBoxView._super.tempXfaFixes.apply(this);
28051            }
28052        },
28053
28054        handleAccessibility : function () {
28055            GuideTextBoxView._super.handleAccessibility.apply(this);
28056            if (this._model.jsonModel.multiLine) {
28057                this.$element.find("textarea").attr("aria-multiLine", true);
28058            }
28059        }
28060    });
28061}($, guidelib));
28062(function ($, guidelib) {
28063    var xfaUtil = xfalib.ut.XfaUtil.prototype,
28064        GuideImageView = guidelib.view.GuideImageView = guidelib.view.GuideBaseView.extend({
28065            initialize : function () {
28066                GuideImageView._super.initialize.call(this);
28067                if (this._model.value != null) {
28068                    var srcString = "data:image/*;base64," + this._model.value;
28069                    this.$element.children('img').attr('src', srcString);
28070                }
28071            },
28072
28073            postInitialize : function () {
28074                this._syncGuideNodeToHtml();
28075            },
28076
28077            setActive : function (activeItemToken, focus, muteScripts) {
28078                guidelib.view.GuideFieldView._super.setActive.call(this, activeItemToken, focus, muteScripts);
28079                if (focus && !this._guideView.skipFieldFocus) {
28080                    if (this.$element) {
28081                        this.$element.focus();
28082                    }
28083                    this._guideView.currentFocusItemSom = this._model.somExpression;
28084                }
28085                return true;
28086            }
28087
28088        });
28089}($, guidelib));
28090
28091(function ($, guidelib) {
28092    var GuideChartView = guidelib.view.GuideChartView = guidelib.view.GuideBaseView.extend({
28093
28094        initialize : function () {
28095            GuideChartView._super.initialize.call(this);
28096            var chartView = this;
28097            $(window).on("resize orientationchange", function () {
28098                chartView.renderChart.apply(chartView);
28099            });
28100        },
28101
28102        postInitialize : function () {
28103            this._syncGuideNodeToHtml(true);
28104        },
28105
28106        handleModelChanged : function (event) {
28107            switch (event._property) {
28108                case "data":
28109                case "chartType":
28110                    this.renderChart();
28111                    break;
28112
28113                case "visible":
28114                    this.handleVisibleChanged(event);
28115                    break;
28116            }
28117        },
28118
28119        handleVisibleChanged : function (event) {
28120            
28121            
28122            if (!event.newText) {
28123                
28124                this.$element.addClass("hidden");
28125                if (this.parentView.currentActiveItemView == this) {
28126                    this.parentView.setActive("nextItem");
28127                }
28128            }   else {
28129                
28130                this.$element.removeClass("hidden");
28131            }
28132        },
28133
28134        _generateChart : function () {
28135            var $chartElement = this.$element, chartModel = this._model, isChartVisible, chart;
28136            
28137            var plottedChartSelector = chartModel.jsonModel.isInteractiveCommunicationChartResource ? '.highcharts-container'
28138                    : '.dv-chart-container';
28139            var $plottedChart = $chartElement
28140                    .find(plottedChartSelector);
28141            isChartVisible = ($chartElement.parent().width() > 0)
28142                    && ($chartElement.width() > 0) ? true : false;
28143            
28144            
28145            
28146            
28147            if ((isChartVisible || $plottedChart.length == 0)
28148                    && chartModel.repeatableItem) {
28149                try {
28150                    
28151                    $plottedChart.remove();
28152                    if (chartModel.jsonModel.isInteractiveCommunicationChartResource) {
28153                        chart = new fd.chart.ChartInstanceGenerator()
28154                                .generate(chartModel.jsonModel,
28155                                        chartModel.jsonModel.data);
28156                        Highcharts.chart($chartElement.attr('id'),
28157                                chart);
28158                    } else {
28159                        chart = guidelib.chartUtils.constructChart(
28160                                chartModel, $chartElement);
28161                        if (chart) {
28162                            chart.render();
28163                        }
28164                    }
28165                } catch (exception) {
28166                    this.logger().error("AF Chart view",
28167                            "Error while rendering chart " + exception);
28168                }
28169            }
28170        },
28171
28172        renderChart : function () {
28173            if (this._model.data) {
28174                var chartView = this;
28175                window.requestAnimationFrame(function () {
28176                    chartView._generateChart.apply(chartView);
28177                });
28178            }
28179        },
28180
28181        _syncGuideNodeToHtml : function (deepSync) {
28182            this.renderChart();
28183            guidelib.view.GuideChartView._super._syncGuideNodeToHtml.call(this, deepSync);
28184        },
28185
28186        setActive : function (activeItemToken, focus, muteScripts) {
28187            guidelib.view.GuideChartView._super.setActive.call(this, activeItemToken, focus, muteScripts);
28188            if (focus && !this._guideView.skipFieldFocus) {
28189                if (this.$element) {
28190                    this.$element.focus();
28191                }
28192                this._guideView.currentFocusItemSom = this._model.somExpression;
28193            }
28194            return true;
28195        }
28196    });
28197}($, guidelib));
28198(function ($, guidelib) {
28199    var GuideAdModuleView = guidelib.view.GuideAdModuleView = guidelib.view.GuideBaseView.extend({
28200
28201        initialize : function () {
28202            GuideAdModuleView._super.initialize.call(this);
28203            if (this._model) {
28204                
28205                this._model.on(guidelib.event.GuideModelEvent.VALUE_CHANGED, this.handleValueChanged, this);
28206            }
28207            this.oldValue = null;
28208        },
28209
28210        postInitialize : function () {
28211            this._syncGuideNodeToHtml(true);
28212        },
28213
28214        handleValueChanged : function (event) {
28215            switch (event._property) {
28216                case "value":
28217                    this.$element.html(event.newText);
28218                    break;
28219            }
28220        },
28221
28222        handleVisibleChanged : function (event) {
28223            
28224            
28225            if (!event.newText) {
28226                
28227                this.$element.addClass("hidden");
28228                if (this.parentView.currentActiveItemView == this) {
28229                    this.parentView.setActive("nextItem");
28230                }
28231            }   else {
28232                
28233                this.$element.removeClass("hidden");
28234            }
28235        },
28236
28237        handleModelChanged : function (event) {
28238            GuideAdModuleView._super.handleModelChanged.apply(this, arguments);
28239        },
28240        _syncGuideNodeToHtml : function (deepSync) {
28241            if (this._model.value) {
28242                this.$element
28243                    .html(this._model.value)
28244                    .find('img')
28245                    .attr('src', function (idx, val) {
28246                        return Granite.HTTP.externalize(val);
28247                    });
28248            }
28249
28250            if (this._model.layoutConfigs) {
28251                var options = {
28252                                $element : this.$element,
28253                                layoutConfigs : this._model.layoutConfigs
28254                            };
28255                guidelib.util.AdUtil.applyLayouts(options);
28256            }
28257            if (this._model) {
28258                this.handleModelChanged(guidelib.event.GuideModelEvent.createEvent(
28259                    guidelib.event.GuideModelEvent.MODEL_CHANGED,
28260                    this,
28261                    "visible",
28262                    this._model.visible,
28263                    this._model.visible
28264                ));
28265            }
28266        },
28267
28268        setActive : function (activeItemToken, focus, muteScripts) {
28269            guidelib.view.GuideFieldView._super.setActive.call(this, activeItemToken, focus, muteScripts);
28270            if (focus) {
28271                if (this.$element) {
28272                    this.$element.focus();
28273                }
28274                this._guideView.currentFocusItemSom = this._model.somExpression;
28275            }
28276            return true;
28277        }
28278    });
28279}($, guidelib));
28280(function ($, _, guidelib) {
28281    var GuideItemsView = guidelib.view.GuideItemsView = guidelib.view.GuideBaseView.extend({
28282        initialize : function () {
28283            GuideItemsView._super.initialize.call(this);
28284            this.childViews = [];
28285        },
28286
28287        
28288        _unloadView : function () {
28289            if (this._model._selfOrAncestorIsLazyReference) {
28290                var fragmentPlaceHolderSelector = "#" + this.id,
28291                    ind;
28292                
28293                $(fragmentPlaceHolderSelector).children().remove();
28294                
28295                var queueForLazyItems = this._guideView._queueViewForLazyItems;
28296                
28297                if ((ind = _.indexOf(queueForLazyItems, this)) !== -1) {
28298                    queueForLazyItems[ind] = undefined;
28299                }
28300                _.each(this.childViews, function (view) {
28301
28302                    view._unloadView();
28303                }, this);
28304                
28305                this.childViews = [];
28306                
28307                this._currentActiveItemView = null;
28308                
28309                this._guideView._domTemplateCacheStore.removeDomElement("#" + this._model.templateId);
28310                
28311                this._guideView._reInitializeGuideContainerDom();
28312            }
28313        },
28314        postInitialize : function () {
28315            this.childViews = _.reduce(this._model.children, function (childViews, childModel) {
28316                var childView = this._createNonRepeatChildView(childModel);
28317                if (childView) {
28318                    childViews.push(childView);
28319                }
28320                return childViews;
28321            }, [], this);
28322            
28323            this._syncGuideNodeToHtml(false);
28324        },
28325
28326        _createNonRepeatChildView : function (childModel) {
28327            
28328
28329            
28330            
28331            var childElSelector = this.guideUtil.modelElSelector(childModel.id);
28332            var $childEl = this.$element.find(childElSelector);
28333            if (!$childEl.length) {
28334                $childEl = this.$element.find(this.guideUtil.modelElSelector(childModel.templateId));
28335                this._updateIds($childEl, childModel.templateId, childModel.id);
28336            }
28337            if ($childEl.length) {
28338                var childView = guidelib.view.GuideViewRegistry.prototype.createView($childEl, this);
28339                childView.postInitialize();
28340                return childView;
28341            }
28342            return null;
28343        },
28344
28345        _syncGuideNodeToHtml : function (deepSync) {
28346            if (deepSync) {
28347                _.each(this.childViews, function (childView) {
28348                    childView._syncGuideNodeToHtml(true);
28349                }, this);
28350            }
28351            GuideItemsView._super._syncGuideNodeToHtml.call(this, deepSync);
28352        },
28353
28354        _findChildView : function (childModel) {
28355            var view = _.find(this.childViews, function (childView) {
28356                return childView._model == childModel;
28357            }, this);
28358            return view;
28359        }
28360    });
28361
28362    GuideItemsView.defineProps({
28363        itemsView : {
28364            get : function () {
28365                var views = _.filter(this.childViews, function (childView) {
28366                    return childView.isItem;
28367                }, this);
28368                return views;
28369            }
28370        }
28371    });
28372}($, _, guidelib));
28373
28374(function ($, guidelib) {
28375    var GuideAdModuleGroupView = guidelib.view.GuideAdModuleGroupView = guidelib.view.GuideItemsView.extend({
28376        initialize : function () {
28377            GuideAdModuleGroupView._super.initialize.call(this);
28378            if (this._model) {
28379                
28380                this._model.on(guidelib.event.GuideModelEvent.VALUE_CHANGED, this.handleValueChanged, this);
28381            }
28382        },
28383
28384        postInitialize : function () {
28385            if (this._model.value || this._model.value === "") {
28386                this._syncGuideNodeToHtml(true);
28387            } else {
28388                GuideAdModuleGroupView._super.postInitialize.call(this);
28389            }
28390        },
28391
28392        handleValueChanged : function (event) {
28393            switch (event._property) {
28394                case "value":
28395                    this.$element.html(event.newText);
28396                    break;
28397            }
28398        },
28399
28400        _syncGuideNodeToHtml : function (deepSync) {
28401            if (this._model.value || this._model.value === "") {
28402                this.$element
28403                    .html(this._model.value)
28404                    .find('img')
28405                    .attr('src', function (idx, val) {
28406                        return Granite.HTTP.externalize(val);
28407                    });
28408            } else {
28409                GuideAdModuleGroupView._super._syncGuideNodeToHtml.call(this, deepSync);
28410            }
28411        },
28412
28413        setActive : function (activeItemToken, focus, muteScripts) {
28414            guidelib.view.GuideAdModuleGroupView._super.setActive.call(this, activeItemToken, focus, muteScripts);
28415            if (focus) {
28416                if (this.$element) {
28417                    this.$element.focus();
28418                }
28419                this._guideView.currentFocusItemSom = this._model.somExpression;
28420            }
28421            return true;
28422        }
28423
28424    });
28425}($, guidelib));
28426(function ($, _, guidelib) {
28427
28428    var GuidePanelView = guidelib.view.GuidePanelView = guidelib.view.GuideItemsView.extend({
28429        initialize : function () {
28430            GuidePanelView._super.initialize.call(this);
28431            this._currentActiveItemView = null;
28432            this._$itemsContainer = null;
28433            this._$itemsNavContainer = null;
28434            this._$summary = null;
28435            this._$title = null;
28436            
28437            this._childInitializeWaiting = true;
28438            
28439            this._model.on(guidelib.event.GuideModelEvent.CHILD_CHANGED, this.handleChildChanged, this);
28440            this._model.on(guidelib.event.GuideModelEvent.MULTIPLE_CHILD_ADDED, this.multipleChildAdded, this);
28441            this._summarySelector = this.guideUtil.summarySelector(this._model.id);
28442            this._titleSelector = this.guideUtil.propSelector("title", this._model.id);
28443        },
28444
28445        addRemoveTemplateMarker : function () {
28446            var featureToggle = FD.isToggleEnabled(guidelib.util.FeatureToggleConstants.FT_VALID_NAV_UL_CHILDREN) ? true : false;
28447            
28448            _.each(this._model.children, function (childModel) {
28449                if (childModel instanceof guidelib.model.GuideInstanceManager) {
28450                    
28451                    var imId = childModel.id,
28452                        instanceId = (childModel._instances[0] || {}).id || childModel.instanceTemplateId,
28453                        gTemplateMarkerPanel = '<div id="' + imId + 'panel" style="display: none" data-guide-template-marker="true"></div>',
28454                        gTemplateMarkerNav = '<'+ (featureToggle ? 'li' : 'div') +' id="' + imId + 'nav" style="display: none" data-guide-template-marker="true"></' + (featureToggle ? 'li' : 'div') + '>',
28455                        instanceItem = this.guideUtil.itemSelector(instanceId, childModel),
28456                        navItem = this.guideUtil.itemNavSelector(instanceId);
28457                    this.$itemsContainer.find(instanceItem).before(gTemplateMarkerPanel);
28458                    this.$itemsNavContainer.find(navItem).before(gTemplateMarkerNav);
28459                    if (childModel._instances && childModel._instances.length === 0) { 
28460                        $(navItem, this.$element).remove(); 
28461                        $(instanceItem, this.$element).remove(); 
28462                    }
28463                }
28464            }, this);
28465
28466        },
28467
28468        postInitialize : function () {
28469
28470            
28471            
28472            
28473            this.handleSummaryChanged();
28474            this.handleTitleChanged();
28475            if (this._model.repeatable) {
28476                this._toggleAddRemoveButtons();
28477            }
28478            if (!this.parentView._model.enableLayoutOptimization) {
28479                
28480                this._postInitializeChildren();
28481            } else {
28482                
28483                
28484                
28485                
28486                
28487                
28488                this.handleVisibleChanged(guidelib.event.GuideModelEvent.createEvent(
28489                    guidelib.event.GuideModelEvent.MODEL_CHANGED,
28490                    this,
28491                    "visible",
28492                    this._model.visible,
28493                    this._model.visible
28494                ), {skipLazyAutoLoad: true});  
28495            }
28496            
28497            
28498            
28499            
28500            
28501            this.addRemoveTemplateMarker();
28502        },
28503
28504        handleVisibleChanged : function (event, options) {
28505            GuidePanelView._super.handleVisibleChanged.apply(this, arguments);
28506            
28507            
28508            
28509            
28510            
28511            
28512            
28513            options = options || {};
28514            if (event.newText === true &&
28515                this._model._lazyReference &&
28516                !this._model._itemsLoaded &&
28517                this._model.getAttribute('autoLoad') === false &&
28518                options.skipLazyAutoLoad !== true &&
28519                this._model._guide().getGuideState() === guidelib.model.GuideSchema.prototype.GuideStateConstants.GUIDE_STATE_MODEL_COMPLETE) {
28520                
28521                
28522                this._loadLazyFragment({ preserveLazy: true });
28523            }
28524        },
28525
28526        _postInitializeChildren : function () {
28527            this._childInitializeWaiting = false;
28528            this._syncGuideNodeToHtml(true);
28529            this.handleAccessibility();
28530            
28531            
28532            
28533            if (this.parentView.$itemsNavContainer && this.parentView.$itemsNavContainer.filter(":not(.tab-navigators-mobile)").length === 0) {
28534                this.setActive("firstItem", false, true);
28535            }
28536        },
28537
28538        _syncGuideNodeToHtml : function (deepSync, currentAddedChildIndex) {
28539            if (this._childInitializeWaiting) {
28540                return;
28541            }
28542            
28543            
28544            
28545            
28546            
28547            
28548            
28549
28550            var that = this;
28551            var htmlTemplateCache = this._guideView._domTemplateCacheStore;
28552            var oldItems = {}; 
28553            var oldNonItems = {}; 
28554            var newChildren = {};
28555
28556            
28557            _.each(this.childViews, function (childView) {
28558                if (childView.isItem) {
28559                    oldItems[childView.id] = childView;
28560                } else {
28561                    oldNonItems[childView.id] = childView;
28562                }
28563            }, this);
28564
28565            
28566            
28567            
28568            
28569            
28570            
28571            
28572            _.each(this._model.items, function (childModel) {
28573                    var cTemplateId = childModel.templateId;
28574                    var childId = childModel.id,
28575                        $childItem = null,
28576                        $childItemNav = null;
28577                    
28578                    
28579                    $childItem = this._find(this.guideUtil.itemSelector(childId, childModel));
28580                    $childItemNav = this._find(this.guideUtil.itemNavSelector(childId));
28581
28582                    
28583                    
28584                    if (!$childItem.length && !newChildren[cTemplateId] && currentAddedChildIndex !== 0) {
28585                        
28586                        
28587                        $childItem = this.$itemsContainer.find(this.guideUtil.itemSelector(cTemplateId, childModel));
28588                        $childItemNav = this.$itemsNavContainer.find(this.guideUtil.itemNavSelector(cTemplateId));
28589                    }
28590                    if (!$childItem.length) {
28591                        
28592                        $childItem = htmlTemplateCache.cloneDomElement(this.guideUtil.itemSelector(cTemplateId, childModel));
28593                        $childItemNav = htmlTemplateCache.cloneDomElement(this.guideUtil.itemNavSelector(cTemplateId));
28594                        if (!$childItem.length) {
28595                            this.logger().error("AF", "Html template could not be found. cTemplateId:" + cTemplateId + ", som:" + childModel.somExpression);
28596                            return;
28597                        }
28598                    }
28599                    this._updateIds($childItem, cTemplateId, childId);
28600                    this._updateIds($childItemNav, cTemplateId, childId);
28601                    
28602                    
28603                    $childItem.attr("data-guide-parent-id", this._model.id);
28604                    $childItemNav.attr("data-guide-parent-id", this._model.id);
28605                    var view = null;
28606                    if (oldItems.hasOwnProperty(childId)) {
28607                        view = oldItems[childId];
28608                        if (view instanceof guidelib.view.GuidePanelView && view._model.instanceManager.repeatable && !_.isUndefined(that._model.bindNode)) {
28609                            
28610                            this._fixChildDom(view);
28611                        }
28612                        if (deepSync) {
28613                            view._syncGuideNodeToHtml(deepSync);
28614                        } 
28615                    } else {
28616                        var $childEl = this._find("#" + childId);
28617                        if ($childEl.length) {
28618                            view = this._createChild($childEl);
28619                        } else {
28620                            $childEl = $childItem.find("#" + childId).addBack("#" + childId);
28621                            if ($childEl.length) {
28622                                view = this._createChild($childEl, $childItem, $childItemNav);
28623                            } else {
28624                                this.logger().debug("AF", "Skip creating view. could not find el for id:" + childId
28624);
28625                            }
28626                        }
28627                        if (this._model.repeatable) {
28628                            guidelib.util.GuideUtil._initializeShortDescription($childEl);
28629                        }
28630                    }
28631                    if (view) {
28632                        newChildren[childId] = view;
28633                    }
28634                }, this
28635            );
28636
28637            
28638            this.$itemsContainer.find('[data-guide-parent-id="' + that._model.id + '"]').each(function () {
28639                var $this = $(this);
28640                var thisId = $this.attr("id");
28641                
28642                if (thisId.indexOf(that.guideUtil.GUIDE_ITEM_SUFFIX) === -1) {
28643                    thisId = $this.attr(that.guideUtil.DATA_GUIDE_ITEM);
28644                }
28645                var childId = thisId.substring(0, thisId.length - that.guideUtil.GUIDE_ITEM_SUFFIX.length);
28646                if (!newChildren.hasOwnProperty(childId) && !window.guideBridge._resolveId(childId)) {
28647                    that.logger().log("guideView", 5, "removing element as no corresponding form dom node found. id:" + thisId + ", parent id:" + that.id);
28648                    $this.remove();
28649                    that._find(that.guideUtil.itemNavSelector(childId)).remove();
28650                }
28651            });
28652
28653            this.childViews = [];
28654            _.each(this._model.children, function (childModel) {
28655                var childIsItem = childModel._isItem;
28656                var childId = childModel.id;
28657                if (childIsItem && newChildren.hasOwnProperty(childId)) {
28658                    
28659                    this.childViews.push(newChildren[childId]);
28660                } else if (!childIsItem) {
28661                    var nonItemChildView = null;
28662                    if (oldNonItems.hasOwnProperty(childId)) {
28663                        nonItemChildView = oldNonItems[childId];
28664                    } else {
28665                        nonItemChildView = this._createNonRepeatChildView(childModel);
28666                    }
28667                    if (nonItemChildView) {
28668                        if (deepSync) {
28669                            nonItemChildView._syncGuideNodeToHtml(deepSync);
28670                        }
28671                        this.childViews.push(nonItemChildView);
28672                    }
28673                }
28674            }, this);
28675            
28676            guidelib.view.GuideBaseView.prototype._syncGuideNodeToHtml.apply(this, arguments);   
28677        },
28678
28679        _createChild : function ($childEl, $item, $itemNav) {
28680            var guideViewBind = $childEl.data("guideViewBind");
28681            var model = window.guideBridge._resolveId(guideViewBind);
28682            if (model && model.getAttribute('skipViewCreation') !== 'true') {
28683                var view = guidelib.view.GuideViewRegistry.prototype.createView($childEl, this);
28684                this._fixChildDom(view, $item, $itemNav);
28685                view.postInitialize();
28686                return view;
28687            }
28688        },
28689
28690        _fixChildDom : function (view, $item, $itemNav) {
28691            
28692            
28693            
28694            var newChild = view._model;
28695            if (!(newChild instanceof guidelib.model.GuidePanel) || !newChild.repeatable) {
28696                return;
28697            }
28698            var $childItem = $item || view.$item;
28699            var $childItemNav = $itemNav || view.$itemNav;
28700            var children = this._model.children;
28701            var insertAfterId = (newChild.instanceIndex > 0) ? children[children.indexOf(newChild) - 1].id : null;
28702            
28703            var insertAfterItemSelector = insertAfterId ? this.guideUtil.itemSelector(insertAfterId, newChild) : "#" + newChild.instanceManager.id + "panel";
28704            var insertAfterNavSelector = insertAfterId ? this.guideUtil.itemNavSelector(insertAfterId) : "#" + newChild.instanceManager.id + "nav";
28705            
28706            
28707            this.$itemsContainer.each(function (index) {
28708                var insertEl = $childItem.get(index) || $childItem.get(0),
28709                    $insertAfterItem = $(this).find(insertAfterItemSelector);
28710                
28711                if ($insertAfterItem.length == 0) {
28712                    insertAfterItemSelector = "[data-guide-template-marker=" + newChild.instanceManager.id + "]";
28713                    $insertAfterItem = $(this).find(insertAfterItemSelector);
28714                    
28715                    if (newChild.instanceIndex === 0 && $insertAfterItem.length > 0) {
28716                        $insertAfterItem.removeAttr("data-guide-template-marker");
28717                        $(insertEl).attr("data-guide-template-marker", newChild.instanceManager.id);
28718                    }
28719                }
28720                
28721                if ($insertAfterItem.get(0) !== insertEl) {
28722                    
28723                    $insertAfterItem.after($(insertEl));
28724                }
28725            });
28726            
28727            
28728            
28729            this.$itemsNavContainer.each(function (index) {
28730                var insertNavEl = $childItemNav.get(index) || $childItemNav.get(0);
28731                $(this).find(insertAfterNavSelector).after($(insertNavEl));
28732            });
28733        },
28734
28735        multipleChildAdded : function (event) {
28736            if (event.jsonModel.newText && event.jsonModel.newText.length > 0) {
28737                this._syncGuideNodeToHtml(true);
28738                this.childViews.forEach(function (childView) {
28739                    if (childView._model.repeatable) {
28740                        childView._toggleAddRemoveButtons();
28741                    }
28742                });
28743            }
28744        },
28745
28746        handleChildChanged : function (event) {
28747            var newlyCreatedInstance = null,
28748                currentAddedInstanceIndex = -1; 
28749            if (event._property == "childRemoved") {
28750                var $elementRemoved = this.$element.find("#" + event.prevText.id),
28751                    index = $elementRemoved.index();
28752            }
28753            if (event._property == "childAdded") {
28754                newlyCreatedInstance = event.newText;
28755                currentAddedInstanceIndex = newlyCreatedInstance.instanceIndex;
28756            }
28757            
28758            this._syncGuideNodeToHtml(true, currentAddedInstanceIndex);
28759            this.childViews.forEach(function (childView) {
28760                if (childView._model.repeatable) {
28761                    childView._toggleAddRemoveButtons();
28762                }
28763            });
28764            if (event._property == "childRemoved") {
28765                
28766                
28767                this.$element.trigger("panelRemoved.af", [$elementRemoved, index]);
28768                if (this.currentActiveItemView && event.prevText == this.currentActiveItemView._model) {
28769                    
28770                    this._currentActiveItemView = null;
28771                    this.setActive("nextItem");
28772                }
28773            }
28774            if (newlyCreatedInstance != null) {
28775                
28776                
28777                this.$element.trigger("panelAdded.af", [this.$element.find("#" + newlyCreatedInstance.id)]);
28778            }
28779        },
28780
28781        handleSummaryChanged : function () {
28782            if (this.$summary.length > 0) {
28783                if (this._model.summary) {
28784                    this.$summary.text(this._model.summary);
28785                } else {
28786                    var title = this._model.title;
28787                    if (this._model.instanceIndex && this._model.repeatable) {
28788                        title += " " + this._model.instanceIndex;
28789                    }
28790                    this.$summary.text(title);
28791                }
28792            }
28793        },
28794
28795        handleTitleChanged : function () {
28796            if (this.$title.length > 0) {
28797                this.$title.text(this._model.title);
28798            }
28799            
28800            var isPanelActive = $("#" + this.id + "_guide-item").hasClass("active");
28801            if (isPanelActive) {
28802                $("[data-target-guide-content]").text(this._model.title);
28803            }
28804        },
28805
28806        handleModelChanged : function (event) {
28807            switch (event._property) {
28808                case "summary":
28809                    this.handleSummaryChanged();
28810                    break;
28811                case "title":
28812                    this.handleTitleChanged();
28813                    break;
28814                default:
28815                    GuidePanelView._super.handleModelChanged.apply(this, arguments);
28816            }
28817        },
28818
28819        _createReferredView : function () {
28820            
28821            this._postInitializeChildren();
28822        },
28823
28824        _loadLazyFragment : function (options) {
28825            
28826            
28827            
28828            
28829            
28830            
28831            var that = this;
28832            options = options || {};
28833            
28834            this._model._guide().internal.liveDataUtils.updateLiveData();
28835            
28836            
28837            
28838            
28839            var preserveLazy = options.preserveLazy === true;
28840            if (!preserveLazy) {
28841                this._guideView._clearInactiveLazyViews(this);
28842            }
28843            
28844            
28845            this._viewCreationInProgress = true;
28846
28847            
28848            var guide = this._model._guide();
28849            var callbacks = guide._lazyLoadCallbacks || {};
28850            
28851            this._model._loadLazyFragment({
28852                "preFetch" : callbacks.preFetch || function () {
28853                    $("#loadingPage").addClass("guideLoading");
28854                },
28855                "postFetch" : callbacks.postFetch || function () {
28856                    $("#loadingPage").removeClass("guideLoading");
28857                },
28858                "success" : function () {
28859                    
28860                    that._createReferredView();
28861                    
28862                    
28863                    that._viewCreationInProgress = undefined;
28864                    that._itemsLoaded = true;
28865                }
28866            });
28867            
28868            
28869        },
28870
28871        
28872        setActive : function (activeItemToken, focus, muteScripts) {
28873            
28874            
28875            
28876            if (this._model._lazyReference && this._model.getAttribute('autoLoad') !== false) {
28877                
28878                
28879                
28880                
28881                
28882                if (_.isUndefined(this._viewCreationInProgress) && _.isUndefined(this._itemsLoaded)
28883                    && this._guideView._currentActiveItemView !== this) {
28884                    this._loadLazyFragment();
28885                }
28886            }
28887
28888            var currentActiveItemQName = this.getOrElse(this.currentActiveItemView, "qualifiedName", null);
28889            
28890            activeItemToken = activeItemToken || currentActiveItemQName || "firstItem";
28891            if (activeItemToken != currentActiveItemQName) {
28892                var newActiveItemModel = this._model.navigationContext.getItemForNav(activeItemToken);
28893                if (!newActiveItemModel) {
28894                    this.logger().log("AF", "activeItemToken not found:" + activeItemToken + ",currentActiveItem:" +
28895                        currentActiveItemQName + ":" + this._model.somExpression);
28896                    return false;
28897                }
28898                var newActiveItemView = this.getQualifiedNamedView(newActiveItemModel._escapeQualifiedName());
28899                if (!muteScripts && this._model.completionExpReq && this.currentActiveItemView && this.currentActiveItemView.focusable() && (this.childViews.indexOf(newActiveItemView) > this.childViews.indexOf(this.currentActiveItemView))) {
28900                    var completed = true;
28901                    if (this._model.getAttribute("validateOnStepCompletion")) {
28902                        completed = window.guideBridge.validate([], this._model.panel.navigationContext.currentItem.somExpression);
28903                    }
28904                    
28905                    completed = completed && this._model.executeExpression("completionExp");
28906                    if (!completed) {
28907                        return false;
28908                    } else if (this.currentActiveItemView) {
28909                        this.currentActiveItemView.$item.addClass("completed");
28910                        this.currentActiveItemView.$itemNav.addClass("completed");
28911                    }
28912                }
28913                this.currentActiveItemView = newActiveItemView;
28914                
28915                
28916                
28917                
28918                
28919            }
28920            if (this.currentActiveItemView) {
28921                this.currentActiveItemView.setActive(null, focus, muteScripts);
28922            }
28923            return true;
28924        },
28925        
28926        _clearInactiveLazyViews : function (that) {
28927            _.each(this.childViews, function (item) {
28928                if (item && item._model.className === "guidePanel" && item._ancestorHasNavigableLayout) {
28929                    if (item._model._itemsLoaded && !that._isSelfOrAncestor(item) && !item._hasEffectiveActiveClass()
28930                        && item._model._lazyReference) {
28931                        
28932                        item._model._unloadLazyReferenceModel();
28933                        
28934                        item._model._itemsLoaded = undefined;
28935                        
28936                        item._unloadView();
28937                        
28938                        item._itemsLoaded = undefined;
28939                    } else {
28940                        
28941                        item._clearInactiveLazyViews(that);
28942                    }
28943                }
28944            }, this);
28945        },
28946        
28947        _isSelfOrAncestor : function (panelView) {
28948
28949            var selfOrParentView = this;
28950            while (!_.isUndefined(selfOrParentView) && selfOrParentView._model.className !== "rootPanelNode") {
28951                if (panelView === selfOrParentView) {
28952                    return true;
28953                }
28954                selfOrParentView = selfOrParentView.parentView;
28955            }
28956            return false;
28957        },
28958        
28959        _hasEffectiveActiveClass : function () {
28960            var hierarchy = this;
28961            while (!_.isUndefined(hierarchy) && this._model.className !== "rootPanelNode") {
28962                if (hierarchy.$item.hasClass("active")) {
28963                    hierarchy = hierarchy.parentView;
28964                } else {
28965                    return false;
28966                }
28967            }
28968            return true;
28969        },
28970
28971        handleAccessibility : function () {
28972            var role, screenReaderText;
28973            screenReaderText = this._model._getScreenReaderText();
28974            role = this._model._getRole();
28975            if (screenReaderText) {
28976                this.$itemNav.attr("aria-label", screenReaderText);
28977            }
28978            this.$itemNav.find('a').attr("tabindex", function (index, currentValue) {
28979                return (currentValue == -1 ? currentValue : 0);
28980            });
28981        },
28982
28983        getQualifiedNamedView : function (qName) {
28984            var view = _.find(this.childViews, function (childView) {
28985                return (childView._model._escapeQualifiedName() == qName);
28986            }, this);
28987            return view;
28988        },
28989
28990        _toggleAddRemoveButtons : function () {
28991            var panelModel = this._model,
28992                instanceManager = panelModel.instanceManager;
28993            $('[data-guide-id="' + panelModel.id + '"][data-guide-addremove="remove"]').toggleClass("hidden", instanceManager.instanceCount == instanceManager.minOccur);
28994            $('[data-guide-id="' + panelModel.id + '"][data-guide-addremove="add"]').toggleClass("hidden", instanceManager.instanceCount == instanceManager.maxOccur);
28995        }
28996    });
28997
28998    GuidePanelView.defineProps({
28999        hasNavigableLayout : {
29000            get : function () {
29001                return this.$itemsNavContainer.length > 0;
29002            }
29003        },
29004        $itemsContainer : {
29005            get : function () {
29006                
29007                if (this._model._selfOrAncestorIsLazyReference || !this._$itemsContainer || this._$itemsContainer.length === 0) {
29008                    this._$itemsContainer = this._find(this.guideUtil.itemContainerSelector(this._model.id));
29009                    
29010                    if (this._$itemsContainer.length === 0) {
29011                        this._$itemsContainer = this._find(this.guideUtil.alternateItemContainerSelector(this._model.id));
29012                    }
29013                }
29014                return this._$itemsContainer;
29015            }
29016        },
29017        $itemsNavContainer : {
29018            get : function () {
29019                if (this._model._selfOrAncestorIsLazyReference || !this._$itemsNavContainer || this._$itemsNavContainer.length === 0) {
29020                    this._$itemsNavContainer = this._find(this.guideUtil.itemNavContainerSelector(this._model.id));
29021                }
29022                return this._$itemsNavContainer;
29023            }
29024        },
29025        $summary : {
29026            get : function () {
29027                if (!this._$summary) {
29028                    this._$summary = this._find(this._summarySelector);
29029                }
29030                return this._$summary;
29031            }
29032        },
29033        $title : {
29034            get : function () {
29035                if (!this._$title) {
29036                    this._$title = this._find(this._titleSelector);
29037                }
29038                return this._$title;
29039            }
29040        },
29041        currentActiveItemView : {
29042            get : function () {
29043                return this._currentActiveItemView;
29044            },
29045            set : function (value) {
29046                if (value != this._currentActiveItemView) {
29047                    if (this._currentActiveItemView) {
29048                        
29049                        this._currentActiveItemView._model.viewVisited = true;
29050                    }
29051                    if (!value) {
29052                        var itemModel = this._model.navigationContext.firstItem;
29053                        if (itemModel) {
29054                            value = this.getQualifiedNamedView(itemModel._escapeQualifiedName());
29055                        }
29056                    }
29057                    this._currentActiveItemView = value;
29058                    
29059                    this._model.navigationContext.currentItem = (this._currentActiveItemView || {})._model;
29060                    _.each(this.childViews, function (childView) {
29061                        if (childView == this._currentActiveItemView) {
29062                            childView.$item.addClass("active");
29063                            childView.$itemNav.addClass("active");
29064                            childView.$itemNav.attr("aria-selected", true);
29065                            childView.$itemNav.attr("aria-disabled", false);
29066                            childView.$itemNav.removeClass("wizard-tab-disabled");
29067                        } else {
29068                            childView.$item.removeClass("active");
29069                            childView.$itemNav.removeClass("active");
29070                            childView.$itemNav.attr("aria-selected", false);
29071                        }
29072                    }, this);
29073                    
29074                    
29075                    
29076                    
29077                    if (this._currentActiveItemView instanceof guidelib.view.GuidePanel
29077View && this._currentActiveItemView._childInitializeWaiting) {
29078                        this._currentActiveItemView._postInitializeChildren();
29079                    }
29080
29081                    if (true && _.isUndefined(this._model._ajaxCallDone)) {
29082                        
29083                        
29084                        var model = this._model;
29085                        
29086                        while (model && !(model instanceof guidelib.model.RootPanelNode)) {
29087                            if (model.toolbar) {
29088                                model.toolbar.execNavigationChangeExpression();
29089                            }
29090                            model = model.parent;
29091                        }
29092                        
29093                        if (model && model.toolbar && model instanceof  guidelib.model.RootPanelNode) {
29094                            model.toolbar.execNavigationChangeExpression();
29095                        }
29096                    }
29097                }
29098            }
29099        },
29100        
29101        _ancestorHasNavigableLayout : {
29102            get : function () {
29103                var parentView = this.parentView;
29104                while (parentView) {
29105                    if (parentView.$itemsNavContainer && parentView.$itemsNavContainer.length > 0) {
29106                        return true;
29107                    }
29108                    parentView = parentView.parentView;
29109                }
29110                return false;
29111            }
29112        }
29113    });
29114}($, _, guidelib));
29115(function ($, _, guidelib) {
29116
29117    var cloneCounter = 0;
29118
29119    var tableMobileLayoutConstants = {
29120        COLLAPSIBLE_COLUMNS : "collapsibleColumns",
29121        HEADERS_LEFT : "headersLeft",
29122        COLLAPSIBLE_COLUMNS_CONTROL_ROW_SELECTOR : "tr.child",
29123        RUNTIME_TABLE_CONTROL : "guideTableRuntimeControls",
29124        RUNTIME_TABLE_RIGHT_CONTROL : "guideTableRuntimeRightControls",
29125        RUNTIME_TABLE_LEFT_CONTROL : "guideTableRuntimeLeftControls",
29126        RUNTIME_TABLE_ADD_CONTROL : "guideTableRuntimeAddControl",
29127        RUNTIME_TABLE_DELETE_CONTROL : "guideTableRuntimeDeleteControl",
29128        RUNTIME_TABLE_EDIT_CONTROL : "guideTableRuntimeEditControl"
29129    };
29130
29131    var tableSortingComponents = {
29132        GUIDE_INSTANCE_MANAGER : "guideInstanceManager",
29133        WEB_CHANNEL_HEADER_COMPONENT : "fd/ccm/web-channel/components/tableHeader/v1/tableHeader",
29134        AF_TABLE_HEADER_COMPONENT : "fd/af/components/tableHeader",
29135        SORTING_ENABLED : "sortingEnabled"
29136    };
29137
29138    var GuideTableView = guidelib.view.GuideTableView = guidelib.view.GuidePanelView.extend({
29139
29140        
29141        TABLE_WIDTH_BUFFER : 23,
29142        
29143        _getPluginOptions : function () {
29144            var defaultOptions  = {
29145                "bAutoWidth" : this.bAutoWidth
29146            }, columnWidthArray = null,
29147                sum = 0,
29148                sWidthArray = null,
29149                numOfTableCol = this.$tableElement.find("th").length;
29150
29151            if (this.bAutoWidth === false) {
29152                columnWidthArray = this._model.columnWidth.split(",");
29153                if (columnWidthArray.length === numOfTableCol) {
29154                    
29155                    _.each(columnWidthArray, function (item) {
29156                        sum += parseInt(item, 10);
29157                    });
29158                    
29159                    sWidthArray = _.map(columnWidthArray, function (item) {
29160                        return {
29161                            "pWidth" : Math.floor((item * 100) / sum)
29162                        };
29163                    });
29164                }
29165                
29166                defaultOptions = _.extend({}, defaultOptions, {
29167                    aWidthPercentage : sWidthArray,
29168                    aWidth : columnWidthArray
29169                });
29170            }
29171            return defaultOptions;
29172
29173        },
29174
29175        
29176        setAutoWidth : function () {
29177            if (this._model.columnWidth && this._model.columnWidth.length > 0) {
29178                this.bAutoWidth = false;
29179            }  else {
29180                this.bAutoWidth = true;
29181            }
29182        },
29183
29184        
29185        createView : function (id) {
29186            var $htmlTemplate = this._guideView._domTemplateCacheStore.cloneDomElement("#" + id),
29187                formElemSelector = "#" + id + "_widget",
29188                counter = ++cloneCounter;
29189            if ($htmlTemplate.length == 0) {
29190                
29191                $htmlTemplate = this.$element.find("#" + id).clone();
29192            }
29193            
29194            $htmlTemplate.find(formElemSelector).attr("id", id + "_widget" + counter);
29195
29196            var view = guidelib.view.GuideViewRegistry.prototype.createView($htmlTemplate, this);
29197            view.postInitialize();
29198            return $htmlTemplate;
29199        },
29200
29201        initializeTableColumnWidth : function (pluginOptions) {
29202            
29203            if (this.bAutoWidth == false && this._model.mobileLayout === tableMobileLayoutConstants.HEADERS_LEFT) {
29204                
29205                
29206                this.$tableElement.css("table-layout", "fixed");
29207                var widthArray = pluginOptions["aWidthPercentage"],
29208                    numOfTableCol = this.$tableElement.find("th").length;
29209                if (widthArray && widthArray.length == numOfTableCol) {
29210                    
29211                    this.$tableElement.find("th").each(function (index) {
29212                        $(this).css("width", widthArray[index]["pWidth"] + "%");
29213                    });
29214                }
29215            }
29216        },
29217
29218        _checkIfTableSortingEnabled : function () {
29219            var jsonModel = this._model.jsonModel;
29220            return (jsonModel[tableSortingComponents.SORTING_ENABLED] === "true");
29221        },
29222
29223        
29224        handleParentVisibleChanged : function (event) {
29225            switch (event._property) {
29226                case "visible":
29227                    this.handleTableShown();
29228                    break;
29229            }
29230        },
29231
29232        
29233        _checkParentModelChanged : function() {
29234            var currentParent = this.parentView;
29235            while(currentParent != null) {
29236                currentParent._model.on(guidelib.event.GuideModelEvent.MODEL_CHANGED, this.handleParentVisibleChanged, this);
29237                currentParent = currentParent.parentView;
29238            }
29239        },
29240
29241        
29242        initialize : function () {
29243            GuideTableView._super.initialize.apply(this, arguments);
29244            
29245            this._checkParentModelChanged();
29246            
29247            this.$tableElement = this.$element.find("> table");
29248            
29249            this.setAutoWidth();
29250            
29251            var widgetOptions = this._getPluginOptions(),
29252                that = this;
29253            
29254            this.initializeTableColumnWidth(widgetOptions);
29255            this._fixTableControls(true);
29256            if (this._model.mobileLayout ===  tableMobileLayoutConstants.COLLAPSIBLE_COLUMNS) {
29257                widgetOptions = _.extend({}, widgetOptions, {
29258                    
29259                    bControlRowHiddenCells : false,
29260
29261                    
29262                    bDisableControlRowCells : true,
29263                    
29264                    viewCallback : $.proxy(this.createView, this),
29265                    
29266                    tableRuntimeEditControlClass : tableMobileLayoutConstants.RUNTIME_TABLE_EDIT_CONTROL,
29267                    
29268                    fixTableControls : $.proxy(this._fixTableControls, this)
29269                });
29270                
29271                this.jqwidget = this.$tableElement.responsiveTablePlugin(widgetOptions).data("responsiveTablePlugin");
29272            }  else {
29273                
29274                $(window).on("resize orientationchange", function (event) {
29275                    that._fixTableControls(event);
29276                });
29277            }
29278            
29279            if (this._checkIfTableSortingEnabled()) {
29280                this.$tableElement.tableSorting = this.guideTableSorter.initialize;
29281                this.$tableElement.tableSorting({
29282                    model : this._model,
29283                    tableContext : this
29284                });
29285            }
29286        },
29287
29288        handleVisibleChanged : function (event) {
29289            GuideTableView._super.handleVisibleChanged.apply(this, arguments);
29290            
29291            this.handleTableShown();
29292            this._resetTableCellWidth();
29293        },
29294
29295        handleTableShown : function () {
29296            if (this._model.mobileLayout ===  tableMobileLayoutConstants.COLLAPSIBLE_COLUMNS) {
29297                
29298                this.jqwidget._initializeColumnVisibility();
29299                
29300                if (this.jqwidget.isColumnHidden()) {
29301                    
29302                    this.$tableElement.find(".guideFieldNode").addClass("dontSyncEnabled");
29303                    
29304                    this.$tableElement.find("input, select, textarea, button").attr("disabled", "disabled");
29305                }
29306            }
29307        },
29308
29309        _resetTableCellWidth : function () {
29310            var that = this,
29311                tableWidthBuffer = this.TABLE_WIDTH_BUFFER;
29312            
29313            this.$tableElement.find("." + tableMobileLayoutConstants.RUNTIME_TABLE_CONTROL).each(function () {
29314                var element = this;
29315                setTimeout(function () {
29316                    that._resetTableCell($(element), tableWidthBuffer);
29317                }, 1);
29318            });
29319        },
29320
29321        _resetTableCell : function ($element, tableWidthBuffer) {
29322            var componentWidth;
29323            
29324            if ($element.hasClass(tableMobileLayoutConstants.RUNTIME_TABLE_RIGHT_CONTROL)) {
29325                var $component = $element.prev(),
29326                    $td = $element.parent();
29327                
29328                
29329                if ($element.is(":visible")) {
29330                    
29331                    $component.css("display", "inline-block");
29332                    $component.css("float", "left");
29333                    componentWidth = $td.width() - $element.outerWidth() - tableWidthBuffer;
29334                    var percentage = ((componentWidth / $td.width()) * 100);
29335                    
29336                    
29337                    $component.width(percentage + "%");
29338                } else {
29339                    
29340                    
29341                    $component.css("display", "block");
29342                    $component.css("float", "none");
29343                    $component.width($td.width());
29344                }
29345            } else if ($element.hasClass(tableMobileLayoutConstants.RUNTIME_TABLE_LEFT_CONTROL)) {
29346                
29347                if ($element.is(":visible")) {
29348                    $element.next().css("display", "inline-block");
29349                    componentWidth = $element.parent().width() - $element.outerWidth() - tableWidthBuffer;
29350                    var percentage = ((componentWidth / $element.parent().width()) * 100);
29351                    $element.next().width(percentage + "%");
29352                } else {
29353                    
29354                    $element.next().css("display", "block");
29355                }
29356            }
29357        },
29358
29359        _fixTableControls : function (event) {
29360            
29361            
29362            
29363            if ((this._model.mobileLayout ===  tableMobileLayoutConstants.COLLAPSIBLE_COLUMNS) && (this.jqwidget)) {
29364                
29365                if (this.jqwidget.isColumnHidden()) {
29366                    
29367                    this.$tableElement.find("tr:not(.child)").find(".guideFieldNode").addClass("dontSyncEnabled");
29368                    
29369                    this.$tableElement.find("tr:not(.child)").find("input, select, textarea, button").attr("disabled", "disabled");
29370                } else {
29371                    
29372                    this.$tableElement.find(".guideFieldNode").removeClass("dontSyncEnabled");
29373                    
29374                    this.$tableElement.find("input, select, textarea, button").removeAttr("disabled");
29375                }
29376            }
29377            
29378            
29379            if (event) {
29380                this._resetTableCellWidth();
29381            }
29382        },
29383
29384        
29385        _fixChildDom : function (view, $item, $itemNav) {
29386            GuideTableView._super._fixChildDom.apply(this, arguments);
29387            
29388            
29389            if (this._model.mobileLayout ===  tableMobileLayoutConstants.COLLAPSIBLE_COLUMNS) {
29390                
29391                this.jqwidget._fixControlRows();
29392            }
29393            
29394            this._fixTableControls();
29395            
29396            this._resetTableCellWidth();
29397        },
29398
29399        _postInitializeChildren : function () {
29400            
29401            GuideTableView._super._postInitializeChildren.call(this);
29402            
29403            
29404            
29405            
29406            
29407            if (this._model.mobileLayout ===  tableMobileLayoutConstants.COLLAPSIBLE_COLUMNS) {
29408                
29409                this.handleTableShown();
29410            }
29411            
29412            
29413            else if (this._model.mobileLayout === tableMobileLayoutConstants.HEADERS_LEFT) {
29414                this._fixTableCellForHeaderLeftLayout();
29415            }
29416            this._resetTableCellWidth();
29417        },
29418
29419        _fixTableCellForHeaderLeftLayout : function () {
29420            var that = this,
29421                guideUtil = guidelib.util.GuideUtil;
29422            this.$tableElement.find("tr td").each(function () {
29423                guideUtil._setGuideDataHeader($(this), that.$tableElement);
29424            });
29425        },
29426
29427        
29428        handleChildChanged : function (event) {
29429            GuideTableView._super.handleChildChanged.apply(this, arguments);
29430            
29431            
29432            if (this._model.mobileLayout === tableMobileLayoutConstants.HEADERS_LEFT) {
29433                this._fixTableCellForHeaderLeftLayout();
29434            }
29435            if (event._property == "childAdded") {
29436                this._resetTableCellWidth();
29437            }
29438        },
29439
29440        addRemoveTemplateMarker : function () {
29441            
29442            _.each(this._model.children, function (childModel) {
29443                if (childModel instanceof guidelib.model.GuideInstanceManager) {
29444                    
29445                    var imId = childModel.id,
29446                        instanceId = (childModel._instances[0] || {}).id || childModel.instanceTemplateId,
29447                        gTemplateMarker = null,
29448                        
29449                        instanceItem = this.guideUtil.itemSelector(instanceId, childModel._instances[0]),
29450                        navItem = this.guideUtil.itemNavSelector(instanceId),
29451                        $instanceItem = this.$itemsContainer.find(instanceItem);
29452                    if ($instanceItem.is("tr")) {
29453                        $instanceItem.attr("data-guide-template-marker", imId);
29454                    }
29455                    
29456                    
29457                    
29458                    
29459                    
29460                }
29461            }, this);
29462        },
29463
29464        tableSortComparator : {
29465            DATE : function (tableModelDataRows, sortList, tableContext) {
29466                    return tableModelDataRows.sort(function (a, b) {
29467                        var currColumn = sortList[0][0], currOrder = sortList[0][1],
29468                            guideTableSorter = tableContext.guideTableSorter,
29469                            value_a = guideTableSorter.formatDateValue(guideTableSorter.getValueFromJsonModel(a, currColumn)),
29470                            value_b = guideTableSorter.formatDateValue(guideTableSorter.getValueFromJsonModel(b, currColumn));
29471                        return guideTableSorter.ComparedOrder(value_a, value_b, currOrder);
29472                    });
29473                },
29474            NUMBER : function (tableModelDataRows, sortList, tableContext) {
29475                    return tableModelDataRows.sort(function (a, b) {
29476                        var currColumn = sortList[0][0], currOrder = sortList[0][1],
29477                            guideTableSorter = tableContext.guideTableSorter,
29478                            value_a = guideTableSorter.formatRegexFloatData(guideTableSorter.getValueFromJsonModel(a, currColumn)),
29479                            value_b = guideTableSorter.formatRegexFloatData(guideTableSorter.getValueFromJsonModel(b, currColumn));
29480                        return guideTableSorter.ComparedOrder(value_a, value_b, currOrder);
29481                    });
29482
29483                },
29484            STRING : function (tableModelDataRows, sortList, tableContext) {
29485                    return tableModelDataRows.sort(function (a, b) {
29486                        var currColumn = sortList[0][0], currOrder = sortList[0][1],
29487                            guideTableSorter = tableContext.guideTableSorter,
29488                            value_a = guideTableSorter.formatRichTextString(guideTableSorter.getValueFromJsonModel(a, currColumn, true)),
29489                            value_b = guideTableSorter.formatRichTextString(guideTableSorter.getValueFromJsonModel(b, currColumn, true));
29490                        return guideTableSorter.ComparedOrder(value_a, value_b, currOrder);
29491                    });
29492                }
29493        },
29494
29495        
29496        guideTableSorter : new function () {
29497            this.initialize = function (tableSortingConfig) {
29498                return this.each(function () {
29499                    this.tableConfig = {};
29500                    var defaultSortingConfig = {sortList : [], selectorsHeaders : 'thead th',
29501                        headerCss : {asc : "asc", desc : "desc", random : "random"}
29502                    };
29503                    if (!this.tHead || !this.tBodies) {return;}
29504                    var table = $(this), tableConfig = {};
29505                    tableConfig = $.extend(this.tableConfig, defaultSortingConfig, tableSortingConfig);
29506                    var tableHeaderModel, tableModel = tableConfig.model;
29507                    for (var index = 0 ; index < tableModel.children.length ; index++) {
29508                        if (isTableHeaderRow(tableModel.children[index])) {
29509                            tableHeaderModel = tableModel.children[index];
29510                            tableConfig.tableHeader = tableHeaderModel;
29511                            break;
29512                        }
29513                    }
29514                    var $tableHeaders = filterSortableHeaders(tableConfig, this);
29515                    $tableHeaders.click(function () {
29516                        if (this.sortingAllowed) {
29517                            sortCurrentColumn(this, table, tableConfig, $tableHeaders);
29518                        }
29519                    });
29520                    
29521                    $tableHeaders.each(function (index) {
29522                        if (this.sortingAllowed) {
29523                            sortOnFirstColumn(this, tableModel);
29524                            return false;
29525                        }
29526                    });
29527                });
29528            };
29529
29530            
29531            function sortOnFirstColumn(firstColumn, tableModel) {
29532                if (typeof tableModel._guide !== "undefined" && tableModel._guide()) {
29533                    var isSubmittedData = guidelib.util.GuideUtil._fetchJSONNodeValue(tableModel._guide().runtime.guideContext.guidePrefillJson, "afSubmissionInfo");
29534                    isSubmittedData = isSubmittedData || guidelib.util.GuideUtil.fetchXMLNodeValue(tableModel._guide().runtime.guideContext.guidePrefillXml, "afSubmissionInfo");
29535                    if (!isSubmittedData) {
29536                        $(firstColumn).trigger("click");
29537                    }
29538                }
29539            }
29540
29541            
29542            function filterSortableHeaders(tableConfig, tableDom) {
29543                var $tableHeaders = $(tableConfig.selectorsHeaders, tableDom).each(function (index) {
29544                    this.column = index;
29545                    this.order = 1;
29546                });
29547                for (var column = 0 ; column < tableConfig.tableHeader.children.length ; column++) {
29548                    var currColumnModel = tableConfig.tableHeader.children[column];
29549                    $tableHeaders[column].sortingAllowed = true;
29550                    var sortDataType = currColumnModel.jsonModel["sortingDataType"];
29551                    sortDataType = !sortDataType ? "STRING" : sortDataType;
29552                    currColumnModel.jsonModel.sortingDataType = sortDataType;
29553                    if (!tableConfig.tableHeader.visible || sortDataType === "noSort") {
29554                        $tableHeaders[column].sortingAllowed = false;
29555                        $($tableHeaders[column]).removeClass("sortEnabled");
29556                        var $sortingButton = $($tableHeaders[column]).find(".sortingButton").remove();
29557                    }
29558                }
29559                return $tableHeaders;
29560            }
29561
29562            
29563            function sortCurrentColumn(currentHeader, table, tableConfig, $tableHeaders) {
29564                var tableRows = (table[0].tBodies[0] && table[0].tBodies[0].rows.length) || 0;
29565                if (tableRows > 0) {
29566                    currentHeader.order = (++(currentHeader.order) % 2);
29567                    tableConfig.sortList = [];
29568                    tableConfig.sortList.push([currentHeader.column, currentHeader.order]);
29569                    setTimeout(function () {
29570                        updateTableHeaderStyles($tableHeaders, tableConfig.sortList, tableConfig);
29571                        sortGuideTableDataModel(tableConfig, tableConfig.sortList, tableConfig.model);
29572                    }, 1);
29573                }
29574            }
29575
29576            
29577            function updateTableHeaderStyles($headers, sortingList, tableConfig) {
29578                var order, headerCSS = [tableConfig.headerCss.asc, tableConfig.headerCss.desc, tableConfig.headerCss.random];
29579                $headers.each(function (index) {
29580                    var $sortingButton = $(this).find(".sortingButton");
29581                    $sortingButton.removeClass(headerCSS[0]).removeClass(headerCSS[1]).removeClass(headerCSS[2]);
29582                    if ($headers[index].sortingAllowed) {
29583                        if (index === sortingList[0][0]) {
29584                            order = sortingList[0][1];
29585                            $sortingButton.addClass(headerCSS[order]);
29586                        } else {
29587                            $sortingButton.addClass(tableConfig.headerCss.random);
29588                        }
29589                    }
29590                });
29591            }
29592
29593            
29594            function sortGuideTableDataModel(tableConfig, sortList, tableModel) {
29595                var i,j = 0,tableModelChildren = tableModel.children, tableDataRows = [], prevTableModel = tableModel,
29596                    modifiedGuideTableModel = [], tableContext = tableConfig.tableContext;
29597                
29598                for (i = 0; i < tableModelChildren.length; i++) {
29599                    if (tableModelChildren[i].className !== tableSortingComponents.GUIDE_INSTANCE_MANAGER) {
29600                        if (isTableRowsWithData(tableModelChildren[i])) {
29601                            tableDataRows.push(tableModelChildren[i]);
29602                        }
29603                    }
29604                }
29605                var dataType = tableConfig.tableHeader.children[[sortList[0][0]]].jsonModel.sortingDataType;
29606                tableDataRows = tableContext.tableSortComparator[dataType].call(tableConfig, tableDataRows, sortList, tableContext);
29607                for (i = 0; i < tableModel.children.length; i++) {
29608                    if (isTableRowsWithData(tableModel.children[i])) {
29609                        modifiedGuideTableModel.push(tableDataRows[j]);
29610                        j++;
29611                    } else {
29612                        modifiedGuideTableModel.push(tableModel.children[i]);
29613                    }
29614                }
29615                tableModel.children = modifiedGuideTableModel;
29616                tableModel._triggerEvent(guidelib.event.GuideModelEvent.MODEL_CHANGED, "tableModelSorted", prevTableModel, tableModel);
29617                syncNewModelToHTML(tableConfig.tableContext, tableModel);
29618            }
29619
29620            
29621            function isTableRowsWithData(tableModelChildElement) {
29622                var resourceType = tableModelChildElement.options.jsonModel["sling:resourceType"],
29623                    childElementClassName = tableModelChildElement.className;
29624                return !((childElementClassName === tableSortingComponents.GUIDE_INSTANCE_MANAGER) || (resourceType === tableSortingComponents.AF_TABLE_HEADER_COMPONENT) || (resourceType === tableSortingComponents.WEB_CHANNEL_HEADER_COMPONENT));
29625            }
29626
29627            function isTableHeaderRow(tableModelChildElement) {
29628                var resourceType = tableModelChildElement.options.jsonModel["sling:resourceType"];
29629                return ((resourceType === tableSortingComponents.AF_TABLE_HEADER_COMPONENT) || (resourceType === tableSortingComponents.WEB_CHANNEL_HEADER_COMPONENT));
29630            }
29631
29632            this.formatRegexFloatData = function (data) {
29633                return (isNaN(parseFloat(data))) ? 0 : parseFloat(data);
29634            };
29635
29636            this.formatDateValue = function (data) {
29637                return (isNaN(new Date(data).getTime())) ? 0 : new Date(data).getTime();
29638            };
29639
29640            this.formatRichTextString = function (data) {
29641                data = "<div>" + data + "</div>";
29642                return $(data).text().trim();
29643            };
29644
29645            this.ComparedOrder = function (value_a, value_b, currOrder) {
29646                if (value_a > value_b) {
29647                    return (currOrder === 0) ? 1 : -1;
29648                } else if (value_a < value_b) {
29649                    return (currOrder === 0) ? -1 : 1;
29650                } else {
29651                    return -1;
29652                }
29653            };
29654
29655            this.getValueFromJsonModel = function (tableRow, currColumn, isString) {
29656                var jsonModel = tableRow.children[getValidCurrentColumn(tableRow.children, currColumn)].jsonModel, value = null;
29657                if (!isString && jsonModel.defaultValue && jsonModel.defaultValue.length === 1) {
29658                    value = jsonModel.defaultValue[0];
29659                }
29660                if (!value) {
29661                    value = jsonModel._value;
29662                }
29663                return value === null ? "" : this.formatRichTextString(value);
29664            };
29665
29666            
29667            function getValidCurrentColumn(tableRowModel, currColumn) {
29668                var validCurrColumn = currColumn, index = 0 ;
29669                while (currColumn > 0) {
29670                    if (tableRowModel[index].jsonModel.guideNodeClass === tableSortingComponents.GUIDE_INSTANCE_MANAGER) {
29671                        validCurrColumn++;
29672                    } else {
29673                        currColumn--;
29674                    }
29675                    index++;
29676                }
29677                return validCurrColumn;
29678            }
29679
29680            
29681            function syncNewModelToHTML(tableContext, tableModel) {
29682                var tableItemsViews = {}, childView, index;
29683                
29684                for (index = 0; index < tableContext.childViews.length; index++) {
29685                    childView = tableContext.childViews[index];
29686                    if (childView.isItem) {
29687                        tableItemsViews[childView.id] = childView;
29688                    }
29689                }
29690                for (index = 1; index < tableContext._model.items.length; index++) {
29691                    var childModel = tableContext._model.items[index], childId = childModel.id, view = tableItemsViews[childId],newChild = view._model,
29692                        $childItem = view.$item, $childItemNav = view.$itemNav, insertBeforeId, insertAfterId;
29693                    if (index === 1) {
29694                        if (tableModel.items.length > 2) {
29695                            insertBeforeId = tableModel.items[index + 1].id;
29696                        }
29697                    } else {
29698                        insertAfterId = tableModel.items[index - 1].id;
29699                    }
29700                    var insertAfterItemSelector = insertAfterId ? tableContext.guideUtil.itemSelector(insertAfterId, newChild) : "#" + newChild.instanceManager.id,
29701                        insertBeforeItemSelector = insertBeforeId ? tableContext.guideUtil.itemSelector(insertBeforeId, newChild) : "#" + newChild.instanceManager.id;
29702                    tableContext.$itemsContainer.each(function (index) {
29703                        var insertEl = $childItem.get(index) || $childItem.get(0),
29704                            $insertBeforeItem,
29705                            $insertAfterItem = $(this).find(insertAfterItemSelector);
29706                        if ($insertAfterItem.get(0) !== insertEl) {
29707                            $insertAfterItem.after($(insertEl));
29708                        } else {
29709                            $insertBeforeItem = $(this).find(insertBeforeItemSelector);
29710                            $insertBeforeItem.before($(insertEl));
29711                        }
29712                    });
29713                }
29714            }
29715        }
29716    });
29717}($, _, guidelib));
29718
29719(function ($, guidelib) {
29720    var GuideTableRowView = guidelib.view.GuideTableRowView = guidelib.view.GuidePanelView.extend({
29721
29722        handleChildChanged : function (event) {
29723            
29724        }
29725
29726    });
29727}($, guidelib));
29728(function ($, guidelib, _) {
29729    var GuideContainerView = guidelib.view.GuideContainerView =  guidelib.view.GuideItemsView.extend({
29730        initialize : function () {
29731            this._queueViewForLazyItems = [];
29732            
29733            window.guideBridge._guideView = this;
29734            var $htmlTemplateDom =  $(this.options.element).clone();
29735            this._domTemplateCacheStore =
29736                new guidelib.view.util.DomTemplateCacheStore({$htmlTemplateDom : $htmlTemplateDom});
29737            this._lastFocussedPanelForNonActionFields = null;
29738            GuideContainerView._super.initialize.call(this);
29739            this._currentFocusItemSom = null;
29740            
29741            
29742            this._previousFocusItemSom = "FIRST_TIME";
29743            $(window).on("keydown.guides", $.proxy(this.hotKeys, this));
29744            this.postInitialize();
29745            this._model.on(guidelib.event.GuideModelEvent.MODEL_REFRESH, function (evnt) {
29746                switch (evnt._property) {
29747                case "jsonModel":
29748                    this._syncGuideNodeToHtml(true);
29749                    break;
29750                default:
29751                    this._model.logger().error("unexpected event property " + evnt._property);
29752                }
29753            }, this);
29754        },
29755
29756        _reInitializeGuideContainerDom : function () {
29757            var $guideContainerDom = $('div.guideContainerWrapperNode');
29758            this.$element = $guideContainerDom;
29759        },
29760
29761        setFocus : function (somExp, focusOpt, runNavScr) {
29762            var options,
29763                focusOption,
29764                runNavScript,
29765                somExpression,
29766                muteScripts;
29767            if (_.isObject(somExp)) {
29768                options = somExp;
29769                somExpression = options.somExpression;
29770                focusOption = options.focusOption;
29771                runNavScript = options.runCompletionScript;
29772            } else {
29773                somExpression = somExp;
29774                focusOption = focusOpt;
29775                runNavScript = runNavScr;
29776            }
29777            muteScripts = !runNavScript;
29778            if (focusOption == "nextItemDeep" || focusOption == "prevItemDeep") {
29779                
29780                if (somExpression) {
29781                    this.logger().warn("AF", "somExpression is currently not supported for deepNavigation:" + somExpression + ":" + focusOption);
29782                    return false;
29783                }
29784                var existingFocusNavItem = this.getSomOnNavigableAncestor(this._lastFocussedPanelForNonActionFields);
29785                var existingNavView = this.getView(existingFocusNavItem);
29786                var siblingNavName = (focusOption == "nextItemDeep") ? "nextItem" : "prevItem";
29787                
29788                while (existingNavView && (existingNavView.parentView != this) && !existingNavView.getSiblingItemView(siblingNavName)) {
29789                    var navigableParentItem = this.getSomOnNavigableAncestor(existingNavView.parentView._model.somExpression);
29790                    existingNavView = this.getView(navigableParentItem);
29791                }
29792                if (existingNavView && existingNavView.parentView != this && existingNavView.getSiblingItemView(siblingNavName)) {
29793                    var madeActive = existingNavView.parentView.setActive(siblingNavName, false, muteScripts); 
29794                    if (!madeActive) {
29795                        this.logger().log("AF", "could not setActive for the deepNav:" + existingNavView._model.somExpression);
29796                        return false;
29797                    }
29798                    
29799                    var deepChildNav = (siblingNavName == "nextItem") ? "firstItem" : "lastItem";
29800                    var currentActiveChildView = existingNavView.parentView.currentActiveItemView;
29801                    while (currentActiveChildView) {
29802                        currentActiveChildView.setActive(deepChildNav, !currentActiveChildView.currentActiveItemView, true); 
29803                        currentActiveChildView = currentActiveChildView.currentActiveItemView;
29804                    }
29805                    return true;
29806                } else {
29807                    this.logger().warn("AF", "could not locate view for given somExpression:" + somExpression + ":" + focusOption);
29808                    return false;
29809                }
29810            }
29811
29812            if (!somExpression) {
29813                
29814                somExpression = this.guideModel.rootPanel.somExpression;
29815            }
29816            var currentView = this.rootPanelView;
29817            
29818            
29819            if (currentView) {
29820                var relativeSom = this.guideUtil.relativeSom(this.guideModel.rootPanel.somExpression, somExpression);
29821                if (relativeSom) {
29822                    var somTokens = relativeSom.split(".");
29823                    var error =
29824                        _.find(somTokens, function (qName) {
29825                            currentView.setActive(qName, false, muteScripts);
29826                            if (currentView instanceof guidelib.view.GuidePanelView && (currentView.currentActiveItemView == null || currentView.currentActiveItemView.qualifiedName != qName)) {
29827                                this.logger().log("AF", "could not find token:" + qName + ", som:" + somExpression);
29828                                return true; 
29829                            } else {
29830                                if (currentView.currentActiveItemView != null) {
29831                                    currentView = currentView.currentActiveItemView;
29832                                }
29833                            }
29834                        }, this);
29835                    if (error) {
29836                        return false;
29837                    }
29838                }
29839            } else {
29840                
29841                var $element = this._getGuideDomElement(somExpression);
29842                
29843                
29844                if ($element && $element.length > 0) {
29845                    
29846                    
29847                    currentView = $element.data("guideView");
29848                }
29849            }
29850
29851            if (currentView) {
29852                return currentView.setActive(focusOption, true, muteScripts);
29853            } else {
29854                return false;
29855            }
29856        },
29857
29858        _getGuideDomElement : function (somExpression, option) {
29859            var nav = "", res, node, nodeElSelector;
29860            if (somExpression && typeof somExpression === 'string') {
29861                node = this.guideModel.resolveNode(somExpression);
29862                if (!node) {
29863                    return;
29864                }
29865                nodeElSelector = "#" + node.id;
29866                if (option === "nav") {
29867                    nodeElSelector = this.guideUtil.itemNavSelector(node.id);
29868                }
29869                res = this.$element.find(nodeElSelector);
29870                return res;
29871            }
29872        },
29873
29874        getView : function (somExpression) {
29875            if (!somExpression) {
29876                return null;
29877            }
29878            var $focusEl = this._getGuideDomElement(somExpression),
29879                view = null,
29880                ancestorView = null;
29881            if ($focusEl && $focusEl.length > 0) {
29882                if (!$focusEl.data("guideView")) {
29883                    var rootPanelSom = this.guideModel.rootPanel.somExpression;
29884                    var relativeSom = guidelib.util.GuideUtil.relativeSom(rootPanelSom, somExpression) || "";
29885                    
29886                    _.reduce(relativeSom.split("."), function (currentSom, somToken) {
29887                        currentSom = currentSom ? currentSom + "." + somToken : somToken;
29888                        ancestorView = this.getView(currentSom);
29889                        if (ancestorView instanceof guidelib.view.GuidePanelView && ancestorView._childInitializeWaiting) {
29890                            ancestorView._postInitializeChildren();
29891                        }
29892                        return currentSom;
29893                    }, rootPanelSom, this);
29894                }
29895                view = $focusEl.data("guideView");
29896                if (view instanceof guidelib.view.GuidePanelView && view._childInitializeWaiting) {
29897                    view._postInitializeChildren();
29898                }
29899
29900                return view;
29901            }
29902            return null;
29903        },
29904
29905        hotKeys : function (evnt) {
29906            var handled = false, currentFocusItemSom;
29907
29908            switch (evnt.keyCode) {
29909            case 37: 
29910                if (evnt.altKey) {
29911                    window.guideBridge.setFocus(null, 'prevItemDeep', true);
29912                    handled = true;
29913                }
29914                break;
29915            case 39: 
29916                if (evnt.altKey) {
29917                    window.guideBridge.setFocus(null, 'nextItemDeep', true);
29918                    handled = true;
29919                }
29920                break;
29921            case 82: 
29922                if (evnt.altKey) {
29923                    window.guideBridge.reset();
29924                    handled = true;
29925                }
29926                break;
29927            case 83: 
29928                if (evnt.altKey) {
29929                    window.guideBridge.submit();
29930                    handled = true;
29931                }
29932                break;
29933            }
29934            if (handled) {
29935                evnt.preventDefault();
29936            }
29937        },
29938
29939        getSomOnNavigableAncestor : function (somExpression) {
29940            if (!somExpression || somExpression === "") {
29941                return null;
29942            }
29943
29944            var index, parentView, parentSom, isNavigable;
29945            index = somExpression.lastIndexOf(".");
29946
29947            if (index !== -1) {
29948                parentSom = somExpression.substring(0, index);
29949                parentView = this.getView(parentSom);
29950                if (parentView) {
29951                    isNavigable = parentView.hasNavigableLayout;
29952                }
29953                if (isNavigable) {  
29954                    return somExpression;
29955                }
29956                return this.getSomOnNavigableAncestor(parentSom);
29957            }
29958            
29959            return this.guideModel.rootPanel.somExpression;
29960        },
29961
29962        __printSyncPending : function () {
29963            
29964            _.each(this.childViews, function (childView) {
29965                if (childView._syncPending) {
29966                    this.logger().error("AF", childView._model.somExpression);
29967                } else {
29968                    GuideContainerView.prototype.__printSyncPending.call(childView);
29969                }
29970            }, this);
29971        },
29972        
29973        _clearInactiveLazyViews : function (that) {
29974            _.each(this.childViews, function (item) {
29975                if (item._model.className === "rootPanelNode") {
29976                    item._clearInactiveLazyViews(that);
29977                }
29978            });
29979        }
29980
29981    });
29982
29983    GuideContainerView.defineProps({
29984        guideModel : {
29985            get : function () {
29986                return this._model;
29987            }
29988        },
29989
29990        rootPanelView : {
29991            get : function () {
29992                return this._findChildView(this.guideModel.rootPanel);
29993            }
29994        },
29995
29996        currentFocusItemSom : {
29997            get : function () {
29998                return this._currentFocusItemSom;
29999            },
30000            set : function (newSom) {
30001                if (this._currentFocusItemSom !== newSom) {
30002                    var oldValue = this._currentFocusItemSom;
30003                    if (oldValue) {
30004                        this._previousFocusItemSom = oldValue;
30005                    }
30006                    this._currentFocusItemSom = newSom;
30007                    
30008                    if (newSom != null && this._model.resolveNode(newSom).parent.className !== "guideToolbar") {
30009                        this._lastFocussedPanelForNonActionFields = this.get
30009SomOnNavigableAncestor(this._currentFocusItemSom);
30010                        
30011                        
30012                        this._model._currentNavigablePanelSom =  this._lastFocussedPanelForNonActionFields;
30013                    }
30014                    if (newSom) {
30015                        this._triggerOnBridge("elementFocusChanged", this._model.resolveNode(newSom), "focus", this._previousFocusItemSom, newSom);
30016                        if (this._previousFocusItemSom) {
30017                            var getPreviousItemNavigableSom = this.getSomOnNavigableAncestor(this._previousFocusItemSom),
30018                                getCurrentItemNavigableSom = this.getSomOnNavigableAncestor(newSom);
30019                            if (getCurrentItemNavigableSom !== getPreviousItemNavigableSom) {
30020                                this._triggerOnBridge("elementNavigationChanged", this._model.resolveNode(getCurrentItemNavigableSom),
30021                                    "navigate", getPreviousItemNavigableSom, getCurrentItemNavigableSom);
30022                            }
30023                        }
30024                    }
30025                }
30026            }
30027        },
30028
30029        skipFieldFocus : {
30030            
30031            get : function () {
30032                return this._skipFieldFocus;
30033            },
30034            
30035            set : function (newVal) {
30036                this._skipFieldFocus = newVal;
30037            }
30038        }
30039    });
30040}($, guidelib, _));
30041(function (_, guidelib) {
30042    guidelib.model.mixin.ValidationsDisabled = {
30043        normalProperties : {
30044            setParentValidationsDisabled : function (bParentValidationsDisabled) {
30045                var oldValidationsDisabled = this.validationsDisabled,
30046                    newValidationsDisabled;
30047                this._bParentValidationsDisabled = bParentValidationsDisabled;
30048                newValidationsDisabled = this.validationsDisabled;
30049                this.handleChildValidationsDisabled(newValidationsDisabled, oldValidationsDisabled);
30050            },
30051
30052            handleChildValidationsDisabled : function (newValidationsDisabled, oldValidationsDisabled) {
30053                if (newValidationsDisabled !== oldValidationsDisabled) {
30054                    if (this instanceof guidelib.model.Field) {
30055                        if (newValidationsDisabled === true) {
30056                            if (this.validationState === false) {
30057                                this._errorText = "";
30058                                this.validationState = true;
30059                                this._triggerEvent(guidelib.event.GuideModelEvent.ERROR_CHANGED,
30060                                    "validationStatus", this.validationState, this._errorText);
30061                            }
30062                        }
30063                    }
30064                    _.each(this._children, function (child) {
30065                        if (child instanceof guidelib.model.Field || child instanceof guidelib.model.GuideItemsContainer) {
30066                            child.setParentValidationsDisabled(newValidationsDisabled);
30067                        }
30068                    });
30069                }
30070            }
30071        },
30072        propertyDescriptors : {
30073            validationsDisabled : {
30074                get : function () {
30075                    return this._bParentValidationsDisabled || this._validationsDisabled;
30076                },
30077                set : function (bValidationsDisabled) {
30078                    var oldValidationsDisabled = this.validationsDisabled,
30079                        newValidationsDisabled;
30080                    this._validationsDisabled = bValidationsDisabled;
30081                    newValidationsDisabled = this.validationsDisabled;
30082                    this.handleChildValidationsDisabled(newValidationsDisabled, oldValidationsDisabled);
30083                }
30084            }
30085        }
30086    };
30087
30088}(_, guidelib));
30089(function (_, guidelib) {
30090
30091    
30092    var GuideItemsContainer = guidelib.model.GuideItemsContainer = guidelib.model.Scriptable.extend({
30093        msClassName : "guideItemsContainer",
30094
30095        initialize : function () {
30096            GuideItemsContainer._super.initialize.call(this);
30097            this._children = [];
30098            this._nameArray = {};
30099            this._private = {};
30100            this._initChildren();
30101            this._normalizeChildren();
30102            this._bParentValidationsDisabled = false;
30103            this._validationsDisabled = false;
30104        },
30105
30106        _postInitialize : function () {
30107            
30108            
30109            GuideItemsContainer._super._postInitialize.call(this);
30110            _.each(this._children, function (childNode) {
30111                childNode._postInitialize();
30112            }, this);
30113        },
30114
30115        
30116        validate : function (errorList) {
30117            var validationStatus = true,
30118                tempValidationStatus;
30119            
30120            if (!this.visible) {
30121                return true;
30122            }
30123            if (_.isUndefined(errorList)) {
30124                errorList = [];
30125            }
30126
30127            var subContainerErrorArray = [],
30128                arrLen;
30129            _.each(this.children, function (child) {
30130                tempValidationStatus = child.validate(subContainerErrorArray);
30131                if (tempValidationStatus === false) {
30132                    validationStatus = false;
30133                }
30134            }, this);
30135
30136            tempValidationStatus = GuideItemsContainer._super.validate.call(this, subContainerErrorArray);
30137            if (tempValidationStatus === false) {
30138                validationStatus = false;
30139            }
30140            arrLen = subContainerErrorArray.length;
30141            while (arrLen > 0) {
30142                errorList[errorList.length] = subContainerErrorArray[subContainerErrorArray.length - arrLen];
30143                arrLen--;
30144            }
30145            return validationStatus;
30146        },
30147
30148        prepare : function () {
30149            _.each(this._children, function (childNode) {
30150                childNode.prepare();
30151            }, this);
30152            GuideItemsContainer._super.prepare.call(this);
30153        },
30154
30155        syncXFAProps : function () {
30156            GuideItemsContainer._super.syncXFAProps.apply(this, arguments);
30157            _.each(this._children, function (childNode) {
30158                childNode.syncXFAProps();
30159            });
30160        },
30161
30162        _initChildren : function (bLazyInitialization) {
30163            var panelItems = [],
30164                jsonModelItemsWithoutRepeatJson = {},
30165                keyLengthForJsonWithoutRepeat = 0,
30166                keyLengthJsonItemsOriginal = 0;
30167            
30168            
30169            
30170            
30171            
30172            _.each(this.jsonModel.items, function (item) {
30173                
30174                
30175                
30176                if (item.templateId && item.templateId.indexOf("GUID") === -1) {
30177                    jsonModelItemsWithoutRepeatJson[item.templateId] = item;
30178                }
30179            });
30180            keyLengthForJsonWithoutRepeat = _.keys(jsonModelItemsWithoutRepeatJson).length;
30181            
30182            keyLengthJsonItemsOriginal = _.keys(this.jsonModel.items || {}).length;
30183            if (keyLengthForJsonWithoutRepeat > 0 && keyLengthForJsonWithoutRepeat !== keyLengthJsonItemsOriginal) {
30184                this.jsonModel.items = jsonModelItemsWithoutRepeatJson;
30185            }
30186            _.each(this.jsonModel.items,
30187                function (item) {
30188                    if (_.isObject(item)) {
30189                        
30190                        
30191                        
30192                        
30193                        var options = {};
30194                        if (this.options._guideContainer) {
30195                            options = _.extend({}, options, {"_guideContainer" : this.options._guideContainer});
30196                        }
30197                        var panelItemModel = guidelib.model.GuideModelRegistry.prototype.createModel(item, options);
30198                        panelItemModel._isItem = true;
30199                        this._initializeChild(panelItemModel);
30200                        panelItems.push(panelItemModel);
30201                    }
30202                },
30203                this);
30204            this._children = panelItems;
30205        },
30206
30207        _initializeChild : function (childItem) {
30208            childItem.parent = this;
30209        },
30210
30211        _normalizeChildren : function () {
30212            this._nameArray = {};
30213            this._private = {};
30214            _.each(this.children, function (child) {
30215                child._index = this._addProperty(child);
30216                
30217                child.getNaked(child._index, guidelib.__runtime__, null);
30218                child.getNaked(child._index, this._guide().runtime, null);
30219            }, this);
30220        },
30221
30222        nakedChildReferences : function (nIndex, obj) {
30223            var i, oNode;
30224            for (i = 0; i < this._children.length; i++) {
30225                oNode = this._children[i];
30226                oNode.getNaked(nIndex, obj, this);
30227            }
30228        },
30229        _getReducedJSON : function (isRepeatable) {
30230            var reducedJSONChildren,
30231                that = this,
30232                index =  0;
30233            
30234            reducedJSONChildren = GuideItemsContainer._super._getReducedJSON.call(this);
30235            reducedJSONChildren.items = {};
30236            
30237            
30238            
30239            
30240            _.each(this.jsonModel.items, function (childNode, key) {
30241                reducedJSONChildren.items[key] = that.items[index]._getReducedJSON(isRepeatable);
30242                index += 1;
30243            });
30244            return reducedJSONChildren;
30245        },
30246
30247        _addProperty : function (oValueObject) {
30248            var sName = oValueObject.getAttribute("name"),
30249                nIndex = 0;
30250            
30251            
30252            
30253            this._nameArray[sName] = this._nameArray[sName] || nIndex;
30254            nIndex = this._nameArray[sName]++;
30255            if (nIndex === 0) {
30256                
30257                
30258                
30259                
30260                guidelib.util.GuideUtil._createGetterSetter(this, sName, oValueObject);
30261            }
30262            return nIndex;
30263        },
30264
30265        _getTitle : function () {
30266            return this.jsonModel["jcr:title"];
30267        },
30268
30269        visit : function (callback, context) {
30270            GuideItemsContainer._super.visit.apply(this, arguments);
30271            _.each(this._children, function (child, index) {
30272                child.visit(callback, context);
30273            });
30274        },
30275
30276        playJson : function (pJsonModel) {
30277            if (pJsonModel) {
30278                var pJsonItems = _.filter(pJsonModel.items, function (item) {
30279                    if (_.isObject(item)) {
30280                        return true;
30281                    }
30282                    return false;
30283                }, this);
30284                
30285                _.each(this.items, function (childNode, index) {
30286                    childNode.playJson(pJsonItems[index]);
30287                }, this);
30288                GuideItemsContainer._super.playJson.call(this, pJsonModel);
30289            }
30290
30291        },
30292
30293        _collectValues : function (keyValue) {
30294            _.each(this._children, function (childNode) {
30295                childNode._collectValues(keyValue);
30296            }, this);
30297        },
30298
30299        getElement : function (elClassName) {
30300            var element = _.find(this._children, function (childModel) {
30301                return childModel.className === elClassName;
30302            }, this);
30303            return element;
30304        },
30305
30306        
30307        _unloadModel : function () {
30308            _.each(this.children, function (child) {
30309                child._unloadModel();
30310            }, this);
30311            GuideItemsContainer._super._unloadModel.call(this);
30312        },
30313
30314        _findChildren : function (oSOM, bMultiple) {
30315            var arr = [],
30316                elemFound = false;
30317            _.find(this._children, function (child) {
30318                if (oSOM === child._escapeQualifiedName()) {
30319                    arr.push(child._getNakedThis());
30320                    elemFound = true;
30321                }
30322                if (elemFound && !bMultiple) {
30323                    return true; 
30324                }
30325                if (elemFound && oSOM.indexOf("[*]") < 0) {
30326                    return true; 
30327                }
30328            }, this);
30329            return arr;
30330        },
30331
30332        
30333        resetData : function () {
30334            _.each(this._children, function (childNode) {
30335                childNode.resetData();
30336            }, this);
30337        },
30338
30339        
30340        _changeDescendantsAccess : function (value) {
30341            _.each(this.items, function (child) {
30342                child._setParentAccess(value);
30343                if (child instanceof guidelib.model.GuideItemsContainer) {
30344                    child._changeDescendantsAccess(value);
30345                }
30346            }, this);
30347        },
30348
30349        
30350        _changeContainerAccess : function (value) {
30351            this._changeDescendantsAccess(value);
30352        },
30353
30354        
30355        _changeDescendantsProperty : function (value, property, leafNodesOnly) {
30356            _.each(this.items, function (child) {
30357                if (child instanceof guidelib.model.GuideItemsContainer) {
30358                    if (!leafNodesOnly) {
30359                        child[property] = value;
30360                    }
30361                    child._changeDescendantsProperty(value, property);
30362                } else {
30363                    child[property] = value;
30364                }
30365            }, this);
30366        },
30367
30368        
30369        disableAllFields : function () {
30370            this.enabled = false;
30371            var property = "enabled";
30372            this._changeDescendantsProperty(false, property, true);
30373        }
30374
30375    });
30376
30377    GuideItemsContainer.defineProps({
30378        children : {
30379            get : function () {
30380                return (this._children || []).slice(0); 
30381            },
30382            set : function (value) {
30383                this._children = value;
30384            }
30385        },
30386
30387        
30388        items : {
30389            get : function () {
30390                var itemChildren = _.filter(this._children, function (child) {
30391                    if (child._isItem) {
30392                        return true;
30393                    }
30394                    return false;
30395                }, this);
30396                return itemChildren;
30397            }
30398        },
30399        
30400        _selfOrAncestorIsLazyReference : {
30401            get : function () {
30402                if (this._lazyReference) {
30403                    return true;
30404                }
30405                return guidelib.util.GuideUtil._checkIfAncestorIsALazyReference(this);
30406            }
30407        },
30408        _lazyReference : {
30409            get : function () {
30410                return !_.isUndefined(this.jsonModel["fragRef"])
30411                    && !_.isUndefined(this.jsonModel["optimizeRenderPerformance"]);
30412            }
30413        }
30414    });
30415
30416    GuideItemsContainer.addMixins([
30417        guidelib.model.mixin.ValidationsDisabled
30418    ]);
30419
30420}(_, guidelib));
30421
30422(function (_, guidelib) {
30423    var GuideToolbar = guidelib.model.GuideToolbar = guidelib.model.GuideItemsContainer.extend({
30424        msClassName : "guideToolbar",
30425
30426        initialize : function () {
30427            GuideToolbar._super.initialize.call(this);
30428        },
30429
30430        execNavigationChangeExpression : function () {
30431            _.each(this.items, function (childModel) {
30432                if (childModel.navigationChangeExp) {
30433                    this._guide().queueExpressions(childModel, "navigationChangeExp");
30434                }
30435            }, this);
30436        }
30437
30438    });
30439
30440})(_, guidelib);
30441
30442(function (_, guidelib) {
30443
30444    
30445    var GuideCompositeField = guidelib.model.GuideCompositeField = guidelib.model.GuideItemsContainer.extend({
30446        msClassName : "guideCompositeField",
30447        initialize : function () {
30448            this._uuid = guideBridge._produceUUID();
30449            GuideCompositeField._super.initialize.call(this);
30450        },
30451
30452        _setGuideValue : function (value) {
30453            if (!_.isEmpty(value)) {
30454                _.each(this.items, function (item) {
30455                    if (value.hasOwnProperty(item.name) && _.isFunction(item._setGuideValue)) {
30456                        item._setGuideValue(value[item.name]);
30457                    }
30458                }, this);
30459            }
30460        },
30461
30462        _collectExpressions : function () {
30463            GuideCompositeField._super._collectExpressions.apply(this);
30464            if (this.valueCommitScript) {
30465                
30466                this._compiledScripts.valueCommitScript = this._compileExpression(this.valueCommitScript, null);
30467            }
30468        }
30469    });
30470
30471    GuideCompositeField.defineProps({
30472        valueCommitScript : {
30473            get : function () {
30474                return this.getAttribute("valueCommitScript");
30475            }
30476        },
30477        uuid : {
30478            get : function () {
30479                return this._uuid;
30480            },
30481            set : function (newUuid) {
30482                if (this._uuid != newUuid) {
30483                    this._uuid = newUuid;
30484                }
30485            }
30486        }
30487    });
30488
30489})(_, guidelib);
30490
30491(function (_, guidelib) {
30492    
30493    var GuideTermsAndConditions = guidelib.model.GuideTermsAndConditions =  guidelib.model.GuideCompositeField.extend({
30494        msClassName : "guideTermsAndConditions",
30495
30496        playJson : function (pJsonModel) {
30497            this.jsonModel.clickStatus = pJsonModel.clickStatus;
30498            GuideTermsAndConditions._super.playJson.apply(this, arguments);
30499        },
30500
30501        _updateLiveData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar) {
30502            this._syncModelAndData(bound_indexedXpathSoFar, unBound_indexedXpathSoFar, '_updateLiveData');
30503        },
30504
30505        _playLiveData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar) {
30506            this._syncModelAndData(bound_indexedXpathSoFar, unBound_indexedXpathSoFar, '_playLiveData');
30507            if (this.reviewStatus.value === "true") {
30508                this.clickStatus = "agree";
30509            } else {
30510                this.clickStatus = "unreviewed";
30511            }
30512        },
30513
30514        _syncModelAndData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar, recurse) {
30515            if (_.isString(recurse)) {
30516                var dataContext = this._guide().internal.liveDataUtils._getDataContext(this, bound_indexedXpathSoFar, unBound_indexedXpathSoFar);
30517                if (dataContext.xmlSec === this._guide().internal.liveDataUtils.constants.BOUND_TAG) {
30518                    bound_indexedXpathSoFar = dataContext.indexedXpath;
30519                } else {
30520                    unBound_indexedXpathSoFar = dataContext.indexedXpath;
30521                }
30522                _.each(this.items, function (item) {
30523                    if (_.isFunction(item[recurse])) {
30524                        item[recurse](bound_indexedXpathSoFar, unBound_indexedXpathSoFar);
30525                    }
30526                });
30527            }
30528        }
30529    });
30530
30531    GuideTermsAndConditions.defineProps({
30532        showLink : {
30533            get : function () {
30534                return this.getAttribute("showLink");
30535            }
30536        },
30537
30538        
30539        clickStatus : {
30540            get : function () {
30541                return this.getAttribute("clickStatus");
30542            },
30543            set : function (status) {
30544                this.setAttribute(status, "clickStatus");
30545            }
30546        },
30547
30548        showAsPopUp : {
30549            get : function () {
30550                return this.getAttribute("showAsPopUp");
30551            }
30552        }
30553    });
30554
30555})(_, guidelib);
30556(function (_, guidelib) {
30557
30558    
30559    var GuideFileUpload = guidelib.model.GuideFileUpload = guidelib.model.GuideCompositeField.extend({
30560        msClassName : "guideFileUpload",
30561
30562        _getReducedJSON : function () {
30563            this._syncModelToAttachments();
30564            var reducedJSONChildren = GuideFileUpload._super._getReducedJSON.call(this),
30565                addtionalWhitelistedProperties = ["id", "files"];
30566            guidelib.model.util.CommonUtils.returnMinimalJSON(addtionalWhitelistedProperties, reducedJSONChildren, this);
30567            var fileAttachmentValue = reducedJSONChildren.files;
30568            reducedJSONChildren.files = this._getFileAttachmentNames(fileAttachmentValue);
30569            return reducedJSONChildren;
30570        },
30571
30572        _getContentType : function(fileUrl) {
30573            var contentType = null,
30574                self = this;
30575            if (self._fileAttachmentWrapper) {
30576                var element = self._fileAttachmentWrapper.find(function(x) { return x.data === fileUrl});
30577                if (element) {
30578                    contentType = element.contentType;
30579                }
30580            }
30581            return contentType
30582        },
30583
30584        
30585        _getFileAttachmentNames : function (fileAttachmentValue) {
30586            var value = fileAttachmentValue || this.value;
30587            if (value) {
30588                var self = this,
30589                    fileNames = _.map(value.split("\n"), function (val) {
30590                        if (self._fileAttachmentWrapper) {
30591                            var element = self._fileAttachmentWrapper.find(function(x) { return x.data === val});
30592                            if (element) {
30593                                return element.name;
30594                            }
30595                        }
30596                        var fName = val;
30597                        
30598                        if (fName.lastIndexOf("/") === fName.length - 1) {
30599                            fName = fName.substring(0, fName.length - 1);
30600                        }
30601                        return fName.substring(fName.lastIndexOf("/") + 1);
30602                }).join("\n");
30603                return fileNames;
30604            }
30605        },
30606
30607        _getInputFileSubmissionNames : function () {
30608            var fileNames = (this._getFileAttachmentNames() || "").split("\n"),
30609                fileList = this.fileList || [],
30610                submissionNames = [],
30611                fileNamesIndex = 0;
30612            _.each(fileList, function (inputFileDOM) {
30613                if (_.isString(inputFileDOM)) {
30614                    fileNamesIndex++;
30615                    return;
30616                }
30617                var files = inputFileDOM[0] && inputFileDOM[0].files;
30618                _.each(files, function () {
30619                    submissionNames.push(fileNames[fileNamesIndex++]);
30620                });
30621            });
30622            return submissionNames;
30623        },
30624
30625        _triggerFileListChange : function () {
30626            var currValue = this._fileList;
30627            this.trigger(guidelib.event.GuideModelEvent.MODEL_CHANGED,
30628                guidelib.event.GuideModelEvent.createEvent(
30629                    guidelib.event.GuideModelEvent.MODEL_CHANGED,
30630                    this,
30631                    "fileList",
30632                    currValue,
30633                    currValue
30634                )
30635            );
30636        },
30637
30638        _getCurrentFileAttachmentWrapper : function(attachments) {
30639            var currentListOfAttachments = null,
30640                effectiveBindRef = this._getEffectiveBindRef(),
30641                self = this;
30642            if (_.isArray(attachments) && attachments.length > 0) {
30643                currentListOfAttachments = attachments.filter(function(x) {
30644                    return x.bindRef === effectiveBindRef;
30645                })
30646            }
30647            return currentListOfAttachments;
30648        },
30649
30650        _playAttachmentWrappers : function(currentAttachmentWrappers) {
30651            var currValue = this.fileAttachment.value,
30652                _guide = this._guide();
30653            if (_.isArray(currentAttachmentWrappers) && currentAttachmentWrappers.length > 0) {
30654                this._fileAttachmentWrapper = currentAttachmentWrappers;
30655                
30656                if (this.valueCommitScript && _guide.version.isOn(_guide.version.Flags.RUN_VALUE_COMMMIT_ON_PREFILL) && currValue) {
30657                    
30658                    _guide.queueExpressions(this, ["valueCommitScript"]);
30659                }
30660                var data = currentAttachmentWrappers.map(function(x) {return x.data});
30661                
30662                var fieldValue = data.join("\n");
30663                this.fileAttachment._setGuideValue(fieldValue);
30664                if (!_.isEmpty(fieldValue)) {
30665                    this._fileList = fieldValue.split("\n");
30666                }
30667            }
30668        },
30669
30670        playJson : function (pJsonModel, attachments) {
30671            if (attachments) {
30672                var currentListOfAttachments = this._getCurrentFileAttachmentWrapper(attachments);
30673                this._playAttachmentWrappers(currentListOfAttachments);
30674            } else {
30675                
30676                GuideFileUpload._super.playJson.call(this, pJsonModel);
30677            }
30678        },
30679
30680        _syncModelToAttachments : function () {
30681            var files = this.fileAttachment.value || "",
30682                filesArray = files.split('\n'),
30683                uniqueNames = guideBridge._makeFileNameUnique();
30684            var isIOS = guidelib.util.GuideUtil._isIOS();
30685            var files = this.fileAttachment.value || "",
30686                filesArray = files.split('\n'),
30687                areNamesUnique = (new Set(filesArray)).size === filesArray.length;
30688            this.jsonModel.files =
30689                _.map(files.split('\n'), function (file, index) {
30690                    if (!_.isEmpty(file)) {
30691                        if ((uniqueNames || (!areNamesUnique && isIOS))  && file[0] !== '/') {
30692                            file = this.uuid + "-" + (index + 1) + "__afAttachment__" + file; 
30693                        }
30694                    }
30695                    return file;
30696                }, this).join('\n');
30697        },
30698
30699        _updateLiveData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar) {
30700            this._syncModelAndData(bound_indexedXpathSoFar, unBound_indexedXpathSoFar, "_updateLiveData");
30701        },
30702
30703        _playLiveData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar) {
30704            this._syncModelAndData(bound_indexedXpathSoFar, unBound_indexedXpathSoFar, "_playLiveData");
30705        },
30706
30707        _handleFileAttachmentItem : function (fileAttachmentModel, bound_indexedXpathSoFar, unBound_indexedXpathSoFar, recurse) {
30708            
30709            var dataUtils = this._guide().internal.liveDataUtils,
30710                dataContext = dataUtils._getDataContext(fileAttachmentModel, bound_indexedXpathSoFar, unBound_indexedXpathSoFar);
30711            if (recurse == "_updateLiveData") {
30712                dataUtils._updateLazyAttachmentMapFromModel(this);
30713                dataUtils.setDataValue(dataContext.indexedXpath, dataContext.xmlSec,
30714                    !fileAttachmentModel.isEmpty(), fileAttachmentModel.isEmpty() ? "" : this._getFileAttachmentValue());
30715            } else {
30716                var data = dataUtils._getAttachmentDataForModel(this);
30717                if (!_.isArray(data) && !_.isEmpty(data)) {
30718                    this.fileList = data.fileList;
30719                    var fileAttachmentValue = [];
30720                    var value = data.value.split("\n");
30721                    _.each(value, function (value, index) {
30722                        if (value[0] != '/')
30722 {
30723                            
30724                            
30725                            var name = value.substr(value.lastIndexOf("_") + 1);
30726                            fileAttachmentValue.push(name);
30727                        } else {
30728                            
30729                            fileAttachmentValue.push(value);
30730                        }
30731                    });
30732                    fileAttachmentModel.value = fileAttachmentValue.join("\n");
30733                }
30734                if (_.isArray(data) && data.length > 0) {
30735                    this._playAttachmentWrappers(data);
30736                }
30737                this._syncModelToAttachments();
30738            }
30739        },
30740
30741        _syncModelAndData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar, recurse) {
30742            if (_.isString(recurse)) {
30743                var liveDataUtils = this._guide().internal.liveDataUtils;
30744                var dataContext = liveDataUtils._getDataContext(this, bound_indexedXpathSoFar, unBound_indexedXpathSoFar);
30745                if (dataContext.xmlSec === liveDataUtils.constants.BOUND_TAG) {
30746                    bound_indexedXpathSoFar = dataContext.indexedXpath;
30747                } else {
30748                    unBound_indexedXpathSoFar = dataContext.indexedXpath;
30749                }
30750                _.each(this.items, function (item) {
30751                    if (_.isFunction(item[recurse])) {
30752                        if (item.name == "fileAttachment") {
30753                            
30754                            
30755                            this._handleFileAttachmentItem(item, bound_indexedXpathSoFar, unBound_indexedXpathSoFar, recurse);
30756                        } else {
30757                            item[recurse](bound_indexedXpathSoFar, unBound_indexedXpathSoFar);
30758                        }
30759                    }
30760                }, this);
30761            }
30762        },
30763
30764        
30765        _getIndexedXpath : function (model, bound_indexedXpathSoFar, unBound_indexedXpathSoFar) {
30766            var name = model.getAttribute("name").replace(/\s+/g, '');
30767            return unBound_indexedXpathSoFar ? unBound_indexedXpathSoFar + '/' + name : bound_indexedXpathSoFar + '/' + name;
30768        },
30769
30770        
30771        _getFileAttachmentValue : function () {
30772            
30773            
30774            
30775            this._syncModelToAttachments();
30776            return this._getFileAttachmentNames(this.jsonModel.files);
30777        }
30778
30779    });
30780
30781    GuideFileUpload.defineProps({
30782        
30783        multiSelection : {
30784            get : function () {
30785                return this.getAttribute("multiSelection");
30786            }
30787        },
30788
30789        buttonText : {
30790            get : function () {
30791                return this.getAttribute("buttonText");
30792            }
30793        },
30794
30795        showComment : {
30796            get : function () {
30797                return this.getAttribute("showComment");
30798            }
30799        },
30800
30801        
30802        fileSizeLimit : {
30803            get : function () {
30804                return this.getAttribute("fileSizeLimit");
30805            }
30806        },
30807
30808        fileList : {
30809            get : function () {
30810                return this._fileList;
30811            },
30812
30813            set : function (newValue) {
30814                var oldValue = this._fileList;
30815                var newTypedValue = newValue;
30816                if (newTypedValue != oldValue) {
30817                    this._fileList = newTypedValue;
30818                }
30819                
30820                
30821                
30822                var isIOS = guidelib.util.GuideUtil._isIOS(),
30823                    fileList = this._fileList,
30824                    that = this;
30825                if (isIOS && fileList) {
30826                    
30827                    this._fileAttachmentWrapperIOS = [];
30828                    
30829                    for (var i = 0; i < fileList.length; i++) {
30830                        if (!_.isString(fileList[i])) {
30831                            
30832                            var files = fileList[i].get(0).files,
30833                                _readFile = function (file) {
30834                                    
30835                                    that._fileAttachmentWrapperIOS.push(
30836                                        new Promise(function(resolve, reject){
30837                                            var reader = new FileReader();
30838                                            reader.onload = function() {
30839                                                var faWrapper = new guidelib.model.FileAttachmentWrapper({
30840                                                    name: file.name,
30841                                                    data: this.result,
30842                                                    formElementName : that.name,
30843                                                    contentType: file.type,
30844                                                    bindRef: that._getEffectiveBindRef()
30845                                                });
30846                                                resolve(faWrapper);
30847                                            };
30848                                            reader.onerror = reject;
30849                                            reader.readAsDataURL(file);
30850                                        })
30851                                    )
30852                                };
30853                            if (files) {
30854                                
30855                                [].forEach.call(files, _readFile);
30856                            }
30857                        }
30858                    }
30859                }
30860                this._triggerFileListChange();
30861            }
30862        },
30863        value : {
30864            get : function () {
30865                this._syncModelToAttachments();
30866                return this.jsonModel.files;
30867            }
30868        }
30869    });
30870
30871})(_, guidelib);
30872(function (_, guidelib) {
30873    var GuideAdModuleGroup = guidelib.model.GuideAdModuleGroup = guidelib.model.GuideItemsContainer.extend({
30874        msClassName : "guideAdModuleGroup",
30875
30876        _getTypedValue : function (value) {
30877            
30878            if (_.isUndefined(value) || value === null) {
30879                return null;
30880            }
30881            return value + "";
30882        },
30883
30884        playJson : function (pJsonModel) {
30885            var typedValue = this._getTypedValue(pJsonModel._value);
30886            
30887            if (typedValue || typedValue === "") {
30888                
30889                var olval = this.jsonModel._value;
30890                this.jsonModel._value = pJsonModel._value;
30891                this._triggerOnBridge("elementValueChanged", this, "value", olval, this.jsonModel._value);
30892            } else {
30893                
30894                GuideAdModuleGroup._super.playJson.call(this, pJsonModel);
30895            }
30896        }
30897    });
30898
30899    GuideAdModuleGroup.defineProps({
30900        
30901        value : {
30902            get : function () {
30903                return this._getTypedValue(this.jsonModel._value);
30904            },
30905            set : function (newValue) {
30906                var oldValue = this._getTypedValue(this.jsonModel._value),
30907                    newTypedValue = this._getTypedValue(newValue);
30908                
30909                if (newTypedValue !== undefined && (newTypedValue !== oldValue)) {
30910                    if (this.jsonModel._value !== newValue) {
30911                        this.jsonModel._value = newTypedValue || "";
30912                    }
30913                    this._triggerOnBridge("elementValueChanged", this, "value", oldValue, newTypedValue);
30914                }
30915            }
30916        }
30917    });
30918
30919}(_, guidelib));
30920(function (_, guidelib) {
30921    guidelib.model.mixin.AddDependencyMgmt = {
30922        normalProperties : {
30923            _addDependant : function (oNode, expressionType) {
30924                var dependantConf = this._findDependant(oNode);
30925                if (!dependantConf) {
30926                    dependantConf = {dependant : oNode, events : []};
30927                    this.dependants.push(dependantConf);
30928                }
30929
30930                if (dependantConf.events.indexOf(expressionType) < 0) {
30931                    dependantConf.events.push(expressionType);
30932                    oNode.on(guidelib.event.GuideModelEvent.OBJECT_DESTROYED, this._handleDependentDestroyed, this);
30933                }
30934            },
30935
30936            _notifyDependants : function () {
30937                _.each(this.dependants, function (dependantConf) {
30938                    this._guide().queueExpressions(dependantConf.dependant, dependantConf.events);
30939                }, this);
30940            },
30941
30942            _removeDependant : function (oNode) {
30943                oNode.off(guidelib.event.GuideModelEvent.OBJECT_DESTROYED, this._handleDependentDestroyed, this);
30944                var dependantConf = this._findDependant(oNode);
30945                this.dependants = _.without(this.dependants, dependantConf);
30946            },
30947
30948            _findDependant : function (oNode) {
30949                return _.find(this.dependants, function (conf) { return (conf.dependant === oNode); });
30950            },
30951
30952            _handleDependentDestroyed : function (event) {
30953                this._removeDependant(event.target);
30954            }
30955        }
30956    };
30957})(_, guidelib);
30958
30959(function (_, guidelib) {
30960    var GuideChart = guidelib.model.GuideChart = guidelib.model.Scriptable.extend({
30961        msClassName : "guideChart",
30962
30963        _collectExpressions : function () {
30964            GuideChart._super._collectExpressions.apply(this);
30965            this._compiledExpressions["aggregateExp"] = this._compileExpression('guidelib.chartUtils.gatherAxisData(this);', "data");
30966        }
30967    });
30968
30969    GuideChart.defineProps({
30970        
30971        data : {
30972            get : function () {
30973                var context = this._guide()._currentContext;
30974                if (context && context.contextNode && context.expression
30975                    && !(context.contextNode === this && context.expression === "aggregateExp")) {
30976                    this._addDependant(context.contextNode, context.expression);
30977                }
30978                return this.jsonModel.data;
30979            },
30980
30981            set : function (newValue) {
30982                var oldValue = this.jsonModel.data;
30983                this.jsonModel.data = newValue;
30984                
30985                var valueHasChanged = !_.isEqual(oldValue, newValue);
30986                if (valueHasChanged) {
30987                    
30988                    this._notifyDependants();
30989                    this._triggerEvent(guidelib.event.GuideModelEvent.MODEL_CHANGED, "data", oldValue, newValue);
30990                }
30991            }
30992        },
30993
30994        
30995        dataSourceType : {
30996            get : function () {
30997                return this.getAttribute("dataSourceType");
30998            },
30999            set : function (newValue) {
31000                var oldValue = this.jsonModel.dataSourceType;
31001                this.jsonModel.dataSourceType = newValue;
31002                this._triggerEvent(guidelib.event.GuideModelEvent.MODEL_CHANGED, "dataSourceType", oldValue, newValue);
31003            }
31004        },
31005
31006        
31007        width : {
31008            get : function () {
31009                return this.getAttribute("width");
31010            },
31011
31012            set : function (newValue) {
31013                this.jsonModel.width = newValue;
31014            }
31015        },
31016        
31017        height : {
31018            get : function () {
31019                return this.getAttribute("height");
31020            },
31021
31022            set : function (newValue) {
31023                this.jsonModel.height = newValue;
31024            }
31025        },
31026        
31027        xAxisTitle : {
31028            get : function () {
31029                return this.getAttribute("xAxisTitle");
31030            },
31031            set : function (newValue) {
31032                this.jsonModel.chartType = newValue;
31033            }
31034        },
31035        
31036        yAxisTitle : {
31037            get : function () {
31038                return this.getAttribute("yAxisTitle");
31039            },
31040            set : function (newValue) {
31041                this.jsonModel.chartType = newValue;
31042            }
31043        },
31044        
31045        chartType : {
31046            get : function () {
31047                return this.getAttribute("chartType");
31048            },
31049            set : function (newValue) {
31050                var oldValue = this.jsonModel.chartType;
31051                this.jsonModel.chartType = newValue;
31052                this._triggerEvent(guidelib.event.GuideModelEvent.MODEL_CHANGED, "chartType", oldValue, newValue);
31053            }
31054        },
31055        
31056        repeatableItem : {
31057            get : function () {
31058                return this.getAttribute("repeatableItem");
31059            },
31060            set : function (newValue) {
31061                this.jsonModel.repeatableItem = newValue;
31062            }
31063        },
31064        
31065        xExp : {
31066            get : function () {
31067                return this.getAttribute("xExp");
31068            },
31069            set : function (newValue) {
31070                this.jsonModel.xExp = newValue;
31071            }
31072        },
31073        
31074        reducerXFunction : {
31075            get : function () {
31076                return this.getAttribute("reducerXFunction");
31077            },
31078            set : function (newValue) {
31079                this.jsonModel.reducerXFunction = newValue;
31080                if (newValue !== 'none') {
31081                    this.jsonModel.reducerYFunction = 'none';
31082                }
31083            }
31084        },
31085        
31086        yExp : {
31087            get : function () {
31088                return this.getAttribute("yExp");
31089            },
31090            set : function (newValue) {
31091                this.jsonModel.yExp = newValue;
31092            }
31093        },
31094        
31095        reducerYFunction : {
31096            get : function () {
31097                return this.getAttribute("reducerYFunction");
31098            },
31099            set : function (newValue) {
31100                this.jsonModel.reducerYFunction = newValue;
31101                if (newValue !== 'none') {
31102                    this.jsonModel.reducerXFunction = 'none';
31103                }
31104            }
31105        },
31106        
31107        innerRadius : {
31108            get : function () {
31109                return this.getAttribute("innerRadius");
31110            },
31111            set : function (newValue) {
31112                this.jsonModel.innerRadius = newValue;
31113            }
31114        },
31115        
31116        lineColor : {
31117            get : function () {
31118                return this.getAttribute("lineColor");
31119            },
31120            set : function (newValue) {
31121                this.jsonModel.lineColor = newValue;
31122            }
31123        },
31124        
31125        pointColor : {
31126            get : function () {
31127                return this.getAttribute("pointColor");
31128            },
31129            set : function (newValue) {
31130                this.jsonModel.pointColor = newValue;
31131            }
31132        },
31133        
31134        areaColor : {
31135            get : function () {
31136                return this.getAttribute("areaColor");
31137            },
31138            set : function (newValue) {
31139                this.jsonModel.areaColor = newValue;
31140            }
31141        },
31142        
31143        tooltipHtml : {
31144            get : function () {
31145                return this.getAttribute("tooltipHtml");
31146            },
31147            set : function (newValue) {
31148                this.jsonModel.tooltipHtml = newValue;
31149            }
31150        },
31151        
31152        showLegends : {
31153            get : function () {
31154                return this.getAttribute("showLegends");
31155            },
31156            set : function (newValue) {
31157                this.jsonModel.showLegends = newValue;
31158            }
31159        },
31160        
31161        legendPosition : {
31162            get : function () {
31163                return this.getAttribute("legendPosition");
31164            },
31165            set : function (newValue) {
31166                this.jsonModel.legendPosition = newValue;
31167            }
31168        }
31169    });
31170
31171    GuideChart.addMixins([
31172        guidelib.model.mixin.AddDependencyMgmt
31173    ]);
31174}(_, guidelib));
31175(function (_, guidelib) {
31176    
31177    var GuideInstanceManager = guidelib.model.GuideInstanceManager = guidelib.model.GuideNode.extend({
31178        msClassName : "guideInstanceManager",
31179        initialize : function () {
31180            GuideInstanceManager._super.initialize.call(this);
31181            this._instances = [];
31182            this.dependants = [];
31183            this.deafen = false; 
31184            this._bindPending = true;
31185        },
31186
31187        _postInitializeBinding : function () {
31188            
31189            
31190            
31191            if (!this._bindPending) {
31192                return;
31193            } else {
31194                this._bindPending = false; 
31195            }
31196            
31197            
31198            
31199            
31200            
31201            
31202            var instance = this._instances[this.instanceCount - 1];
31203            if (!instance) {
31204                this.logger().log("There was no instance found for InstanceManager at postInitialize:" + this.somExpression);
31205            }
31206            if (instance.bindNode && instance.bindNode.instanceManager) {
31207                this.bindNode = instance.bindNode.instanceManager;
31208                this.bindNode.parent.on(xfalib.script.XfaModelEvent.CHILD_ADDED, this);
31209                this.bindNode.parent.on(xfalib.script.XfaModelEvent.CHILD_REMOVED, this);
31210            }
31211        },
31212
31213        _unloadModel : function () {
31214            var instance = this._instances[this.instanceCount - 1];
31215
31216            if (instance.bindNode && instance.bindNode.instanceManager) { 
31217                this.bindNode.parent.off(xfalib.script.XfaModelEvent.CHILD_ADDED, this);
31218                this.bindNode.parent.off(xfalib.script.XfaModelEvent.CHILD_REMOVED, this);
31219            }
31220
31221            GuideInstanceManager._super._unloadModel.call(this);
31222        },
31223
31224        
31225        handleEvent : function (event) {
31226            if (!this.deafen && event instanceof xfalib.script.XfaModelEvent) {
31227                switch (event.name) {
31228                    case xfalib.script.XfaModelEvent.CHILD_ADDED:
31229                        var addedInstance = event.newText;
31230                        if (addedInstance.instanceManager == this.bindNode) {
31231                            this._insertInstance(addedInstance.instanceIndex, addedInstance);
31232                        }
31233                        break;
31234                    case xfalib.script.XfaModelEvent.CHILD_REMOVED:
31235                        var removedInstance = event.prevText;
31236                        if (removedInstance.instanceManager == this.bindNode) {
31237                            this._removeInstance(removedInstance.instanceIndex, false);
31238                        }
31239                        break;
31240                    case xfalib.script.XfaModelEvent.CHILD_MOVED:
31241                        this.logger().log("CHILD_REMOVED should never be dispatched. It's achieved via ad and remove child.");
31242                        break;
31243                    default:
31244                        
31245                        break;
31246                }
31247            }
31248        },
31249
31250        _instanceTemplate : function () {
31251            return this._guide()._modelTemplateCacheStore.cloneJsonTemplate(this.jsonModel.instanceTemplateId);
31252        },
31253
31254        
31255        addInstance : function (addedXfaInstance) {
31256            return this._insertInstance(undefined, addedXfaInstance);
31257        },
31258
31259        
31260        addInstances : function (instancesConfig, addedXfaInstances) {
31261            var instanceCount = instancesConfig.instanceCount,
31262                instancesToAdd, availableInstances;
31263            if (this.maxOccur == -1) {
31264                instancesToAdd = instanceCount;
31265            }else {
31266                availableInstances = this.maxOccur - this.instanceCount;
31267                
31268                instancesToAdd = instanceCount > availableInstances ? availableInstances : instanceCount;
31269            }
31270            var oChildsAdded = [];
31271            for (var i = 0; i < instancesToAdd ; i++) {
31272                oChildsAdded.push(this._insertInstance(undefined, addedXfaInstances, true));
31273            }
31274            var oParentContainer = this.parent;
31275            oParentContainer._triggerEvent(guidelib.event.GuideModelEvent.MULTIPLE_CHILD_ADDED, "multipleChildAdded",
31276                null, oChildsAdded);
31277        },
31278
31279        _manageChild : function (oCreatedChild, nIndex) {
31280            oCreatedChild._instanceManager = this;
31281            if (nIndex === undefined) {
31282                this._instances.push(oCreatedChild);
31283            } else {
31284                this._instances.splice(nIndex, 0, oCreatedChild);
31285            }
31286        },
31287
31288        
31289        _insertInstance : function (nIndex, addedXfaInstance, muteEvent) {
31290            if ((+this.maxOccur >= 0) && (+this.maxOccur == this.instanceCount)) {
31291                return null;
31292            }
31293            
31294            if (nIndex !== undefined && nIndex > +this.maxOccur && +this.maxOccur > -1) {
31295                return null;
31296            }
31297
31298            var addedBindNode = addedXfaInstance;
31299            if (addedXfaInstance && this.bindNode == null) {
31300                this.logger().error("AF", "Invalid argument addedXfaInstance.");
31301            }
31302            if (!addedXfaInstance && this.bindNode) {
31303                this.deafen = true;
31304                try {
31305                    
31306                    addedBindNode = this.bindNode.insertInstance(nIndex);
31307                }
31308                finally {
31309                    this.deafen = false;
31310                }
31311            }
31312            var template = this._instanceTemplate();
31313            
31314            
31315            
31316            var clonedJson = {};
31317            var uniquePrefix = this.guideUtil.generateUID(),
31318                that = this;
31319            this.copyObject(template, clonedJson,
31320                {
31321                    transformMaps : {
31322                        "id" : function (srcValue, options, parentObj) {
31323                            return uniquePrefix + "__" + parentObj.templateId;
31324                        },
31325
31326                        
31327                        
31328                        "bindRef" : function (originalBindRef, options, src) {
31329                            if (addedBindNode != null && that.bindNode != null) {
31330                                if (template.bindRef === originalBindRef) {
31331                                    return addedBindNode.somExpression;
31332                                } else if (originalBindRef.substring(0, template.bindRef.length) === template.bindRef) {
31333                                    return originalBindRef.replace(template.bindRef, addedBindNode.somExpression);
31334                                }
31335                            }
31336
31337                            return originalBindRef;
31338                        }
31339                    }
31340                }
31341            );
31342            
31343            var options = ((addedBindNode && this.bindNode) ? {bindNode : addedBindNode} : null);
31344            if (this.options._guideContainer) {
31345                options = _.extend({}, options, {"_guideContainer" : this.options._guideContainer});
31346            }
31347            var oChildAdded = guidelib.model.GuideModelRegistry.prototype.createModel(clonedJson, options);
31348            if (oChildAdded != null) {
31349                
31350                
31351                
31352                this._manageChild(oChildAdded, nIndex);
31353                var oParentContainer = this.parent;
31354                if (oParentContainer != null) {
31355                    if (this._instances.length > 0) {
31356                        
31357                        
31358                        
31359                        
31360                        nIndex = nIndex !== undefined ? nIndex : this._instances.length - 1 ;
31361                        if(nIndex === 0 ) {
31362                            
31363                            
31364                            
31365                            oParentContainer._addChildAt(oChildAdded, oParentContainer._children.indexOf(this) + 1, muteEvent);
31366                        } else {
31367                            var lastInstanceIndex = oParentContainer._children.indexOf(this._instances[nIndex - 1]);
31368                            oParentContainer._addChildAt(oChildAdded, lastInstanceIndex + 1, muteEvent);
31369                        }
31370                    } else {
31371                        
31372                        
31373                        
31374                        
31375                        oParentContainer._addChildAt(oChildAdded, oParentContainer._children.indexOf(this) + 1, muteEvent);
31376                    }
31377                    var guideStateConstants = guidelib.model.GuideSchema.prototype.GuideStateConstants;
31378                    var dataUtils = this._guide().internal.liveDataUtils;
31379                    if (this._isDataNodeUpdateRequired(oChildAdded)) {
31380                        var parentNode = dataUtils.getParentDataNode(this._getDataContext(oChildAdded), true, {});
31381                        var index = dataUtils._convertModelIndexToDataIndex(oChildAdded.instanceIndex);
31382                        var node = dataUtils._getElement(parentNode, oChildAdded._getDataNodeName(), {index : index});
31383                        
31384                        
31385                        if (!node || (node && !(oChildAdded.instanceIndex == this._instances.length - 1))) {
31386                            var dataNode = dataUtils.insertNode(parentNode, oChildAdded._getDataNodeName(), oChildAdded.instanceIndex);
31387                            if (!dataNode) {
31388                                this.logger().warn("AF", "Unable to store the data of the element");
31389                            }
31390                        }
31391                    }
31392                }
31393                this._execExpressions(nIndex);
31394                return oChildAdded;
31395            } else {
31396                this.logger().log("guide", "insertInstance could not create child" + this.jsonModel.instanceTemplateId);
31397            }
31398            return null;
31399        },
31400
31401        
31402        insertInstance : function (nIndex) {
31403            return this._insertInstance(nIndex);
31404        },
31405
31406        
31407        removeInstance : function (index) {
31408            this._removeInstance(index, true);
31409        },
31410
31411        
31412        _removeInstance : function (index, removeXfaInstance) {
31413            
31414            if (this.instanceCount == 0 || this.minOccur >= this.instanceCount) {
31415                return;
31416            }
31417
31418            if (index >= +this.instanceCount) {
31419                return;
31420            }
31421
31422            if (removeXfaInstance && this.bindNode) {
31423                this.deafen = true;
31424                try {
31425                    this.bindNode.removeInstance(index);
31426                }
31427                finally {
31428                    this.deafen = false;
31429                }
31430            }
31431            
31432            
31433            
31434            var oChild =  this._instances[index];
31435            var dataUtils = this._guide().internal.liveDataUtils;
31436            if (this._isDataNodeUpdateRequired(oChild)) {
31437                var parentNode = dataUtils.getParentDataNode(this._getDataContext(oChild));
31438                dataUtils.removeChild(parentNode, oChild._getDataNodeName(), oChild.instanceIndex);
31439            }
31440            this._instances.splice(index, 1);
31441            var parent = oChild.parent;
31442            parent._removeChild(oChild);
31443            this._execExpressions(index);
31444        },
31445
31446        _isDataNodeUpdateRequired : function (child) {
31447            var guideStateConstants = guidelib.model.GuideSchema.prototype.GuideStateConstants,
31448                guide = guideBridge._guide;
31449            return guide && guide.getGuideState() === guideStateConstants.GUIDE_STATE_MODEL_COMPLETE
31450                && child._hasLazyDescendant;
31451        },
31452
31453        _getDataContext : function (model) {
31454            var dataUtils = this._guide().internal.liveDataUtils,
31455                elementContext = dataUtils._getXpathContext(model),
31456                xmlContext = dataUtils._getDataContext(model, elementContext.bound,
31457                    elementContext.unBound),
31458                xpath = xmlContext.indexedXpath;
31459            xpath = dataUtils.addIndexToPath(xpath, model.instanceIndex);
31460            return {
31461                indexedXpath : xpath,
31462                xmlSec : xmlContext.xmlSec
31463            };
31464        },
31465
31466        _getInstanceName : function () {
31467            return this.jsonModel.instanceName;
31468        },
31469
31470        _instanceIsTableRow : function () {
31471            
31472            return this._instanceTemplate()["guideNodeClass"] === "guideTableRow";
31473        },
31474
31475        
31476        _execExpressions : function (modifiedIndex) {
31477            try {
31478                
31479                this._notifyDependants();
31480                
31481                
31482                for (var i = modifiedIndex; i < this.instances.length; i++) {
31483                    this.instances[i]._notifyDependants();
31484                }
31485                
31486                this._guide().runPendingExpressions();
31487            } catch (ex) {
31488                this.logger().error("guide", ex.message);
31489            }
31490        }
31491
31492    });
31493    GuideInstanceManager.defineProps({
31494        
31495        minOccur : {
31496            get : function () {
31497                var isTableRow = this._instanceIsTableRow();
31498                
31499                if (isTableRow) {
31500                    return ((+this.jsonModel.minOccur) || 1);
31501                } else {
31502                    return this.getOrElse(this.jsonModel.minOccur, 1);
31503                }
31504            }
31505        },
31506
31507        
31508        maxOccur : {
31509            get : function () {
31510                return this.getOrElse(this.jsonModel.maxOccur, 1);
31511            }
31512        },
31513
31514        initialOccur : {
31515            get : function () {
31516                return this.getOrElse(this.jsonModel.initialOccur, 1);
31517            }
31518        },
31519
31520        
31521        instanceTemplateId : {
31522            get : function () {
31523                return this.jsonModel.instanceTemplateId;
31524            }
31525        },
31526
31527        
31528        instanceCount : {
31529            get : function () {
31530                var context = this._guide()._currentContext;
31531                if (context && context.managedExp) {
31532                    
31533                    this._addDependant(context.contextNode, context.expression);
31534                }
31535                return this._instances.length ;
31536            }
31537        },
31538
31539        
31540        repeatable : {
31541            get : function () {
31542                return (this.minOccur != 1 || this.maxOccur != 1);
31543            }
31544        },
31545        
31546        instances : {
31547            
31548            get : function () {
31549                var context = this._guide()._currentContext;
31550                if (context && context.managedExp) {
31551                    
31552                    this._addDependant(context.contextNode, context.expression);
31553                }
31554                return (this._instances || []).slice(0);
31555            }
31556        }
31557    });
31558
31559    GuideInstanceManager.addMixins([
31560        guidelib.model.mixin.AddDependencyMgmt
31561    ]);
31562})(_, guidelib);
31563(function (_, guidelib) {
31564
31565    
31566    var Field = guidelib.model.Field = guidelib.model.Scriptable.extend({
31567        msClassName : "field",
31568        
31569        _runValidation : true,
31570        initialize : function () {
31571            Field._super.initialize.call(this);
31572            this.jsonModel["{default}"] = this.getOrElse(this.jsonModel, "{default}", this.jsonModel._value);
31573            this.isValid = true;
31574            this.forceErrorShow = false;
31575            
31576            this._bParentValidationsDisabled = false;
31577            
31578            this._validationsDisabled = false;
31579            
31580            this._failedTest = null;
31581
31582            
31583            this._errorText = "";
31584
31585            var effectiveBindRef = this._getEffectiveBindRef();
31586            
31587            if (this.isGlobal || (this._guide() && this._guide().internal.liveModel.isLive(effectiveBindRef))) {
31588                this._guide().internal.liveModel.add(effectiveBindRef, this);
31589            }
31590        },
31591        _postInitialize: function() {
31592            Field._super._postInitialize.call(this);
31593            if (this.getAttribute("dorExclusion") !== null && this.jsonModel.visible === false) {
31594                if ((this._guide().getAttribute("excludeFromDoRIfHidden") === "true")
31595                    ||
31596                    (this._guide().print &&
31597                        this._guide().print["excludeFromDoRIfHidden"] === "true")) {
31598                    this.dorExclusion = true;
31599                }
31600            }
31601        },
31602        _unloadModel : function () {
31603            var effectiveBindRef = this.bindRef || this.getAttribute("name");
31604            if (this.isGlobal || this._guide().internal.liveModel.isLive(effectiveBindRef)) {
31605                this._guide().internal.liveModel.remove(effectiveBindRef, this);
31606            }
31607            Field._super._unloadModel.call(this);
31608        },
31609
31610        _collectExpressions : function () {
31611            Field._super._collectExpressions.apply(this);
31612            if (this.calcExp) {
31613                this._compiledExpressions.calcExp = this._compileExpression(this.calcExp, "value");
31614            }
31615            if (this.validateExp) {
31616                
31617                this._compiledScripts.validateExp = this._compileExpression(this.validateExp, null);
31618            }
31619            if (this.valueCommitScript) {
31620                
31621                
31622                this._compiledScripts.valueCommitScript = this._compileExpression(this.valueCommitScript, null);
31623            }
31624            
31625            this._compiledScripts.validateAllExp = this._compileExpression("this._runTests()", null);
31626        },
31627
31628        _handleXfaModelChanged : function (event) {
31629            if (event._property === "rawValue") {
31630                this._triggerEvent(guidelib.event.GuideModelEvent.VALUE_CHANGED, "value",
31631                    event.prevText, event.newText);
31632            } else if (event._property == "ClearError" || event._property == "ValidationState") {
31633                
31634                this._guide().queueExpressions(this, ["validateAllExp"]);
31635            } else {
31636                Field._super._handleXfaModelChanged.call(this, event);
31637            }
31638        },
31639
31640        
31641        
31642        validate : function (errorList) {
31643            
31644            if (!this.visible) {
31645                return true;
31646            }
31647            if (_.isUndefined(errorList)) {
31648                errorList = [];
31649            }
31650            var status = true;
31651            this._runTests(true);
31652            if (this._errorText) {
31653                errorList.push({
31654                    som : this.somExpression,
31655                    errorText : this._errorText
31656                });
31657                status = false;
31658            }
31659            return status;
31660        },
31661
31662        _getTypedValue : function (value) {
31663            if (this.checkIfNull(value)) {
31664                return null;
31665            }
31666            return value + "";
31667        },
31668
31669        _getFormattedValue : function (value) {
31670            if (_.isUndefined(value) || value === null || value === "") {
31671                return null;
31672            }
31673
31674            var picture = this.jsonModel.displayPictureClause;
31675            
31676            if (picture) {
31677                try {
31678                    
31679                    var formattedValue = xfalib.ut.PictureFmt.format(value + "", picture, null, true);
31680                    
31681                    return formattedValue != null && formattedValue !== "" ? formattedValue : value;
31682                } catch (exception) {
31683                    
31684                }
31685            }
31686            return value;
31687        },
31688
31689        _getValue : function () {
31690            if (this.bindNode) {
31691                return this.bindNode.rawValue;
31692            }
31693            return this._getTypedValue(this.jsonModel._value);
31694        },
31695
31696        _triggerDisplayFormatChange : function () {
31697            var currValue = this._getValue();
31698            this._triggerEvent(guidelib.event.GuideModelEvent.VALUE_CHANGED, "value",
31699                currValue, this._getFormattedValue(currValue));
31700        },
31701
31702        
31703        checkIfNull : function (value) {
31704            return value == null || value === ""; 
31705        },
31706
31707        
31708        isEmpty : function () {
31709            return this.checkIfNull(this.value);
31710        },
31711
31712        _setXFAValue : function (value) {
31713            this.bindNode.rawValue = value;
31714        },
31715
31716        
31717        _setXFAMandatory : function (value) {
31718            
31719            
31720            var convertor = this._guide()._guideSchema.getConvertor("mandatory");
31721            if (convertor) {
31722                
31723                
31724                this.bindNode.validate.nullTest = convertor.guideToXfa.apply(this, [!!value]);
31725            }
31726        },
31727
31728        _setGuideValue : function (value) {
31729            this.jsonModel._value = (value === undefined || value === null) ? null : value;
31730        },
31731
31732        _runMandatoryTest : function () {
31733            var currValue = this._getValue(),
31734                isNull = this.checkIfNull(currValue);
31735            return !isNull;
31736        },
31737
31738        _runValidatePictureTest : function () {
31739            var value = this._getValue(),
31740                validateFlag = true,
31741                regex;
31742            if (!this.checkIfNull(value) && this.validatePictureClause) {
31743                
31744                try {
31745                    value = xfalib.ut.PictureFmt.format(value + "", this.validatePictureClause, null, false);
31746                } catch (exception) {
31747                    
31748                    this.logger().log("AF", exception);
31749                    
31750                    if (exception.indexOf("Invalid picture clause") !== -1) {
31751                        value = undefined;
31752                    } else {
31753                        value = null;
31754                    }
31755                }
31756            }
31757            if (_.isUndefined(value)) {
31758                try {
31759                    
31760                    regex = new RegExp(this.validatePictureClause);
31761                    if (regex) {
31762                        validateFlag = regex.test(this._getValue());
31763                    }
31764                } catch (exception) {
31765                    
31766                    this.logger().error("AF", "Invalid Regular Expression" + exception);
31767                    validateFlag = false;
31768                }
31769            } else if (value === null) {
31770                validateFlag = false;
31771            }
31772
31773            return validateFlag;
31774        },
31775
31776        
31777        _runTests : function (forceRun) {
31778            
31779            var validFlag = true,
31780                prevErrorText = this._errorText,
31781                prevValidationState = this.validationState,
31782                obj = {
31783                    'validFlag' : validFlag,
31784                    'forceRun' : forceRun
31785                };
31786
31787            if (this.validationsDisabled === true) {
31788                
31789                
31790                return true;
31791            }
31792
31793            this._runValidations(obj);
31794            validFlag = obj.validFlag;
31795
31796            if (validFlag) {
31797                this._errorText = "";
31798                this.validationState = true;
31799                
31800                this._failedTest = null;
31801            } else {
31802                this.validationState = false;
31803            }
31804            
31805            if ((prevErrorText !== this._errorText) || (prevValidationState !== this.validationState) || forceRun) {
31806                
31807                if (forceRun) {
31808                    this.forceErrorShow = true;
31809                }
31810                this._triggerEvent(guidelib.event.GuideModelEvent.ERROR_CHANGED,
31811                    "validationStatus", this.validationState, this._errorText);
31812            }
31813
31814            return this.validationState;
31815        },
31816
31817        playJson : function (pJsonModel) {
31818            var currValue = pJsonModel._value,
31819                _guide = this._guide();
31820            
31821            if (this.valueCommitScript && _guide.version.isOn(_guide.version.Flags.RUN_VALUE_COMMMIT_ON_PREFILL) && currValue) {
31822                
31823                _guide.queueExpressions(this, ["valueCommitScript"]);
31824            }
31825            this._setGuideValue(pJsonModel._value);
31826        },
31827
31828        
31829        _runValidations : function (obj) {
31830            var isRegex = false,
31831                INVALID_PICTURE_CLAUSE_LIST = ["date.default{}", "date.short{}", "date.medium{}",
31832                    "date.long{}", "date.full{}", "num.percent{}", "num.decimal{}", "num.currency{}"];
31833            if (this.bindNode) {
31834                if (this.validatePictureClause && (this.value || this.value === 0)) {
31835                    
31836                    
31837                    try {
31838                        xfalib.ut.PictureFmt.format(this.value + "", this.validatePictureClause, null, false);
31839                    } catch (exception) {
31840                        if (INVALID_PICTURE_CLAUSE_LIST.indexOf(this.validatePictureClause) >= 0) {
31841                            isRegex = false;
31842                        } else if (exception.indexOf("Invalid picture clause") !== -1) {
31843                            isRegex = true;
31844                        }
31845                    }
31846                }
31847                if (isRegex) {
31848                    try {
31849                        
31850                        var regex = new RegExp(this.validatePictureClause);
31851                        if (regex) {
31852                            obj.validFlag = regex.test(this._getValue());
31853                        }
31854                    } catch (exception) {
31855                        this.logger().error("AF", "Error in running regular expression" + exception);
31856                        obj.validFlag = false;
31857                    }
31858                    if (!obj.validFlag) {
31859                        this.bindNode._setErrorData("formatTest", this.getOrElse(this.bindNode.validate.formatTest, this.bindNode._defaults.validate.formatTest), this.bindNode.formatMessage);
31860                        this._errorText = this.bindNode._errorText;
31861                        xfalib.ut.XfaUtil.prototype._triggerOnBridge("elementValidationStatusChanged", this.bindNode, "validationStatus", false, true);
31862                        this.bindNode.execEvent("validationState");
31863                    }
31864                } else {
31865                    if (obj.forceRun) {
31866                        this.bindNode.execValidate();
31867                    }
31868                    this._errorText = this.bindNode._errorText;
31869                    if (this._errorText) {
31870                        obj.validFlag = false;
31871                    }
31872                }
31873                
31874                this._failedTest = this.bindNode._mFailedValTest;
31875            } else {
31876                
31877                if (this.mandatory) {
31878                    obj.validFlag = this._runMandatoryTest();
31879                    if (!obj.validFlag) {
31880                        this._errorText = this.mandatoryMessage;
31881                        this._failedTest = this.guideUtil.MANDATORY_TEST;
31882                    }
31883                }
31884                if (obj.validFlag && this.validatePictureClause && !this.checkIfNull(this.value)) {
31885                    obj.validFlag = this._runValidatePictureTest();
31886                    if (!obj.validFlag) {
31887                        this._errorText = this.validatePictureClauseMessage;
31888                        this._failedTest = this.guideUtil.FORMAT_TEST;
31889                    }
31890                }
31891            }
31892
31893            if (obj.validFlag && this.validateExp) {
31894                obj.validFlag = this.executeExpression("validateExp");
31895                if (!obj.validFlag) {
31896                    this._errorText = this.validateExpMessage;
31897                    this._failedTest = this.guideUtil.SCRIPT_TEST;
31898                }
31899            }
31900        },
31901
31902        _collectValues : function (keyValue) {
31903            
31904            keyValue[this.name] = this.value;
31905        },
31906
31907        
31908        resetData : function () {
31909            this._runValidation = false;
31910            this.value = this.jsonModel["{default}"];
31911            this._runValidation = true;
31912            
31913            this._errorText = "";
31914            this.validationState = true;
31915            this._failedTest = null;
31916            this._triggerEvent(guidelib.event.GuideModelEvent.ERROR_RESET,
31917                "validationStatus", this.validationState, this._errorText);
31918        },
31919
31920        _preserveLazyValue : function () {
31921            return !(_.contains(['guideButton', 'guideTextDraw', 'guideAdobeSignBlock'], this.className) || this._isXfaNode());
31922        },
31923
31924        
31925        _updateLiveData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar) {
31926            if (this._preserveLazyValue()) {
31927                var dataUtils = this._guide().internal.liveDataUtils,
31928                    dataContext = dataUtils._getDataContext(this, bound_indexedXpathSoFar,
31929                        unBound_indexedXpathSoFar),
31930                    isRichText = this instanceof guidelib.model.GuideTextBox && this.allowRichText,
31931                    setValue = isRichText ? dataUtils.setRichTextValue : dataUtils.setDataValue;
31932                setValue.apply(dataUtils, [dataContext.indexedXpath, dataContext.xmlSec,
31933                    !this.isEmpty(), this.isEmpty() ? "" : this.value]);
31934            }
31935        },
31936
31937        
31938        _playLiveData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar) {
31939            if (this._preserveLazyValue()) {
31940                var dataUtils = this._guide().internal.liveDataUtils,
31941                    dataContext = dataUtils._getDataContext(this, bound_indexedXpathSoFar,
31942                        unBound_indexedXpathSoFar),
31943                    isRichText = this instanceof guidelib.model.GuideTextBox && this.allowRichText,
31944                    getValue = isRichText ? dataUtils.getRichTextValue : dataUtils.getDataValue;
31945                var value = getValue.apply(dataUtils, [dataContext.indexedXpath, dataContext.xmlSec]);
31946                if (value != undefined) {
31947                    this.value = value;
31948                } else if (this.jsonModel && this.jsonModel._value) {
31949                    
31950                    var _guide = this._guide();
31951                    
31952                    if (this.valueCommitScript && _guide.version.isOn(_guide.version.Flags.RUN_VALUE_COMMMIT_ON_PREFILL)) {
31953                        
31954                        _guide.queueExpressions(this, ["valueCommitScript"]);
31955                    }
31956                }
31957            }
31958        },
31959
31960        
31961        _allowEmptyValueString : function () {
31962            return false;
31963        },
31964
31965        markAsInvalid : function (errorText, shouldShowError) {
31966            shouldShowError = (typeof shouldShowError !== 'undefined') ? shouldShowError : false;
31967            this.validationState = false;
31968            if (!errorText) {
31969                errorText = this.validateExpMessage;
31970            }
31971            if(shouldShowError) {
31972                this._errorText = errorText;
31973                this.forceErrorShow = true;
31974            }
31975            this._triggerEvent(guidelib.event.GuideModelEvent.ERROR_CHANGED,
31976                "validationStatus", this.validationState, errorText);
31977        },
31978
31979        
31980        _isStateOverridden : function (property) {
31981            return this.getOrElse(this.jsonModel.stateOverrides, property, null) != null;
31982        }
31983    });
31984
31985    Field.defineProps({
31986        calcExp : {
31987            get : function () {
31988                return this.getAttribute("calcExp");
31989            }
31990        },
31991
31992        
31993        isGlobal : {
31994            get : function () {
31995                return this.getAttribute('isGlobal') === "true";
31996            }
31997        },
31998
31999        
32000        title : {
32001            get : function () {
32002                return this.getAttribute("jcr:title");
32003            },
32004            set : function (title) {
32005                this.setAttribute(title, "jcr:title");
32006            }
32007        },
32008
32009        valueCommitScript : {
32010            get : function () {
32011                return this.getAttribute("valueCommitScript");
32012            }
32013        },
32014
32015        validateExp : {
32016            get : function () {
32017                return this.getAttribute("validateExp");
32018            }
32019        },
32020
32021        
32022        placeholderText : {
32023            get : function () {
32024                return this.getAttribute("placeholderText");
32025            }
32026        },
32027
32028        
32029        value : {
32030            get : function () {
32031                var context = this.getOrElse(this._guide(), "_currentContext", null);
32032                if (context && context.managedExp
32033                    
32034                    && !(context.contextNode === this
32035                    && context.expression === "calcExp")) {
32036                    
32037                    this._addDependant(context.contextNode, context.expression);
32038                }
32039                return this._getValue();
32040            },
32041            set : function (newValue) {
32042                var oldValue = this._getValue(),
32043                    newTypedValue = this._getTypedValue(newValue),
32044                    _guide = this._guide();
32045                
32046                if (this._allowEmptyValueString() && newValue === "") {
32047                    newTypedValue = "";
32048                }
32049
32050                
32051                if (newTypedValue !== undefined && !(this.checkIfNull(newTypedValue) && this.checkIfNull(oldValue))
32052                    && (newTypedValue !== oldValue)) {
32053                    if (this.bindNode) {
32054                        this._setXFAValue(newTypedValue);
32055                    } else if (this.jsonModel._value !== newValue) {
32056                        this._setGuideValue(newTypedValue);
32057                    }
32058                    if (_guide && _guide.version.isOn(_guide.version.Flags.RUN_VALUE_COMMMIT_ON_SCRIPT_CHANGE)) {
32059                        var context = _guide._currentContext,
32060                            contextNode = this.getOrElse(context, "contextNode", null),
32061                            contextExpression = this.getOrElse(context, "expression", null);
32062                        if (!context || contextNode != this || contextExpression != "valueCommitScript") {
32063                            
32064                            _guide.queueExpressions(this, ["valueCommitScript"]);
32065                        }
32066                    }
32067                    
32068                    this._notifyDependants();
32069                    
32070                    if (this._runValidation && _guide) {
32071                        _guide.queueExpressions(this, ["validateAllExp"]);
32072                    }
32073                    this._triggerOnBridge("elementValueChanged", this, "value", oldValue, newTypedValue);
32074                    
32075                    
32076                    if (!this.bindNode || (this.bindNode && this.getAttribute("html5Type") !== undefined)) {
32077                        this._triggerDisplayFormatChange();
32078                    }
32079                }
32080            }
32081        },
32082
32083        
32084        formattedValue : {
32085            get : function () {
32086                var value;
32087                if (this.bindNode) {
32088                    value = this.bindNode.formattedValue;
32089                } else {
32090                    value = this._getFormattedValue(this._getValue());
32091                }
32092                return value;
32093            }
32094        },
32095
32096        
32097        displayPictureClause : {
32098            get : function () {
32099                return this.getAttribute("displayPictureClause");
32100            }
32101        },
32102
32103        
32104        validatePictureClause : {
32105            get : function () {
32106                if (this.jsonModel.displayIsSameAsValidate) {
32107                    return this.displayPictureClause;
32108                }
32109                return this.getAttribute("validatePictureClause");
32110            }
32111        },
32112
32113        
32114        editPictureClause : {
32115            get : function () {
32116                if (this.jsonModel.isEditSameAsDisplayPattern) {
32117                    return this.displayPictureClause;
32118                }
32119                return this.getAttribute("editPictureClause");
32120            }
32121        },
32122
32123        
32124        isEditPictureClausePresent : {
32125            get : function () {
32126                return typeof this.editPictureClause !== 'undefined';
32127            }
32128        },
32129
32130        
32131        mandatory : {
32132            get : function () {
32133                return this.getAttribute("mandatory");
32134            },
32135
32136            set : function (newValue) {
32137                var oldValue = this.getAttribute("mandatory");
32138                if (newValue !== undefined && oldValue !== newValue) {
32139                    if (this.bindNode) {
32140                        this._setXFAMandatory(newValue);
32141                    } else {
32142                        
32143                        this.jsonModel.mandatory = !!newValue;
32144                    }
32145                    
32146                    this._triggerEvent(guidelib.event.GuideModelEvent.MODEL_CHANGED, "mandatory", oldValue, newValue);
32147                }
32148            }
32149        },
32150
32151        
32152        mandatoryMessage : {
32153            get : function () {
32154                return this.getAttribute("mandatoryMessage");
32155            }
32156        },
32157
32158        
32159        validateExpMessage : {
32160            set : function (message) {
32161                
32162                if (this.isValid) {
32163                    this.jsonModel.validateExpMessage = message;
32164                } else {
32165                    this.setAttribute(message, "validateExpMessage");
32166                }
32167            },
32168            get : function () {
32169                return this.getAttribute("validateExpMessage");
32170            }
32171        },
32172
32173        
32174        validatePictureClauseMessage : {
32175            get : function () {
32176                return this.getAttribute("validatePictureClauseMessage");
32177            }
32178        },
32179
32180        
32181        validationState : {
32182            get : function () {
32183                return this.isValid;
32184            },
32185            set : function (newValue) {
32186                var oldVal = this.isValid;
32187                if (oldVal != newValue) {
32188                    this.isValid = newValue;
32189                    this._triggerOnBridge("elementValidationStatusChanged", this,
32190                        "validationStatus", oldVal, newValue);
32191                }
32192            }
32193        },
32194        
32195        width : {
32196            get : function () {
32197                return this.getAttribute("width");
32198            },
32199
32200            set : function (newValue) {
32201                this.jsonModel.width = newValue;
32202            }
32203        },
32204        
32205        height : {
32206            get : function () {
32207                return this.getAttribute("height");
32208            },
32209
32210            set : function (newValue) {
32211                this.jsonModel.height = newValue;
32212            }
32213        }
32214    });
32215
32216    Field.addMixins([
32217        guidelib.model.mixin.AddDependencyMgmt,
32218        guidelib.model.mixin.ValidationsDisabled
32219    ]);
32220}(_, guidelib));
32221
32222(function (_, guidelib) {
32223    
32224    var GuideButton = guidelib.model.GuideButton = guidelib.model.Field.extend({
32225        msClassName : "guideButton",
32226        defaultClickExpressions : {
32227            "moveNext" : "window.guideBridge.setFocus(this.panel.somExpression, 'nextItem', true)",
32228            "movePrev" : "window.guideBridge.setFocus(this.panel.somExpression, 'prevItem', true)"
32229        },
32230        defaultNavigationExpressions : {
32231            "moveNext" : "this.visible=this.panel.navigationContext.hasNextItem",
32232            "movePrev" : "this.visible=this.panel.navigationContext.hasPrevItem"
32233        },
32234
32235        _collectExpressions : function () {
32236            GuideButton._super._collectExpressions.apply(this);
32237            if (this.clickExp) {
32238                this._compiledScripts["clickExp"] = this._compileExpression(this.clickExp, null);
32239            } else if (this.targetVersion >= 1.1 && this.defaultClickExpressions[this.type]) {                  
32240                this.jsonModel.clickExp = this.defaultClickExpressions[this.type];                              
32241                this._compiledScripts["clickExp"] = this._compileExpression(this.clickExp, null);               
32242            }
32243            if (this.navigationChangeExp) {
32244                this._compiledScripts["navigationChangeExp"] = this._compileExpression(this.navigationChangeExp, null);
32245            } else if (this.targetVersion >= 1.1 &&  this.defaultNavigationExpressions[this.type]) {
32246                this.jsonModel.navigationChangeExp = this.defaultNavigationExpressions[this.type];
32247                this._compiledScripts["navigationChangeExp"] = this._compileExpression(this.navigationChangeExp, null);
32248            }
32249        },
32250
32251    });
32252
32253    GuideButton.defineProps({
32254        clickExp : {
32255            get : function () {
32256                return this.jsonModel.clickExp;
32257            }
32258        },
32259        navigationChangeExp : {
32260            get : function () {
32261                return this.jsonModel.navigationChangeExp;
32262            }
32263        },
32264        
32265        type : {
32266            get : function () {
32267                return this.getAttribute("type");
32268            }
32269        }
32270    });
32271})(_, guidelib);
32272
32273(function (_, guidelib) {
32274    var GuideListFileAttachmentButton = guidelib.model.GuideListFileAttachmentButton = guidelib.model.GuideButton.extend({
32275        msClassName : "guideListFileAttachmentButton",
32276        initialize : function () {
32277            
32278            if (_.isUndefined(this.jsonModel.clickExp)) {
32279                this.jsonModel.clickExp = "guideBridge._updateFileListing.call(this,this)";
32280
32281            }
32282            GuideListFileAttachmentButton._super.initialize.apply(this, arguments);
32283        }
32284    });
32285
32286})(_, guidelib);
32287(function (_, guidelib) {
32288    var GuideCompositeFieldItem = guidelib.model.GuideCompositeFieldItem = guidelib.model.Field.extend({
32289        msClassName : "GuideCompositeFieldItem"
32290    });
32291
32292    GuideCompositeFieldItem.defineProps({
32293        
32294        bindRef : {
32295            get : function () {
32296                if (this.parent && !this.parent._isXfaNode() && !_.isEmpty(this.parent.bindRef)) {
32297                    return this.parent.bindRef + '/' + this.getAttribute("name").replace(/\s+/g, '');
32298                } else {
32299                    return (this.getAttribute("bindRef") || "").replace(/\s+/g, '');
32300                }
32301            }
32302        }
32303    });
32304
32305})(_, guidelib);
32306(function (_, guidelib) {
32307    var GuideTextDraw = guidelib.model.GuideTextDraw = guidelib.model.Field.extend({
32308        msClassName : "guideTextDraw",
32309
32310        _valueEscapeRegex : new RegExp('\\$', 'g'),
32311
32312        
32313        _getValue : function () {
32314            if (this.bindNode) {
32315                return this.bindNode._getValue(null, true);
32316            }
32317            return this._getTypedValue(this.jsonModel._value);
32318        },
32319
32320        
32321        playJson : function (pJsonModel) {
32322            
32323            this._setGuideValue(this._floatingFieldResolutionFunction(pJsonModel));
32324        },
32325
32326        _allowEmptyValueString : function () {
32327            return true;
32328        },
32329
32330        _isFloatingField : function () {
32331            return this.documentFragmentVariables && this.documentFragmentVariables.length > 0;
32332        },
32333
32334        _floatingFieldResolutionFunction : function (jsonModel) {
32335            var resolvedValue = this.value,
32336                variableRegexMap = this._variableRegexMap,
32337                valueEscapeRegex = this._valueEscapeRegex,
32338                somExpression = this.somExpression,
32339                self = this,
32340
32341                
32342                variablesDefaultValue = [],
32343                documentFragmentVariables = this.documentFragmentVariables;
32344            if (jsonModel.documentFragmentVariables) {
32345                for (var index = 0 ; index < jsonModel.documentFragmentVariables.length ; index++) {
32346                    variablesDefaultValue[index] = jsonModel.documentFragmentVariables[index]._value;
32347                }
32348            }
32349            this.jsonModel.defaultValue = variablesDefaultValue;
32350            _.each(variableRegexMap, function (regexPattern, variableId) {
32351                var textVariable,
32352                    bindRef,
32353                    floatingFieldValue;
32354                textVariable = documentFragmentVariables.filter(function (variable) {
32355                    return variable.variableId === variableId;
32356                })[0];
32357                bindRef = textVariable.bindRef;
32358                if (!bindRef) {
32359                    bindRef = textVariable.name;
32360                }
32361                
32362                if (jsonModel && jsonModel.documentFragmentVariables && jsonModel.documentFragmentVariables.length > 0) {
32363                    var variableFromPlayJson = jsonModel.documentFragmentVariables.filter(function (variable) {
32364                        return variable.variableId === variableId;
32365                    })[0];
32366                    floatingFieldValue = variableFromPlayJson._value;
32367                } else {
32368                    floatingFieldValue = guidelib.util.GuideUtil.getValueForBindRefField(bindRef, somExpression, this._guide());
32369                }
32370                if (!floatingFieldValue) {
32371                    
32372                    floatingFieldValue = "";
32373                } else {
32374                    
32375                    
32376                    floatingFieldValue = floatingFieldValue.replace(valueEscapeRegex, '$$$$');
32377                }
32378                if (floatingFieldValue) {
32379                    var dataType = textVariable.dataType,
32380                        displayPattern = textVariable.displayPictureClause;
32381                    if (dataType === 'number' || dataType === 'integer') {
32382                        displayPattern = displayPattern ? displayPattern : 'num{zzz,zzz,zzz,zzz,zzz,zzz,zzz.zzzzzzzzzzzzzzz}';
32383                    } else if (dataType === 'date-time' || dataType === 'date') {
32384                        displayPattern = displayPattern ? displayPattern : 'date{' + guidelib.i18n.datePatterns.med + '}';
32385                    }
32386
32387                    if (displayPattern) {
32388                        if (floatingFieldValue.indexOf(',') !== -1) {
32389                            
32390                            var valArray = floatingFieldValue.split(','),
32391                            tmpValue = "";
32392                            valArray.forEach(function (val) {
32393                                tmpValue = tmpValue + guidelib.util.GuideUtil.formatValue(val, displayPattern, dataType) + ", " ;
32394                            });
32395                            floatingFieldValue = tmpValue.substr(0, tmpValue.length - 2);
32396                        } else {
32397                            floatingFieldValue = guidelib.util.GuideUtil.formatValue(floatingFieldValue, displayPattern, dataType);
32398                        }
32399                    }
32400                }
32401                resolvedValue = resolvedValue.replace(regexPattern, floatingFieldValue);
32402            });
32403            return resolvedValue;
32404        },
32405
32406        initialize : function () {
32407            if (this._isFloatingField()) {
32408                var variableRegexMap = this._variableRegexMap = {};
32409                _.each(this.documentFragmentVariables, function (documentFragmentVariable) {
32410                    var variableId = documentFragmentVariable.variableId,
32411                        regexPattern;
32412                    if (!variableRegexMap[variableId]) {
32413                        
32414                        regexPattern = '(?:<df-variable[^>]*variableid="' + variableId + '"[^>]*>)[^<]*(?:<\/df-variable>)';
32415                        variableRegexMap[variableId] = new RegExp(regexPattern, 'ig');
32416                    }
32417                });
32418            }
32419            GuideTextDraw._super.initialize.apply(this, [arguments]);
32420        }
32421    });
32422
32423    GuideTextDraw.defineProps({
32424        calcExp : {
32425            get : function () {
32426                return this._calcExp;
32427            }
32428        },
32429
32430        documentFragmentVariables : {
32431            get : function () {
32432                return this.jsonModel.documentFragmentVariables;
32433            }
32434        }
32435    });
32436}(_, guidelib));
32437
32438(function (_, guidelib) {
32439    var GuideAdobeSignBlock = guidelib.model.GuideAdobeSignBlock = guidelib.model.GuideTextDraw.extend({
32440        msClassName : "guideAdobeSignBlock"
32441    });
32442}(_, guidelib));
32443 (function (_, guidelib) {
32444    var GuideFootnotePlaceHolder = guidelib.model.GuideFootnotePlaceHolder = guidelib.model.GuideTextDraw.extend({
32445        msClassName : "guideFootnotePlaceHolder",
32446
32447        initialize : function () {
32448            GuideFootnotePlaceHolder._super.initialize.apply(this);
32449        }
32450    });
32451    GuideFootnotePlaceHolder.defineProps({
32452        footnoteMap : {
32453            get : function () {
32454            if (this.options._guideContainer.jsonModel.textReplacementMap) {
32455                var footnoteMap = {};
32456                var footnoteArray = Object.entries(this.options._guideContainer.jsonModel.textReplacementMap)
32457                var parentDiv = document.createElement("p");
32458                parentDiv.setAttribute("class", "footnoteClass");
32459                for (var i = 0; i < footnoteArray.length; i++) {
32460                    var pTag = $("p[id=\"" + footnoteArray[i][0] + "\"]")[0];   
32461                    if (pTag != null && pTag.tagName == 'P') {
32462                        var childTag = document.createElement("p");
32463                        
32464                        childTag.setAttribute("role", "footnote");
32465                        childTag.setAttribute("aria-live", "polite");
32466                        childTag.setAttribute("aria-atomic", "true");
32467                        var supTag = document.createElement('sup');
32468                        var anchorTag = document.createElement('a');
32469                        var parentTag = pTag.cloneNode(true);
32470                         parentTag.removeAttribute("id");
32471                        anchorTag.setAttribute('id', footnoteArray[i][0]+ "_ftn");
32472                        anchorTag.innerHTML = footnoteArray[i][1];
32473                        supTag.appendChild(anchorTag);
32474                        parentTag.insertBefore(supTag, parentTag.children[0]);
32475                        parentTag.style.display = "block";
32476                        childTag.appendChild(parentTag);
32477                        footnoteMap[footnoteArray[i][0]] = childTag.outerHTML;
32478                    }
32479                }
32480                return footnoteMap;
32481            }
32482            return null;
32483        }
32484        }
32485    });
32486
32487}(_, guidelib));
32488
32489
32490(function (_, guidelib) {
32491    
32492    var GuideTextBox = guidelib.model.GuideTextBox = guidelib.model.Field.extend({
32493        msClassName : "guideTextBox",
32494
32495        
32496        _runMinimumLengthTest : function () {
32497            return this.value && this.value.length >= this.minLength;
32498        },
32499
32500        
32501        _runTotalLengthTest : function () {
32502            return this.value && this.value.length === this.length;
32503        },
32504
32505        
32506        _runValidations : function (obj) {
32507            GuideTextBox._super._runValidations.call(this, obj);
32508            if (obj.validFlag) {
32509
32510                if (this.length != null) {
32511                    obj.validFlag = this._runTotalLengthTest();
32512                    if (!obj.validFlag) {
32513                        this._errorText = this.guideUtil.getLocalizedMessage("", guidelib.i18n.strings.totalLengthMessage, [this.length]);
32514                        this._failedTest = this.guideUtil.LENGTH_TEST;
32515                    }
32516                } else if (this.minLength != null) {
32517                    obj.validFlag =  this._runMinimumLengthTest();
32518                    if (!obj.validFlag) {
32519                        this._errorText = this.guideUtil.getLocalizedMessage("", guidelib.i18n.strings.minimumLengthMessage, [this.minLength]);
32520                        this._failedTest = this.guideUtil.MINIMUM_LENGTH_TEST;
32521                    }
32522                }
32523
32524            }
32525        },
32526
32527        
32528        _runMandatoryTest : function () {
32529            if (this.allowRichText) {
32530                
32531                
32532                var getTextContent = function (htmlString) {
32533                        var result = htmlString,
32534                            regex = null;
32535                        if (htmlString != null) {
32536                            
32537                            
32538                            regex = /(<([^>]+)>)/ig;
32539                            result = htmlString.replace(regex, "");
32540                        }
32541                        return result;
32542                    },
32543                    currValue = getTextContent(this._getValue()),
32544                    isNull = this.checkIfNull(currValue);
32545                return !isNull;
32546            } else {
32547                return GuideTextBox._super._runMandatoryTest.apply(this, arguments);
32548            }
32549        },
32550
32551        _allowEmptyValueString : function () {
32552            return true;
32553        }
32554
32555    });
32556
32557    GuideTextBox.defineProps({
32558        
32559        "multiLine" : {
32560            get : function () {
32561                return this.getAttribute("multiLine");
32562            }
32563        },
32564
32565        
32566        "maxChars" : {
32567            get : function () {
32568                return this.getAttribute("maxChars");
32569            }
32570        },
32571
32572        
32573        "minLength" : {
32574            get : function () {
32575                return this.getAttribute("minLength");
32576            }
32577        },
32578
32579        
32580        "length" : {
32581            get : function () {
32582                return this.getAttribute("length");
32583            }
32584        },
32585        
32586        "allowRichText" : {
32587            get : function () {
32588                return this.getAttribute("allowRichText");
32589            }
32590        }
32591    });
32592
32593}(_, guidelib));
32594
32595(function (_, guidelib) {
32596    
32597    var countriesDialingCodesMap = {
32598        '441481' : 'Guernsey',
32599        '441624' : 'Isle of Man',
32600        '441534' : 'Jersey',
32601        '1868' : 'Trinidad and Tobago',
32602        '1473' : 'Grenada',
32603        '1670' : 'Northern Mariana Islands',
32604        '1869' : 'Saint Kitts and Nevis',
32605        '1758' : 'Saint Lucia',
32606        '1671' : 'Guam',
32607        "1684" : "American Samoa",
32608        "1268" : "Antigua and Barbuda",
32609        "1264" : "Anguilla",
32610        "1242" : "Bahamas",
32611        "1246" : "Barbados",
32612        '1441' : 'Bermuda',
32613        '1284' : 'British Virgin Islands',
32614        '1345' : 'Cayman Islands',
32615        '1787' : 'Puerto Rico',
32616        '1876' : 'Jamaica',
32617        '1939' : 'Puerto Rico',
32618        '1767' : 'Dominica',
32619        '1809' : 'Dominican Republic',
32620        '1829' : 'Dominican Republic',
32621        '1664' : 'Montserrat',
32622        '1849' : 'Dominican Republic',
32623        '1340' : 'U.S. Virgin Islands',
32624        '1784' : 'Saint Vincent and the Grenadines',
32625        '1649' : 'Turks and Caicos Islands',
32626        '1721' : 'Sint Maarten',
32627        "355" : "Albania",
32628        "213" : "Algeria",
32629        "376" : "Andorra",
32630        "244" : "Angola",
32631        "672" : "Antarctica",
32632        "374" : "Armenia",
32633        "297" : "Aruba",
32634        "994" : "Azerbaijan",
32635        "973" : "Bahrain",
32636        "880" : "Bangladesh",
32637        "375" : "Belarus",
32638        "501" : "Belize",
32639        "229" : "Benin",
32640        '975' : 'Bhutan',
32641        '591' : 'Bolivia',
32642        '387' : 'Bosnia and Herzegovina',
32643        '267' : 'Botswana',
32644        '246' : 'British Indian Ocean Territory',
32645        '673' : 'Brunei',
32646        '359' : 'Bulgaria',
32647        '226' : 'Burkina Faso',
32648        '257' : 'Burundi',
32649        '855' : 'Cambodia',
32650        '237' : 'Cameroon',
32651        '238' : 'Cape Verde',
32652        '236' : 'Central African Republic',
32653        '235' : 'Chad',
32654        '269' : 'Comoros',
32655        '682' : 'Cook Islands',
32656        '506' : 'Costa Rica',
32657        '385' : 'Croatia',
32658        
32659        '357' : 'Cyprus',
32660        '420' : 'Czech Republic',
32661        '243' : 'Democratic Republic of the Congo',
32662        '253' : 'Djibouti',
32663        '670' : 'East Timor',
32664        '593' : 'Ecuador',
32665        '503' : 'El Salvador',
32666        '240' : 'Equatorial Guinea',
32667        '291' : 'Eritrea',
32668        '372' : 'Estonia',
32669        '251' : 'Ethiopia',
32670        '500' : 'Falkland Islands',
32671        '298' : 'Faroe Islands',
32672        '679' : 'Fiji',
32673        '358' : 'Finland',
32674        '689' : 'French Polynesia',
32675        '241' : 'Gabon',
32676        '220' : 'Gambia',
32677        '995' : 'Georgia',
32678        '233' : 'Ghana',
32679        '350' : 'Gibraltar',
32680        '299' : 'Greenland',
32681        '502' : 'Guatemala',
32682        '224' : 'Guinea',
32683        '245' : 'Guinea-Bissau',
32684        '592' : 'Guyana',
32685        '509' : 'Haiti',
32686        '504' : 'Honduras',
32687        '852' : 'Hong Kong',
32688        '354' : 'Iceland',
32689        '964' : 'Iraq',
32690        '353' : 'Ireland',
32691        '972' : 'Israel',
32692        '225' : 'Ivory Coast',
32693        '962' : 'Jordan',
32694        '254' : 'Kenya',
32695        '686' : 'Kiribati',
32696        '383' : 'Kosovo',
32697        '965' : 'Kuwait',
32698        '996' : 'Kyrgyzstan',
32699        '856' : 'Laos',
32700        '371' : 'Latvia',
32701        '961' : 'Lebanon',
32702        '266' : 'Lesotho',
32703        '231' : 'Liberia',
32704        '218' : 'Libya',
32705        '423' : 'Liechtenstein',
32706        '370' : 'Lithuania',
32707        '352' : 'Luxembourg',
32708        '853' : 'Macau',
32709        '389' : 'Macedonia',
32710        '261' : 'Madagascar',
32711        '265' : 'Malawi',
32712        '960' : 'Maldives',
32713        '223' : 'Mali',
32714        '356' : 'Malta',
32715        '692' : 'Marshall Islands',
32716        '222' : 'Mauritania',
32717        '230' : 'Mauritius',
32718        
32719        '691' : 'Micronesia',
32720        '373' : 'Moldova',
32721        '377' : 'Monaco',
32722        '976' : 'Mongolia',
32723        '382' : 'Montenegro',
32724        
32725        '258' : 'Mozambique',
32726        '264' : 'Namibia',
32727        '674' : 'Nauru',
32728        '977' : 'Nepal',
32729        '599' : 'Netherlands Antilles',
32730        '687' : 'New Caledonia',
32731        '505' : 'Nicaragua',
32732        '227' : 'Niger',
32733        '234' : 'Nigeria',
32734        '683' : 'Niue',
32735        '850' : 'North Korea',
32736        '968' : 'Oman',
32737        '680' : 'Palau',
32738        '970' : 'Palestine',
32739        '507' : 'Panama',
32740        '675' : 'Papua New Guinea',
32741        '595' : 'Paraguay',
32742        '351' : 'Portugal',
32743        '974' : 'Qatar',
32744        '242' : 'Republic of the Congo',
32745        '262' : 'Reunion',
32746        '250' : 'Rwanda',
32747        
32748        '290' : 'Saint Helena',
32749        '590' : 'Saint Martin',
32750        '508' : 'Saint Pierre and Miquelon',
32751        '685' : 'Samoa',
32752        '378' : 'San Marino',
32753        '239' : 'Sao Tome and Principe',
32754        '966' : 'Saudi Arabia',
32755        '221' : 'Senegal',
32756        '381' : 'Serbia',
32757        '248' : 'Seychelles',
32758        '232' : 'Sierra Leone',
32759        '421' : 'Slovakia',
32760        '386' : 'Slovenia',
32761        '677' : 'Solomon Islands',
32762        '252' : 'Somalia',
32763        '211' : 'South Sudan',
32764        '249' : 'Sudan',
32765        '597' : 'Suriname',
32766        '268' : 'Swaziland',
32767        '963' : 'Syria',
32768        '886' : 'Taiwan',
32769        '992' : 'Tajikistan',
32770        '255' : 'Tanzania',
32771        '228' : 'Togo',
32772        '690' : 'Tokelau',
32773        '676' : 'Tonga',
32774        '216' : 'Tunisia',
32775        '993' : 'Turkmenistan',
32776        '688' : 'Tuvalu',
32777        '256' : 'Uganda',
32778        '380' : 'Ukraine',
32779        '971' : 'United Arab Emirates',
32780        '598' : 'Uruguay',
32781        '998' : 'Uzbekistan',
32782        '678' : 'Vanuatu',
32783        '379' : 'Vatican',
32784        '681' : 'Wallis and Futuna',
32785        '212' : 'Western Sahara',
32786        '967' : 'Yemen',
32787        '260' : 'Zambia',
32788        '263' : 'Zimbabwe',
32789        '60' : 'Malaysia',
32790        '58' : 'Venezuela',
32791        '30' : 'Greece',
32792        '84' : 'Vietnam',
32793        '44' : 'United Kingdom',
32794        '45' : 'Denmark',
32795        '53' : 'Cuba',
32796        '46' : 'Sweden',
32797        '52' : 'Mexico',
32798        '41' : 'Switzerland',
32799        '40' : 'Romania',
32800        
32801        '36' : 'Hungary',
32802        
32803        "43" : "Austria",
32804        '34' : 'Spain',
32805        '91' : 'India',
32806        '62' : 'Indonesia',
32807        '98' : 'Iran',
32808        '94' : 'Sri Lanka',
32809        '27' : 'South Africa',
32810        '95' : 'Myanmar',
32811        '65' : 'Singapore',
32812        '39' : 'Italy',
32813        '82' : 'South Korea',
32814        "32" : "Belgium",
32815        '81' : 'Japan',
32816        '31' : 'Netherlands',
32817        '20' : 'Egypt',
32818        "54" : "Argentina",
32819        "93" : "Afghanistan",
32820        
32821        '56' : 'Chile',
32822        '86' : 'China',
32823        '51' : 'Peru',
32824        '63' : 'Philippines',
32825        '64' : 'Pitcairn',
32826        '48' : 'Poland',
32827        '47' : 'Norway',
32828        '33' : 'France',
32829        
32830        '61' : 'Cocos Islands',
32831        '55' : 'Brazil',
32832        '92' : 'Pakistan',
32833        '49' : 'Germany',
32834        '57' : 'Colombia',
32835        '66' : 'Thailand',
32836        '90' : 'Turkey',
32837        
32838        '1' : 'Canada',
32839        
32840        '7' : 'Russia'
32841    };
32842
32843    var GuideTelephone = guidelib.model.GuideTelephone = guidelib.model.GuideTextBox.extend({
32844        msClassName : "guideTelephone",
32845
32846        _extractNumericDigits : function (telephoneNumber) {
32847            var digitArray,
32848                number = "";
32849            if (telephoneNumber) {
32850                digitArray = telephoneNumber.match(/\d+/g);
32851                if (digitArray) {
32852                    number = digitArray.join("");
32853                }
32854            }
32855            return number;
32856        },
32857
32858        _extractCountryCode : function (telephoneNumber) {
32859            var number = this._extractNumericDigits(telephoneNumber);
32860            if (!number || (telephoneNumber && number && telephoneNumber.lastIndexOf("+", 0) !== 0)) {
32861                return "";
32862            }
32863            for (var countryCode in countriesDialingCodesMap) {
32864                if (number && number.lastIndexOf(countryCode, 0) === 0) {
32865                    return countryCode;
32866                }
32867            }
32868            return "";
32869        },
32870
32871        _extractPhoneNumber : function (telephoneNumber) {
32872            var countryCode = this._extractCountryCode(telephoneNumber),
32873                number = this._extractNumericDigits(telephoneNumber),
32874                phoneNumber = "";
32875            if (number) {
32876                phoneNumber = number.substr(countryCode.length);
32877            }
32878            return phoneNumber;
32879        }
32880    });
32881
32882    GuideTelephone.defineProps({
32883        
32884        countryCode : {
32885            get : function () {
32886                var value = this._getValue();
32887                return this._extractCountryCode(value);
32888            }
32889        },
32890
32891        
32892        phoneNumber : {
32893            get : function () {
32894                var value = this._getValue();
32895                return this._extractPhoneNumber(value);
32896            }
32897        }
32898    });
32899
32900}(_, guidelib));
32901
32902(function (_, guidelib) {
32903    
32904    var GuideCaptcha = guidelib.model.GuideCaptcha = guidelib.model.Field.extend({
32905        msClassName : "guideCaptcha",
32906
32907        initialize : function () {
32908            GuideCaptcha._super.initialize.call(this);
32909            var invisibleMandatoryRecaptchaInitialization = "af.invisibleMandatoryRecaptchaInitialization";
32910
32911            var isHcaptchaOrTurnstileInvisible = (this.isWidgetHcaptcha || this.isWidgetTurnstile) && this.captchaInvisible;
32912            var isRecaptchaInvisible = (this.isWidgetRecaptcha && ((this.captchaEnterprise && !this.checkBoxkey) || (this.captchaInvisible && this.mandatory)));
32913
32914            if (isHcaptchaOrTurnstileInvisible || isRecaptchaInvisible) {
32915                
32916                this.captchaValidate = false;
32917                this._triggerOnBridge(invisibleMandatoryRecaptchaInitialization, this, null, null, null);
32918            }
32919        },
32920        
32921        showCaptchaError : function (serverErrorMessage) {
32922            if (this.captchaEnterprise) {
32923                if (this.checkBoxkey) {
32924                    serverErrorMessage = this.errorMessage;
32925                } else {
32926                    window.alert(this.errorMessage);
32927                    return;
32928                }
32929            }
32930            if (this.captchaInvisible) {
32931                window.alert(this.errorMessage);
32932                return;
32933            }
32934            if (this.isWidgetHcaptcha || this.isWidgetTurnstile) {
32935                serverErrorMessage = this.errorMessage;
32936            } else {
32937                if (_.isEmpty(serverErrorMessage)) {
32938                    serverErrorMessage = guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.LogMessages["AEM-AF-901-006"]);
32939                }
32940            }
32941            
32942            this._triggerEvent(guidelib.event.GuideModelEvent.ERROR_CHANGED,
32943                "validationStatus", false, serverErrorMessage);
32944        },
32945
32946        validate : function (errorList) {
32947            if (_.isUndefined(errorList)) {
32948                errorList = [];
32949            }
32950
32951            if(!this.captchaValidate) {
32952                return;
32953            }
32954            if (window.guideBridge.hostName !== "server") {
32955                if ((this.visible && !this.value) || (this.mandatory && !this.visible)) {
32956                    errorList.push({
32957                    som : this.somExpression,
32958                    errorText : this.mandatoryMessage
32959                });
32960                    this._triggerEvent(guidelib.event.GuideModelEvent.ERROR_CHANGED,
32961                                "validationStatus", false, this.mandatoryMessage);
32962                    return false;
32963                } else {
32964                    this._triggerEvent(guidelib.event.GuideModelEvent.ERROR_CHANGED,
32965                                "validationStatus", true, null);
32966                }
32967            }
32968        },
32969        
32970        _updateLiveData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar) {
32971
32972        },
32973
32974        _playLiveData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar) {
32975
32976        }
32977    });
32978
32979    GuideCaptcha.defineProps({
32980        value : {
32981            get : function () {
32982                return this.jsonModel._value;
32983            },
32984            set : function (value) {
32985                var oldValue = this.jsonModel._value,
32986                    newTypedValue;
32987                
32988                this.jsonModel._value = (value === undefined) ? oldValue : value;
32989                newTypedValue = this.jsonModel._value;
32990                this.validate();
32991                this._triggerOnBridge("elementValueChanged", this, "value", oldValue, newTypedValue);
32992            }
32993        },
32994        captchaWidget : {
32995            get : function () {
32996                return this.getAttribute("captchaService");
32997            }
32998        },
32999        captchaValidate : {
33000            get : function () {
33001                return this._captchaValidate == undefined ? true : this._captchaValidate;
33002            },
33003            set : function (value) {
33004                this._captchaValidate = value;
33005            }
33006        },
33007        captchaInvisible : {
33008            get : function () {
33009                if (this.captchaWidget === "turnstile") {
33010                    return this.getAttribute("widgetType") == "invisible" ? true : false;
33011                } else if (this.captchaWidget === "hcaptcha") {
33012                    return this.getAttribute("size") == "invisible" ? true : false;
33013                } else if (this.captchaWidget === "recaptcha" && this.captchaEnterprise) {
33014                    return this.getAttribute("rcKeyType") === "score" ? true : false;
33015                } else {
33016                    return this.getAttribute("rcSize") == "invisible" ? true : false;
33017                }
33018            }
33019        },
33020        captchaEnterprise : {
33021            get : function () {
33022                return (this.getAttribute("rcVersion") === "enterprise") ? true : false;
33023            }
33024        },
33025        checkBoxkey : {
33026            get : function () {
33027                return this.getAttribute("rcKeyType") === "checkbox" ? true : false;
33028            }
33029        },
33030        errorMessage : {
33031            get: function () {
33032                return this.getAttribute("errorMessage");
33033            }
33034        },
33035        isWidgetRecaptcha : {
33036            get: function () {
33037                return (this.captchaWidget === "recaptcha");
33038            }
33039        },
33040        isWidgetHcaptcha : {
33041            get: function () {
33042                return (this.captchaWidget === "hcaptcha");
33043            }
33044        },
33045        isWidgetTurnstile : {
33046            get: function () {
33047                return (this.captchaWidget === "turnstile");
33048            }
33049        }
33050
33051
33052    });
33053
33054}(_, guidelib));
33055
33056(function (_, guidelib) {
33057    var GuidePasswordBox = guidelib.model.GuidePasswordBox = guidelib.model.Field.extend({
33058        msClassName : "guidePasswordBox",
33059        
33060        _getReducedJSON : function () {
33061            
33062            
33063            if (this.submitPassword) {
33064                return GuidePasswordBox._super._getReducedJSON.call(this);
33065            }
33066            
33067            var whitelistedProperties = ["name", "templateId", "guideNodeClass"],
33068                reducedJsonObject = {};
33069            guidelib.model.util.CommonUtils.returnMinimalJSON(whitelistedProperties, reducedJsonObject, this);
33070            return reducedJsonObject;
33071        },
33072
33073        _preserveLazyValue : function () {
33074            return !!this.submitPassword && GuidePasswordBox._super._preserveLazyValue.call(this);
33075        },
33076
33077        _allowEmptyValueString : function () {
33078            return true;
33079        }
33080    });
33081    GuidePasswordBox.defineProps({
33082        submitPassword : {
33083            get : function () {
33084                return this.getAttribute("submitPassword");
33085            }
33086        }
33087    });
33088
33089})(_, guidelib);
33090
33091(function (_, guidelib) {
33092    var GuideScribble = guidelib.model.GuideScribble = guidelib.model.Field.extend({
33093        msClassName : "guideScribble"
33094    });
33095})(_, guidelib);
33096
33097
33098(function (_, guidelib) {
33099    var AbstractField = guidelib.model.AbstractField = guidelib.model.GuideNode.extend({
33100        msClassName : "abstractField",
33101
33102        initialize : function () {
33103            this._name = this.options.name || "";
33104            this._className = this.options.className || "";
33105            this._bindRef = this.options.bindRef || "";
33106            this._afDataSom = this.options.afDataSom || "";
33107            this._dataSom = this._isXfaNode() ? this.options.dataSom : "";
33108            this.dependants = [];
33109            
33110            this._depdendantIds = [];
33111        },
33112
33113        _getValue : function () {
33114            return this.jsonModel._value;
33115        },
33116
33117        _setValue : function (value) {
33118            this.jsonModel._value = value;
33119        },
33120
33121        resetData : function () {
33122            return guidelib.model.Field.prototype.resetData.call(this);
33123        },
33124
33125        _isXfaNode : function () {
33126            return this.bindRef.indexOf("xfa[0].form[0].") === 0;
33127        },
33128
33129        getAttribute : function (attrName) {
33130            var attrValue;
33131            switch (attrName) {
33132                case "name":
33133                    attrValue = this.name;
33134                    break;
33135                case "bindRef":
33136                    attrValue = this.bindRef;
33137                    break;
33138                default:
33139                    attrValue = null;
33140                    break;
33141            }
33142            return attrValue;
33143        }
33144    });
33145
33146    AbstractField.defineProps({
33147        somExpression : {
33148            get : function () {
33149                return "";
33150            }
33151        },
33152        name : {
33153            get : function () {
33154                return (this._name || "").replace(/\s+/g, '');
33155            }
33156        },
33157        className : {
33158            get : function () {
33159                return (this._className || "");
33160            }
33161        },
33162        bindRef : {
33163            get : function () {
33164                return (this._bindRef || "").replace(/\s+/g, '');
33165            }
33166        },
33167        dataSom : {
33168            get : function () {
33169                return this._dataSom;
33170            }
33171        },
33172        afDataSom : {
33173            get : function () {
33174                return this._afDataSom.replace(/\s+/g, '');
33175            }
33176        },
33177
33178        value : {
33179            get : function () {
33180                var context = this._guide()._currentContext;
33181                if (context && context.managedExp && context.contextNode && context.expression) {
33182                    this._addDependant(context.contextNode, context.expression);
33183                    
33184                    this._depdendantIds.push(context.contextNode.id);
33185                }
33186                return this.jsonModel._value;
33187            },
33188            set : function (newValue) {
33189                if (this.jsonModel._value !== newValue) {
33190                    this.jsonModel._value = newValue;
33191                    
33192                    var guideDirtyMarkerAndVisitor = this._guide().internal.GuideDirtyMarkerAndVisitor,
33193                        visitMap = guideDirtyMarkerAndVisitor.visitMap,
33194                        listOfDependents = this._depdendantIds;
33195                    guideDirtyMarkerAndVisitor._findAndMarkDirty(visitMap, listOfDependents);
33196                    this._notifyDependants();
33197                }
33198            }
33199        }
33200    });
33201
33202    AbstractField.addMixins([
33203        guidelib.model.mixin.AddDependencyMgmt
33204    ]);
33205}(_, guidelib));
33206
33207(function ($, guidelib, _) {
33208    var ModelTemplateCacheStore = guidelib.model.util.ModelTemplateCacheStore = xfalib.ut.Class.extend({
33209        initialize : function () {
33210            ModelTemplateCacheStore._super.initialize.apply(this);
33211            this._modelIdCache = {};
33212            this._templateIdCache = {};
33213            
33214            
33215            
33216            
33217            this._lazyTemplateIdCache = {};
33218            var guideJson = JSON.parse(JSON.stringify(this.options.modelTemplateJson));
33219            this._putTemplate(guideJson);
33220        },
33221
33222        
33223        putModel : function (model) {
33224            if (model.id) {
33225                var modelId = model.id;
33226                this._modelIdCache[modelId] = model;
33227                if (model.children) {
33228                    _.each(model.children, function (child) {
33229                        this.putModel(child);
33230                    }, this);
33231                }
33232            } else {
33233                this.logger().log("no Id found for model" + model.getAttribute("name"));
33234            }
33235        },
33236
33237        
33238        removeModel : function (id) {
33239            if (this._modelIdCache.hasOwnProperty(id)) {
33240                delete this._modelIdCache[id];
33241            }
33242        },
33243
33244        getModel : function (id) {
33245            if (this._modelIdCache.hasOwnProperty(id)) {
33246                return this._modelIdCache[id];
33247            }
33248        },
33249
33250        
33251        _putTemplate : function (jsonTemplate) {
33252            if (jsonTemplate.templateId && jsonTemplate.guideNodeClass) {
33253                this._templateIdCache[jsonTemplate.templateId] = jsonTemplate;
33254            }
33255            _.each(jsonTemplate, function (childTemplate, key) {
33256                if (_.isObject(childTemplate)) {
33257                    this._putTemplate(childTemplate);
33258                }
33259            }, this);
33260        },
33261
33262        
33263        _putLazyTemplate : function (lazyTemplateJson) {
33264            if (lazyTemplateJson.templateId && lazyTemplateJson.guideNodeClass) {
33265                this._lazyTemplateIdCache[lazyTemplateJson.templateId] = lazyTemplateJson;
33266            }
33267        },
33268
33269        cloneJsonTemplate : function (templateId) {
33270            if (this._templateIdCache[templateId]) {
33271                var template = this._templateIdCache[templateId];
33272                return JSON.parse(JSON.stringify(template)); 
33273            }
33274        },
33275        
33276        _getTemplate : function (templateId, lookupLazyStore) {
33277            var template = this._templateIdCache[templateId];
33278            
33279            
33280            
33281            if (lookupLazyStore && guidelib.util.GuideUtil.isLazyJson(template)) {
33282                template = this._lazyTemplateIdCache[templateId];
33283            }
33284
33285            if (!_.isUndefined(template)) {
33286                return JSON.parse(JSON.stringify(template));
33287
33288            }
33289        }
33290    });
33291
33292    ModelTemplateCacheStore.defineProps({
33293    });
33294}($, guidelib, window._));
33295(function ($, guidelib) {
33296    var DomTemplateCacheStore = guidelib.view.util.DomTemplateCacheStore = xfalib.ut.Class.extend({
33297        cloneDomElement : function (htmlId) {
33298            return this.$htmlTemplateDom.find(htmlId).clone();
33299        },
33300
33301        putDomElement : function (parentIdSelector, $child) {
33302            
33303            this.$htmlTemplateDom.find(parentIdSelector).eq(0).append($child);
33304        },
33305
33306        removeDomElement : function (parentIdSelector) {
33307            
33308            this.$htmlTemplateDom.find(parentIdSelector).children().remove();
33309        }
33310    });
33311
33312    DomTemplateCacheStore.defineProps({
33313        $htmlTemplateDom : {
33314            get : function () {
33315                return this.options.$htmlTemplateDom;
33316            }
33317        }
33318    });
33319}($, guidelib));
33320(function (_, guidelib) {
33321    
33322    var AddMinMaxValidation = guidelib.model.mixin.AddMinMaxValidation = {
33323        normalProperties : {
33324
33325            _runMaximumValueTest : function () {
33326                if (this.exclusiveMaximum) {
33327                    return this.value < this.maximum;
33328                } else {
33329                    return this.value <= this.maximum;
33330                }
33331            },
33332
33333            _runMinimumValueTest : function () {
33334                if (this.exclusiveMinimum) {
33335                    return this.value > this.minimum;
33336                } else {
33337                    return this.value >= this.minimum;
33338                }
33339            },
33340
33341            
33342            _minMaxValidation : function (value, obj) {
33343                if (value != null && obj.validFlag) {
33344
33345                    if (this.maximum) {
33346                        obj.validFlag = this._runMaximumValueTest();
33347                        if (!obj.validFlag) {
33348                            var maxFormattedValue = this._getFormattedValue(this.maximum);
33349                            this._errorText = this.exclusiveMaximum ? this.guideUtil.getLocalizedMessage("", guidelib.i18n.strings.exclusiveMaxValErrorMessage, [maxFormattedValue]) :
33350                                this.guideUtil.getLocalizedMessage("", guidelib.i18n.strings.maxValErrorMessage, [maxFormattedValue]);
33351                            this._failedTest = this.guideUtil.MAXIMUM_VALUE_TEST;
33352                        }
33353                    }
33354
33355                    if (obj.validFlag && this.minimum !== null) {
33356                        obj.validFlag = this._runMinimumValueTest();
33357                        if (!obj.validFlag) {
33358                            var minFormattedValue = this._getFormattedValue(this.minimum);
33359                            this._errorText = this.exclusiveMinimum ? this.guideUtil.getLocalizedMessage("", guidelib.i18n.strings.exclusiveMinValErrorMessage, [minFormattedValue]) :
33360                                this.guideUtil.getLocalizedMessage("", guidelib.i18n.strings.minValErrorMessage, [minFormattedValue]);
33361                            this._failedTest = this.guideUtil.MINIMUM_VALUE_TEST;
33362                        }
33363                    }
33364                }
33365            }
33366
33367        },
33368        propertyDescriptors : {
33369            
33370            maximum : {
33371                get : function () {
33372                    return this.getAttribute("maximum");
33373                }
33374            },
33375
33376            
33377            minimum : {
33378                get : function () {
33379                    return this.getAttribute("minimum");
33380                }
33381            },
33382
33383            
33384            exclusiveMaximum : {
33385                get : function () {
33386                    return this.getAttribute("exclusiveMaximum");
33387                }
33388            },
33389
33390            
33391            exclusiveMinimum : {
33392                get : function () {
33393                    return this.getAttribute("exclusiveMinimum");
33394                }
33395            }
33396
33397        }
33398    };
33399
33400}(_, guidelib));
33401(function (_, guidelib) {
33402
33403    
33404    var GuideNumericBox = guidelib.model.GuideNumericBox = guidelib.model.Field.extend({
33405        msClassName : "guideNumericBox",
33406
33407        _getTypedValue : function (value) {
33408            var dataType = this.dataType,
33409                tmpValue, str, leadD, fracD;
33410
33411            if (this.checkIfNull(value)) {
33412                return null;
33413            }
33414            switch (dataType) {
33415                case "integer":
33416                    tmpValue = parseInt(value);
33417                    break;
33418                case "float":
33419                    tmpValue = parseFloat(value);
33420                    break;
33421                case "decimal":
33422                    tmpValue = parseFloat(value);
33423                    if (!isNaN(tmpValue)) {
33424                        str =  tmpValue.toString();
33425                        leadD = str.indexOf(".");
33426                        leadD = leadD === -1 ? str.length : leadD;
33427                        leadD = str.indexOf("-") === 0 ? leadD - 1 : leadD;
33428                        fracD = str.length - leadD - 1;
33429                        if (fracD > this.fracDigits && this.fracDigits !== -1) {
33430                            tmpValue = parseFloat(tmpValue.toFixed(this.fracDigits));
33431                        }
33432                        if (leadD > this.leadDigits && this.leadDigits !== -1) {
33433                            return undefined;
33434                        }
33435                    }
33436                    break;
33437            }
33438            if (isNaN(tmpValue)) {
33439                return undefined;
33440            }
33441            return tmpValue;
33442        },
33443        _getFormattedValue : function (value) {
33444            if (_.isUndefined(value) || value === null || value === "") {
33445                return null;
33446            }
33447
33448            var picture = this.jsonModel.displayPictureClause,
33449                defaultPattern = "zzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzz";
33450
33451            
33452            try {
33453                if (picture && this.jsonModel.html5Type !== "number") {
33454                    return xfalib.ut.PictureFmt.format(value + "", picture, guideBridge._readRuntimeLocale(), true);
33455                } else {
33456                    var pattern = (this.jsonModel.html5Type === "number") ? defaultPattern : guidelib.i18n.numberPatterns.numeric;
33457                    return xfalib.ut.PictureFmt.format(value + "", "num{" + pattern + "}",
33458                        guideBridge._readRuntimeLocale(), true, true);
33459                }
33460            } catch (exception) {
33461                this.logger().error("Cannot format value " + value + " " + exception);
33462                
33463                return value;
33464            }
33465        },
33466
33467        
33468        _totalDigitValidation : function (value, obj) {
33469            if (value && obj.validFlag && this.leadDigits > -1) {
33470                obj.validFlag = true;
33471                if (this.dataType === "integer") {
33472                    obj.validFlag = this.value.toString().length <= this.leadDigits;
33473                }
33474                if (!obj.validFlag) {
33475                    this._errorText = guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.totalDigitMessage, [this.leadDigits]);
33476                    this._failedTest = this.guideUtil.TOTAL_DIGITS_TEST;
33477                }
33478            }
33479        },
33480
33481        
33482        _datatypeValidation : function (obj) {
33483            if (obj.validFlag) {
33484                var value = this.getAttribute("_value");
33485                obj.validFlag = !isNaN(value);
33486                if (!obj.validFlag) {
33487                    this._errorText = guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.datatypeMessage, ["numeric"]);
33488                    this._failedTest = this.guideUtil.FORMAT_TEST;
33489                }
33490            }
33491        },
33492
33493        
33494        _runValidations : function (obj) {
33495            var value = this.value;
33496            GuideNumericBox._super._runValidations.call(this, obj);
33497            this._datatypeValidation(obj);
33498            this._minMaxValidation(value, obj);
33499            this._totalDigitValidation(value, obj);
33500        }
33501    });
33502    GuideNumericBox.defineProps({
33503        
33504        dataType : {
33505            get : function () {
33506                return this.getAttribute("dataType");
33507            }
33508        },
33509
33510        
33511        leadDigits : {
33512            get : function () {
33513                return this.getAttribute("leadDigits");
33514            }
33515        },
33516
33517        
33518        fracDigits : {
33519            get : function () {
33520                return this.getAttribute("fracDigits");
33521            }
33522        }
33523    });
33524
33525    GuideNumericBox.addMixins([
33526        guidelib.model.mixin.AddMinMaxValidation
33527    ]);
33528
33529})(_, guidelib);
33530
33531(function (_, guidelib) {
33532    
33533    var GuideDatePicker = guidelib.model.GuideDatePicker = guidelib.model.Field.extend({
33534        msClassName : "guideDatePicker",
33535        errorList : [],
33536        that : this,
33537
33538        initialize : function () {
33539            GuideDatePicker._super.initialize.call(this);
33540            if (_.isEmpty(this.jsonModel._value) && this.jsonModel.defaultToCurrentDate === "true") {
33541                this._setGuideValue(new Date().toISOString().slice(0, 10));
33542            }
33543        },
33544
33545        _setGuideValue : function (value) {
33546            var retVal = guidelib.util.GuideUtil._reformatDate(value, this.isEditPictureClausePresent);
33547            GuideDatePicker._super._setGuideValue.call(this, retVal);
33548        },
33549
33550        _getTypedValue : function (value) {
33551            if (value) {
33552                return value;
33553            }
33554            return null;
33555        },
33556
33557        
33558        _datatypeValidation : function (obj) {
33559            if (obj.validFlag) {
33560                var value = this.getAttribute("_value");
33561                obj.validFlag = true;
33562                if (value != null && xfalib.ut.DateInfo.Parse(value, undefined, this.isEditPictureClausePresent) == null) {
33563                    obj.validFlag = false;
33564                }
33565                if (!obj.validFlag) {
33566                    this._errorText = guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.datatypeMessage, ["date"]);
33567                    this._failedTest = this.guideUtil.FORMAT_TEST;
33568                }
33569            }
33570        },
33571
33572        _validateDatePart : function (field, datePart, errorList) {
33573            if (field === "D") {
33574                if (datePart > 31) {
33575                    errorList.push(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.genericInvalidDatePart, [guidelib.i18n.calendarSymbols.month, guidelib.i18n.calendarSymbols.more, 31, guidelib.i18n.calendarSymbols.days]));
33576                }
33577                if (datePart < 1) {
33578                    errorList.push(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.genericInvalidDatePart, [guidelib.i18n.calendarSymbols.month, guidelib.i18n.calendarSymbols.less, 1, guidelib.i18n.calendarSymbols.days]));
33579                }
33580            }
33581            if (field === "M") {
33582                if (datePart > 12) {
33583                    errorList.push(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.genericInvalidDatePart, [guidelib.i18n.calendarSymbols.year, guidelib.i18n.calendarSymbols.more, 12, guidelib.i18n.calendarSymbols.months]));
33584                }
33585                if (datePart < 1) {
33586                    errorList.push(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.genericInvalidDatePart, [guidelib.i18n.calendarSymbols.year, guidelib.i18n.calendarSymbols.less, 1, guidelib.i18n.calendarSymbols.months]));
33587                }
33588            }
33589            if (field === "Y") {
33590                if (datePart.length < 4) {
33591                    errorList.push(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.genericInvalidYearPart));
33592                }
33593
33594            }
33595        },
33596        _getOrderedDateParts : function (value) {
33597            var dateFormat = this.jsonModel.dateDisplayFormat || "date{M/D/YYYY}";
33598            var separator = dateFormat.match(/^date\{.*([^mdy]).*\}$/i)[1];
33599            var fieldOrder = ['M', 'D', 'Y']
33600                .map(function (val) {
33601                    return {
33602                        value : val,
33603                        index : dateFormat.indexOf(val)
33604                    };
33605                })
33606                .sort(function (a, b) {
33607                    return a.index - b.index;
33608                })
33609                .map(function (obj) {
33610                    return obj.value;
33611                });
33612            var dateParts = value.split(separator);
33613            return [dateParts, fieldOrder];
33614        },
33615        _checkIsolatedDateValidity : function (obj, value, errorList) {
33616            var orderedParts = this._getOrderedDateParts(value);
33617            var dateParts = orderedParts[0], fieldOrder = orderedParts[1]; 
33618            for (var i = 0; i < fieldOrder.length; i++) {
33619                var field = fieldOrder[i];
33620                var datePart = dateParts[i];
33621                if (!_.isEmpty(datePart)) {
33622                    this._validateDatePart(field, datePart, errorList);
33623                }
33624            }
33625        },
33626        _validateDaysOfMonth : function (obj, value, errorList) {
33627            var orderedParts = this._getOrderedDateParts(value);
33628            var dateParts = orderedParts[0], fieldOrder = orderedParts[1]; 
33629                month = dateParts[fieldOrder.indexOf('M')],
33630                day = dateParts[fieldOrder.indexOf('D')],
33631                year = dateParts[fieldOrder.indexOf('Y')];
33632            if (month !== "" && day !== "") {
33633                month = Number(month) || 0;
33634                day = Number(day) || 0;
33635                var currentMonthName = guidelib.i18n.calendarSymbols.monthNames[month - 1];
33636                if (31 === day && [4,6,9,11].includes(month)) {
33637                    errorList.push(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.nonFebruaryMessage, [currentMonthName, day - 1]));
33638                }
33639            }
33640        },
33641        _validateFieldCompleteness : function (obj, value, errorList) {
33642            var orderedParts = this._getOrderedDateParts(value);
33643            var dateParts = orderedParts[0], fieldOrder = orderedParts[1]; 
33644            var localizedFieldMapping = {
33645                M : guidelib.i18n.calendarSymbols.month,
33646                D : guidelib.i18n.calendarSymbols.day,
33647                Y : guidelib.i18n.calendarSymbols.year
33648            };
33649            var emptyFields = fieldOrder
33650                .map(function (fieldName) {
33651                    return localizedFieldMapping[fieldName];
33652                })
33653                .filter(function (_, index) {
33654                    return dateParts[index] === "";
33655                });
33656            if (emptyFields.length !== 3 && emptyFields.length > 0) {
33657                errorList.push(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.fieldCompletenessMessage, [emptyFields.join(", ")]));
33658            }
33659        },
33660        _validateFullDate : function (obj, value, errorList) {
33661            var orderedParts = this._getOrderedDateParts(value);
33662            var dateParts = orderedParts[0], fieldOrder = orderedParts[1]; 
33663                month = dateParts[fieldOrder.indexOf('M')],
33664                day = dateParts[fieldOrder.indexOf('D')],
33665                year = dateParts[fieldOrder.indexOf('Y')];
33666            if (month !== "" && day !== "" && year !== "") {
33667                month = Number(month) || 0;
33668                day = Number(day) || 0;
33669                year = Number(year) || 0;
33670                var isLeapYear = (year % 400 === 0 || (year % 4 === 0 && year % 100 !== 0));
33671                if (month === 2) {
33672                    var maxFebruary = isLeapYear ? 29 : 28;
33673                    if (day === 29 && !isLeapYear) {
33674                        errorList.push(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.februaryMessage, [maxFebruary, year]));
33675                    }
33676                    if (day >= 30) {
33677                        errorList.push(guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.strings.februaryMessage, [maxFebruary, year]));
33678                    }
33679                }
33680            }
33681        },
33682        _computeErrors : function (obj, errorList) {
33683            var that = this;
33684            obj.validFlag = errorList.length === 0;
33685            if (!obj.validFlag) {
33686                that._errorText = errorList.join(" ");
33687                that._failedTest = that.guideUtil.FORMAT_TEST;
33688            }
33689        },
33690
33691        
33692        _runValidations : function (obj) {
33693            var value = this.value;
33694            if (this.jsonModel.titleDay || this.jsonModel.titleMonth || this.jsonModel.titleYear) {
33695                if (null === value) {
33696                    value = "//";
33697                }
33698                var errorList = [];
33699                
33700                this._checkIsolatedDateValidity(obj, value, errorList);
33701                
33702                if (errorList.length === 0) {
33703                    this._validateDaysOfMonth(obj, value, errorList);
33704                }
33705                
33706                if (errorList && errorList.length === 0) {
33707
33708                    this._validateFieldCompleteness(obj, value, errorList);
33709                }
33710                
33711                if (errorList.length === 0) {
33712                    this._validateFullDate(obj, value, errorList);
33713                }
33714                this._computeErrors(obj, errorList);
33715
33716                
33717                if (errorList.length === 0) {
33718                    this.value = value = this.value === "//" ? "" : this.value;
33719                    GuideDatePicker._super._runValidations.call(this, obj);
33720                    try {
33721                        this.value = value = this.value !== null && this.value !== "" ? xfalib.ut.PictureFmt.parseDate(this.value, (this.jsonModel.dateDisplayFormat || "date{M/D/YYYY}")) : this.value;
33722                    } catch (error) {}
33723                    this._minMaxValidation(value, obj);
33724                }
33725            } else {
33726                GuideDatePicker._super._runValidations.call(this, obj);
33727                this._datatypeValidation(obj);
33728                this._minMaxValidation(value, obj);
33729            }
33730        }
33731    });
33732
33733    GuideDatePicker.addMixins([
33734        guidelib.model.mixin.AddMinMaxValidation
33735    ]);
33736
33737})(_, guidelib);
33738
33739(function (guidelib, $, _) {
33740    var ErrorConstants = guidelib.util.ErrorConstants = {
33741        DATA_ATTRIBUTE_ERROR_ITEM : "data-af-global-error-item",
33742        DATA_ATTRIBUTE_DISPLAY_ON : "data-af-global-errors-display-on",
33743        DATA_ATTRIBUTE_ERROR_TEXT_CONTAINER : "data-af-global-error-text",
33744        DATA_ATTRIBUTE_ERROR_CONTAINER : "data-af-global-errors",
33745        DATA_ATTRIBUTE_SOM : "data-af-som",
33746        CONTEXT_SUBMISSION : "form",
33747        CONTEXT_NAVIGATION : "panel",
33748        CONTEXT_FIELD : "field" 
33749
33750    };
33751    ErrorConstants[ErrorConstants.CONTEXT_SUBMISSION] = 4;
33752    ErrorConstants[ErrorConstants.CONTEXT_NAVIGATION] = 2;
33753    ErrorConstants[ErrorConstants.CONTEXT_FIELD] = 1;
33754
33755    var GlobalErrorContainer = function ($el, options) {
33756        this.$container = $el;
33757        var $items = $el.find("[" + ErrorConstants.DATA_ATTRIBUTE_ERROR_ITEM + "]").first(),
33758            displayOnAttribute = $el.attr(ErrorConstants.DATA_ATTRIBUTE_DISPLAY_ON) || "";
33759        this.displayOn = 0;
33760        this.errorCount = 0;
33761        this.$container.addClass("no-validation-errors");
33762        _.each(displayOnAttribute.split(","), function (displayOn) {
33763            var val = ErrorConstants[displayOn] || 0;
33764            this.displayOn += val;
33765        }, this);
33766        this.$item = $items.eq(0).clone();
33767        $items.remove();
33768    };
33769    _.extend(GlobalErrorContainer.prototype, {
33770        
33771        showError : function (msg, context, fieldSom) {
33772            var nContext,
33773            $el  = this.$container.find('[' + ErrorConstants.DATA_ATTRIBUTE_SOM + '="' + fieldSom + '"]');;
33774            if ($el.length > 0) {
33775                $el.find("[" + ErrorConstants.DATA_ATTRIBUTE_ERROR_TEXT_CONTAINER + "]")
33776                    .addBack("[" + ErrorConstants.DATA_ATTRIBUTE_ERROR_TEXT_CONTAINER + "]")
33777                    .text(msg);
33778            } else {
33779                if (typeof ErrorConstants[context] !== "number") {
33780                    return;
33781                }
33782                nContext = ErrorConstants[context];
33783                if ((nContext & this.displayOn) === nContext) {
33784                    if (this.errorCount === 0) {
33785                        this.$container.removeClass("no-validation-errors");
33786                    }
33787                    this.errorCount++;
33788                    this.$item.clone()
33789                        .find("[" + ErrorConstants.DATA_ATTRIBUTE_ERROR_TEXT_CONTAINER + "]")
33790                        .addBack("[" + ErrorConstants.DATA_ATTRIBUTE_ERROR_TEXT_CONTAINER + "]")
33791                        .text(msg)
33792                        .click(function (evnt) {
33793                            guideBridge.setFocus(fieldSom);
33794                        })
33795                        .end()
33796                        .end()
33797                        .attr(ErrorConstants.DATA_ATTRIBUTE_SOM, fieldSom)
33798                        .appendTo(this.$container);
33799                }
33800            }
33801        },
33802        hideError : function (fieldSom) {
33803            var $err = this.$container.find('[' + ErrorConstants.DATA_ATTRIBUTE_SOM + '="' + fieldSom + '"]');
33804            if ($err.length > 0) {
33805                $err.remove();
33806                this.errorCount--;
33807            }
33808            if (this.errorCount === 0) {
33809                this.$container.addClass("no-validation-errors");
33810            }
33811        }
33812    });
33813
33814    $.fn.globalErrorContainer = function (options) {
33815        var args = arguments;
33816        return this.each(function () {
33817            var $this = $(this),
33818                obj = $this.data("global-error-container");
33819            if (obj === undefined) {
33820                obj = new GlobalErrorContainer($this, $.extend({}, typeof options === "object" && options));
33821                $this.data("global-error-container", obj);
33822            }
33823            if (typeof options === "string" && typeof obj[options] === "function") {
33824                obj[options].apply(obj, [].splice.apply(args, [1]));
33825            }
33826        });
33827    };
33828}(guidelib, $, _));
33829
33830(function (guidelib, $, _) {
33831
33832    var ErrorConstants = guidelib.util.ErrorConstants,
33833        $GlobalErrorContainer;
33834    var GuideErrorManager = guidelib.util.GuideErrorManager = xfalib.ut.Class.extend({
33835
33836        _defaultErrorMessage : "There is an error in this field !",
33837
33838        initialize : function () {
33839            GuideErrorManager._super.initialize.apply(arguments);
33840            $GlobalErrorContainer = $("[" + ErrorConstants.DATA_ATTRIBUTE_ERROR_CONTAINER + "]").globalErrorContainer();
33841        },
33842
33843        
33844        
33845        markError : function (msg, wrapper, fieldSom, context, type) {
33846            var errorDiv;
33847            
33848            if (_.isUndefined(msg)) {
33849                msg = this._defaultErrorMessage;
33850            }
33851
33852            msg = msg.trim();
33853
33854            $GlobalErrorContainer.globalErrorContainer("showError", msg, context, fieldSom);
33855
33856            
33857            if (wrapper) {
33858                if (wrapper.length >= 1) {
33859                    errorDiv = wrapper.find(".guideFieldError");
33860                    if (errorDiv.length < 1) {
33861                        $("<div class='guideFieldError'></div>").appendTo(wrapper).text(msg);
33862                    } else {
33863                        errorDiv.text(msg);
33864                        var roleAttr = errorDiv.attr('role');
33865                        if (roleAttr != undefined || roleAttr !== false) {
33866                            errorDiv.attr('role', 'alert');
33867                        }
33868                        errorDiv.show();
33869                    }
33870
33871                }
33872            }
33873        },
33874
33875        unMarkError : function (wrapper, fieldSom) {
33876            
33877            
33878            wrapper.find(".guideFieldError").text("");
33879            $GlobalErrorContainer.globalErrorContainer("hideError", fieldSom);
33880        }
33881    });
33882})(guidelib, $, _);
33883(function (_, guidelib) {
33884    guidelib.model.mixin.ChoiceGroupOptionHandler = {
33885        normalProperties : {
33886            
33887            _getOptionsArray : function (saveValueKey, displayValueKey) {
33888                var items = [], items1 = this.items;
33889                saveValueKey = saveValueKey || "saveValue";
33890                displayValueKey = displayValueKey || "displayValue";
33891                if (_.isArray(items1)) {
33892                    _.each(items1, function (val) {
33893                        
33894                        
33895                        var temp = val.split('='),
33896                            obj = {};
33897                        obj[saveValueKey] = temp[0];
33898                        obj[displayValueKey] = temp[1] || temp[0];
33899                        items.push(obj);
33900                    });
33901                }
33902                return items;
33903            },
33904
33905            
33906            _getPossibleValueArray : function () {
33907                var values = [], items1 = this.items;
33908                if (_.isArray(items1)) {
33909                    _.each(items1, function (val) {
33910                        
33911                        var temp = val.split('=');
33912                        values.push(temp[0]);
33913                    });
33914                }
33915                return values;
33916            },
33917
33918            
33919            _triggerItemsChange : function (oldValue, newValue) {
33920                this.trigger(guidelib.event.GuideModelEvent.ITEMS_CHANGED,
33921                    guidelib.event.GuideModelEvent.createEvent(
33922                        guidelib.event.GuideModelEvent.ITEMS_CHANGED,
33923                        this,
33924                        "items",
33925                        oldValue,
33926                        newValue
33927                    )
33928                );
33929            },
33930
33931            _resetModelValueForOptionChange : function () {
33932                if (!_.isUndefined(this.jsonModel._value) && this.jsonModel._value != null) {
33933                    var valueArr = this.jsonModel._value.split(",");
33934                    var possibleValues = this._getPossibleValueArray();
33935                    var modelValue = "";
33936                    _.each(valueArr, function (val) {
33937                        if ($.inArray(val, possibleValues, 0) !== -1) {
33938                            modelValue += val + ",";
33939                        }
33940                    }, this);
33941                    if (modelValue.length > 0) {
33942                        modelValue = modelValue.substring(0, modelValue.length - 1);
33943                    }
33944                    this.jsonModel._value = modelValue;
33945                }
33946            }
33947        }
33948    };
33949
33950}(_, guidelib));
33951(function (_, guidelib) {
33952    var GuideCheckBox = guidelib.model.GuideCheckBox = guidelib.model.Field.extend({
33953        msClassName : "guideCheckBox",
33954        
33955        _collectExpressions : function () {
33956            GuideCheckBox._super._collectExpressions.apply(this);
33957            if (this.optionsExp) {
33958                this._compiledExpressions.optionsExp = this._compileExpression(this.optionsExp, "items");
33959            }
33960        },
33961
33962        getOnOffValues : function (index) {
33963            var temp = this.jsonModel.options || [], items = [], on, off;
33964            if (this.bindNode) {
33965                on = this.bindNode.getSaveItem(0);
33966                off = this.bindNode.getSaveItem(1);
33967            } else {
33968
33969                if (temp.length == 0) {
33970                    on = "0";
33971                } else {
33972                    on = temp[index].split('=')[0].trim();
33973                }
33974                off = "-100";
33975            }
33976
33977            items = [on, off];
33978            return items;
33979        },
33980
33981        _setXFAValue : function (value) {
33982            
33983            if (value === "" || value === null) {
33984                this.bindNode.rawValue = this.bindNode.getSaveItem(1) || null;
33985            } else {
33986                this.bindNode.rawValue = value;
33987            }
33988        },
33989
33990        _getCustomAssist : function (index) {
33991            var customAssist, item;
33992
33993            if (index == null) {
33994
33995                if (this.bindNode && this.bindNode.assist && this.bindNode.assist.speak && this.bindNode.assist.speak.value) {
33996                    return this.bindNode.assist.speak.value;
33997                }
33998                return null;
33999            }
34000
34001            if (this.bindNode && this.bindNode.members && this.bindNode.members.item) {
34002                item = this.bindNode.members.item(index);
34003                if (item && item.assist && item.assist.speak && item.assist.speak.value) {
34004                    customAssist = item.assist.speak.value;
34005                }
34006            } else if (this.jsonModel.custom) {
34007
34008                var custom;
34009                custom = this.jsonModel.custom || [];
34010                if (_.isString(custom) && index <= 0) {
34011                    customAssist = custom;
34012                } else if (!custom.length === 0) {
34013                    customAssist = custom[index];
34014                }
34015            }
34016            return customAssist;
34017        },
34018        _getToolTip : function (index) {
34019            var toolTip, item;
34020            if (this.bindNode && this.bindNode.members && this.bindNode.members.item) {
34021                item = this.bindNode.members.item(index);
34022
34023                if (item && item.assist && item.assist.speak && item.assist.speak.value) {
34024                    toolTip = item.assist.toolTip.value;
34025                }
34026
34027            }
34027 else if (this.jsonModel.shortDescription) {
34028                toolTip = this.jsonModel.shortDescription;
34029            }
34030            return toolTip;
34031        },
34032        _getCaption : function (index) {
34033            var item, caption, option;
34034            if (index == null) {
34035
34036                if (this.bindNode && this.bindNode.caption && this.bindNode.caption.value && this.bindNode.caption.value.oneOfChild && this.bindNode.caption.value.oneOfChild.value) {
34037                    return this.bindNode.caption.value.oneOfChild.value;
34038                }
34039                return null;
34040            }
34041            if (this.bindNode && this.bindNode.members && this.bindNode.members.item) {
34042                item = this.bindNode.members.item(index);
34043                if (item.caption && item.caption.value && item.caption.value.oneOfChild && item.caption.value.oneOfChild.value) {
34044                    caption = item.caption.value.oneOfChild.value;
34045                }
34046
34047            } else if (this.jsonModel.options) {
34048                var options;
34049                options = this.jsonModel.options || [];
34050                if (index < 0) {
34051                    index = 0;
34052                }
34053                if (!options.length == 0) {
34054                    option = options[index];
34055                    caption = guidelib.util.GuideUtil.getOptionsKeyValue(option).pop();
34056                }
34057
34058            }
34059            return caption;
34060        },
34061        _getName : function (index) {
34062            if (this.bindNode && this.bindNode.members && this.bindNode.members.item && this.bindNode.members.item(index)) {
34063                
34064                return this.bindNode.members.item(index).name;
34065            }
34066            return null;
34067        },
34068
34069        _getScreenReaderText : function (index) {
34070            var screenReaderText, assistPriority = this._getAssistPriority() || "caption";
34071
34072            if (this.bindNode) {
34073                screenReaderText = GuideCheckBox._super._getScreenReaderText.apply(this, [index]);
34074            } else {
34075                if (assistPriority == "custom") {
34076                    screenReaderText = this._getCustomAssist(index) || this._getCaption(index);
34077                } else if (assistPriority == "caption") {
34078                    screenReaderText = this._getCaption(index);
34079                }
34080            }
34081            return screenReaderText;
34082        }
34083    });
34084
34085    GuideCheckBox.defineProps({
34086        
34087        optionsExp : {
34088            get : function () {
34089                return this.getAttribute("optionsExp");
34090            }
34091        },
34092
34093        
34094        items : {
34095            get : function () {
34096                var items  =  this.jsonModel.options;
34097                if (items && !_.isArray(items)) {
34098                    items = items.split(",");
34099                } else if (items) {
34100                    items = items.slice(0);
34101                }
34102                return items;
34103            },
34104            set : function (newValue) {
34105                if (!this.bindNode) {
34106                    var oldValue = this.jsonModel.options;
34107                    if (JSON.stringify(newValue) !== JSON.stringify(oldValue)) {
34108                        
34109                        this.jsonModel.options = newValue;
34110                        this._resetModelValueForOptionChange();
34111                        this._addStateOverride("options", {"option" : this._getOptionsArray()});
34112                        this._triggerItemsChange(oldValue, newValue);
34113                    }
34114                }
34115            }
34116        }
34117    });
34118
34119    GuideCheckBox.addMixins([
34120        guidelib.model.mixin.ChoiceGroupOptionHandler
34121    ]);
34122})(_, guidelib);
34123(function (_, guidelib) {
34124    var GuideSwitch = guidelib.model.GuideSwitch = guidelib.model.GuideCheckBox.extend({
34125        msClassName : "guideSwitch",
34126
34127        initialize : function () {
34128            
34129            var uncheckedValue = this.getOnOffValues()[1];
34130            this.jsonModel["_value"] = this.getOrElse(this.jsonModel, "_value", uncheckedValue);
34131            GuideSwitch._super.initialize.call(this);
34132        },
34133
34134        getOnOffValues : function (index) {
34135            var options, checkedLabel, uncheckedLabel, items;
34136            if (this.bindNode) {
34137                checkedLabel = this.bindNode.getSaveItem(0);
34138                uncheckedLabel = this.bindNode.getSaveItem(1);
34139            } else {
34140                items = this.jsonModel.options;
34141                
34142                if (Array.isArray(items) && items.length > 0) {
34143                    checkedLabel = items[0].split('=')[0].trim();
34144                } else if (!_.isUndefined(items) && items.length > 0) {
34145                    checkedLabel = items.split('=')[0].trim();
34146                } else {
34147                    checkedLabel = "1";
34148                }
34149                if (Array.isArray(items) && items.length > 1) {
34150                    uncheckedLabel = items[1].split('=')[0].trim();
34151                } else {
34152                    uncheckedLabel = "0";
34153                }
34154            }
34155            options = [checkedLabel, uncheckedLabel];
34156            return options;
34157        },
34158
34159        resetData : function () {
34160            this.value = this.jsonModel["{default}"];
34161        }
34162    });
34163})(_, guidelib);
34164(function (_, guidelib) {
34165    var GuideRadioButton = guidelib.model.GuideRadioButton = guidelib.model.Field.extend({
34166        msClassName : "guideRadioButton",
34167        prevOnItem : null,
34168        initialize : function () {
34169            
34170            GuideRadioButton._super.initialize.call(this);
34171        },
34172
34173        _postInitialize : function () {
34174            GuideRadioButton._super._postInitialize.call(this);
34175            this.prevOnItem = this.getSelectedIndex(this.value);
34176            if (this.bindNode && this.bindNode.members) {
34177                for (var i = 0; i < this.bindNode.members.length; i++) {
34178                    var field = this.bindNode.members.item(i);
34179                    field.on(xfalib.script.XfaModelEvent.FORM_MODEL_CHANGED, this);
34180                }
34181            }
34182        },
34183
34184        _unloadModel : function () {
34185            if (this.bindNode && this.bindNode.members) {
34186                for (var i = 0; i < this.bindNode.members.length; i++) {
34187                    var field = this.bindNode.members.item(i);
34188                    field.off(xfalib.script.XfaModelEvent.FORM_MODEL_CHANGED, this);
34189                }
34190            }
34191
34192            GuideRadioButton._super._unloadModel.call(this);
34193        },
34194
34195        
34196        _collectExpressions : function () {
34197            GuideRadioButton._super._collectExpressions.apply(this);
34198            if (this.optionsExp) {
34199                this._compiledExpressions.optionsExp = this._compileExpression(this.optionsExp, "items");
34200            }
34201        },
34202
34203        
34204        getItemIdentifier : function (index) {
34205            if (this.bindNode) {
34206                return this.bindNode.members.item(index).somExpression;
34207            } else {
34208                return index;
34209            }
34210
34211        },
34212
34213        playJson : function (pJsonModel) {
34214            GuideRadioButton._super.playJson.call(this, pJsonModel);
34215            this.prevOnItem = this.getSelectedIndex(this.jsonModel._value);
34216        },
34217
34218        getOnOffValues : function (index) {
34219            var temp = this.jsonModel.options || [],
34220                items = [],
34221                on,
34222                off;
34223            if (this.bindNode) {
34224                var item = this.bindNode.members.item(index);
34225                on = item.getSaveItem(0);
34226                off = item.getSaveItem(1) ? item.getSaveItem(1) : null;
34227            } else {
34228
34229                if (temp.length == 0) {
34230                    on = "0";
34231                } else {
34232                    on = temp[index].split('=')[0].trim();
34233                }
34234                off = null;
34235            }
34236
34237            items = [on, off];
34238            return items;
34239        },
34240
34241        _handleXfaModelChanged : function (event) {
34242            if (event._property == "rawValue") {
34243                this.trigger(guidelib.event.GuideModelEvent.VALUE_CHANGED,
34244                    guidelib.event.GuideModelEvent.createEvent(
34245                        guidelib.event.GuideModelEvent.VALUE_CHANGED,
34246                        this,
34247                        "value",
34248                        event.target.somExpression,
34249                        event.newText
34250                    )
34251                );
34252            } else {
34253                GuideRadioButton._super._handleXfaModelChanged.call(this, event);
34254            }
34255        },
34256
34257        getSelectedIndex : function (value) {
34258            var index = null;
34259            if (!_.isEmpty(this.jsonModel.options) && !_.isArray(this.jsonModel.options)) {
34260                this.jsonModel.options = [this.jsonModel.options];
34261            }
34262            var currOption = _.find(this.jsonModel.options, function (opt, i) {
34263                var items = this.getOnOffValues(i);
34264                index = i;
34265                return (items[0] == value);
34266            }, this);
34267
34268            if (currOption) {
34269                return index;
34270            } else {
34271                return null;
34272            }
34273
34274        },
34275
34276        
34277
34278        _triggerDisplayFormatChange : function () {
34279            if (!this.bindNode) {
34280                var currValue = this._getValue();
34281                var currSelected = this.getSelectedIndex(currValue);
34282
34283                if (this.prevOnItem !== null) {
34284                    this._triggerEvent(guidelib.event.GuideModelEvent.VALUE_CHANGED, "value", this.prevOnItem, null);
34285                }
34286                if (currSelected !== null) {
34287                    this._triggerEvent(guidelib.event.GuideModelEvent.VALUE_CHANGED, "value", currSelected, this._getFormattedValue(currValue));
34288                }
34289                this.prevOnItem = currSelected;
34290            }
34291        },
34292        _getCustomAssist : function (index) {
34293            var customAssist, item;
34294
34295            if (index == null) {
34296
34297                if (this.bindNode && this.bindNode.assist && this.bindNode.assist.speak && this.bindNode.assist.speak.value) {
34298                    return this.bindNode.assist.speak.value;
34299                }
34300                return null;
34301            }
34302
34303            if (this.bindNode && this.bindNode.members && this.bindNode.members.item) {
34304                item = this.bindNode.members.item(index);
34305                if (item && item.assist && item.assist.speak && item.assist.speak.value) {
34306                    customAssist = item.assist.speak.value;
34307                }
34308            } else if (this.jsonModel.custom) {
34309
34310                var custom;
34311                custom = this.jsonModel.custom || [];
34312                if (_.isString(custom) && index <= 0) {
34313
34314                    customAssist = custom;
34315                } else {
34316                    if (!custom.length == 0) {
34317                        customAssist = custom[index];
34318                    }
34319                }
34320            }
34321            return customAssist;
34322        },
34323        _getToolTip : function (index) {
34324            var toolTip, item;
34325            if (this.bindNode && this.bindNode.members && this.bindNode.members.item) {
34326                item = this.bindNode.members.item(index);
34327
34328                if (item && item.assist && item.assist.speak && item.assist.speak.value) {
34329                    toolTip = item.assist.toolTip.value;
34330                }
34331
34332            }
34332 else if (this.jsonModel.shortDescription) {
34333                toolTip = this.jsonModel.shortDescription;
34334            }
34335            return toolTip;
34336        },
34337        _getCaption : function (index) {
34338            var item, caption, option;
34339            if (index == null) {
34340
34341                if (this.bindNode && this.bindNode.caption && this.bindNode.caption.value && this.bindNode.caption.value.oneOfChild && this.bindNode.caption.value.oneOfChild.value) {
34342                    return this.bindNode.caption.value.oneOfChild.value;
34343                }
34344                return null;
34345            }
34346            if (this.bindNode && this.bindNode.members && this.bindNode.members.item) {
34347                item = this.bindNode.members.item(index);
34348                if (item.caption && item.caption.value && item.caption.value.oneOfChild && item.caption.value.oneOfChild.value) {
34349                    caption = item.caption.value.oneOfChild.value;
34350                }
34351
34352            } else if (this.jsonModel.options) {
34353                var options;
34354                options = this.jsonModel.options || [];
34355                if (index < 0) {
34356                    index = 0;
34357                }
34358                if (!options.length == 0) {
34359                    option = options[index];
34360                    caption = guidelib.util.GuideUtil.getOptionsKeyValue(option).pop();
34361                }
34362
34363            }
34364            return caption;
34365        },
34366        _getName : function (index) {
34367            if (this.bindNode && this.bindNode.members && this.bindNode.members.item && this.bindNode.members.item(index)) {
34368                
34369                return this.bindNode.members.item(index).name;
34370            }
34371            return null;
34372        },
34373
34374        _getScreenReaderText : function (index) {
34375            var screenReaderText, assistPriority = this._getAssistPriority() || "caption";
34376
34377            if (this.bindNode) {
34378                screenReaderText = GuideRadioButton._super._getScreenReaderText.apply(this, [index]);
34379            } else {
34380                if (assistPriority == "custom") {
34381                    screenReaderText = this._getCustomAssist(index) || this._getCaption(index);
34382                } else if (assistPriority == "caption") {
34383                    screenReaderText = this._getCaption(index);
34384                }
34385            }
34386            return screenReaderText;
34387        }
34388    });
34389
34390    GuideRadioButton.defineProps({
34391        
34392        optionsExp : {
34393            get : function () {
34394                return this.getAttribute("optionsExp");
34395            }
34396        },
34397
34398        
34399        items : {
34400            get : function () {
34401                var items  =  this.jsonModel.options;
34402                if (items && !_.isArray(items)) {
34403                    items = items.split(",");
34404                } else if (items) {
34405                    items = items.slice(0);
34406                }
34407                return items;
34408            },
34409            set : function (newValue) {
34410                if (!this.bindNode && newValue && newValue.length > 1) {
34411                    var oldValue = this.jsonModel.options;
34412                    if (JSON.stringify(newValue) !== JSON.stringify(oldValue)) {
34413                        
34414                        this.jsonModel.options = newValue;
34415                        this._resetModelValueForOptionChange();
34416                        this._addStateOverride("options", {"option" : this._getOptionsArray()});
34417                        this._triggerItemsChange(oldValue, newValue);
34418                    }
34419                }
34420            }
34421        }
34422    });
34423
34424    GuideRadioButton.addMixins([
34425        guidelib.model.mixin.ChoiceGroupOptionHandler
34426    ]);
34427})(_, guidelib);
34428
34429(function (_, guidelib) {
34430
34431    
34432    var GuideDropDownList = guidelib.model.GuideDropDownList = guidelib.model.Field.extend({
34433        msClassName : "guideDropDownList" ,
34434
34435        _collectExpressions : function () {
34436            GuideDropDownList._super._collectExpressions.apply(this);
34437            if (this.optionsExp) {
34438                this._compiledExpressions["optionsExp"] = this._compileExpression(this.optionsExp, "items");
34439            }
34440        },
34441
34442        _handleXfaModelChanged : function (event) {
34443            if (event._property === "addItem" || event._property === "clearItems" || event._property === "deleteItem") {
34444                this._triggerEvent(guidelib.event.GuideModelEvent.MODEL_CHANGED, event._property, event.prevText, event.newText);
34445            } else {
34446                GuideDropDownList._super._handleXfaModelChanged.call(this, event);
34447            }
34448        },
34449
34450        _getDisplayValue : function (saveValue) {
34451            var items = this._getOptionsArray(),
34452                displayValue = null;
34453            _.each(items, function (val) {
34454                if (saveValue === val.saveValue) {
34455                    displayValue = val.displayValue;
34456                }
34457            }, this);
34458            return displayValue;
34459        },
34460
34461        _getItems : function () {
34462            return this.jsonModel.options;
34463        },
34464
34465        _setXFAItems : function (options) {
34466            var optionsStr = this._getXFAOptionStringFromGuideItems(options);
34467            var SET_ITEMS_INSERT_MODE_PAIR = 2;
34468            if (optionsStr) {
34469                this.bindNode.setItems(optionsStr, SET_ITEMS_INSERT_MODE_PAIR);
34470            } else {
34471                this.bindNode.clearItems();
34472            }
34473        },
34474
34475        
34476        _allowEmptyValueString : function () {
34477            return true;
34478        }
34479
34480    });
34481
34482    GuideDropDownList.defineProps({
34483
34484        
34485        
34486        multiSelect : {
34487            get : function () {
34488                return this.getAttribute("multiSelect");
34489            },
34490            set : function () {
34491                this.setAttribute("multiSelect");
34492            }
34493        },
34494
34495        optionsExp : {
34496            get : function () {
34497                return this.getAttribute("optionsExp");
34498            }
34499        },
34500
34501        
34502        displayValue : {
34503            get : function () {
34504                return this._getDisplayValue(this.value);
34505            }
34506        },
34507
34508        
34509        
34510        items : {
34511            get : function () {
34512                var items = [];
34513                if (this.bindNode) {
34514                    var that = this.bindNode;
34515                    for (var index = 0; index < that.length; index++) {
34516                        var item = that.getSaveItem(index) + "=" + that.getDisplayItem(index);
34517                        items.push(item);
34518                    }
34519                    return items;
34520                } else {
34521                    items  =  this._getItems();
34522                    if (items && !_.isArray(items)) {
34523                        items = items.split(",");
34524                    } else if (items) {
34525                        items = items.slice(0);
34526                    }
34527                    return items;
34528                }
34529            },
34530            set : function (newValue) {
34531                var oldValue = this._getItems();
34532                if (JSON.stringify(newValue) !== JSON.stringify(oldValue)) {
34533                    if (this.bindNode) {
34534                        this._setXFAItems(newValue);
34535                    } else {
34536                        this.jsonModel.options = newValue;
34537                    }
34538                    if (this.multiSelect) {
34539                        this._resetModelValueForOptionChange();
34540                    }
34541                    this._addStateOverride("options", {"option" : this._getOptionsArray()});
34542                    this._triggerItemsChange(oldValue, this.items);
34543                }
34544            }
34545        }
34546    });
34547    GuideDropDownList.addMixins([
34548        guidelib.model.mixin.ChoiceGroupOptionHandler
34549    ]);
34550})(_, guidelib);
34551
34552
34553(function (guidelib, $, _) {
34554
34555    var GuideLazyUtil = guidelib.util.GuideLazyUtil = xfalib.ut.Class.extend({
34556
34557        
34558        putDirtyToTemplateCacheIfMissing : function (guide) {
34559            var guideDirtyMarker = guide.internal.GuideDirtyMarkerAndVisitor || this._guide().internal.GuideDirtyMarkerAndVisitor,
34560                listOfDirtyChildren = guideDirtyMarker._flattenDirtyPanelToList();
34561            this._getAllDirtyJsonTemplateInCache(listOfDirtyChildren);
34562        },
34563        
34564
34565        _getAllDirtyJsonTemplateInCache : function (listOfTemplateIds) {
34566            var modelTemplateCache = window.guideBridge._guide._modelTemplateCacheStore,
34567                toGetFromServer = this._generateListOfCacheMissFromTemplateJson(listOfTemplateIds);
34568            if (toGetFromServer.length > 0 && window.guideBridge.panelProvider) {
34569                var options = {
34570                    path : window.guideBridge._getGuidePathUrl(".jsonhtmlemitter"),
34571                    listOfTemplateIds : toGetFromServer,
34572                    success : addToTemplateCache
34573                };
34574                window.guideBridge.panelProvider.getMultipleTemplateJson(options);
34575            }
34576
34577            function addToTemplateCache(toInsertToTemplateCache) {
34578                _.each(toInsertToTemplateCache, function (jsonModelString) {
34579                    var template = JSON.parse(jsonModelString);
34580                    modelTemplateCache._putLazyTemplate(template);
34581                });
34582            }
34583        },
34584
34585        
34586        _generateListOfCacheMissFromTemplateJson : function (listOfTemplateIds) {
34587            var templateCache = window.guideBridge._guide._modelTemplateCacheStore,
34588                cacheMiss = [];
34589            _.each(listOfTemplateIds, function (templateID) {
34590                var templateJson = templateCache._getTemplate(templateID, true);
34591                if (guidelib.util.GuideUtil.isLazyJson(templateJson)) {
34592                    cacheMiss.push(templateID);
34593                }
34594            });
34595            return cacheMiss;
34596        },
34597
34598        _guide : function () {
34599            return this.options._guideContainer;
34600        }
34601
34602    });
34603})(guidelib, $, _);
34604(function (_, guidelib) {
34605    var guideSchema = {},
34606        convertor = {
34607            "visible" : {
34608                "xfaToGuide" : function (xfaValue) {
34609                    return xfaValue === "visible";
34610                },
34611                "guideToXfa" : function (guideValue) {
34612                    return guideValue === true ? "visible" : "hidden";
34613                }
34614            },
34615            "enabled" : {
34616                "xfaToGuide" : function (xfaValue) {
34617                    return xfaValue === "open";
34618                },
34619                "guideToXfa" : function (guideValue) {
34620                    return guideValue === true ? "open" : "readOnly";
34621                }
34622            },
34623            "assistPriority" : {
34624                "xfaToGuide" : function (xfaValue) {
34625                    return {
34626                        "custom" : "custom",
34627                        "toolTip" : "shortDescription",
34628                        "caption" : "label",
34629                        "name" : "name"
34630                    }[xfaValue];
34631                },
34632                "guideToXfa" : function (guideValue) {
34633                    return {
34634                        "custom" : "custom",
34635                        "shortDescription" : "toolTip",
34636                        "title" : "caption",
34637                        "name" : "name"
34638                    }[guideValue];
34639                }
34640            },
34641            "mandatory" : {
34642                "xfaToGuide" : function (xfaValue) {
34643                    return xfaValue === "error";
34644                },
34645                "guideToXfa" : function (guideValue) {
34646                    return guideValue === true ? "error" : "disabled";
34647                }
34648            },
34649            "multiLine" : {
34650                "xfaToGuide" : function (xfaValue) {
34651                    return xfaValue == 1;
34652                },
34653                "guideToXfa" : function (guideValue) {
34654                    return guideValue === true ? 1 : 0;
34655                }
34656            },
34657            
34658            
34659            "options" : {
34660                "xfaToGuide" : function (xfaValue) {
34661                    var items = [];
34662                    if (xfaValue) {
34663                        var bndNode = this.bindNode;
34664                        _.each(xfaValue, function (item, index, list) {
34665                            items.push(bndNode.getSaveItem(index) + "=" + bndNode.getDisplayItem(index));
34666                        });
34667                    }
34668                    return items;
34669                },
34670                "guideToXfa" : function (guideValue) {
34671                    return guideValue;
34672                }
34673            },
34674            "multiSelect" : {
34675                "xfaToGuide" : function (xfaValue) {
34676                    return xfaValue === "multiSelect";
34677                },
34678                "guideToXfa" : function (guideValue) {
34679                    return guideValue === true ? "multiSelect" : "userControl";
34680                }
34681            },
34682            "calcExp" : {
34683                "xfaToGuide" : function (xfaValue) {
34684                    return xfaValue !== null && xfaValue !== "" ? null : undefined;
34685                },
34686                "guideToXfa" : function (guideValue) {
34687                    return guideValue !== null && guideValue !== "" ? null : undefined;
34688                }
34689            },
34690            "dataType" : {
34691                "xfaToGuide" : function (xfaValue) {
34692                    return xfaValue;
34693                },
34694                "guideToXfa" : function (guideValue) {
34695                    return undefined;
34696                }
34697            }
34698        };
34699    convertor.validateExp = convertor.visibleExp =
34700                          convertor.enabledExp =
34701                          convertor.clickExp =
34702                          convertor.calcExp;
34703
34704    guidelib.model.GuideSchema = xfalib.ut.Class.extend({
34705
34706        GuideStateConstants : {
34707            
34708            GUIDE_STATE_MODEL_CREATION : 0,
34709            
34710            GUIDE_STATE_MODEL_CREATED : 1,
34711            
34712            GUIDE_STATE_MERGE_PROGRESS : 2,
34713            
34714            GUIDE_STATE_MERGE_COMPLETE : 3,
34715            
34716            GUIDE_STATE_MODEL_COMPLETE : 4
34717        },
34718
34719        initialize : function () {
34720            
34721            this.addSchema('guideNode',
34722                [
34723                    ["name", "string", null],
34724                    ["id", "string", null],
34725                    ["jcr:title", "string", null],
34726                    ["jcr:description", "string", null],
34727                    ["css", "string", ""],
34728                    ["fd:targetVersion", "float", 1.0]
34729                ]);
34730
34731            this.addSchema("scriptable",
34732                [
34733                    ["visibleExp", "string", null],
34734                    ["enabledExp", "string", null],
34735                    ["visible", "boolean", true, "presence"],
34736                    ["enabled", "boolean", true, "access"],
34737                    ["assistPriority", "string", null, "assist.speak.priority"],
34738                    ["custom", "string", null, "assist.speak.value"],
34739                    ["shortDescription", "string", null, "assist.toolTip.value"],
34740                    ["longDescription", "string", null]
34741                ],
34742                'guideNode');
34743
34744            this.addSchema("guideInstanceManager", [], "guideNode");
34745
34746            this.addSchema("esign", [], "guideNode");
34747
34748            this.addSchema("verify", [], "guideNode");
34749
34750            this.addSchema("guideItemsContainer", [], "scriptable");
34751
34752            this.addSchema("guideImage", [], "scriptable");
34753
34754            this.addSchema("guideContainerNode",
34755            [
34756                ["disableSwipeGesture", "boolean", false]
34757            ],
34758            "guideItemsContainer");
34759
34760            this.addSchema("guidePanel",
34761                [
34762                  ["validateOnStepCompletion","boolean",false]
34763                ],
34764                "guideItemsContainer");
34765
34766            this.addSchema("rootPanelNode", [], "guidePanel");
34767
34768            this.addSchema("guideTable", [], "guidePanel");
34769
34770            this.addSchema("guideTableRow", [], "guidePanel");
34771
34772            this.addSchema("guideToolbar", [], "guideItemsContainer");
34773
34774            this.addSchema("guideCompositeField", [], "guideItemsContainer");
34775
34776            this.addSchema("guideFileUpload",
34777                [
34778                    ["multiSelection", "boolean", false],
34779                    ["buttonText", "string", null],
34780                    ["fileSizeLimit", "integer", 2],
34781                    ["showComment", "boolean", false]
34782                ],
34783                "guideCompositeField");
34784
34785            
34786            
34787            this.addSchema("guideField",
34788                [
34789                    ["jcr:title", "string", null, "caption.value.oneOfChild.value","Guide"],
34790                    ["calcExp", "string", null, "calculate.script.value", "Guide"],
34791                    ["validateExp", "string", null, "validate.script.value", "Guide"],
34792                    ["_value", "string", null, "rawValue"],
34793                    ["displayPictureClause", "string", null, "format.picture.value"],
34794                    ["validatePictureClause", "string", null, "validate.picture.value"],
34795                    ["mandatory", "boolean", false, "validate.nullTest"],
34796                    ["mandatoryMessage", "string", guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.LogMessages["AEM-AF-901-005"]),
34797                        "mandatoryMessage"],
34798                    ["validateExpMessage", "string", guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.LogMessages["AEM-AF-901-006"]),
34799                        "validationMessage","Guide"],
34800                    ["validatePictureClauseMessage", "string", guidelib.util.GuideUtil.getLocalizedMessage("", guidelib.i18n.LogMessages["AEM-AF-901-007"]),
34801                        "formatMessage"],
34802                    ["validationState", "boolean", false], 
34803                    ["width", "string", null],
34804                    ["height", "string", null]
34805                ],
34806                "scriptable");
34807
34808            this.addSchema("guideTextBox",
34809                [
34810                    ["multiLine", "boolean", false, "ui.textEdit.multiLine"],
34811                    ["maxChars", "integer", 0, "value.text.maxChars"],
34812                    ["minLength", "integer", null],
34813                    ["length", "integer", null]
34814                ],
34815                "guideField");
34816
34817            this.addSchema("guideCaptcha", [], "guideField");
34818
34819            this.addSchema("guideTelephone", [], "guideField");
34820
34821            this.addSchema("guideNumericBox",
34822                [
34823                    ["dataType", "string", "decimal", "value.oneOfChild.className"],
34824                    ["leadDigits", "integer", -1, "value.decimal.leadDigits"],
34825                    ["fracDigits", "integer", 2, "value.decimal.fracDigits"],
34826                    ["maximum", "integer", null],
34827                    ["minimum", "integer", null],
34828                    ["exclusiveMaximum", "boolean", null],
34829                    ["exclusiveMinimum", "boolean", null]
34830                ],
34831                "guideField");
34832
34833            this.addSchema("guidePasswordBox", [], "guideField");
34834
34835            this.addSchema("guideRadioButton", [
34836                ["optionsExp", "string", null],
34837                ["options", "object", null, "items"]
34838            ], "guideField");
34839
34840            this.addSchema("guideCheckBox", [
34841                ["optionsExp", "string", null],
34842                ["options", "object", null, "items"]
34843            ], "guideField");
34844
34845            this.addSchema("guideSwitch", [], "guideCheckBox");
34846
34847            this.addSchema("guideScribble", [], "guideField");
34848
34849            this.addSchema("guideDatePicker",
34850                [
34851                    ["maximum", "string", null],
34852                    ["minimum", "string", null],
34853                    ["exclusiveMaximum", "boolean", null],
34854                    ["exclusiveMinimum", "boolean", null]
34855                ], "guideField");
34856
34857            this.addSchema("guideButton", [], "guideField");
34858
34859            this.addSchema("guideListFileAttachmentButton", [], "guideButton");
34860
34861            this.addSchema("guideTextDraw",
34862                [
34863                    ["documentFragmentVariables", "string", null]
34864                ],
34865                "guideField");
34866
34867            this.addSchema("guideFootnotePlaceHolder",[], "guideTextDraw");
34868
34869            this.addSchema("guideAdobeSignBlock",
34870                [
34871                    ["documentFragmentVariables", "string", null]
34872                ],
34873                "guideField");
34874
34875            this.addSchema("guideCompositeFieldItem", [], "guideField");
34876
34877            this.addSchema("guideDropDownList",
34878                [
34879                    ["title", "string", "DropDown"],
34880                    ["multiSelect", "boolean", false, "ui.oneOfChild.open"],
34881                    ["optionsExp", "string", null],
34882                    ["options", "object", null, "items"]
34883                ],
34884                "guideField");
34885
34886            this.addSchema("guideTermsAndConditions",
34887                [
34888                    ["showLink", "boolean", false],
34889                    ["showAsPopUp", "boolean", false],
34890                    ["clickStatus", "string", null]
34891                ],
34892                "guideCompositeField");
34893
34894            this.addSchema("guideChart", [
34895                ["height", "integer", 300],
34896                ["width", "integer", 100],
34897                ["data", "object", null],
34898                ["xAxisTitle", "string", null],
34899                ["yAxisTitle", "string", null],
34900                ["chartType", "string", "linepoint"],
34901                ["repeatableItem", "string", null],
34902                ["xExp", "string", null],
34903                ["reducerXFunction", "string", "none"],
34904                ["yExp", "string", null],
34905                ["reducerYFunction", "string", "none"],
34906                ["innerRadius", "integer", 0],
34907                ["lineColor", "string", "#000000"],
34908                ["pointColor", "string", "#000000"],
34909                ["areaColor", "string", "#000000"],
34910                ["tooltipHtml", "string", "<p>${x}(${y})</p>"],
34911                ["showLegends", "boolean", false],
34912                ["legendPosition", "string", "right"]
34913            ], "scriptable");
34914
34915            this.addSchema("guideAdModule", [["_value", "string", null]], "scriptable");
34916            this.addSchema("guideAdModuleGroup", [["_value", "string", null]], "scriptable");
34917        },
34918
34919        addSchema : function (elementName, attrArray, superElement) {
34920            var el = {};
34921            if (typeof superElement === "object") {
34922                _.extend(el, superElement);
34923            } else if (typeof superElement === "string" && guideSchema[superElement]) {
34924                _.extend(el, guideSchema[superElement]);
34925            }
34926            this.addAttributes(el, attrArray);
34927            guideSchema[elementName] = el;
34928        },
34929
34930        addAttributes : function (element, attrArray) {
34931            _.each(attrArray, function (elem) {
34932                element[elem[0]] = {
34933                    "type" : elem[1],
34934                    "default" : elem[2],
34935                    "xfaProp" : elem[3],
34936                    "priority" : elem[4]
34937                };
34938            });
34939        },
34940
34941        getAttributeProps : function (element, attribute) {
34942            try {
34943                return guideSchema[element][attribute] || {};
34944            } catch (e) {
34945                this.logger().error("AF", "schema has no element " + element);
34946            }
34947        },
34948        getAttributes : function (element) {
34949            return guideSchema[element];
34950        },
34951
34952        getTypedValue : function (type, value) {
34953            if (value === null || value === undefined) {
34954                return value;
34955            }
34956            if (type instanceof Array) {
34957                return value;
34958            }
34959            switch (type) {
34960                case "string":
34961                    return value + "";
34962                case "integer":
34963                    return parseInt(value);
34964                case "boolean":
34965                    return value === true || value === "true" ? true : false;
34966                case "float":
34967                    return parseFloat(value);
34968                default :
34969                    return value;
34970            }
34971        },
34972
34973        getConvertor : function (attr) {
34974            return convertor[attr];
34975        }
34976    });
34977
34978}(_, guidelib));
34979
34980(function (_, guidelib) {
34981
34982    
34983    
34984    var GuideContainerNode = guidelib.model.GuideContainerNode = guidelib.model.GuideItemsContainer.extend({
34985        msClassName : "guideContainerNode",
34986
34987        setGuideState : function (guideState) {
34988            var isStateValid = _.some(guidelib.model.GuideSchema.prototype.GuideStateConstants, function (val) {
34989                return val === guideState;
34990            });
34991            if (isStateValid === true) {
34992                this._guideState = guideState;
34993            }
34994        },
34995
34996        getGuideState : function () {
34997            return this._guideState;
34998        },
34999
35000        initialize : function () {
35001            var configString = "";
35002            
35003            guidelib.__runtime__.guide = this;
35004
35005            
35006            
35007            this._guideState = guidelib.model.GuideSchema.prototype.GuideStateConstants.GUIDE_STATE_MODEL_CREATION;
35008
35009            
35010            this.internal = this.internal || {};
35011            
35012            
35013            this.internal.liveDataUtils = this.options.liveDataUtils || new guidelib.model.LiveXmlUtils();
35014            this.internal.liveModel = this.options.liveModel || new guidelib.model.LiveModel();
35015            this.internal.GuideDirtyMarkerAndVisitor = new guidelib.model.GuideDirtyMarkerAndVisitor();
35016
35017            
35018            this.runtime =  {
35019                guideContext : {},
35020                _private : {},
35021                errorManager : {}
35022            };
35023
35024            
35025            this.runtime.errorManager = new guidelib.util.GuideErrorManager();
35026
35027            this._modelTemplateCacheStore =
35028                new guidelib.model.util.ModelTemplateCacheStore({modelTemplateJson : this.jsonModel});
35029            this._guideSchema = new guidelib.model.GuideSchema();
35030            this.guideLazyUtil = new guidelib.util.GuideLazyUtil({"_guideContainer" : this});
35031            this._pendingQueues = {
35032                calcExp : [],
35033                valueCommitScript : [],
35034                enabledExp : [],
35035                visibleExp : [],
35036                validateAllExp : [],
35037                optionsExp : [],
35038                navigationChangeExp : [],
35039                summaryExp : [],
35040                autoSaveStartExp : [],
35041                aggregateExp : [],
35042                submitSuccess : [],
35043                submitError : [],
35044                saveSuccess : [],
35045                saveError : []
35046            };
35047            this._resetExpressionCounters();
35048            this._currentContext = null;
35049            GuideContainerNode._super.initialize.call(this);
35050            this.autoSaveStart = false;
35051            
35052            
35053            this._modelTemplateCacheStore.putModel(this);
35054            this._postInitialize();
35055            var xfaHost = this.getOrElse(xfalib, "runtime.xfa.host", null);
35056            if (xfaHost !== null) {
35057                xfaHost.on(xfalib.script.XfaModelEvent.FORM_MODEL_REFRESH,
35058                    function (evnt) {
35059                        switch (evnt.name) {
35060                        case xfalib.script.XfaModelEvent.FORM_MODEL_REFRESH:
35061                            this._triggerEvent(guidelib.event.GuideModelEvent.MODEL_REFRESH, "jsonModel", null, null);
35062                            break;
35063                        default:
35064                        
35065                        }
35066                    },
35067                    this);
35068            }
35069        },
35070
35071        _resetExpressionCounters : function () {
35072            this._runningExpressionCount = {
35073                calcExp : {},
35074                valueCommitScript : {},
35075                enabledExp : {},
35076                visibleExp : {},
35077                validateAllExp : {},
35078                optionsExp : {},
35079                navigationChangeExp : {},
35080                summaryExp : {},
35081                autoSaveStartExp : {},
35082                aggregateExp : {},
35083                submitSuccess : {},
35084                submitError : {},
35085                saveSuccess : {},
35086                saveError : {}
35087            };
35088        },
35089
35090        _getReducedJSON : function () {
35091            
35092            
35093            var reducedJSONChildren = guidelib.model.GuideNode.prototype._getReducedJSON.call(this),
35094                addtionalWhitelistedProperties = ["xdpRef", "xsdRef", "id", "dorTemplateRef", "dorType", "excludeFromDoRIfHidden", "schemaRef", "schemaType"];
35095            guidelib.model.util.CommonUtils.returnMinimalJSON(addtionalWhitelistedProperties, reducedJSONChildren, this);
35096            reducedJSONChildren["rootPanel"] = this["rootPanel"]._getReducedJSON();
35097            if (this.jsonModel.toolbar) {
35098                reducedJSONChildren["toolbar"]  = this["toolbar"]._getReducedJSON();
35099            }
35100            return reducedJSONChildren;
35101        },
35102
35103        _initChildren : function () {
35104            
35105            var options =  {"_guideContainer" : this};
35106            this.rootPanel = guidelib.model.GuideModelRegistry.prototype.createModel(this.jsonModel.rootPanel, options);
35107            this._initializeChild(this.rootPanel);
35108            this._children.push(this.rootPanel);
35109            
35110            var instanceManager = guidelib.model.GuideModelRegistry.prototype.createInstanceManager(this.rootPanel);
35111            this._initializeChild(instanceManager);
35112            this._children.splice(this._children.indexOf(this.rootPanel), 0, instanceManager);
35113            instanceManager._manageChild(this.rootPanel);
35114
35115            if (this.jsonModel.toolbar) {
35116                var options = {};
35117                if (this._guide()) {
35118                    options = _.extend({}, options, {"_guideContainer" : this._guide()});
35119                }
35120                this.toolbar = guidelib.model.GuideModelRegistry.prototype.createModel(this.jsonModel.toolbar, options);
35121                this._initializeChild(this.toolbar);
35122                this._children.push(this.toolbar);
35123            }
35124        },
35125
35126        
35127        _addToExcludeFromDorMap : function (fieldTemplateId, bExcludeFromDor) {
35128            this._excludeFromDorMap = this._excludeFromDorMap || {};
35129            this._excludeFromDorMap[fieldTemplateId] = bExcludeFromDor;
35130        },
35131
35132        
35133        _getExcludeFromDorMap : function () {
35134            var that = this;
35135            if (!_.isUndefined(that._excludeFromDorMap)) {
35136                return _.keys(that._excludeFromDorMap).map(function (key) {
35137                    
35138                    return key  + "="  + that._excludeFromDorMap[key];
35139                });
35140            }
35141        },
35142
35143        
35144        _addToStateOverrideMap : function (fieldName, fieldsOverrid
35144denMap) {
35145            this._stateOverrideMap = this._stateOverrideMap || {};
35146            this._stateOverrideMap[fieldName] = fieldsOverriddenMap;
35147        },
35148
35149        
35150        _getStateOverrideMap : function () {
35151            var that = this;
35152            var retval = {};
35153            if (!_.isUndefined(that._stateOverrideMap)) {
35154                var elementsArray = _.keys(that._stateOverrideMap).map(function (key) {
35155                    return that._stateOverrideMap[key];
35156                });
35157                retval = {"element" : elementsArray};
35158            }
35159            return retval;
35160
35161        },
35162
35163        
35164        _resolveAfDataSom : function (afDataSom) {
35165            var resolvedField = null;
35166            
35167            
35168            _.each(this.internal.liveModel.getCrossFragmentFields(), function (fields) {
35169                
35170                var globalFieldModels = this.internal.liveModel.getAllAbstractFieldModels(_.keys(fields));
35171                _.each(globalFieldModels, function (globalField) {
35172                    if (globalField.afDataSom === afDataSom) {
35173                        resolvedField = globalField;
35174                        return false;
35175                    }
35176                });
35177                if (resolvedField) {
35178                    return false;
35179                }
35180            });
35181            return resolvedField;
35182        },
35183
35184        
35185        _getSigners : function () {
35186           var signers = {};
35187           
35188           if (this.enableAdobeSign && (_.isString(this.xdpRef) ||  _.isString(this.xsdRef) || (!_.isString(this.jsonModel.schemaRef)))) {
35189               var signer,
35190                  that = this,
35191                  email,
35192                  number,
35193                  countryCode,
35194                   evalExp = function (fldSom, fldAfDataSom, type) {
35195                       var val = null,
35196                           resolvedField;
35197                       try {
35198                           resolvedField = guideBridge._guide.resolveNode(fldSom);
35199                           if (!resolvedField) {
35200                               resolvedField = guideBridge._guide._resolveAfDataSom(fldAfDataSom);
35201                           }
35202                           val = resolvedField.value;
35203                           if (resolvedField.className === 'guideTelephone') {
35204                               if (type === 'countryCode') {
35205                                   val = guidelib.model.GuideTelephone.prototype._extractCountryCode(val);
35206                               } else if (type === 'phone') {
35207                                   val = guidelib.model.GuideTelephone.prototype._extractPhoneNumber(val);
35208                               }
35209                           }
35210                       } catch (e) {
35211                           
35212                       }
35213                       
35214                       
35215                       return val ? val.toString() : val;
35216                   };
35217               if (this.signerInfo) {
35218                   _.each(_.keys(this.signerInfo), function (name) {
35219                       signer = that.signerInfo[name];
35220                       if (signer && typeof signer === "object") {
35221                           email = null;
35222                           number = null;
35223                           countryCode = null;
35224                           if (signer.emailSource === 'form' && signer.email) {
35225                               email = evalExp(signer.email, signer.emailAfDataSom, 'email');
35226                           }
35227                           signers[name] = {};
35228                           signers[name].email = email ? email : "";
35229                           if (signer.securityOption === 'PHONE') {
35230                               if (signer.phoneSource === 'form' && signer.phone) {
35231                                   number = evalExp(signer.phone, signer.phoneAfDataSom, 'phone');
35232                               }
35233                               if (signer.countryCodeSource === 'form' && signer.countryCode) {
35234                                   countryCode = evalExp(signer.countryCode, signer.countryCodeAfDataSom, 'countryCode');
35235                               }
35236                               signers[name].phone = {};
35237                               signers[name].phone.countryCode = countryCode ? countryCode : "";
35238                               signers[name].phone.number = number ? number : "";
35239                           }
35240                       }
35241                   });
35242               }
35243           }
35244
35245           return signers;
35246       },
35247
35248        
35249        defaultSubmitSuccess : "window.guideBridge._defaultSubmitSuccessHandler($event.data)",
35250
35251        
35252        defaultSubmitError : "window.guideBridge._handleServerValidationError($event.data)",
35253
35254        
35255        defaultSaveSuccess : "window.guideBridge._defaultSaveSuccessHandler($event.data)",
35256        defaultSaveError : "window.guideBridge._defaultSaveErrorHandler($event.data)",
35257
35258        
35259        _collectExpressions : function () {
35260            if (this.autoSaveStartExpression) {
35261                this._compiledExpressions["autoSaveStartExp"] = this._compileExpression(this.autoSaveStartExpression, "autoSaveStart");
35262            }
35263
35264            
35265            if (!this.submitSuccess) {
35266                this.jsonModel.submitSuccess = this.defaultSubmitSuccess;
35267            }
35268            this._compiledScripts.submitSuccess = this._compileExpression(this.submitSuccess, null);
35269
35270            if (!this.submitError) {
35271                this.jsonModel.submitError = this.defaultSubmitError;
35272            }
35273            this._compiledScripts.submitError = this._compileExpression(this.submitError, null);
35274
35275            if (!this.saveSuccess) {
35276                this.jsonModel.saveSuccess = this.defaultSaveSuccess;
35277            }
35278            this._compiledScripts.saveSuccess = this._compileExpression(this.saveSuccess, null);
35279
35280            if (!this.saveError) {
35281                this.jsonModel.saveError = this.defaultSaveError;
35282            }
35283            this._compiledScripts.saveError = this._compileExpression(this.saveError,  null);
35284        },
35285
35286        prepare : function () {
35287            
35288            
35289            if ((this.getGuideState() !== guidelib.model.GuideSchema.prototype.GuideStateConstants.GUIDE_STATE_MERGE_PROGRESS) && (this.getGuideState() !== guidelib.model.GuideSchema.prototype.GuideStateConstants.GUIDE_STATE_MODEL_CREATION)) {
35290                _.each(this._children, function (childNode) {
35291                    childNode.prepare();
35292                }, this);
35293                this.queueExpressions(this, ["autoSaveStartExp"]);
35294                this.runPendingExpressions();
35295            }
35296        },
35297
35298        runPendingExpressions : function () {
35299            
35300            this._runExpressionQueue("calcExp");
35301            this._runExpressionQueue("enabledExp");
35302            this._runExpressionQueue("visibleExp");
35303            this._runExpressionQueue("valueCommitScript");
35304            this._runExpressionQueue("validateAllExp");
35305            this._runExpressionQueue("optionsExp");
35306            this._runExpressionQueue("navigationChangeExp");
35307            this._runExpressionQueue("summaryExp");
35308            this._runExpressionQueue("aggregateExp");
35309            this._runExpressionQueue("submitSuccess");
35310            this._runExpressionQueue("submitError");
35311            this._runExpressionQueue("saveSuccess");
35312            this._runExpressionQueue("saveError");
35313
35314            if (window.guideBridge.hostName !== "server") {
35315                this._runExpressionQueue("autoSaveStartExp");
35316            }
35317            this._resetExpressionCounters();
35318        },
35319
35320        _runExpressionQueue : function (expName) {
35321            var expQueue = this._pendingQueues[expName], node;
35322            if (expQueue) {
35323                while (expQueue.length > 0) {
35324                    node = this._pendingQueues[expName].shift();
35325                    if (node) {
35326                        node.executeExpression(expName);
35327                    }
35328                }
35329            }
35330        },
35331
35332        queueExpressions : function (node, expressionArray) {
35333            if (!node || !expressionArray) {
35334                return;
35335            }
35336            if (_.isString(expressionArray)) {
35337                expressionArray = [expressionArray];
35338            }
35339            _.each(expressionArray, function (expression) {
35340                var expQueue = this._pendingQueues[expression],
35341                    som = node.somExpression,
35342                    counters = this._runningExpressionCount[expression];
35343                counters[som] = counters[som] || 0;
35344                if (expQueue && expQueue.indexOf(node) < 0 && counters[som] < 10) {
35345                    expQueue.push(node);
35346                    counters[som] += 1;
35347                }
35348            }, this);
35349        },
35350
35351        playJson : function (pJsonModel, attachments) {
35352            this.rootPanel.playJson(pJsonModel.rootPanel, attachments);
35353            if (this.toolbar) {
35354                this.toolbar.playJson(pJsonModel.toolbar, attachments);
35355            }
35356        },
35357
35358        _guide : function () {
35359            return this;
35360        },
35361
35362        _collectValues : function (keyValue) {
35363            _.each(this._children, function (childNode) {
35364                childNode._collectValues(keyValue);
35365            }, this);
35366        },
35367
35368        
35369        _isFirstSignerFormFiller : function () {
35370            return this.signerInfo.firstSignerFormFiller === "true";
35371        },
35372
35373        
35374        resolveNode : function (somExpression) {
35375            if (!somExpression || somExpression === "") {
35376                return;
35377            }
35378            var hierarchy = somExpression.split("."),
35379                componentInModel = null;
35380            if (hierarchy[0] === "guide[0]") {
35381                hierarchy.shift();
35382                componentInModel = this;
35383            }
35384            if (hierarchy[0] === this._escapeQualifiedName()) {
35385                componentInModel = this;
35386                hierarchy.shift();
35387            } else if (this.hasOwnProperty(hierarchy[0])) {
35388                componentInModel = this[hierarchy[0]];
35389                hierarchy.shift();
35390            } else if (!componentInModel) {
35391                componentInModel = this.rootPanel;
35392            }
35393            _.each(hierarchy, function (element) {
35394                if (componentInModel && componentInModel._findChildren) {
35395                    componentInModel = componentInModel._findChildren(element, false)[0];
35396                } else {
35397                    componentInModel = null;
35398                }
35399            }, this);
35400            if (componentInModel == null) {
35401                
35402                var relativeName = somExpression;
35403                componentInModel = this.getOrElse(this._guide().runtime, relativeName, null);
35404            }
35405            return componentInModel;
35406        }
35407    });
35408
35409    GuideContainerNode.defineProps({
35410
35411        submitSuccess : {
35412            get : function () {
35413                return this.jsonModel.submitSuccess;
35414            }
35415        },
35416
35417        submitError : {
35418            get : function () {
35419                return this.jsonModel.submitError;
35420            }
35421        },
35422
35423        saveSuccess : {
35424            get : function () {
35425                return this.jsonModel.saveSuccess;
35426            }
35427        },
35428
35429        saveError : {
35430            get : function () {
35431                return this.jsonModel.saveError;
35432            }
35433        },
35434
35435        
35436        "autoSaveStart" : {
35437            get : function () {
35438                return this.jsonModel.autoSaveStart;
35439            },
35440
35441            set : function (newValue) {
35442                this.jsonModel.autoSaveStart = newValue;
35443                if (newValue === true) {
35444                    delete this._compiledExpressions.autoSaveStartExp;
35445                    this._triggerOnBridge(window.guideBridge.GUIDE_AUTO_SAVE_START, this);
35446                }
35447            }
35448        },
35449
35450        
35451        "enableAutoSave" : {
35452            set : function (newValue) {
35453                this.jsonModel.enableAutoSave = newValue;
35454            },
35455
35456            get : function () {
35457                return this.jsonModel.enableAutoSave || false;
35458            }
35459        },
35460
35461        
35462        "autoSaveStartExpression" : {
35463            get : function () {
35464                return this.jsonModel.autoSaveStartExpression;
35465            }
35466        },
35467
35468        
35469        "autoSaveInfo" : {
35470            get : function () {
35471                return this.jsonModel.autoSaveInfo;
35472            }
35473        },
35474
35475        
35476        "globalMetaInfo" : {
35477            get : function () {
35478                return this.jsonModel.globalMetaInfo;
35479            }
35480        },
35481
35482        
35483        "submissionMetaInfo" : {
35484            get : function () {
35485                return this.jsonModel.submissionMetaInfo;
35486            }
35487        },
35488
35489        
35490        "signerInfo" : {
35491           get : function () {
35492               return this.jsonModel.signerInfo;
35493           }
35494       },
35495
35496        "xdpRef" : {
35497            get : function () {
35498                return this.jsonModel.xdpRef;
35499            }
35500        },
35501
35502        "dorTemplateRef" : {
35503            get : function () {
35504                return this.jsonModel.dorTemplateRef;
35505            }
35506        },
35507
35508        "dorType" : {
35509            get : function () {
35510                return this.jsonModel.dorType;
35511            }
35512        },
35513
35514        "actionType" : {
35515            get : function () {
35516                return this.jsonModel.actionType;
35517            }
35518        },
35519
35520        "xsdRef" : {
35521            get : function () {
35522                return this.jsonModel.xsdRef;
35523            }
35524        },
35525
35526        
35527        panel : {
35528            get : function () {
35529                return this.rootPanel;
35530            }
35531        },
35532
35533        
35534        print : {
35535            get : function () {
35536                if (this.dorType === "generate" && this.jsonModel.view) {
35537                    return this.jsonModel.view.print;
35538                }
35539
35540                return null;
35541            }
35542        },
35543
35544        
35545        "allLazyChildren" : {
35546            get : function () {
35547                return this.jsonModel.allLazyChildren;
35548            }
35549        },
35550
35551        
35552        "enableAsyncSubmission" : {
35553            set : function (newValue) {
35554                this.jsonModel.enableAsyncSubmission = newValue;
35555            },
35556
35557            get : function () {
35558                if (this.jsonModel.enableAsyncSubmission && (this.jsonModel.enableAsyncSubmission === "true" || this.jsonModel.enableAsyncSubmission === true)) {
35559                    return true;
35560                } else {
35561                    return false;
35562                }
35563            }
35564        },
35565
35566        
35567        "enableAdobeSign" : {
35568            get : function () {
35569                return this.jsonModel._useSignedPdf;
35570            }
35571        },
35572
35573        
35574        "enableFocusOnFirstField" : {
35575            set : function (newValue) {
35576                this.jsonModel.enableFocusOnFirstField = newValue;
35577            },
35578
35579            get : function () {
35580                if (this.jsonModel.enableFocusOnFirstField === undefined) {
35581                    return true;
35582                }
35583                return this.jsonModel.enableFocusOnFirstField;
35584            }
35585        }
35586    });
35587}(_, guidelib));
35588(function (_, guidelib) {
35589    guidelib.model.mixin.AddNavigationContext = {
35590        propertyDescriptors : {
35591            "navigationContext" : {
35592                get : function () {
35593                    if (!this._navigationContext) {
35594                        this._navigationContext = new guidelib.model.util.GuideNavigationContext({
35595                            currentItem : null,
35596                            parentPanel : this.panel
35597                        });
35598                    }
35599                    return this._navigationContext;
35600                }
35601            }
35602        }
35603    };
35604})(_, guidelib);
35605
35606(function (_, guidelib) {
35607
35608    
35609    var GuidePanel = guidelib.model.GuidePanel = guidelib.model.GuideItemsContainer.extend({
35610        msClassName : "guidePanel",
35611        defaultExpressions : {
35612            "summary" : "this.title + (this.instanceIndex > 0 ? ' ' + this.instanceIndex : '')"
35613        },
35614
35615        initialize : function () {
35616            GuidePanel._super.initialize.call(this);
35617            this._currentItem = null;
35618            
35619            this._navigationContext = null;
35620        },
35621
35622        _collectExpressions : function () {
35623            GuidePanel._super._collectExpressions.call(this);
35624            if (this.completionExp) {
35625                this._compiledScripts.completionExp = this._compileExpression(this.completionExp, null);
35626            }
35627            if (this.jsonModel.summaryExp) {
35628                this._compiledExpressions.summaryExp = this._compileExpression(this.jsonModel.summaryExp, "summary");
35629            } else {
35630                this._compiledExpressions.summaryExp = this._compileExpression(this.defaultExpressions["summary"], "summary");
35631            }
35632        },
35633
35634        _initializeInstanceManager : function (child, index, insertOffset) {
35635            var instanceManager = guidelib.model.GuideModelRegistry.prototype.createInstanceManager(child);
35636            this._initializeChild(instanceManager);
35637            
35638            this._children.splice(index + insertOffset++, 0, instanceManager);
35639            instanceManager._manageChild(child);
35640            
35641            var bindNode = child._getBindNode(),
35642                bindNodeInstCount = this.getOrElse(bindNode, "instanceManager.count", 0),
35643            
35644                panelInstancesToAdd = Math.max(child.minOccur, bindNodeInstCount) - 1,
35645                bindNodeOffset = 1,
35646                addedXfaInstance;
35647            while (panelInstancesToAdd > 0) {
35648                
35649                addedXfaInstance = null;
35650                if (bindNodeInstCount > 1) {
35651                    
35652                    addedXfaInstance = bindNode.instanceManager.instances[bindNodeOffset++];
35653                }
35654                instanceManager.addInstance(addedXfaInstance);
35655                panelInstancesToAdd -= 1;
35656                insertOffset += 1;
35657            }
35658            return insertOffset;
35659        },
35660
35661        
35662        _initChildren : function (bLazyInitialization) {
35663            GuidePanel._super._initChildren.call(this);
35664            if (!bLazyInitialization) {
35665                this._instanceManager = null;
35666            }
35667            this._childInitializeGoingOn = true;
35668            var currentChildren = this.children,
35669                insertOffset = 0;
35670            _.each(currentChildren, function (child, index) {
35671                if (child instanceof guidelib.model.GuidePanel) {
35672                    insertOffset = this._initializeInstanceManager(child, index, insertOffset);
35673                }
35674            }, this);
35675            if (this.jsonModel.toolbar) {
35676                var options = {};
35677                if (this.options._guideContainer) {
35678                    options = _.extend({}, options, {"_guideContainer" : this.options._guideContainer});
35679                }
35680                var toolbar = guidelib.model.GuideModelRegistry.prototype.createModel(this.jsonModel.toolbar, options);
35681                this._initializeChild(toolbar);
35682                this._children.push(toolbar);
35683            }
35684            this._summary = null;
35685            this._childInitializeGoingOn = false;
35686        },
35687
35688        _postInitialize : function () {
35689            GuidePanel._super._postInitialize.call(this);
35690            
35691            this.instanceManager._postInitializeBinding();
35692        },
35693
35694        _addChildAt : function (child, childIndex, muteEvent) {
35695            if (child) {
35696                this._initializeChild(child);
35697                this._guide()._modelTemplateCacheStore.putModel(child);
35698                var newItemIndex = this._getItemsInsertIndex(childIndex - 1);
35699                var newItems = {};
35700                var newItemKey = child.id;
35701                var lastItemIndex = -1;
35702                _.each(this.jsonModel.items, function (value, key) {
35703                    if (lastItemIndex == newItemIndex - 1) {
35704                        newItems[newItemKey] = child.jsonModel;
35705                    }
35706                    newItems[key] = value;
35707                    lastItemIndex++;
35708                }, this);
35709                if (lastItemIndex == newItemIndex - 1) {
35710                    newItems[newItemKey] = child.jsonModel;
35711                }
35712                this.jsonModel.items = newItems;
35713                child._isItem = true;
35714                this._children.splice(childIndex, 0, child);
35715                this._normalizeChildren();
35716                child._postInitialize();
35717                if (this._guide().getGuideState() >= guidelib.model.GuideSchema.prototype.GuideStateConstants.GUIDE_STATE_MERGE_COMPLETE) {
35718                    child.prepare();
35719                }
35720                
35721                
35722                
35723                if (!(this._lazyReference && this._childInitializeGoingOn)) {
35724                    if (!muteEvent) {
35725                        this._triggerEvent(guidelib.event.GuideModelEvent.CHILD_CHANGED, "childAdded", null, child);
35726                    }
35727                }
35728            }
35729        },
35730
35731        
35732        validate : function (errorList) {
35733            var markInvalid = false;
35734
35735            
35736            if (!this.visible) {
35737                return true;
35738            }
35739            var lazyModelUnloadPending = false;
35740            
35741            if (this._lazyReference && this.guideUtil.isLazyJson(this.jsonModel)) {
35742                var guideDirtyMarker = this._guide().internal.GuideDirtyMarkerAndVisitor,
35743                    visitMap = guideDirtyMarker.visitMap,
35744                    modelTemplateCacheStore = this._guide()._modelTemplateCacheStore,
35745                    guideUtil = guidelib.util.GuideUtil,
35746                    templateJson,
35747                    templateId = this.templateId,
35748                    uniquePrefix;
35749                
35750                if (visitMap[templateId] === 0) {
35751                    if (this._ancestorRepeatable) {
35752                        uniquePrefix = guideUtil.generateUID();
35753                    }
35754                    
35755                    templateJson = modelTemplateCacheStore._getTemplate(templateId, true);
35756                    
35757                    
35758                    if (!_.isEmpty(templateJson)) {
35759                        this._embedJson(templateJson.items, uniquePrefix);
35760                        this._guide().internal.liveDataUtils.playLiveData(this);
35761                        
35762                        this.prepare();
35763                        this._guide().runPendingExpressions();
35764                        this._guide().internal.liveDataUtils.updateLiveData(); 
35765                        lazyModelUnloadPending = true;
35766                    } else {
35767                        
35768                        markInvalid = true;
35769                    }
35770
35771                }
35772
35773            }
35774            var validationResult = GuidePanel._super.validate.call(this, errorList);
35775            if (lazyModelUnloadPending) {
35776                
35777                
35778                this._unloadLazyReferenceModel(true);
35779            }
35780            if (markInvalid === true) {
35781                validationResult = false;
35782            }
35783            return validationResult;
35784        },
35785
35786        _loadLazyFragment : function (options) {
35787            options = options || {};
35788            
35789            
35790            if (_.isUndefined(this._itemsLoaded)) {
35791                
35792                var modelAlreadyLoaded = this._children && this._children.length > 0;
35793                
35794                
35795                var externalizedPath;
35796                
35797                externalizedPath = guideBridge._getGuidePathUrl(".jsonhtmlemitter");
35798                
35799                
35800                this._fetchFromAjaxCall(externalizedPath, options, modelAlreadyLoaded);
35801            } else {
35802                if (_.isFunction(options.success)) {
35803                    options.success.call(this);
35804                }
35805            }
35806            
35807            
35808        },
35809
35810        _fetchFromAjaxCall : function (externalizedPath, options, skipJsonEmbedding) {
35811            if (options && _.isFunction(options.preFetch)) {
35812                options.preFetch.call(this);
35813            }
35814            var that = this,
35815                urlSuffix = "",
35816                lazyOptions,
35817                commonCallbacks = {
35818                    success: fetchCallback,
35819                    error: (options && _.isFunction(options.error)) ? options.error : errorCallback,
35820                    complete: completeCallback,
35821                    async: options.async
35822                };
35823
35824            
35825            
35826            urlSuffix = [
35827                "/templateId-" + that.templateId,
35828                "/fetchJSON-" + (skipJsonEmbedding ? "false" : "true"),
35829                "/fetchHTML-true",
35830                ".json"  
35831            ].join("");
35832            
35833            lazyOptions = _.extend({
35834                path: externalizedPath + urlSuffix
35835            }, commonCallbacks);
35836
35837            window.guideBridge.panelProvider.getHtmlJson(lazyOptions);
35838
35839            function fetchCallback(jsonHtml) {
35840                var uniquePrefix;
35841                
35842                
35843                
35844                if (that.repeatable || that._ancestorRepeatable) {
35845                    uniquePrefix = that.guideUtil.generateUID();
35846                }
35847                if (guidelib.util.GuideUtil._embedHtml(that, jsonHtml["html"], uniquePrefix)) {
35848                    that._ajaxCallDone = true;
35849
35850                    
35851                    if (!skipJsonEmbedding) {
35852                        
35853                        
35854                        var referredJson = JSON.parse(jsonHtml["json"])["items"];
35855                        that._embedJson(referredJson, uniquePrefix);
35856                        
35857                        var guideDirtyMarkerAndVisitor = that._guide().internal.GuideDirtyMarkerAndVisitor;
35858                        
35859                        if (!that.repeatable) {
35860                            guideDirtyMarkerAndVisitor._updateCountOrInsert(guideDirtyMarkerAndVisitor.visitMap, that.templateId);
35861                        }
35862                        
35863                        that._guide().internal.liveDataUtils.playLiveData(that);
35864                        
35865                        that.prepare();
35866                    }
35867                    
35868                    
35869                    that._postProcessLazyLoad(options);
35870                }
35871            }
35872
35873            function errorCallback() {
35874                var errorMessage = skipJsonEmbedding ? "Failed to fetch HTML for :" : "Failed to fetch HTML and JSON for :";
35875                that.logger().error("AF", errorMessage + externalizedPath);
35876            }
35877
35878            function completeCallback() {
35879                if (options && _.isFunction(options.postFetch)) {
35880                    options.postFetch.call(this);
35881                }
35882            }
35883
35884        },
35885
35886        
35887        _postProcessLazyLoad : function (options) {
35888            
35889            this._itemsLoaded = true;
35890            this._guide().trigger(guidelib.event.GuideModelEvent.LAZY_LOADED);
35891            
35892            this._triggerOnBridge("elementLazyLoaded", this);
35893            
35894            
35895            if (options && _.isFunction(options.success)) {
35896                options.success.call(this);
35897            }
35898            
35899            
35900            
35901        },
35902
35903        
35904        _unloadLazyReferenceModel : function (muteValidation) {
35905            try {
35906                if (this._lazyReference) {
35907                    window.guideBridge._populateBindRefToSomMap(this);
35908                    if (!muteValidation) {
35909                        var validationStatus = this.validate(),
35910                            visitMap = this._guide().internal.GuideDirtyMarkerAndVisitor.visitMap;
35911                        if (validationStatus === false && visitMap[this.id] > 0) {
35912                            visitMap[this.id] = 0;
35913                        }
35914                    }
35915                    
35916                    
35917                    _.each(this.children, function (child) {
35918                        child._unloadModel(muteValidation);
35919                        var nIndex = this._children.indexOf(child);
35920                        
35921                        this._children.splice(nIndex, 1);
35922                        var childKey = null;
35923                        
35924                        _.each(this.jsonModel.items, function (value, key) {
35925                            if (value === child.jsonModel) {
35926                                childKey = key;
35927                            }
35928                        }, this);
35929                        if (childKey) {
35930                            delete this.jsonModel.items[childKey];
35931                        }
35932                        
35933                        this._normalizeChildren();
35934                    }, this);
35935                    
35936                    this._navigationContext = null;
35937                    this._currentItem = null;
35938                }
35939            } catch (exception) {
35940                this.logger().error(exception);
35941            }
35942
35943        },
35944        
35945        _unloadModel : function (muteValidation) {
35946            var visitMap = this._guide().internal.GuideDirtyMarkerAndVisitor.visitMap;
35947            _.each(this.children, function (child) {
35948                if (this._lazyReference && !muteValidation) {
35949                    var validationStatus = child.validate();
35950                    if (validationStatus === false) {
35951                        if (!_.isUndefined(visitMap[this.templateId])) {
35952                            visitMap[this.templateId] = 0;
35953                        }
35954                    }
35955                }
35956                child._unloadModel(muteValidation);
35957            }, this);
35958            guidelib.model.Scriptable.prototype._unloadModel.call(this);
35959        },
35960
35961        _removeChild : function (oChild) {
35962            oChild._unloadModel();
35963            var nIndex = this._children.indexOf(oChild);
35964            this._children.splice(nIndex, 1);
35965            var childKey = null;
35966            _.each(this.jsonModel.items, function (value, key) {
35967                if (value === oChild.jsonModel) {
35968                    childKey = key;
35969                }
35970            }, this);
35971            if (childKey) {
35972                delete this.jsonModel.items[childKey];
35973            }
35974            this._normalizeChildren();
35975            this._triggerEvent(guidelib.event.GuideModelEvent.CHILD_CHANGED, "childRemoved", oChild, null);
35976        },
35977
35978        
35979        _embedJson : function (referredJson, uniquePrefix) {
35980            
35981            var bIsSuccess = false;
35982            var clonedJson = JSON.parse(JSON.stringify(referredJson)),
35983                currentPanelId = this.id,
35984                referredPanelRoot = null,
35985                referredPanelRootName = null,
35986                bindRefPrefix = this.jsonModel.bindRef;
35987            
35988            currentPanelId = currentPanelId.slice(0, -2);
35989            if (referredJson) {
35990                
35991                if (this.repeatable || this._ancestorRepeatable) {
35992                    this.copyObject(referredJson, clonedJson,
35993                        {
35994                            transformMaps : {
35995                                "id" : function (srcValue, options, parentObj) {
35996                                    return uniquePrefix + "__" + parentObj.templateId;
35997                                }
35998                            }
35999                        }
36000                    );
36001                }
36002                
36003                
36004                _.each(clonedJson, function (panelJson, panelName) {
36005                    if (_.isObject(panelJson)) {
36006                        bIsSuccess = true;
36007                        
36008                        this.jsonModel.items = this.jsonModel.items || {};
36009                        this.jsonModel.items[panelName] = panelJson;
36010                        
36011                        this._guide()._modelTemplateCacheStore._putTemplate(JSON.parse(JSON.stringify(panelJson)));
36012                    }
36013                }, this);
36014                
36015                this._embedModel();
36016
36017            }
36018            if (bIsSuccess === true) {
36019                
36020            }
36021            return bIsSuccess;
36022        },
36023
36024        
36025        _embedModel : function () {
36026            
36027            this._initChildren(true);
36028            
36029            
36030            this._guide()._modelTemplateCacheStore.putModel(this);
36031            
36032            this._postInitialize();
36033            
36034            this._normalizeChildren();
36035        },
36036
36037        _getItemsInsertIndex : function (childIndex) {
36038            var itemIndex = 0;
36039            _.find(this._children, function (child, index) {
36040                if (child._isItem) {
36041                    itemIndex++;
36042                }
36043                if (index >= childIndex) {
36044                    return true; 
36045                }
36046            }, this);
36047            return itemIndex;
36048        },
36049
36050        playJson : function (pJsonModel, attachments) {
36051            var playNonPanelItems = {};
36052            var playPanelItems = {};
36053            _.each(pJsonModel.items, function (item) {
36054                if (_.isObject(item)) {
36055                    
36056                    if (item.guideNodeClass === "guidePanel" || item.guideNodeClass === "guideTable" || item.guideNodeClass === "guideTableRow") {
36057                        if (playPanelItems[item.name]) {
36058                            playPanelItems[item.name].push(item);
36059                        } else {
36060                            playPanelItems[item.name] = [item];
36061                        }
36062                    } else {
36063                        if (playNonPanelItems[item.name]) {
36064                            playNonPanelItems[item.name].push(item);
36065                        } else {
36066                            playNonPanelItems[item.name] = [item];
36067                        }
36068                    }
36069                }
36070            }, this);
36071
36072            
36073            var panelIMs = _.filter(this._children, function (child) {
36074                return child instanceof guidelib.model.GuideInstanceManager;
36075            }, this);
36076
36077            _.each(panelIMs, function (instanceManager) {
36078                var panelName = instanceManager._getInstanceName();
36079                var newPanelItems = playPanelItems[panelName] || []; 
36080                var panelInstances = instanceManager._instances.slice(0);
36081                _.each(panelInstances, function (panelInstance, index) {
36082                    if (newPanelItems.length > 0) {
36083                        var panelJson = newPanelItems.shift();
36084                        panelInstance.playJson(panelJson, attachments);
36085                    } else {
36086                        instanceManager.removeInstance(index);
36087                    }
36088                }, this);
36089                if (newPanelItems.length > 0) {
36090                    _.each(newPanelItems, function (paneljson) {
36091                        var addedInstance = instanceManager.addInstance();
36092                        if (addedInstance) {
36093                            addedInstance.playJson(paneljson, attachments);
36094                        }
36095                    }, this);
36096                }
36097            }, this);
36098
36099            
36100            _.each(this.items, function (child) {
36101                if (!(child instanceof guidelib.model.GuidePanel)) {
36102                    var nonPanelItemName = child.name;
36103                    var nonPanelItem = playNonPanelItems[nonPanelItemName];
36104                    if (nonPanelItem && nonPanelItem.length > 0) {
36105                        child.playJson(nonPanelItem.shift(), attachments);
36106                    }
36107                }
36108            }, this);
36109
36110            
36111            if (this.toolbar) {
36112                this.toolbar.playJson(pJsonModel.toolbar, attachments);
36113            }
36114        },
36115        
36116        _getReducedJSON : function (isParentRepeatable) {
36117            var reducedJSONChildren,
36118                isRepeatable;
36119            isRepeatable = isParentRepeatable || this.canBeRepeatable;
36120            reducedJSONChildren = GuidePanel._super._getReducedJSON.call(this, isRepeatable);
36121            
36122            
36123            if (this.jsonModel.toolbar) {
36124                reducedJSONChildren["toolbar"] = this.toolbar._getReducedJSON();
36125            }
36126            return reducedJSONChildren;
36127        },
36128
36129        _getRole : function () {
36130            var guideRole, xfaRole, roleMap;
36131            
36132            roleMap = {
36133                "Table" : "grid",
36134                "Header Row" : "rowHeader",
36135                "Body Row" : "rowGroup",
36136                "Footer Row" : "rowGroup",
36137                "List" : "list"
36138            };
36139            if (this.bindNode) {
36140                xfaRole = this.getOrElse(this.bindNode.assist && this.bindNode.assist.role, null);
36141                if (xfaRole) {
36142                    guideRole = roleMap[xfaRole];
36143                }
36144            }
36145            return guideRole;
36146        },
36147        _getAssistPriority : function () {
36148            return (this.getAttribute("assistPriority") || "description");
36149        },
36150
36151        _getScreenReaderText : function () {
36152            var screenReaderText, assistPriority = this._getAssistPriority();
36153            if (assistPriority !== "description") {
36154                screenReaderText = GuidePanel._super._getScreenReaderText.apply(this);
36155            }
36156            return screenReaderText;
36157        },
36158
36159        execCompletion : function () {
36160            var complete = true;
36161            _.find(this.children, function (childModel) {
36162                
36163                if (childModel instanceof guidelib.model.GuidePanel && !childModel.execCompletion()) {
36164                    complete = false;
36165                    return true;    
36166                }
36167            }, this);
36168            if (complete && this.completionExp) {
36169                complete = this.executeExpression("completionExp");
36170            }
36171            return complete;
36172        },
36173
36174        _preserveLazyValue : function () {
36175            return !this._isXfaNode() && !(this instanceof guidelib.model.RootPanelNode)
36176                && (this.canBeRepeatable || this._guide().internal.liveDataUtils.isIndexedPath(this.bindRef));
36177        },
36178
36179        
36180        _syncModelAndData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar, updateInstances, recurse) {
36181            var dataUtils = this._guide().internal.liveDataUtils;
36182            if (this._preserveLazyValue()) {
36183
36184                var dataContext = dataUtils._getDataContext(this, bound_indexedXpathSoFar, unBound_indexedXpathSoFar),
36185                    indexedXpath = dataContext.indexedXpath;
36186
36187                if (this.canBeRepeatable) {
36188                    
36189                    if (_.isFunction(updateInstances) && this.instanceIndex === 0) {
36190                        updateInstances(dataUtils.getDataInstances(dataContext, this._getDataNodeName()),
36191                            dataUtils.getParentDataNode(dataContext));
36192                    }
36193                    indexedXpath = dataUtils.addIndexToPath(indexedXpath, this.instanceIndex);
36194                }
36195
36196                
36197                if (dataContext.xmlSec === dataUtils.constants.UNBOUND_TAG) {
36198                    unBound_indexedXpathSoFar = indexedXpath;
36199                } else if (dataContext.xmlSec === dataUtils.constants.BOUND_TAG) {
36200                    bound_indexedXpathSoFar = indexedXpath;
36201                }
36202            }
36203
36204            if (_.isString(recurse)) {
36205                
36206                _.each(this.items, function (item) {
36207                    if (_.isFunction(item[recurse])) {
36208                        item[recurse](bound_indexedXpathSoFar, unBound_indexedXpathSoFar);
36209                    }
36210                });
36211            }
36212
36213            return {
36214                'bound' : bound_indexedXpathSoFar,
36215                'unBound' : unBound_indexedXpathSoFar
36216            };
36217        },
36218
36219        _getDataNodeName : function () {
36220            var bindRef = this.bindRef,
36221                dataNodeName;
36222            if (bindRef) {
36223                dataNodeName = bindRef.substring(bindRef.lastIndexOf("/") + 1);
36224            } else {
36225                
36226                dataNodeName = this.getAttribute("name");
36227            }
36228            return dataNodeName;
36229        },
36230
36231        _updateLiveData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar) {
36232            var dataUtils = this._guide().internal.liveDataUtils,
36233                that = this;
36234
36235            function updateDataInstances(dataNodes, parentNode) {
36236                var count = that.instanceManager.instanceCount;
36237                if (dataNodes && (dataNodes.length > count)) {
36238                    
36239                    
36240                    for (var i = dataNodes.length -1; i >= count; --i) {
36241                        dataUtils.removeChild(parentNode, that._getDataNodeName(), i);
36242                    }
36243                }
36244            }
36245
36246            var contextSoFar = this._syncModelAndData(bound_indexedXpathSoFar, unBound_indexedXpathSoFar, updateDataInstances, '_updateLiveData');
36247        },
36248
36249        _playLiveData : function (bound_indexedXpathSoFar, unBound_indexedXpathSoFar) {
36250            var parentArgs = arguments,
36251                that = this;
36252
36253            function updateModelInstances(dataNodes, parentNode) {
36254                var _dataNodes = dataNodes;
36255                if (_dataNodes == null) {
36256                    _dataNodes = []; 
36257                }
36258                
36259                var i;
36260                if (_dataNodes && (_dataNodes.length < that.instanceManager.instanceCount)) {
36261                    
36262                    for (i = Math.max(_dataNodes.length, Math.abs(that.minOccur)); i < that.instanceManager.instanceCount; ++i) {
36263                        that.instanceManager.removeInstance(i);
36264                    }
36265                } else if (_dataNodes && (_dataNodes.length > that.instanceManager.instanceCount)) {
36266                    
36267                    var totalInstances = that.maxOccur < 0 ? _dataNodes.length : Math.min(_dataNodes.length, that.maxOccur);
36268                    for (i = that.instanceManager.instanceCount; i < totalInstances; ++i) {
36269                        var addedInstance = that.instanceManager.addInstance();
36270                        if (addedInstance) {
36271                            that._playLiveData.apply(addedInstance, parentArgs);
36272                        }
36273                    }
36274                }
36275            }
36276
36277            this._syncModelAndData(bound_indexedXpathSoFar, unBound_indexedXpathSoFar, updateModelInstances, '_playLiveData');
36278        }
36279    });
36280
36281    GuidePanel.defineProps({
36282        
36283        completionExp : {
36284            get : function () {
36285                return this.getAttribute("completionExp");
36286            }
36287        },
36288
36289        completionExpReq : {
36290            get : function () {
36291                return this.getAttribute("completionExpReq");
36292            }
36293        },
36294
36295        
36296        minOccur : {
36297            get : function () {
36298                return this.getOrElse(this.jsonModel.minOccur, 1);
36299            }
36300        },
36301
36302        
36303        maxOccur : {
36304            get : function () {
36305                return this.getOrElse(this.jsonModel.maxOccur, 1);
36306            }
36307        },
36308        initialOccur : {
36309            get : function () {
36310                return this.getOrElse(this.jsonModel.initialOccur, 1);
36311            }
36312        },
36313        
36314        repeatable : {
36315            get : function () {
36316                return (this.minOccur != 1 || this.maxOccur != 1);
36317            }
36318        },
36319
36320        
36321        canBeRepeatable : {
36322            get : function () {
36323                return (this.maxOccur < 0 || this.maxOccur > 1);
36324            }
36325        },
36326        
36327        panel : {
36328            get : function () {
36329                return this;
36330            }
36331        },
36332        toolbar : {
36333            get : function () {
36334                this.getElement("guideToolbar");
36335            }
36336        },
36337        
36338        instanceManager : {
36339            get : function () {
36340                return this._instanceManager;
36341            }
36342        },
36343
36344        
36345        instanceIndex : {
36346            get : function () {
36347                var context = this._guide()._currentContext;
36348                if (context && context.managedExp) {
36349                    this._addDependant(context.contextNode, context.expression);
36350                }
36351                return this.instanceManager._instances.indexOf(this);
36352            }
36353        },
36354        
36355        title : {
36356            get : function () {
36357                return this.jsonModel["jcr:title"];
36358            },
36359            set : function (value) {
36360                var oldTitle = this.title;
36361                if (oldTitle !== value) {
36362                    this.jsonModel["jcr:title"] = value;
36363                    this.trigger(guidelib.event.GuideModelEvent.MODEL_CHANGED,
36364                        guidelib.event.GuideModelEvent.createEvent(
36365                            guidelib.event.GuideModelEvent.MODEL_CHANGED,
36366                            this,
36367                            "title",
36368                            oldTitle,
36369                            value
36370                        )
36371                    );
36372                }
36373            }
36374        },
36375        
36376        summary : {
36377            get : function () {
36378                return this._summary;
36379            },
36380            set : function (value) {
36381                var oldSummary = this._summary;
36382                if (oldSummary !== value) {
36383                    this._summary = value;
36384                    this.trigger(guidelib.event.GuideModelEvent.MODEL_CHANGED,
36385                        guidelib.event.GuideModelEvent.createEvent(
36386                            guidelib.event.GuideModelEvent.MODEL_CHANGED,
36387                            this,
36388                            "summary",
36389                            oldSummary,
36390                            this._summary
36391                        )
36392                    );
36393                }
36394            }
36395        },
36396        enableLayoutOptimization : {
36397            get : function () {
36398                return this.getOrElse(this.jsonModel, "layout.enableLayoutOptimization", false);
36399            }
36400        },
36401
36402        
36403        isNavigable : {
36404            get : function () {
36405                var isNonNavigable = this.getOrElse(this.jsonModel, "layout.nonNavigable", false);
36406                
36407                
36408                if (typeof isNonNavigable === 'string') {
36409                    return !(isNonNavigable === "true");
36410                } else {
36411                    return !isNonNavigable;
36412                }
36413            }
36414        },
36415        
36416        _hopsToRootPanel : {
36417            get : function () {
36418                return guidelib.util.GuideUtil._countHopsToRootPanel(this);
36419            }
36420
36421        },
36422        
36423        _ancestorRepeatable : {
36424            get : function () {
36425                var parentOrAncestor = this.parent;
36426                while (parentOrAncestor) {
36427                    if (parentOrAncestor && parentOrAncestor.repeatable) {
36428                        return true;
36429                    }
36430                    parentOrAncestor = parentOrAncestor.parent;
36431                }
36432
36433                return false;
36434            }
36435        },
36436
36437        
36438        enabled : {
36439            get : function () {
36440                return guidelib.model.Scriptable.prototype._getEnabled.call(this);
36441            },
36442
36443            set : function (value) {
36444                var oldValue = this.enabled;
36445                guidelib.model.Scriptable.prototype._setEnabled.call(this, value);
36446                if (this._parentAccess && value != oldValue) {
36447                    this._changeContainerAccess(value);
36448                }
36449            }
36450        },
36451
36452        
36453        _hasLazyDescendant : {
36454            get : function () {
36455                if (!_.isEmpty(guideBridge._guide.allLazyChildren)) {
36456                    return true;  
36457                }
36458                return false;
36459            }
36460        }
36461    });
36462
36463    
36464    GuidePanel.addMixins([
36465        guidelib.model.mixin.AddNavigationContext,
36466        guidelib.model.mixin.AddDependencyMgmt
36467    ]);
36468
36469})(_, guidelib);
36470
36471(function (_, guidelib) {
36472    var GuideTableRow = guidelib.model.GuideTableRow = guidelib.model.GuidePanel.extend({
36473        msClassName : "guideTableRow"
36474    });
36475}(_, guidelib));
36476(function (_, guidelib) {
36477
36478    
36479    var GuideTable = guidelib.model.GuideTable = guidelib.model.GuidePanel.extend({
36480        msClassName : "guideTable"
36481    });
36482
36483    GuideTable.defineProps({
36484        
36485        mobileLayout : {
36486            get : function () {
36487                return this.jsonModel.layout.mobileLayout;
36488            }
36489        },
36490
36491        columnWidth : {
36492            get : function () {
36493                return this.jsonModel.columnWidth;
36494            }
36495        }
36496    });
36497})(_, guidelib);
36498
36499(function (_, guidelib) {
36500    var RootPanelNode = guidelib.model.RootPanelNode = guidelib.model.GuidePanel.extend({
36501        msClassName : "rootPanelNode",
36502        
36503        _clearInactiveLazyViews : function (panelView) {
36504            _.each(this.childViews, function (item) {
36505                item._clearInactiveLazyViews(panelView);
36506            });
36507        }
36508
36509    });
36510    RootPanelNode.defineProps({
36511        toolbar : {
36512            get : function () {
36513                
36514                return this.getElement("guideToolbar") || this.parent.toolbar;
36515            }
36516        }
36517    });
36518})(_, guidelib);
36519(function ($, guidelib, _) {
36520    function negate(predicateFunc) {
36521        return function () {
36522            return !predicateFunc.apply(this, arguments);
36523        };
36524    }
36525
36526    function getPredicate(condition) {
36527        return condition instanceof Array
36528            ? Array.prototype.includes.bind(condition)
36529            : condition;
36530    }
36531
36532    var CommonUtils = {
36533        
36534        
36535        returnMinimalJSON : function (whitelistedProperties, reducedJsonObject, that) {
36536            if (!_.isObject(reducedJsonObject)) {
36537                reducedJsonObject = {};
36538            }
36539            _.each(whitelistedProperties, function (whitelistedProperty) {
36540                if (!_.isUndefined(that.jsonModel[whitelistedProperty])) {
36541                    reducedJsonObject[whitelistedProperty] = that.jsonModel[whitelistedProperty] ;
36542
36543                } else if (!_.isUndefined(that[whitelistedProperty])) {
36544                    reducedJsonObject[whitelistedProperty] = that[whitelistedProperty];
36545                }
36546            });
36547        },
36548
36549        createMap : function (list, value) {
36550            return _.mapObject(_.object(list, []), function () {
36551                return value;
36552            });
36553        },
36554
36555        updatedMapIfNot : function (map, condition, value) {
36556            return this._updateMap(map, negate(getPredicate(condition)), value);
36557        },
36558
36559        updateMap : function (map, condition, value) {
36560            return this._updateMap(map, getPredicate(condition), value);
36561        },
36562
36563        _updateMap : function (map, condition, value) {
36564            var newMap = {},
36565                prop;
36566            for (prop in map) {
36567                if (map.hasOwnProperty(prop)) {
36568                    newMap[prop] = condition(prop) ? value : map[prop];
36569                }
36570            }
36571            return newMap;
36572        },
36573
36574        _getScope : function (context) {
36575            var mergedScope = Object.assign(guidelib.runtime, context._guide().runtime);
36576            return mergedScope;
36577        }
36578    };
36579
36580    guidelib.model.util.CommonUtils = CommonUtils;
36581}($, guidelib, _));
36582(function (_, $, guidelib) {
36583    var getOrElse = xfalib.ut.XfaUtil.prototype.getOrElse,
36584        commonUtils = guidelib.model.util.CommonUtils,
36585        logger,
36586        constants = guidelib.model.GuideSchema.prototype.GuideStateConstants;
36587
36588    var initializeLogger = function (isXfaForm) {
36589        var configString = window.AF_log_config === undefined ? "0-a9"
36590            : "1-" + window.AF_log_config;
36591
36592        xfalib.ut.XfaUtil.prototype.registerLocaleProperties(guidelib.i18n);
36593        if (isXfaForm && window.formBridge) {
36594            window.formBridge.registerConfig("contextPath", window.guideBridge.userConfig["contextPath"]);
36595            window.formBridge.registerConfig("LoggerConfig", {
36596                "logConfigString" : configString,
36597                "categoryAcronyms" : {"d" : "AF"}
36598            });
36599        } else {
36600            xfalib.ut.XfaUtil.prototype.logger = new xfalib.ut.Logger({
36601                "jsonModel" : {
36602                    "logConfigString" : configString,
36603                    "categoryAcronyms" : {"d" : "AF"}
36604                }
36605            });
36606            logger = xfalib.ut.XfaUtil.prototype.logger;
36607        }
36608    };
36609
36610    var utils = {
36611        triggerEventOnWindow : function (eventPayload) {
36612            $(window).trigger(eventPayload);
36613        },
36614
36615        postExternalMessage : function (name) {
36616            window.guideBridge._postExternalMessage({name : name});
36617        }
36618    };
36619
36620    var viewOnlyUtils = {
36621        createView : function (guide, $element) {
36622            utils.postExternalMessage("_layoutstart");
36623
36624            var guideContainerView = new guidelib.view.GuideContainerView({
36625                element : $element,
36626                model : guide
36627            });
36628            
36629            
36630            window.guideBridge._setGuideView(guideContainerView);
36631            guidelib.util.GuideUtil.initializeHelp();
36632
36633            
36634            guidelib.util.AdUtil.applyDescriptionPlugin();
36635
36636            utils.postExternalMessage("_layoutend");
36637
36638            $(window).on("mousedown.guidebridge", function () {
36639                window.guideBridge.clickedOnWindow = true;
36640            });
36641        },
36642
36643        getLastFocusItem : function (guide) {
36644            var lastFocusItem;
36645            if (guide.runtime.guideContext) {
36646                lastFocusItem = guidelib.util.GuideUtil.fetchXMLNodeValue(guide.runtime.guideContext.guidePrefillXml, "lastFocusItem");
36647            }
36648            
36649            if (_.isUndefined(lastFocusItem)) {
36650                lastFocusItem = guidelib.util.GuideUtil._fetchJSONNodeValue(guide.runtime.guideContext.guidePrefillJson, "afSubmissionInfo.lastFocusItem");
36651            }
36652            
36653            if (_.isUndefined(lastFocusItem)) {
36654                lastFocusItem = window.guideBridge.customContextProperty("lastFocusItem");
36655            }
36656            return lastFocusItem;
36657        },
36658
36659        setFocus : function (item) {
36660            if (item) {
36661                window.guideBridge.setFocus(item);
36662            } else {
36663                window.guideBridge.setFocus();
36664            }
36665        },
36666
36667        preventCheckBoxMovementOnClick : function () {
36668            
36669            
36670            
36671
36672            if (xfalib.ut.XfaUtil.prototype.isSafari() && !xfalib.ut.TouchUtil.TOUCH_ENABLED) {
36673                $('#guideContainerForm').addClass('macSafariForm');
36674            }
36675        },
36676
36677        disableDefaultSubmit : function () {
36678            
36679            
36680            $("#guideContainerForm").submit(function (evnt) {
36681                evnt.preventDefault();
36682            });
36683        },
36684
36685        preventFormSubmitOnEnter : function () {
36686            
36687            
36688            $("#guideContainerForm input").keypress(function (evnt) {
36689                if (evnt.keyCode == 13 || evnt.charCode == 13 || evnt.which == 13) {
36690                    evnt.preventDefault();
36691                }
36692            });
36693        },
36694
36695        renderView : function (guide, $guideElement) {
36696            viewOnlyUtils.createView(guide, $guideElement);
36697
36698            var lastFocusItem = viewOnlyUtils.getLastFocusItem(guide);
36699            viewOnlyUtils.setFocus(lastFocusItem);
36700            utils.triggerEventOnWindow({type : "guideInitialized", guide : guide});
36701
36702            viewOnlyUtils.preventCheckBoxMovementOnClick();
36703            viewOnlyUtils.disableDefaultSubmit();
36704            viewOnlyUtils.preventFormSubmitOnEnter();
36705        }
36706
36707    };
36708
36709    
36710    guidelib.model._createXfaAndGuideModel = function (guideJson, xfaJson, options) {
36711        if (xfaJson) {
36712            xfalib.script.XfaModelRegistry.prototype.createModel(xfaJson);
36713            
36714            new xfalib.acrobat.Acrobat();
36715        }
36716        var guide = {};
36717        guide = guidelib.model.GuideModelRegistry.prototype.createModel(guideJson, options);
36718        
36719        guide._bindRefMap = {};
36720        return guide;
36721
36722    };
36723
36724    
36725    guidelib.model._getGuideJsonWithSyncXfaProps = function (guideJson, xfaJson) {
36726        
36727        var guide = guidelib.model._createXfaAndGuideModel(guideJson, xfaJson);
36728        
36729        guide.syncXFAProps();
36730
36731        
36732        return {
36733            "guidejson" : JSON.stringify(guideJson),
36734            "xfajson" : JSON.stringify(xfaJson)
36735        };
36736    };
36737
36738    guidelib.model._prepareGuide = function (prefillData, guide) {
36739        var liveDataUtils = guide.internal.liveDataUtils,
36740            liveModel = guide.internal.liveModel,
36741            _getFileAttachmentWrappers = function(prefillDataAttachments) {
36742                var fileAttachmentWrappers = [];
36743                try {
36744                    var atts = JSON.parse(prefillDataAttachments);
36745                    fileAttachmentWrappers = atts.map(function (x) {
36746                        return new guidelib.model.FileAttachmentWrapper(JSON.parse(x))
36747                    });
36748                } catch (e) {
36749                    if (e.stack) {
36750                        guide.logger().error(e.stack);
36751                    }
36752                }
36753                return fileAttachmentWrappers;
36754            };
36755        
36756        if (prefillData.isMergedJson && prefillData.data) {
36757            
36758            if (prefillData.data.guideState && prefillData.data.guideState.attachments) {
36759                prefillData.data["attachments"] = _getFileAttachmentWrappers(prefillData.data.guideState.attachments);
36760            }
36761            window.guideBridge.restoreGuideState(prefillData.data);
36762        } else if (prefillData.data) {
36763            guide.setGuideState(constants.GUIDE_STATE_MERGE_PROGRESS);
36764            liveDataUtils.initLiveData(prefillData.data,
36765                null,
36766                _.isString(guide.xdpRef),
36767                _.isString(guide.xsdRef),
36768                guide.getAttribute("xsdRootElement"),
36769                _getFileAttachmentWrappers(prefillData.attachments));
36770            liveDataUtils.playLiveData(guide.rootPanel);
36771            liveModel.prefillCrossFragFields(guide);
36772            guide.setGuideState(constants.GUIDE_STATE_MERGE_COMPLETE);
36773            guide.prepare();
36774        } else {
36775            guide.prepare();
36776            liveDataUtils.initLiveData(null, null,
36777                _.isString(guide.xdpRef), _.isString(guide.xsdRef),
36778                guide.getAttribute("xsdRootElement"));
36779        }
36780
36781        var fileAttachmentMap,
36782            obj = guideBridge.customContextProperty("fileAttachmentMap");
36783        if (!_.isUndefined(obj) && typeof(obj) === "string") {
36784            try {
36785                obj = JSON.parse(obj);
36786            } catch (e) {
36787                if (e.stack) {
36788                    guide.logger().error(e.stack);
36789                }
36790                obj = undefined;
36791            }
36792        }
36793        fileAttachmentMap = obj;
36794        
36795        var  i, node, fieldValue,
36796            fileAttachmentsList = window.guideBridge._getFileAttachmentsList();
36797        
36798        
36799        if (!_.isUndefined(fileAttachmentMap)) {
36800            for (i = 0; i < fileAttachmentsList.length; i++) {
36801                node = fileAttachmentsList[i];
36802                fieldValue = fileAttachmentMap[node.somExpression];
36803                node.fileAttachment.value = fieldValue;
36804                if (!_.isEmpty(fieldValue)) {
36805                    node._fileList = fieldValue.split("\n");
36806                }
36807            }
36808        }
36809        guide.setGuideState(constants.GUIDE_STATE_MODEL_COMPLETE);
36810    };
36811
36812    guidelib.model.markDirtyPanels = function (lazyChildren, dataString, dirtyPanels, guide) {
36813        var lazyChildrenMap = commonUtils.createMap(lazyChildren, 0);
36814        
36815        if (!_.isEmpty(dataString)) { 
36816            if (dirtyPanels === null || dirtyPanels.length === 0) {
36817                dirtyPanels = guide.internal.liveDataUtils.getListOfDirtyPanels(dataString);
36818            }
36819            if (dirtyPanels && dirtyPanels.length > 0) {
36820                lazyChildrenMap = commonUtils.updatedMapIfNot(lazyChildrenMap, dirtyPanels, 1);
36821                guide.internal.GuideDirtyMarkerAndVisitor.visitMap = lazyChildrenMap;
36822            }
36823        } else {
36824            guide.internal.GuideDirtyMarkerAndVisitor.visitMap = lazyChildrenMap;
36825        }
36826    };
36827
36828    guidelib.model.initializeLiveDataUtils = function (schemaType) {
36829        var liveDataUtils = null;
36830        if (schemaType === "formdatamodel" || schemaType === "jsonschema") {
36831            liveDataUtils = new guidelib.model.LiveJsonUtils();
36832        } else {
36833            liveDataUtils = new guidelib.model.LiveXmlUtils();
36834        }
36835        return liveDataUtils;
36836    };
36837
36838    guidelib.model.prepareInput = function (guideJsonData) {
36839        return {
36840            guideJson : JSON.parse(guideJsonData.guidejson || "null"),
36841            guideContext : JSON.parse(guideJsonData.guidecontext || "null"),
36842            guidemergedjson : JSON.parse(guideJsonData.guidemergedjson || "null"),
36843            xfaJson : JSON.parse(guideJsonData.xfajson || "null"),
36844            xfaRenderContext : JSON.parse(guideJsonData.xfarendercontext || "null")
36845        };
36846    };
36847
36848    guidelib.model.mergeData = function (prefillData, guide, guideContext) {
36849        var rawData = prefillData.data,
36850            liveDataUtils = guide.internal.liveDataUtils,
36851            dirtyPanels = [],
36852            customPropertyMap = {},
36853            mergedXfaRenderContext = null;
36854
36855        guide.runtime.guideContext = guide.runtime.guideContext || {};
36856
36857        if (prefillData.isMergedJson) {
36858            if (typeof prefillData.data === "string") {
36859                try {
36860                    prefillData.data = JSON.parse(prefillData.data);
36861                } catch (e) {
36862                    prefillData.data = "";
36863                }
36864            }
36865            rawData = getOrElse(prefillData.data,
36866                "guideState.guideLiveData",
36867                getOrElse(rawData,
36868                    "guideState.guidePrefillXml",
36869                    getOrElse(prefillData.data,
36870                        "guideState.guidePrefillJson", undefined)));
36871
36872            var dirtyPanelsStr = getOrElse(prefillData.data,
36873                "guideState.guideContext.afSubmissionInfo.afDraft", "")
36874                .replace(/\"/g, "");
36875            
36876            if (dirtyPanelsStr) {
36877                dirtyPanels = dirtyPanelsStr.split(",");
36878            }
36879            customPropertyMap = getOrElse(prefillData.data,
36880                "guideState.guideContext.customPropertyMap",
36881                {});
36882
36883            var ccpMapViaNewPrefillService = getOrElse(prefillData.data, "guideState.customContext", null);
36884            var ccpMapViaOldImplementation = getOrElse(guidelib, "__runtime__.guideContext.customPropertyMap", {});
36885            var ccpMapViaOldAndNewImplementation = _.extend({}, ccpMapViaOldImplementation, getOrElse(guide, "runtime.guideContext.customPropertyMap", {}));
36886            if (!_.isEmpty(ccpMapViaNewPrefillService) && _.isEmpty(ccpMapViaOldAndNewImplementation)) {
36887                guideBridge.customContextProperty(ccpMapViaNewPrefillService);
36888            }
36889
36890            var fileMapViaNewPrefillService = getOrElse(prefillData.data, "guideState.fileAttachmentMap", null);
36891            var fileMapViaOldImplementation = guideBridge.customContextProperty("fileAttachmentMap");
36892            if (!_.isEmpty(fileMapViaNewPrefillService) && _.isEmpty(fileMapViaOldImplementation)) {
36893                guideBridge.customContextProperty("fileAttachmentMap", fileMapViaNewPrefillService);
36894            }
36895        } else {
36896            customPropertyMap = prefillData.customContext || {};
36897            guideBridge.customContextProperty("fileAttachmentMap", prefillData.fileAttachmentMap);
36898            guideBridge.customContextProperty("fileAttachmentWrappers", prefillData.fileAttachmentWrappers);
36899        }
36900
36901        if (guide.xdpRef) {
36902            mergedXfaRenderContext = getOrElse(prefillData.data, "guideState.xfaState.xfaRenderContext", null);
36903
36904            if (mergedXfaRenderContext != null) {
36905                
36906                xfalib.runtime.renderContext = JSON.parse(mergedXfaRenderContext);
36907            }
36908
36909            xfalib.runtime.xfa.form._initialize(true);
36910            $(window).trigger("XfaInitialized");
36911        }
36912
36913        if (rawData !== "") {
36914            if (guideContext.schemaType === "formdatamodel" || guideContext.schemaType === "jsonschema") {
36915                guideContext.guidePrefillJson = rawData;
36916            } else {
36917                guideContext.guidePrefillXml = rawData;
36918            }
36919        }
36920
36921        guideContext.customPropertyMap = $.extend({}, guideContext.customPropertyMap, customPropertyMap);
36922
36923        
36924        $.extend(true, guide.runtime.guideContext, guideContext);
36925
36926        guidelib.model.markDirtyPanels(guide.allLazyChildren, rawData, dirtyPanels, guide);
36927
36928        guidelib.model._prepareGuide(prefillData, guide);
36929
36930        
36931        
36932        if (guide.allLazyChildren.length > 0 && guideBridge.customContextProperty("fileAttachmentMap")) {
36933            var fileAttachmentMap = guideBridge.customContextProperty("fileAttachmentMap");
36934            if (typeof fileAttachmentMap === "string") {
36935                fileAttachmentMap = JSON.parse(fileAttachmentMap);
36936            }
36937            guide.internal.liveDataUtils._updateLazyAttachmentMap(fileAttachmentMap);
36938        }
36939    };
36940
36941    guidelib.model.fireOnContainerDomElementReady = function (guideJsonData, fetchData, $htmlElement, localContextCustomPropertyMap) {
36942
36943        var inputData = this.prepareInput(guideJsonData),
36944            guideJson = inputData.guideJson,
36945            guideContext = inputData.guideContext,
36946            guidemergedjson = inputData.guidemergedjson,
36947            xfaJson = inputData.xfaJson,
36948            xfaRenderContext = inputData.xfaRenderContext,
36949            localStorage,
36950            guide,
36951            dataPromise;
36952        initializeLogger(xfaJson != null);
36953        if (guideJson === null || guideContext == null) {
36954            console.error("Unable to load Form. Adaptive Form Json is invalid.");
36955            return;
36956        }
36957
36958        if (window.guideBridge !== undefined) {
36959            localStorage = window.guideBridge._getStorage();
36960        }
36961        try {
36962            
36963            localContextCustomPropertyMap = _.isObject(localContextCustomPropertyMap) ?
36964                JSON.stringify(localContextCustomPropertyMap) : localContextCustomPropertyMap;
36965            localContextCustomPropertyMap = JSON.parse(localContextCustomPropertyMap);
36966        } catch(e) {
36967            localContextCustomPropertyMap = {};
36968        }
36969
36970        if (fetchData && (guidemergedjson === null || guidemergedjson === "" || getOrElse(localStorage, "guideState", null) !== null)) {
36971            if (fetchData instanceof Function) {
36972                var result = fetchData();
36973                if (result.then instanceof Function) {
36974                    dataPromise = result;
36975                } else {
36976                    dataPromise = _.extend({}, {isMergedJson : false}, fetchData());
36977                }
36978            } else {
36979                
36980                
36981                
36982                var originalRequestParams = getOrElse(window.guideBridge, "userConfig.requestParams", {});
36983                if ((guideJson.prefillService !== undefined && guideJson.prefillService !== "none") ||
36984                        (new URLSearchParams(window.location.search)).get("dataRef") !== null ||
36985                        !!originalRequestParams.dataRef) {
36986                    var formContainerPath = getOrElse(window.guideBridge, "userConfig.submitConfig.aemFormComponentPath", guideContext.guidePath);
36987                    var guideUrl = window.guideBridge._getGuidePathUrl(".af.prefilldata.json", formContainerPath);
36988                    dataPromise = this.fetchData(guideUrl + window.location.search, originalRequestParams);
36989                } else {
36990                    dataPromise = {data: "", isMergedJson: false};
36991                }
36992            }
36993        } else {
36994            var _mergeData = guidemergedjson;
36995            if (getOrElse(localStorage, "guideState", null) !== null) {
36996                _mergeData = localStorage;
36997            }
36998            
36999            
37000            dataPromise = {
37001                data : _mergeData,
37002                isMergedJson : true
37003            };
37004        }
37005
37006        
37007        var liveDataUtils = this.initializeLiveDataUtils(guideContext.schemaType),
37008            liveModel = new guidelib.model.LiveModel();
37009
37010        if (window.guideBridge.hostName == "server") {
37011            
37012            if (!FD.isToggleEnabled(guidelib.util.FeatureToggleConstants.FT_BROWSERLESS_SUBMISSION)) {
37013                liveModel._disableFunctions();
37014                liveDataUtils._disableFunctions();
37015            }
37016
37017            _.each(_.functions(viewOnlyUtils), function (funcName) {
37018                viewOnlyUtils[funcName] = function () {};
37019            });
37020
37021            if (window.formBridge) {
37022                
37023                
37024                
37025                window.formBridge.ajaxCallMode = "server";
37026            }
37027        }
37028
37029        liveModel.createDataNodes(guideJson.repeatBindRef);
37030        var allLazyChildren = getOrElse(guideJson, "allLazyChildren", []);
37031        
37032        var options = {};
37033        options = _.extend({}, options, {"liveModel" : liveModel, "liveDataUtils" : liveDataUtils});
37034
37035        utils.postExternalMessage("_formdomstart");
37036        try {
37037            guide = guidelib.model._createXfaAndGuideModel(guideJson, xfaJson, options);
37038            
37039            guide.runtime.guideContext.customPropertyMap = _.extend({}, guide.runtime.guideContext.customPropertyMap, localContextCustomPropertyMap);
37040            
37041            guide.runtime.guideContext.guidePath = guide.jcrPath;
37042            if (allLazyChildren.length > 0) {
37043                liveModel.createCrossFragFields(guideJson.guideGlobalLazyField, guide);
37044            }
37045            guide.version = new guidelib.util.Version({
37046                scriptingBehaviourVersion: guideContext.scriptingBehaviourVersion
37047            });
37048            guide.setGuideState(constants.GUIDE_STATE_MODEL_CREATED);
37049            if (xfaJson && xfaRenderContext) {
37050                xfalib.runtime.renderContext = xfaRenderContext;
37051            }
37052            utils.triggerEventOnWindow({type: "guideModelInitialized", guide: guide});
37053        } catch (e) {
37054            
37055            if (e.stack) {
37056                console.error(e.stack);
37057            }
37058        }
37059
37060        var $guideElement = $htmlElement || $("div.guideContainerWrapperNode");
37061
37062        if (dataPromise.then instanceof Function) {
37063            return dataPromise.then(function (result) {
37064                guidelib.model.mergeData(result, guide, guideContext);
37065                viewOnlyUtils.renderView(guide, $guideElement);
37066            });
37067        } else {
37068            
37069            guidelib.model.mergeData(dataPromise, guide, guideContext);
37070            viewOnlyUtils.renderView(guide, $guideElement);
37071            return guide;
37072        }
37073    };
37074
37075    
37076    guidelib.model.fetchData = function (path, requestParams) {
37077        var deferred = $.Deferred();
37078        if (window.guideBridge.hostName === "server") { 
37079            deferred.resolve({
37080                data : "",
37081                isMergedJson : false
37082            });
37083        } else {
37084            var url = path;
37085            if (requestParams && !$.isEmptyObject(requestParams)) {
37086                var queryStart = url.indexOf('?');
37087                var existingParams = new URLSearchParams(queryStart !== -1 ? url.slice(queryStart + 1) : '');
37088                var extra = {};
37089                $.each(requestParams, function (key, value) {
37090                    if (!existingParams.has(key)) {
37091                        extra[key] = value;
37092                    }
37093                });
37094                if (!$.isEmptyObject(extra)) {
37095                    url += (queryStart !== -1 ? '&' : '?') + $.param(extra);
37096                }
37097            }
37098            $.ajax({
37099                url : url,
37100                type : 'POST',
37101                dataType : 'json'
37102            }).done(function (data) {
37103                var obj = _.extend({}, data, {isMergedJson : false});
37104                deferred.resolve(obj);
37105            }).fail(function (obj, textStatus, errorThrown) {
37106                console.error(textStatus + " " + errorThrown);
37107                deferred.resolve({
37108                    data : "",
37109                    isMergedJson : false
37110                });
37111            });
37112        }
37113        return deferred.promise();
37114    };
37115})(_, $, window.guidelib);
37116
37117(function ($) {
37118    var xfaUtil = xfalib.ut.XfaUtil.prototype;
37119    $.widget("xfaWidget.imageCheckButtonWidget", $.xfaWidget.XfaCheckBox, {
37120
37121        _widgetName : "imageCheckButtonWidget",
37122
37123        getOptionsMap : function () {
37124            var parentOptionsMap = $.xfaWidget.XfaCheckBox.prototype.getOptionsMap.apply(this, arguments);
37125            return $.extend({}, parentOptionsMap, {
37126                "displayValue" : function (val) {
37127                    parentOptionsMap.displayValue.apply(this, arguments);
37128                    var rbParent = this.$userControl.parents('.guideRadioButtonItem, .guideCheckBoxItem');
37129                    if (rbParent) {
37130                        rbParent.toggleClass('imageCheckButtonChecked', this.checkedState);
37131                    }
37132                    if (this.$userControl.attr('disabled') === 'disabled') {
37133                        rbParent.addClass('imageCheckButtonDisabled');
37134                    }
37135                }
37136            });
37137        }
37138    });
37139})($);
37140(function (_, guidelib) {
37141    var GuideModelRegistry = guidelib.model.GuideModelRegistry = xfalib.ut.Class.extend({
37142
37143        _nodeClassToFactoryMap : {
37144
37145        },
37146
37147        createModel : function (jsonModel, options) {
37148            var model = null;
37149            var guideNodeClassTag = "GuideNode";
37150            if (jsonModel.guideNodeClass && jsonModel.guideNodeClass.length > 0)     {
37151                guideNodeClassTag = jsonModel.guideNodeClass.charAt(0).toUpperCase() + jsonModel.guideNodeClass.substr(1);
37152            }
37153            var factoryFnName = "create" + guideNodeClassTag ;
37154            if (jsonModel.guideNodeClass && this._nodeClassToFactoryMap[jsonModel.guideNodeClass]) {
37155                factoryFnName = this._nodeClassToFactoryMap[jsonModel.guideNodeClass];
37156            }
37157            if (this[factoryFnName]) {
37158                model = this[factoryFnName].call(this, jsonModel, options);
37159            }
37160
37161            if (!model && guidelib.model[guideNodeClassTag]) {
37162                model = new guidelib.model[guideNodeClassTag](this._getOptions(jsonModel, options));
37163            }
37164
37165            if (!model) {
37166                if (jsonModel.items) {
37167                    model = new guidelib.model.GuideItemsContainer(this._getOptions(jsonModel, options));
37168                } else {
37169                    model = new guidelib.model.GuideNode(this._getOptions(jsonModel, options));
37170                }
37171            }
37172            return model;
37173        },
37174
37175        _getOptions : function (jsonModel, options) {
37176            return _.extend({}, options, {"jsonModel" : jsonModel});
37177        },
37178
37179        createInstanceManager : function (guidePanelModel) {
37180            var name =  guidePanelModel.getAttribute("name"),
37181                imJson = {
37182                    guideNodeClass : "guideInstanceManager",
37183                    minOccur : guidePanelModel.minOccur,
37184                    maxOccur : guidePanelModel.maxOccur,
37185                    initialOccur : guidePanelModel.initialOccur,
37186                    instanceTemplateId : guidePanelModel.templateId,
37187                    name : "_" + name,
37188                    instanceName : name,
37189                    templateId : "im_" + guidePanelModel.templateId,
37190                    id : "im_" + guidePanelModel.id
37191                };
37192            var options = {};
37193            if (guidePanelModel.options._guideContainer) {
37194                options = _.extend({}, options, {"_guideContainer" : guidePanelModel.options._guideContainer});
37195            }
37196            return guidelib.model.GuideModelRegistry.prototype.createModel(imJson, options);
37197        }
37198    });
37199})(_, guidelib);
37200
37201/*************************************************************************
37202 *
37203 * ADOBE CONFIDENTIAL
37204 * __________________
37205 *
37206 *  Copyright 2014 Adobe Systems Incorporated
37207 *  All Rights Reserved.
37208 *
37209 * NOTICE:  All information contained herein is, and remains
37210 * the property of Adobe Systems Incorporated and its suppliers,
37211 * if any.  The intellectual and technical concepts contained
37212 * herein are proprietary to Adobe Systems Incorporated and its
37213 * suppliers and may be covered by U.S. and Foreign Patents,
37214 * patents in process, and are protected by trade secret or copyright law.
37215 * Dissemination of this information or reproduction of this material
37216 * is strictly forbidden unless prior written permission is obtained
37217 * from Adobe Systems Incorporated.
37218 **************************************************************************/
37219
37220/**
37221 * Created with IntelliJ IDEA.
37222 * User: rismehta
37223 * Date: 1/15/14
37224 * Time: 5:49 PM
37225 * To change this template use File | Settings | File Templates.
37226 */
37227
37228/*anonymous function to handle show of file list view */
37229(function ($, guidelib) {
37230
37231    // Was causing problem in IE9
37232    // hence have added timeout to ensure that once button is rendered, event handler is registered
37233    // todo: may have to think of better namespace ?
37234    guidelib.intervals = guidelib.intervals || {};
37235    guidelib.intervals.intId = setInterval(function () {
37236        var fileAttachmentListingBtn = $("div.fileattachmentlisting button[data-guide-fileListing]");
37237        if (fileAttachmentListingBtn.length > 0) {
37238            clearInterval(guidelib.intervals.intId);
37239            var self;
37240            fileAttachmentListingBtn.click(function () {
37241                self = $(this);
37242                // added because in mobile devices it was causing problem of backdrop
37243                $("#fileAttachment").addClass("fileAttachmentDialog")
37244                $("#fileAttachment").appendTo('body');
37245                $("#fileAttachment").modal("show");
37246            });
37247            // bring focus back to file attachment listing button on dialog hide
37248            $(".fileAttachmentDialog").on('hidden.bs.modal', function (e) {
37249                $(this).removeClass("fileAttachmentDialog");
37250                self.focus();
37251            });
37252        }
37253    }, 1000);
37254}($, guidelib));
37255
37256/*************************************************************************
37257 *
37258 * ADOBE CONFIDENTIAL
37259 * __________________
37260 *
37261 *  Copyright 2014 Adobe Systems Incorporated
37262 *  All Rights Reserved.
37263 *
37264 * NOTICE:  All information contained herein is, and remains
37265 * the property of Adobe Systems Incorporated and its suppliers,
37266 * if any.  The intellectual and technical concepts contained
37267 * herein are proprietary to Adobe Systems Incorporated and its
37268 * suppliers and may be covered by U.S. and Foreign Patents,
37269 * patents in process, and are protected by trade secret or copyright law.
37270 * Dissemination of this information or reproduction of this material
37271 * is strictly forbidden unless prior written permission is obtained
37272 * from Adobe Systems Incorporated.
37273 **************************************************************************/
37274
37275(function ($) {
37276
37277    // GUIDE ADD REMOVE CLASS DEFINITION
37278    // ====================
37279
37280    var GuideAddRemove = function (element) {
37281        this.element = $(element);
37282    };
37283
37284    GuideAddRemove.prototype.add = function () {
37285        $this = this.element;
37286        var id = $this.attr("data-guide-id"),
37287            nextPanel;
37288
37289        if (id) {
37290            if (window.guideBridge) {
37291                var guidePanel = window.guideBridge._resolveId(id);
37292                if (guidePanel) {
37293                    nextPanel = guidePanel.instanceManager.insertInstance(guidePanel.instanceIndex + 1);
37294                    if (nextPanel) {
37295                        window.guideBridge.setFocus(nextPanel.somExpression, "firstItem");
37296                    }
37297                }
37298            } else {
37299                console.log("could not add new instance" + id);
37300            }
37301        }
37302    };
37303
37304    GuideAddRemove.prototype.remove = function () {
37305        $this = this.element;
37306        var id       = $this.attr("data-guide-id");
37307
37308        if (id) {
37309            if (window.guideBridge) {
37310                var guidePanel = window.guideBridge._resolveId(id);
37311                if (guidePanel) {
37312                    guidePanel.instanceManager.removeInstance(guidePanel.instanceIndex);
37313                }
37314            } else {
37315                console.log("could not remove instance");
37316            }
37317        }
37318    };
37319
37320    // GUIDE ADD REMOVE PLUGIN DEFINITION
37321    // =====================
37322
37323    var old = $.fn.guideAddRemove;
37324
37325    $.fn.guideAddRemove = function (option) {
37326        return this.each(function () {
37327            var $this = $(this);
37328            var data  = $this.data('guideAddRemove');
37329
37330            if (!data) {
37331                $this.data('guideAddRemove', (data = new GuideAddRemove(this)));
37332            }
37333            if (typeof option == 'string') {
37334                data[option]();
37335            }
37336        });
37337    };
37338
37339    $.fn.guideAddRemove.Constructor = GuideAddRemove();
37340
37341    // ADD REMOVE NO CONFLICT
37342    // ===============
37343
37344    $.fn.guideAddRemove.noConflict = function () {
37345        $.fn.guideAddRemove = old;
37346        return this;
37347    };
37348
37349    // ADD REMOVE DATA-API
37350    // ============
37351
37352    $(document).on('click.guideAddRemove.data-api keypress.guideAddRemove.data-api', '[data-guide-addremove="add"]', function (e) {
37353        if (e.type == "keypress" && !guidelib.util.GuideUtil.isEnterKeyPressed(e)) {
37354            return;
37355        }
37356        e.preventDefault();
37357        //This is required for setting the focus on the new panel. Otherwise the focus remains on the previous panel.
37358        e.stopImmediatePropagation();
37359        $(this).guideAddRemove('add');
37360    }).on('click.guideAddRemove.data-api keypress.guideAddRemove.data-api', '[data-guide-addremove="remove"]', function (e) {
37361            if (e.type == "keypress" && !guidelib.util.GuideUtil.isEnterKeyPressed(e)) {
37362                return;
37363            }
37364            e.preventDefault();
37365            $(this).guideAddRemove('remove');
37366        });
37367
37368}($));
37369
37370/*************************************************************************
37371 *
37372 * ADOBE CONFIDENTIAL
37373 * __________________
37374 *
37375 *  Copyright <year> Adobe Systems Incorporated
37376 *  All Rights Reserved.
37377 *
37378 * NOTICE:  All information contained herein is, and remains
37379 * the property of Adobe Systems Incorporated and its suppliers,
37380 * if any.  The intellectual and technical concepts contained
37381 * herein are proprietary to Adobe Systems Incorporated and its
37382 * suppliers and may be covered by U.S. and Foreign Patents,
37383 * patents in process, and are protected by trade secret or copyright law.
37384 * Dissemination of this information or reproduction of this material
37385 * is strictly forbidden unless prior written permission is obtained
37386 * from Adobe Systems Incorporated.
37387 **************************************************************************/
37388
37389(function ($) {
37390
37391    // TABLE LAYOUT PLUGIN
37392    // ============
37393
37394    $(document).on('panelRemoved.af', '.guideTableNode', function (e, $childRemoved, index) {
37395        // this plugin is specific to a layout
37396        // one can also check the layout based on CSS class set and perform things accordingly
37397        // prevent the bubbling up of the event
37398        e.stopPropagation();
37399        // this would work only in runtime
37400        var $bodyRows = $(e.target).find("tr.guideTableRowNode:not(.guideTableHeader)");
37401        // Set focus to first child
37402        if (index > 1) {
37403            // set focus on prev row since index is greater than 1
37404            var $prevRow = $bodyRows.eq(index - 1);
37405            guidelib.util.GuideUtil.setFocusOnFirstItemOfTableRow($prevRow);
37406        } else if (index == 1) {
37407            var $nextRow = $bodyRows.eq(1);
37408            // may there is only one row which has got deleted, hence check if next row actually exists
37409            if ($nextRow.length > 0) {
37410                guidelib.util.GuideUtil.setFocusOnFirstItemOfTableRow($nextRow);
37411            }
37412        }
37413    });
37414
37415}($));
37416
37417/*************************************************************************
37418 *
37419 * ADOBE CONFIDENTIAL
37420 * __________________
37421 *
37422 *  Copyright 2014 Adobe Systems Incorporated
37423 *  All Rights Reserved.
37424 *
37425 * NOTICE:  All information contained herein is, and remains
37426 * the property of Adobe Systems Incorporated and its suppliers,
37427 * if any.  The intellectual and technical concepts contained
37428 * herein are proprietary to Adobe Systems Incorporated and its
37429 * suppliers and may be covered by U.S. and Foreign Patents,
37430 * patents in process, and are protected by trade secret or copyright law.
37431 * Dissemination of this information or reproduction of this material
37432 * is strictly forbidden unless prior written permission is obtained
37433 * from Adobe Systems Incorporated.
37434 **************************************************************************/
37435
37436/*handle click of default next and previous navigator*/
37437$(function ($) {
37438    var getPanelSom = function (panelId) {
37439            var panel = window.guideBridge._resolveId(panelId);
37440            if (panel === undefined || panel === null) {
37441                return "";
37442            }
37443            return panel.somExpression;
37444        },
37445        pointerup_evnt = xfalib.ut.TouchUtil.POINTER_UP;
37446
37447    if (pointerup_evnt === "touchend") {
37448        // touchend happens before blur, hence the value of the current
37449        // focused field is not committed and setFocus API receives the old
37450        // value. So as a hack we are using mouseup instead of touchend to
37451        // make sure that the value gets committed
37452        pointerup_evnt = "mouseup";
37453    }
37454    $('body').on(pointerup_evnt + " keydown", '[data-guide-wizard-nav]', function (e) {
37455        var triggerKeyEvent = false;
37456        //  check for event type  and key press space/enter
37457        if (e.type === "keydown" && (e.keyCode === 32 || e.keyCode === 13)) {
37458            e.preventDefault();
37459            triggerKeyEvent =  true; // set to trigger key event
37460        }
37461
37462        //  when event is pointerup(click) or space/enter key is pressed, trigger navigation
37463        if (e.type === "pointerup" || triggerKeyEvent) {
37464            var $this = $(this),
37465                options = $this.data("guide-wizard-nav");
37466            if (_.isObject(options)) { //case of all the options, get som expression out of id
37467                options.somExpression = getPanelSom(options.panelId);
37468            } else { //case where its value of somId
37469                var somExpr = getPanelSom(options),
37470                    navType = $(this).data("guide-wizard-nav-type");
37471                options = {
37472                    somExpression: somExpr,
37473                    focusOption: navType,
37474                    runCompletionScript: true
37475                };
37476            }
37477            window.guideBridge.setFocus(options);
37478        }
37479    });
37480
37481    window.guideBridge.on("elementNavigationChanged",
37482        function (evntName, evnt) {
37483            var activePanelSom = evnt.newText,
37484                activePanel = window.guideBridge._guideView.getView(activePanelSom),
37485                scrollDirection,
37486                scrollStep,
37487                scrollPos,
37488                list,
37489                $listElements;
37490            if (activePanel instanceof guidelib.view.GuidePanelView) {
37491                $listElements = activePanel.parentView.$element.find('[id*="' + guidelib.util.GuideUtil.GUIDE_ITEM_NAV_CONTAINER_SUFFIX + '"]');
37492                if (!_.isUndefined($listElements) && !_.isNull($listElements) && $listElements.length > 0) {
37493                    list = $listElements.eq(0);
37494                    if (_.isUndefined(list.attr("data-guide-nav-scroll-pos"))) {
37495                        list.attr("data-guide-nav-scroll-pos", 0);
37496                    }
37497                    scrollPos = parseInt(list.attr("data-guide-nav-scroll-pos"), 10);
37498                    //Find index among the visible panels
37499                    var parentChildViews = activePanel.parentView.childViews,
37500                        iterator,
37501                        navPos = 0;
37502                    for (iterator = 0; iterator < parentChildViews.length; iterator++) {
37503                        if (activePanel === parentChildViews[iterator]) {
37504                            break;
37505                        }
37506                        if (parentChildViews[iterator]._model.visible) {
37507                            navPos = navPos + 1;
37508                        }
37509                    }
37510                    if (navPos > scrollPos) {
37511                        scrollDirection = "right";
37512                    } else {
37513                        scrollDirection = "left";
37514                    }
37515                    scrollStep = Math.abs(navPos - scrollPos);
37516                    guidelib.util.GuideUtil.navScroll(list, scrollDirection, scrollStep, '[id*="' + guidelib.util.GuideUtil.GUIDE_ITEM_
37516NAV_SUFFIX + '"]:not(.hidden)');
37517                }
37518            }
37519        });
37520});
37521
37522/*************************************************************************
37523 *
37524 * ADOBE CONFIDENTIAL
37525 * __________________
37526 *
37527 *  Copyright 2014 Adobe Systems Incorporated
37528 *  All Rights Reserved.
37529 *
37530 * NOTICE:  All information contained herein is, and remains
37531 * the property of Adobe Systems Incorporated and its suppliers,
37532 * if any.  The intellectual and technical concepts contained
37533 * herein are proprietary to Adobe Systems Incorporated and its
37534 * suppliers and may be covered by U.S. and Foreign Patents,
37535 * patents in process, and are protected by trade secret or copyright law.
37536 * Dissemination of this information or reproduction of this material
37537 * is strictly forbidden unless prior written permission is obtained
37538 * from Adobe Systems Incorporated.
37539 **************************************************************************/
37540
37541$(function ($) {
37542
37543    /* handle swipe*/
37544    var setSwipeGestureState = function () {
37545        var swipeEnabled = !window.guideBridge._guide.getAttribute("disableSwipeGesture");
37546        window.guideBridge.enableSwipeGesture(swipeEnabled, swipeEnabled);
37547    };
37548    window.guideBridge.connect(setSwipeGestureState, this);
37549
37550    /*show scroll indication on mobile devices*/
37551    var scrollIndicator = function () {
37552        if ($(window).scrollTop() == $(document).height() - $(window).height()) {
37553            $('[data-guide-scroll-indicator]').removeClass('mobileScrollIndicator');
37554        } else if ($(window).scrollTop() < $(document).height() - $(window).height()) {
37555            $('[data-guide-scroll-indicator]').addClass('mobileScrollIndicator');
37556        }
37557    };
37558
37559    //this should be changed back to $(document).ready(scrollIndicator) instead of windows onload,
37560    //once jquery version is bumped
37561    $(window).on('load scroll resize', scrollIndicator);
37562    window.guideBridge.on('elementNavigationChanged', scrollIndicator);
37563});
37564
37565/*************************************************************************
37566 *
37567 * ADOBE CONFIDENTIAL
37568 * __________________
37569 *
37570 *  Copyright 2014 Adobe Systems Incorporated
37571 *  All Rights Reserved.
37572 *
37573 * NOTICE:  All information contained herein is, and remains
37574 * the property of Adobe Systems Incorporated and its suppliers,
37575 * if any.  The intellectual and technical concepts contained
37576 * herein are proprietary to Adobe Systems Incorporated and its
37577 * suppliers and may be covered by U.S. and Foreign Patents,
37578 * patents in process, and are protected by trade secret or copyright law.
37579 * Dissemination of this information or reproduction of this material
37580 * is strictly forbidden unless prior written permission is obtained
37581 * from Adobe Systems Incorporated.
37582 **************************************************************************/
37583/*anonymous function to handle click of default next and previous navigator*/
37584(function ($) {
37585    window.guideBridge.on("elementNavigationChanged",
37586        function (evntName, evnt) {
37587            var activePanelSom = evnt.newText,
37588                activePanel = window.guideBridge.resolveNode(activePanelSom);
37589            if (activePanel) {
37590                var dynamicContentSelector = "[data-target-guide-content]",
37591                    text = $(dynamicContentSelector).text();
37592                // if there is an active panel already set and active panel is not an instance of root panel node
37593                // only then set the active panel title to the content
37594                if (text != null && text.length > 0
37595                    && (!(activePanel instanceof guidelib.model.RootPanelNode)
37596                        && !(activePanel instanceof guidelib.model.GuideToolbar))) {
37597                    $(dynamicContentSelector).text(activePanel.title ? activePanel.title : "");
37598                }
37599            }
37600        });
37601}($));
37602
37603// jscs:disable requireDotNotation
37604/*
37605 * ***********************************************************************
37606 * ADOBE CONFIDENTIAL
37607 * __________________
37608 *
37609 * Copyright 2015 Adobe Systems Incorporated
37610 * All Rights Reserved.
37611 *
37612 * NOTICE:  All information contained herein is, and remains
37613 * the property of Adobe Systems Incorporated and its suppliers,
37614 * if any.  The intellectual and technical concepts contained
37615 * herein are proprietary to Adobe Systems Incorporated and its
37616 * suppliers and may be covered by U.S. and Foreign Patents,
37617 * patents in process, and are protected by trade secret or copyright law.
37618 * Dissemination of this information or reproduction of this material
37619 * is strictly forbidden unless prior written permission is obtained
37620 * from Adobe Systems Incorporated.
37621 * ***********************************************************************
37622 */
37623
37624(function ($, guidelib, _) {
37625    var GuideUtil = guidelib.util.GuideUtil,
37626        CHART_TYPE = GuideUtil.chartType,
37627
37628        ChartUtils = guidelib.chartUtils = {
37629
37630            reducerOptions : window.chartReducer.reducerOptions,
37631
37632            /**
37633             * Returns the display format of axis data
37634             * @param dataType {string} representing data type of axis
37635             * @returns {string}
37636             */
37637            getDisplayFormat : function (dataType) {
37638                var displayFormat = "";
37639                if (dataType === 'date' || dataType === 'date-time') {
37640                    displayFormat = 'date{' + guidelib.i18n.datePatterns.med + '}';
37641                }
37642                return displayFormat;
37643            },
37644
37645            /**
37646             * Reads chart model for chart configuration and computes the data for chart
37647             * @param chartModel
37648             * @returns {{}}
37649             */
37650            gatherAxisData : function (chartModel) {
37651                var categoryExp,
37652                    valueExp,
37653                    reducerFunction,
37654                    repeatableInstances,
37655                    repeatableItem,
37656                    seriesRepeatableItem,
37657                    series,
37658                    relativeSeriesNameExp,
37659                    currentSeries,
37660                    repeatablePath,
37661                    seriesLength = 0,
37662                    seriesRepeatableInstances,
37663                    relativeSeriesRefExp,
37664                    data = new Map(),
37665                    chartBuildOptions = {},
37666                    isWebChannelChart = chartModel.jsonModel["sling:resourceType"] === 'fd/ccm/web-channel/components/chart/v1/chart',
37667                    dataToFill = {};
37668                chartBuildOptions.isFDMDataSource = chartModel.dataSourceType === "fdm" ? true : false;
37669                chartBuildOptions.chartModel = chartModel;
37670                dataToFill.valueDisplayFormat = "";
37671                dataToFill.labelDisplayFormat = "";
37672                dataToFill.categoryDataType = "";
37673                dataToFill.valueDataType = "";
37674
37675                repeatableItem = chartModel.getOrElse(chartModel._guide().runtime, chartModel.repeatableItem, undefined);
37676
37677                //Do not support reducer functions on x-axis for Web channel charts
37678                if (chartModel.reducerXFunction && chartModel.reducerXFunction !== 'none' && !isWebChannelChart) {
37679                    chartBuildOptions.categoryExp = chartModel.yExp;
37680                    chartBuildOptions.valueExp = chartModel.xExp;
37681                    chartBuildOptions.reducerFunction = chartModel.reducerXFunction;
37682                    dataToFill = ChartUtils._setProp(dataToFill, "categoryDataType", chartModel.jsonModel.yDataType);
37683                    dataToFill = ChartUtils._setProp(dataToFill, "valueDataType", chartModel.jsonModel.xDataType);
37684                } else {
37685                    chartBuildOptions.categoryExp = chartModel.xExp;
37686                    chartBuildOptions.valueExp = chartModel.yExp;
37687                    dataToFill = ChartUtils._setProp(dataToFill, "categoryDataType", chartModel.jsonModel.yDataType);
37688                    dataToFill = ChartUtils._setProp(dataToFill, "valueDataType", chartModel.jsonModel.xDataType);
37689                    if (chartModel.reducerYFunction && chartModel.reducerYFunction !== 'none') {
37690                        chartBuildOptions.reducerFunction = chartModel.reducerYFunction;
37691                    }
37692                }
37693
37694                if (chartBuildOptions.isFDMDataSource) {
37695                    dataToFill.valueDisplayFormat = ChartUtils.getDisplayFormat(dataToFill.valueDataType);
37696                    dataToFill.labelDisplayFormat = ChartUtils.getDisplayFormat(dataToFill.categoryDataType);
37697                    repeatableItem = chartModel.repeatableItem;
37698                    chartBuildOptions.categoryExp = chartBuildOptions.categoryExp.substring(repeatableItem.length + 1, chartBuildOptions.categoryExp.length).split("/");
37699                    chartBuildOptions.valueExp = chartBuildOptions.valueExp.substring(repeatableItem.length + 1, chartBuildOptions.valueExp.length).split("/");
37700                    if (isWebChannelChart) {
37701                        dataToFill.series = series = [];
37702                        if (chartModel.jsonModel.chartType === 'quadrant') {
37703                            chartBuildOptions.isXYReferencePointSet = false;
37704                            if (chartModel.jsonModel.referencePointType === 'staticReferencePoint') {
37705                                if (chartModel.jsonModel.xDataType === 'date' || chartModel.jsonModel.xDataType === 'date-time') {
37706                                    //Whenx-axis is of Date type we need to compute reference value in milliseconds.
37707                                    chartModel.jsonModel.xAxisReferencePoint = new Date(chartModel.jsonModel.xAxisReferencePoint).getTime();
37708                                }
37709                                chartBuildOptions.isXYReferencePointSet = true;
37710                            }
37711                        }
37712                    }
37713                    if ("true" == chartModel.jsonModel.multiSeries) {
37714                        seriesRepeatableItem = chartModel.jsonModel.seriesRepeatableItem;
37715                        relativeSeriesNameExp = chartModel.jsonModel.seriesName.substring(seriesRepeatableItem.length + 1, chartModel.jsonModel.seriesName.length);
37716                        seriesRepeatableInstances = this._getRepeatableInstances(seriesRepeatableItem, null, chartModel);
37717                        seriesLength = seriesRepeatableInstances ? seriesRepeatableInstances.length : seriesLength;
37718                        repeatablePath = repeatableItem.substring(seriesRepeatableItem.length, repeatableItem.length);
37719                        if (chartModel.jsonModel.chartType === 'quadrant' && chartModel.jsonModel.referencePointType === 'fdmReferencePoint') {
37720                            relativeSeriesRefExp = chartModel.jsonModel.seriesReferenceExp.substring(seriesRepeatableItem.length + 1, chartModel.jsonModel.seriesReferenceExp.length);
37721                        }
37722                        for (var i = 0; i < seriesLength; i++) {
37723                            chartBuildOptions.repeatableInstances = this._getRepeatableInstances(repeatablePath, seriesRepeatableInstances[i], chartModel);
37724                            chartBuildOptions.repeatableItemForReferencePoint;
37725                            if (relativeSeriesRefExp && !chartBuildOptions.isXYReferencePointSet) {
37726                                chartBuildOptions.repeatableItemForReferencePoint = undefined;
37727                                if (this.matchUserInputWithFDM(chartModel.jsonModel.seriesReferenceDataType, seriesRepeatableInstances[i][relativeSeriesRefExp], chartModel.jsonModel.seriesReferenceValue)) {
37728                                    chartBuildOptions.repeatableItemForReferencePoint = repeatableItem;
37729                                }
37730                            }
37731                            currentSeries = this.buildChartData(chartBuildOptions);
37732                            currentSeries.name = seriesRepeatableInstances[i][relativeSeriesNameExp];
37733                            series.push(currentSeries);
37734                        }
37735                    } else {
37736                        chartBuildOptions.repeatableInstances = this._getRepeatableInstances(repeatableItem, null, chartModel);
37737                        chartBuildOptions.repeatableItemForReferencePoint = repeatableItem;
37738                        currentSeries = this.buildChartData(chartBuildOptions);
37739                        series.push(currentSeries);
37740                    }
37741                    if (isWebChannelChart && chartModel.jsonModel.chartType === 'quadrant' && chartModel.jsonModel.referencePointType === 'fdmReferencePoint' && !chartBuildOptions.isXYReferencePointSet) {
37742                        chartModel.jsonModel.xAxisReferencePoint = undefined;
37743                        chartModel.jsonModel.yAxisReferencePoint = undefined;
37744                    }
37745                    chartBuildOptions.repeatableInstances = null;
37746                } else if (repeatableItem) {
37747                    chartBuildOptions.repeatableInstances = repeatableItem.instanceManager.instances;
37748                }
37749                if (chartBuildOptions.repeatableInstances) {
37750                    var chartData = this.buildChartData(chartBuildOptions);
37751                    dataToFill.label = chartData.label;
37752                    dataToFill.value = chartData.value;
37753                }
37754                return dataToFill;
37755            },
37756
37757            buildChartData : function (chartBuildOptions) {
37758                var dataToFill = {},
37759                    data = new Map(),
37760                    referencePointExp,
37761                    isFDMReferencePointSet = false;
37762                dataToFill.value = [];
37763                dataToFill.label = [];
37764
37765                if (chartBuildOptions.chartModel.jsonModel.chartType === 'quadrant' && chartBuildOptions.chartModel.jsonModel.referencePointType === 'fdmReferencePoint' && chartBuildOptions.repeatableItemForReferencePoint) {
37766                    referencePointExp = chartBuildOptions.chartModel.jsonModel.xyReferencePointExp.substring(chartBuildOptions.repeatableItemForReferencePoint.length + 1, chartBuildOptions.chartModel.jsonModel.xyReferencePointExp.length).split("/");
37767                }
37768                var that = this;
37769                _.each(chartBuildOptions.repeatableInstances, function (repeatableInstance, index) {
37770                    var categoryPropVal,
37771                        valuePropVal,
37772                        xyReferenceVal;
37773                    if (chartBuildOptions.isFDMDataSource) {
37774                        if (_.isArray(chartBuildOptions.categoryExp) && _.isArray(chartBuildOptions.valueExp)) {
37775                            //Handling composite key case.
37776                            var temp = repeatableInstance;
37777                            _.each(chartBuildOptions.categoryExp, function (obj) {
37778                                temp = temp[obj];
37779                            });
37780                            categoryPropVal = temp;
37781
37782                            temp = repeatableInstance;
37783                            _.each(chartBuildOptions.valueExp, function (obj) {
37784                                temp = temp[obj];
37785                            });
37786                            valuePropVal = temp;
37787
37788                            if (chartBuildOptions.chartModel.jsonModel.chartType === 'quadrant' && !chartBuildOptions.isXYReferencePointSet) {
37789                                if (chartBuildOptions.repeatableItemForReferencePoint && chartBuildOptions.chartModel.jsonModel.referencePointType === 'fdmReferencePoint') {
37790                                    temp = repeatableInstance;
37791                                    _.each(referencePointExp, function (obj) {
37792                                        temp = temp[obj];
37793                                    });
37794                                    xyReferenceVal = temp;
37795                                    if (that.matchUserInputWithFDM(chartBuildOptions.chartModel.jsonModel.xyReferencePointDataType, xyReferenceVal, chartBuildOptions.chartModel.jsonModel.xyReferencePointValue)) {
37796                                        //For date type x-axis FDM value we need to get time in milliseconds to send to Highcharts
37797                                        chartBuildOptions.chartModel.jsonModel.xAxisReferencePoint = (chartBuildOptions.chartModel.jsonModel.xDataType === 'date' || chartBuildOptions.chartModel.jsonModel.xDataType === 'date-time') ? new Date(categoryPropVal).getTime() : categoryPropVal;
37798                                        chartBuildOptions.chartModel.jsonModel.yAxisReferencePoint = valuePropVal;
37799                                        chartBuildOptions.isXYReferencePointSet = true;
37800                                    }
37801                                }
37802                            }
37803                        }
37804                    } else {
37805                        categoryPropVal = repeatableInstance[chartBuildOptions.categoryExp].value;
37806                        valuePropVal = repeatableInstance[chartBuildOptions.valueExp].value;
37807                    }
37808
37809                    categoryPropVal = _.isUndefined(categoryPropVal) ? '' : categoryPropVal;
37810                    valuePropVal = _.isUndefined(valuePropVal) ? '' : valuePropVal;
37811                    if (chartBuildOptions.reducerFunction) {
37812                        if (!data.has(categoryPropVal)) {
37813                            data.set(categoryPropVal, []);
37814                        }
37815                        data.get(categoryPropVal).push(valuePropVal);
37816                    } else {
37817                        dataToFill.label.push(categoryPropVal);
37818                        dataToFill.value.push(valuePropVal);
37819                    }
37820                });
37821
37822                if (chartBuildOptions.reducerFunction) {
37823                    var reducer = ChartUtils.reducerOptions[chartBuildOptions.reducerFunction] || window[chartBuildOptions.reducerFunction];
37824                    data.forEach(function (value, key) {
37825                        dataToFill.label.push(key);
37826                        dataToFill.value.push(reducer(data.get(key)));
37827                    });
37828                }
37829                return dataToFill;
37830            },
37831
37832            matchUserInputWithFDM : function (fdmObjectDataType, fdmObjectValue, userInputValue) {
37833                return (((fdmObjectDataType == 'date-time' || fdmObjectDataType == 'date')  && new Date(userInputValue).getTime() == new Date(fdmObjectValue).getTime())
37834                    || (fdmObjectDataType == 'boolean' && JSON.parse(userInputValue) == fdmObjectValue)
37835                    || (userInputValue == fdmObjectValue));
37836            },
37837
37838            /**
37839             * Returns dv.chart object created from chart model.
37840             * @param chartModel
37841             * @param $chartElement
37842             * @returns {dv.chart}
37843             */
37844            constructChart : function (chartModel, $chartElement) {
37845                var chartType = chartModel.chartType,
37846                    showLegends = chartModel.showLegends,
37847                    legendPosition = chartModel.legendPosition,
37848                    tooltipHtml = chartModel.tooltipHtml,
37849                    innerRadius = chartModel.innerRadius,
37850                    lineColor = chartModel.lineColor,
37851                    pointColor = chartModel.pointColor,
37852                    areaColor = chartModel.areaColor,
37853                    dataToFill = chartModel.data,
37854                    chartBehavior = [],
37855                    axisMap = {},
37856                    axisScale = {},
37857                    chartLayers,
37858                    chart,
37859                    categoryAxis,
37860                    valueAxis;
37861                if (chartModel.reducerXFunction && chartModel.reducerXFunction !== 'none') {
37862                    categoryAxis = 'y';
37863                    valueAxis = 'x';
37864                } else {
37865                    categoryAxis = 'x';
37866                    valueAxis = 'y';
37867                }
37868
37869                if (dataToFill.labelDisplayFormat) {
37870                    dataToFill.label = dataToFill.label.map(function (value) {
37871                        return guidelib.util.GuideUtil.formatValue(value,
37872                            dataToFill.labelDisplayFormat,
37873                            dataToFill.categoryDataType);
37874                    });
37875                }
37876
37877                if (dataToFill.valueDisplayFormat) {
37878                    dataToFill.value = dataToFill.value.map(function (value) {
37879                        return guidelib.util.GuideUtil.formatValue(value,
37880                            dataToFill.valueDisplayFormat,
37881                            dataToFill.valueDataType);
37882                    });
37883                }
37884
37885                axisMap[categoryAxis] = 'label';
37886                axisMap[valueAxis] = 'value';
37887                axisScale[valueAxis] = dv.scale.linear().lowerLimit(0);
37888
37889                try {
37890                    if (GuideUtil.isChartTooltipApplicable(chartType)) {
37891                        if (tooltipHtml && tooltipHtml !== '') {
37892                            var xValMap = axisMap['x'],
37893                                yValMap = axisMap['y'];
37894                            chartBehavior = [dv.behavior.rollover().content(function (d) {
37895                                var tooltip = tooltipHtml.replace(/\${x}/g, d.data[xValMap]);
37896                                tooltip = tooltip.replace(/\${y}/g, d.data[yValMap]);
37897                                return tooltip;
37898                            })];
37899                        }
37900                    }
37901                    axisScale[categoryAxis] = dv.scale.ordinal();
37902                    chart = dv.chart();
37903                    chart.map('fill', 'label')
37904                        .map('x', axisMap['x'], axisScale['x'])
37905                        .map('y', axisMap['y'], axisScale['y']);
37906
37907                    var chartPoint = dv.geom.point().set('fill', pointColor).behaviors(chartBehavior),
37908                        chartLine = dv.geom.line().set('fill', lineColor),
37909                        chartArea = dv.geom.area().set('alpha', 0.1).set('fill', areaColor),
37910                        flippedCaretesianCoord = dv.coord.cartesian().flip(true),
37911                        lineCommon = function () {
37912                            chart.set('stroke', lineColor);
37913                            chartLayers = [dv.geom.line()];
37914                        },
37915                        barTypeCommon = function () {
37916                            chartLayers = [dv.geom.bar().behaviors(chartBehavior)];
37917                            chart.map('x', 'label', axisScale[categoryAxis])
37918                                .map('y', 'value');
37919                        },
37920                        barCommon = function () {
37921                            barTypeCommon();
37922                            if (categoryAxis === 'x') {
37923                                chart.coord(flippedCaretesianCoord);
37924                            }
37925                        },
37926                        columnCommon = function () {
37927                            barTypeCommon();
37928                            if (categoryAxis === 'y') {
37929                                chart.coord(flippedCaretesianCoord);
37930                            }
37931                        },
37932                        pieCommon = function (radius) {
37933                            columnCommon();
37934                            dataToFill[categoryAxis] = Array.apply(null, Array(dataToFill["label"].length)).map(function () {
37935                                return 1;
37936                            });
37937                            axisMap[categoryAxis] = categoryAxis;
37938                            if (radius > 0) {
37939                                axisScale[categoryAxis] = axisScale[categoryAxis].padding(.3);
37940                            }
37941
37942                            chart.map('x', axisMap[categoryAxis], axisScale[categoryAxis]);
37943
37944                            chart.coord(dv.coord.polar().flip(true).innerRadius(radius))
37945                                .guide(['x', 'y'], 'none')
37946                                .position('fill');
37947                        };
37948
37949                    switch (chartType) {
37950                        case CHART_TYPE.LINE:
37951                            lineCommon();
37952                            chartLayers.push(chartLine);
37953                            break;
37954                        case CHART_TYPE.POINT:
37955                            lineCommon();
37956                            chartLayers.push(chartPoint);
37957                            break;
37958                        case CHART_TYPE.AREA:
37959                            lineCommon();
37960                            chartLayers.push(chartLine);
37961                            chartLayers.push(chartArea);
37962                            break;
37963                        case CHART_TYPE.LINE_POINT:
37964                            lineCommon();
37965                            chartLayers.push(chartPoint);
37966                            chartLayers.push(chartLine);
37967                            break;
37968                        case CHART_TYPE.BAR:
37969                            barCommon();
37970                            break;
37971                        case CHART_TYPE.COLUMN:
37972                            columnCommon();
37973                            break;
37974                        case CHART_TYPE.PIE:
37975                            pieCommon(0);
37976                            break;
37977                        case CHART_TYPE.DONUT:
37978                            pieCommon(innerRadius);
37979                            break;
37980                    }
37981
37982                    chart.layers(chartLayers);
37983                    chart.data(dataToFill)
37984                        .width(chartModel.width + '%')
37985                        .height(chartModel.height)
37986                        .parent("#" + $chartElement.attr('id'))
37987                        .padding({"left" : 10, "top" : 10, "right" : 10, "bottom" : 10});
37988
37989                    if (GuideUtil.isChartAxisTitleApplicable(chartType)) {
37990                        chart.guide('x', dv.guide.axis().title(chartModel.xAxisTitle))
37991                            .guide('y', dv.guide.axis().title(chartModel.yAxisTitle));
37992                    }
37993
37994                    if (GuideUtil.isChartLegendApplicable(chartType) && showLegends) {
37995                        chart.guide('fill', dv.guide.legend().orientation(legendPosition));
37996                    }
37997                } catch (exception) {
37998                    window.guideBridge._guide.logger().log("Error while constructing chart " + exception);
37999                }
38000                return chart;
38001            },
38002
38003            _setProp : function (object, prop, value) {
38004                if (object.constructor == {}.constructor && !_.isEmpty(value)) {
38005                    object[prop] = value;
38006                }
38007                return object;
38008            },
38009
38010            /**
38011            *   Retrieves Repeatable Instances using liveDataUtils API for the given
38012            *   repeatablePath. This API internally handles naked/non-naked case.
38013            *
38014            *   @param  repeatablePath
38015            *   @param  data
38016            *   @return Repeatable Instances for the given repeatablePath using liveDataUtils.
38017            *
38018            *   TODO Move this API to data utils.
38019            */
38020            _getRepeatableInstances : function (repeatablePath, data, chartModel) {
38021                var liveDataUtils = chartModel._guide().internal.liveDataUtils,
38022                    liveData = data ? data : liveDataUtils._liveDataDoc,
38023                    xpath = "";
38024
38025                if (_.isEmpty(liveData) || _.isEmpty(repeatablePath)) {
38026                    return;
38027                }
38028
38029                if (!_.isEmpty(liveData.afData)) {//Non-Naked data case
38030                    liveData = liveData.afData;
38031                    xpath = liveDataUtils.constants.BOUND_DATA_XPATH;
38032                } else {//Naked data case or multiple series case
38033                    repeatablePath = repeatablePath.substring(1, repeatablePath.length);
38034                }
38035
38036                //Find the repeatable instances.
38037                repeatableInstances = liveDataUtils._getElement(liveData, xpath + repeatablePath);
38038
38039                return repeatableInstances;
38040            }
38041        };
38042}($, guidelib, _));
38043
38044//Poly-filling request animation frame function for IE 9
38045(function () {
38046    var lastFramePaintTime = 0;
38047    if (!window.requestAnimationFrame) {
38048        window.requestAnimationFrame = function (callback, element) {
38049            var currTime = new Date().getTime(),
38050                timeToCall = Math.max(0, 16 - (currTime - lastFramePaintTime)), //16-16 frames per second
38051                id = window.setTimeout(function () {
38052                        callback(currTime + timeToCall);
38053                    }, timeToCall);
38054            lastFramePaintTime = currTime + timeToCall;
38055            return id;
38056        };
38057    }
38058
38059    if (!window.cancelAnimationFrame) {
38060        window.cancelAnimationFrame = function (id) {
38061            clearTimeout(id);
38062        };
38063    }
38064}());
38065
38066/*
38067 * ***********************************************************************
38068 * ADOBE CONFIDENTIAL
38069 * __________________
38070 *
38071 * Copyright 2015 Adobe Systems Incorporated
38072 * All Rights Reserved.
38073 *
38074 * NOTICE:  All information contained herein is, and remains
38075 * the property of Adobe Systems Incorporated and its suppliers,
38076 * if any.  The intellectual and technical concepts contained
38077 * herein are proprietary to Adobe Systems Incorporated and its
38078 * suppliers and may be covered by U.S. and Foreign Patents,
38079 * patents in process, and are protected by trade secret or copyright law.
38080 * Dissemination of this information or reproduction of this material
38081 * is strictly forbidden unless prior written permission is obtained
38082 * from Adobe Systems Incorporated.
38083 * ***********************************************************************
38084 */
38085
38086(function ($, guidelib, xfalib, _) {
38087    var errorHandler = function (jqXHR) {
38088         var errorPayload;
38089
38090         // Actually we need clean-up old data but its not even happening in case of success with empty data
38091        // Running output mapping with empty result set to ensure old data is cleared
38092
38093         if (jqXHR.responseText) {
38094             var inputMapping = this.inputMapping;
38095             try {
38096                 errorPayload = JSON.parse(jqXHR.responseText);
38097             } catch (error) {
38098                 // result should be json if its not wel formed json or empty then ignoring it
38099             }
38100             if(errorPayload && errorPayload.errors) {
38101
38102                 // Iterating over violations received and set it at field level using input mapping provided.
38103                 var violations = errorPayload.errors;
38104                 $.each(violations, function (i, violation) {
38105                     if(violation && violation.bindRef && violation.errorMessages) {
38106                         var key = violation.bindRef.slice(1).split("/").join(".");
38107                         var field = inputMapping[key];
38108                         if (field) {
38109                             field.markAsInvalid(violation.errorMessages.join("\n"));
38110                         }
38111                     }
38112                 });
38113             }
38114         }
38115         // Invoke author register error handler (if any)
38116         if(this.customErrorHandler) {
38117             this.customErrorHandler.call(this, jqXHR, errorPayload);
38118         }
38119    };
38120
38121    var defaultErrorHandler = function (responseJson, headerMap) {
38122        if (responseJson) {
38123            if (responseJson && responseJson.validationErrors) {
38124                var violations = responseJson.validationErrors;
38125                $.each(violations, function (key, violation) {
38126                    if (violation && violation.details && (violation.fieldName || violation.dataRef)) {
38127                        if (!window.guideBridge._guide._bindRefMap || Object.keys(window.guideBridge._guide._bindRefMap).length === 0) {
38128                            window.guideBridge._populateBindRefToSomMap();
38129                        }
38130                        var som = (violation.fieldName) ? violation.fieldName : window.guideBridge._guide._bindRefMap[violation.dataRef];
38131                        var field = window.guideBridge.resolveNode(som);
38132                        if (field) {
38133                            field.markAsInvalid(violation.details.join("\n"));
38134                        }
38135                    }
38136                });
38137            }
38138        }
38139    };
38140
38141    var defaultErrorHandlerWrapper = function(jqXHR) {
38142        if (jqXHR.responseText) {
38143            try {
38144                responseJson = JSON.parse(jqXHR.responseText);
38145            } catch (error) {
38146                // result should be json if its not well formed json or empty then ignoring it
38147            }
38148        }
38149
38150        var headers = jqXHR.getAllResponseHeaders();
38151
38152        // Convert the header string into an array
38153        // of individual headers
38154        var arr = headers.trim().split(/[\r\n]+/);
38155
38156        // Create a map of header names to values
38157        var headerMap = {};
38158        arr.forEach(function (line) {
38159            var parts = line.split(': ');
38160            var header = parts.shift();
38161            var value = parts.join(': ');
38162            headerMap[header] = value;
38163        });
38164
38165        if (this.customErrorHandler === "guidelib.dataIntegrationUtils.defaultErrorHandler") {
38166            defaultErrorHandler(responseJson, headerMap);
38167        } else {
38168            if(this.customErrorHandler) {
38169                this.customErrorHandler.call(this, responseJson, headerMap);
38170            }
38171        }
38172    }
38173
38174    // Counts the number of Array(repeatable) in the output JSON of the WSDL.
38175    var outputJsonRepeatCount = function (wsdlOutputId, outputJSONObj) {
38176        var count = 0,
38177            wsdlOutputHierarchy = wsdlOutputId.split(".");
38178        if (Array.isArray(outputJSONObj)) {
38179            count++;
38180            outputJSONObj = outputJSONObj[0];
38181        }
38182        $.each(wsdlOutputHierarchy, function (depth) {
38183            if (outputJSONObj) {
38184                outputJSONObj = outputJSONObj[wsdlOutputHierarchy[depth]];
38185                if (Array.isArray(outputJSONObj)) {
38186                    count++;
38187                    outputJSONObj = outputJSONObj[0];
38188                }
38189            }
38190        });
38191        return count;
38192    };
38193
38194    //Traversing to the highest repeatable field in hierarchy as a starting point.
38195    var outputRepeatAncestor = function (targetNode, repeatCount, targetNameHierarchy) {
38196        while (repeatCount > 0) {
38197            if (_.isNull(targetNode.parent)) {
38198                return targetNode;
38199            }
38200            targetNameHierarchy.push(targetNode.name);
38201            targetNode = targetNode.parent;
38202            if (targetNode.repeatable) {
38203                repeatCount--;
38204            }
38205        }
38206        return targetNode;
38207    };
38208
38209    /**
38210     * Extract value of a hierarchy of properties
38211     * from a nested javascript object.
38212     * @param {Object} obj Nested javascript object
38213     * @param {Array|String} props list of properties
38214     * or dot separated string from root to leaf object
38215     * @return {Array} return list of values found
38216     */
38217    function extractValues(obj, props) {
38218        // handle easy cases
38219        if (obj === null || typeof(obj) === "undefined") {
38220            return [];
38221        }
38222        if (typeof(props) == "string") {
38223            props = props.split(".");
38224        }
38225        if (props.length == 0) {
38226            return [obj];
38227        }
38228        var ret = [];
38229        if (obj instanceof Array) {
38230            for (var i = 0; i < obj.length; i++) {
38231                ret = ret.concat(extractValues(obj[i], props));
38232            }
38233            return ret;
38234        }
38235        if (!obj.hasOwnProperty(props[0])) {
38236            return [];
38237        }
38238        // handle actual case now
38239
38240        var key = props[0];
38241        var remainingKeys = props.slice(1);
38242        var values = obj[key];
38243        if (!(values instanceof Array)) {
38244            values = [values];
38245        }
38246        for (var x = 0; x < values.length; x++) {
38247            ret = ret.concat(extractValues(values[x], remainingKeys));
38248        }
38249        return ret;
38250    }
38251    //Maps the output JSON(outputJSONObj) to the Model(targetNode)
38252    var outputJsonMapping = function (wsdlOutputId, targetNode, targetNameHierarchy, outputJSONObj) {
38253        if (targetNameHierarchy.length === 0) {
38254            targetNode.value = xfalib.ut.XfaUtil.prototype.getOrElse(outputJSONObj, wsdlOutputId, "");
38255            return;
38256        }
38257        var targetName = targetNameHierarchy.pop();
38258        if (targetNode.repeatable) {
38259            //Gets respective array for this repeatable field.
38260            while (typeof outputJSONObj === "object" && !Array.isArray(outputJSONObj)) {
38261                var argsIndex = wsdlOutputId.indexOf('.');
38262                outputJSONObj = outputJSONObj[wsdlOutputId.substring(0, argsIndex)] || "";
38263                wsdlOutputId = wsdlOutputId.substring(argsIndex + 1);
38264            }
38265            //Adjust the number of instances to the number of array elements.
38266            var jsonLength = outputJSONObj.length,
38267                instanceCount = targetNode.instanceManager.instanceCount;
38268            if (instanceCount < jsonLength) {
38269                targetNode.instanceManager.addInstances({
38270                    instanceCount : jsonLength
38271                });
38272            }
38273            //Check as "" might occur too for incorrect mappings.
38274            if (Array.isArray(outputJSONObj)) {
38275                //Recursive call for every instance with corresponding value.
38276                $.each(outputJSONObj, function (index) {
38277                    // if the output from external API call contains more records, than the number
38278                    // of instances present, return
38279                    if (index >= targetNode.instanceManager.instanceCount) {
38280                        return false;
38281                    }
38282                    targetNode = targetNode.instanceManager.instances[index];
38283                    outputJsonMapping(wsdlOutputId, targetNode[targetName], targetNameHierarchy, outputJSONObj[index]);
38284                });
38285            }
38286        } else {
38287            //Recursive call down the hierarchy.
38288            outputJsonMapping(wsdlOutputId, targetNode[targetName], targetNameHierarchy, outputJSONObj);
38289        }
38290        //Pushing back the hierarchy for next instance if any.
38291        targetNameHierarchy.push(targetName);
38292    };
38293
38294    var populateWsdlOutput = function (wsdlOutput, textStatus, jqXHR) {
38295        if (wsdlOutput == null || wsdlOutput.length == 0) {
38296            return;
38297        }
38298
38299        var origOutputJSONObj,
38300            outputMappingObj = this.callbackData;
38301        try {
38302            origOutputJSONObj = JSON.parse(wsdlOutput);
38303        } catch (e) {
38304            //Handling primitive output
38305            origOutputJSONObj = {"response" : wsdlOutput};
38306        }
38307
38308        /*  For each entry in outputMappingObj, we need to find the corresponding value in responseObj.
38309         *  wsdlOutputId - wsdlOutput hierarchy, targetNode - field in the form whose value is to be set.
38310         *  e.g. {ipinfo.ip, txtfield} */
38311        $.each(outputMappingObj, function (wsdlOutputId, targetNode) {
38312            /* Gets value in outputJSONObj corresponding to targetNode.
38313             * First, It counts the number of Array in hierarchy as repeatCount.
38314             * Next, targetNode is taken to the starting point for traversal.
38315             * It's the topmost repeatable node in hierarchy.
38316             * Lastly, The outputJson is mapped to the TargetNode.*/
38317            var repeatCount = outputJsonRepeatCount(wsdlOutputId, origOutputJSONObj),
38318                targetNameHierarchy = [],
38319                targetNode = outputRepeatAncestor(targetNode, repeatCount, targetNameHierarchy);
38320            outputJsonMapping(wsdlOutputId, targetNode, targetNameHierarchy, origOutputJSONObj);
38321        });
38322        window.guideBridge._guide.runPendingExpressions();
38323    };
38324
38325    /**
38326     * Create and set items to dropdown field from wsdl response.
38327     * @this {Object} is of form {callbackData:data}
38328     */
38329    function setOptionsCallback(wsdlOutput) {
38330       var cbData = this.callbackData;
38331       var options = [];
38332       if (!_.isEmpty(wsdlOutput)) {
38333           var wsdlOutputObj = JSON.parse(wsdlOutput);
38334           var savedValues = extractValues(wsdlOutputObj, cbData.savedValue);
38335           var displayedValues = extractValues(wsdlOutputObj, cbData.displayedValue);
38336           for (var i = 0; i < savedValues.length; i++) {
38337               options.push(savedValues[i] + "=" + displayedValues[i]);
38338           }
38339       }
38340       cbData.field.items = options;
38341   }
38342
38343    function setValueCallback(wsdlOutput) {
38344        var cbData = this.callbackData;
38345        var wsdlOutputObj = JSON.parse(wsdlOutput);
38346        cbData.field.value = extractValues(wsdlOutputObj, cbData.value);
38347    }
38348
38349    function appendLoadingIcon() {
38350        $("#loadingPage").addClass("guideServiceLoading");
38351    }
38352
38353    function removeLoadingIcon() {
38354        $("#loadingPage").removeClass("guideServiceLoading");
38355    }
38356
38357    function executeOperationInternal (wsdlInfoObj, jsonInputMappingObj, jsonOutputMappingObj, processOutputCallback, customErrorHandler, model, defaultErrorHandler, apiVersion) {
38358        // populate operationDetails object
38359        var successHandler = processOutputCallback || populateWsdlOutput;
38360        var wsdlInputObj = {};
38361
38362        /* Iterate through the jsonInputMapping and create the input object.
38363         * wsdlInputId - wsdlInput hierarchy, targetNode - field in the form whose value is to be retrieved.*/
38364        $.each(jsonInputMappingObj, function (wsdlInputId, targetNode) {
38365            var argsHierarchy = wsdlInputId.split("."),
38366                wsdlArgObj = wsdlInputObj,
38367                argDepth,
38368                valueToBeAssigned;
38369
38370            for (argDepth = 0; argDepth < argsHierarchy.length - 1; argDepth++) {
38371                wsdlArgObj[argsHierarchy[argDepth]] = wsdlArgObj[argsHierarchy[argDepth]] || {};
38372                wsdlArgObj = wsdlArgObj[argsHierarchy[argDepth]];
38373            }
38374            // assign the value of targetNode
38375            if (typeof targetNode === "object") {
38376                valueToBeAssigned = targetNode.value;
38377            } else {
38378                valueToBeAssigned = targetNode;
38379            }
38380            wsdlArgObj[argsHierarchy[argDepth]] = valueToBeAssigned;
38381        });
38382
38383        var wsdlEndPoint = wsdlInfoObj.wsdlEndPoint,
38384            operationDetails = {};
38385        operationDetails.operationName = wsdlInfoObj.operationName;
38386        operationDetails.input = JSON.stringify(wsdlInputObj);
38387        operationDetails.port = wsdlInfoObj.port;
38388        operationDetails.soapActionURI = wsdlInfoObj.soapActionURI;
38389        operationDetails.namespace = wsdlInfoObj.namespace;
38390        operationDetails.inputRoot = wsdlInfoObj.inputRoot;
38391        operationDetails.inputAttr = JSON.stringify(wsdlInfoObj.inputAttr);
38392        operationDetails.serviceEndPoint = wsdlInfoObj.serviceEndPoint;
38393        if (!model) {
38394            console.log("No model parameter passed to this API, this may fail during server side re-validation. Please correct your scripts.");
38395        }
38396        // TODO: this needs to be fixed, this API does not have access to guideContext but would execute in context of AF always
38397        var guide = model && model._guide && model._guide();
38398        var wsdlServletURL  = ((guide ? guide.jcrPath : guidelib.__runtime__.guide.jcrPath) + ".af.dermis");
38399        var externalizedWSDLServletURL;
38400        if (guideBridge != null) {
38401            externalizedWSDLServletURL = guideBridge._getUrl(wsdlServletURL);
38402        } else {
38403            externalizedWSDLServletURL = Granite.HTTP.externalize(wsdlServletURL);
38404        }
38405
38406        var invokeData = {};
38407        if (wsdlInfoObj.wsdlEndPoint) {
38408            invokeData.functionToExecute = 'invokeWsdlOperation';
38409            invokeData.wsdlEndPoint = wsdlEndPoint;
38410            invokeData.operationName = operationDetails.operationName;
38411            invokeData.input = operationDetails.input;
38412
38413            if (operationDetails.port) {
38414                invokeData.port = operationDetails.port;
38415            }
38416            if (operationDetails.soapActionURI) {
38417                invokeData.soapActionURI = operationDetails.soapActionURI;
38418            }
38419            if (operationDetails.namespace) {
38420                invokeData.namespace = operationDetails.namespace;
38421            }
38422            if (operationDetails.inputRoot) {
38423                invokeData.inputRoot = operationDetails.inputRoot;
38424            }
38425            if (operationDetails.inputAttr) {
38426                invokeData.inputAttr = operationDetails.inputAttr;
38427            }
38428            if (operationDetails.serviceEndPoint) {
38429                invokeData.serviceEndPoint = operationDetails.serviceEndPoint;
38430            }
38431        } else if (wsdlInfoObj.formDataModelId) {
38432            invokeData.functionToExecute = 'invokeFDMOperation';
38433            invokeData.formDataModelId = wsdlInfoObj.formDataModelId;
38434            invokeData.input = JSON.stringify(wsdlInputObj);
38435            invokeData.operationName = wsdlInfoObj.operationName;
38436            invokeData.runValidation = wsdlInfoObj.runValidation;
38437            invokeData.apiVersion = apiVersion;
38438            if (wsdlInfoObj.schemaRef) {
38439                invokeData.schemaRef = wsdlInfoObj.schemaRef;
38440            }
38441            if (wsdlInfoObj.schemaType) {
38442                invokeData.schemaType = wsdlInfoObj.schemaType;
38443            }
38444        }
38445        invokeData.guideNodePath = guide ? guide._currentContext.contextNode.jcrPath : guidelib.__runtime__.guide._currentContext.contextNode.jcrPath;
38446
38447        $.ajax({
38448            type : 'POST',
38449            url : externalizedWSDLServletURL,
38450            data : invokeData,
38451            beforeSend : appendLoadingIcon,
38452            complete : removeLoadingIcon,
38453            dataType : 'text',
38454            success : successHandler,
38455            error : defaultErrorHandler,
38456            context : {callbackData : jsonOutputMappingObj, inputMapping: jsonInputMappingObj, customErrorHandler: customErrorHandler}
38457        });
38458    }
38459
38460    var DataIntegrationUtils = guidelib.dataIntegrationUtils = {
38461
38462        setOptionsFromService : function (wsdlInfoObj, jsonInputMapping, jsonOutputMapping) {
38463            this.executeOperation(wsdlInfoObj, jsonInputMapping, jsonOutputMapping, setOptionsCallback);
38464            return jsonOutputMapping.field.items;
38465        },
38466
38467        setValueFromService : function (wsdlInfoObj, jsonInputMapping, jsonOutputMapping) {
38468            this.executeOperation(wsdlInfoObj, jsonInputMapping, jsonOutputMapping, setValueCallback);
38469            return jsonOutputMapping.field.items;
38470        },
38471
38472        /**
38473         * @deprecated
38474         */
38475        executeOperation : function (wsdlInfoObj, jsonInputMappingObj, jsonOutputMappingObj, processOutputCallback, customErrorHandler, model) {
38476            var defaultErrorHandler = errorHandler;
38477            executeOperationInternal(wsdlInfoObj, jsonInputMappingObj, jsonOutputMappingObj, processOutputCallback, customErrorHandler, model, defaultErrorHandler);
38478        },
38479
38480        executeOperationV2 : function (wsdlInfoObj, jsonInputMappingObj, jsonOutputMappingObj, processOutputCallback, customErrorHandler, model) {
38481            var defaultErrorHandler = defaultErrorHandlerWrapper;
38482            var apiVersion = "2";
38483            executeOperationInternal(wsdlInfoObj, jsonInputMappingObj, jsonOutputMappingObj, processOutputCallback, customErrorHandler, model, defaultErrorHandler, apiVersion);
38484        },
38485
38486        defaultErrorHandler : defaultErrorHandler
38487    };
38488
38489    var WsdlUtils = guidelib.wsdlUtils = {
38490        /**
38491         *  Internal API, called for invoking webservice and setting items in a drop down
38492         */
38493        setOptionsFromWSDL : function (wsdlInfoObj, jsonInputMapping, jsonOutputMapping) {
38494            DataIntegrationUtils.executeOperation(wsdlInfoObj, jsonInputMapping, jsonOutputMapping, setOptionsCallback);
38495            return jsonOutputMapping.field.items;
38496        },
38497
38498        setValueFromWSDL : function (wsdlInfoObj, jsonInputMapping, jsonOutputMapping) {
38499            DataIntegrationUtils.executeOperation(wsdlInfoObj, jsonInputMapping, jsonOutputMapping, setValueCallback);
38500            return jsonOutputMapping.field.items;
38501        },
38502
38503        executeWSDLFunction : function (wsdlInfoObj, jsonInputMappingObj, jsonOutputMappingObj) {
38504            // populate operationDetails object
38505            DataIntegrationUtils.executeOperation(wsdlInfoObj, jsonInputMappingObj, jsonOutputMappingObj);
38506        }
38507    };
38508}($, guidelib, xfalib, _));
38509
38510/*
38511 * ***********************************************************************
38512 * ADOBE CONFIDENTIAL
38513 * __________________
38514 *
38515 * Copyright 2015 Adobe Systems Incorporated
38516 * All Rights Reserved.
38517 *
38518 * NOTICE:  All information contained herein is, and remains
38519 * the property of Adobe Systems Incorporated and its suppliers,
38520 * if any.  The intellectual and technical concepts contained
38521 * herein are proprietary to Adobe Systems Incorporated and its
38522 * suppliers and may be covered by U.S. and Foreign Patents,
38523 * patents in process, and are protected by trade secret or copyright law.
38524 * Dissemination of this information or reproduction of this material
38525 * is strictly forbidden unless prior written permission is obtained
38526 * from Adobe Systems Incorporated.
38527 * ***********************************************************************
38528 */
38529
38530/**
38531 * @package guidelib.model.GuideDirtyMarkerAndVisitor
38532 * @version 0.0.1
38533 */
38534
38535(function ($, _, guidelib) {
38536    var GuideDirtyMarkerAndVisitor = guidelib.model.GuideDirtyMarkerAndVisitor = xfalib.ut.EventClass.extend({
38537
38538        initialize : function() {
38539            // need to save the map while save and restore - will do it in getGuideState
38540            this.visitMap = {};
38541        },
38542        /**
38543         * Return a list of dirty children
38544         * @returns {Array}
38545         * @private
38546         */
38547        _flattenDirtyPanelToList : function () {
38548            var csv = this.flattenDirtyPanelMapToCSV();
38549            if (csv.length > 0) {
38550                return csv.split(",");
38551            }
38552        },
38553        /**
38554         * If any dirty element then save it to CSV
38555         */
38556        flattenDirtyPanelMapToCSV : function () {
38557            var listOfDirtyPanels = "";
38558            _.each(_.keys(this.visitMap), function (key, index) {
38559                if (this.visitMap[key] === 0) {
38560                    listOfDirtyPanels += key + ",";
38561                }
38562            }, this);
38563            if (listOfDirtyPanels.length > 0) {
38564                // strip last ,
38565                listOfDirtyPanels = listOfDirtyPanels.substring(0, listOfDirtyPanels.length - 1);
38566            }
38567            return listOfDirtyPanels;
38568        },
38569        /**
38570         * This method finds and marks dirty all the lazy children that were dependant of global field's value
38571         * @param mapOfLazyChildren
38572         * @param listOfIdsOfDependents
38573         * @private
38574         */
38575        _findAndMarkDirty : function (mapOfLazyChildren, listOfIdsOfDependents) {
38576            var listOfLazyChildren = _.keys(mapOfLazyChildren);
38577
38578            _.each(listOfIdsOfDependents, function (depenId, index) {
38579                var longestPrefixLenSoFar = 0,
38580                    currentPrefixLen = 0,
38581                    nearestLazyId = null,
38582                    i;
38583                // find hierarchically closest field by matching longest som prefix
38584                for (i = 0; i < listOfLazyChildren.length; ++i) {
38585                    currentPrefixLen = guidelib.util.GuideUtil.commonPrefixLen(depenId, listOfLazyChildren[i]);
38586                    if (longestPrefixLenSoFar < currentPrefixLen) {
38587                        longestPrefixLenSoFar = currentPrefixLen;
38588                        nearestLazyId = listOfLazyChildren[i];
38589                    }
38590                }
38591                //  Mark dirty
38592                if (longestPrefixLenSoFar > 0) {
38593                    mapOfLazyChildren[nearestLazyId] = 0;
38594                }
38595            });
38596        },
38597        /**
38598         * Iterates a map and finds the first occurrence of value found in any key
38599         * @param map
38600         * @param value
38601         */
38602        _iterateMapAndReturnKeyOnValueFound : function (map, value) {
38603            var keyToReturn;
38604            _.each(_.keys(map), function (key, index) {
38605                if (map[key] === value) {
38606                    keyToReturn =  key;
38607                }
38608            });
38609            return keyToReturn;
38610        },
38611        /**
38612         * Updates the value of the key in map by one if present otherwise puts the key with value zero
38613         * @param map
38614         * @param key
38615         * @returns {*}
38616         */
38617        _updateCountOrInsert : function (map, key) {
38618            if (_.isUndefined(map[key])) {
38619                map[key] = 0;
38620            } else {
38621                map[key]++;
38622            }
38623
38624            return map;
38625        }
38626    });
38627
38628}($, _, window.guidelib));
38629
38630/*
38631 * ***********************************************************************
38632 * ADOBE CONFIDENTIAL
38633 * __________________
38634 *
38635 * Copyright 2016 Adobe Systems Incorporated
38636 * All Rights Reserved.
38637 *
38638 * NOTICE:  All information contained herein is, and remains
38639 * the property of Adobe Systems Incorporated and its suppliers,
38640 * if any.  The intellectual and technical concepts contained
38641 * herein are proprietary to Adobe Systems Incorporated and its
38642 * suppliers and may be covered by U.S. and Foreign Patents,
38643 * patents in process, and are protected by trade secret or copyright law.
38644 * Dissemination of this information or reproduction of this material
38645 * is strictly forbidden unless prior written permission is obtained
38646 * from Adobe Systems Incorporated.
38647 * ***********************************************************************
38648 */
38649
38650(function ($) {
38651    //Firing resize as, CSS is loaded after table mobile layout, cell width is adjusted for repeatable row, to accommodate +, - controls
38652    $(function () {
38653        $(window).trigger('resize');
38654    });
38655}($));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.