/* Minification failed. Returning unminified contents.
(2264,22-23): run-time error JS1195: Expected expression: ?
(2266,4-5): run-time error JS1002: Syntax error: }
(2267,44-45): run-time error JS1004: Expected ';': {
(2276,3-4): run-time error JS1002: Syntax error: }
(2278,56-57): run-time error JS1004: Expected ';': {
(2325,14-15): run-time error JS1003: Expected ':': ,
(2333,14-15): run-time error JS1003: Expected ':': ,
(2340,13-14): run-time error JS1003: Expected ':': ,
(2358,63-64): run-time error JS1195: Expected expression: >
(2365,5-6): run-time error JS1195: Expected expression: )
(2373,3-4): run-time error JS1002: Syntax error: }
(2375,54-55): run-time error JS1004: Expected ';': {
(2449,2-3): run-time error JS1002: Syntax error: }
(2454,74-75): run-time error JS1004: Expected ';': {
(2460,2-3): run-time error JS1195: Expected expression: )
(2461,26-27): run-time error JS1197: Too many errors. The file might not be a JavaScript file: [
(2448,3-14): run-time error JS1018: 'return' statement outside of function: return ctor
(2283,5-55): run-time error JS1018: 'return' statement outside of function: return phoneNo.replace(/-/g, '').replace(/ /g, '')
(2286,5-59): run-time error JS1018: 'return' statement outside of function: return phoneNo.replaceAll("-", "").replaceAll(" ", "")
(2279,18-32): run-time error JS1018: 'return' statement outside of function: return phoneNo
(2275,4-15): run-time error JS1018: 'return' statement outside of function: return true
 */
(function () {
    var global = this || (0, eval)('this');

    var config = {
        //baseUrl: '../',
        config: {
        },
        map: {
            '*': {
                'jquery': 'modules/jquery',
                'jQuery': 'modules/jquery',
                'modules/jquery': 'modules/jquery-private',
                'jasmine': 'modules/jasmine',
                'knockout': 'modules/knockout'
            },
            'modules/jquery-private': { 'modules/jquery': 'modules/jquery' },
            'modules/knockout': { 'knockout': 'knockout' },
            'knockout-amd-jquery-shim': { 'knockout': 'knockout' },
            'knockout-validation': { 'knockout': 'knockout' },
            'knockout-utils': { 'knockout': 'knockout' },
            'knockout-validation-extensions': { 'knockout': 'knockout' }
        },
        paths: {
            //botDetect : '/Investor/Scripts/lib/BotDetect/botDetect'
            'bignumber': '/Scripts/lib/bignumber/bignumber'
        },
        bundles: {
            'chartjs-bundle': ['chart']
        },
        shim: {
            'modules/jquery': {
                exports: '$'
            },
            'botDetect': {
                exports: 'BotDetect'
            }
        },
        waitSeconds: 60
    };

    if (!global.jQuery) {
        config.paths['modules/jquery'] = '/Scripts/lib/jQuery/jquery-1.12.3.min.js';
    } else {
        define('modules/jquery', [], function () {
            return global.jQuery;
        });
    };

    require.config(config);

    /// If this module is requested it will hide the $ from global scope
    define('modules/jquery-private', ['modules/jquery'], function ($) {
        return $.noConflict(true);
    });

    // Load the JSON reviver on first use
    define('modules/bignumberwrapper', ['bignumber', 'json-converter-bignumber'], function (BigNumber) {
        return BigNumber;
    });

    define('chartjs-core', ['chart'], function (chart) {
        return chart;
    });

    define('modules/knockout', ['knockout', 'knockout-validation', 'knockout-amd-jquery-shim', 'knockout-utils', 'knockout-validation-extensions'], function (ko, kv) {
        return ko;
    });

    define('modules/ko-debugging', ['modules/knockout', 'globalize', 'resources', 'configuration', 'jQuery', 'contentExplorer'], function (ko, g, r, c, $, ce) {
        window['ko'] = ko;
        window['Globalize'] = g;
        window.CPU = window.CPU || {};
        window.CPU.resources = r;
        window.CPU.configuration = c;
        window.CPU.contentExplorer = ce;

        return ko;
    });

    var appModules = ['InvestorResources',
        'InvestorAjax',
        'InvestorModals-Autocomplete'];
    var usedBindings = [
        /*'knockout-binding-chart' - on demand,*/
        'knockout-binding-resourceText',
        'knockout-binding-blockContext',
        'knockout-binding-number',
        'knockout-binding-date',
        'knockout-binding-validation-container',
        'knockout-binding-validation-summary',
        'knockout-binding-validation-text',
        'knockout-binding-pieChart',
        'knockout-binding-modals',
        'knockout-binding-clickToMessage',
        'knockout-binding-html',
        'knockout-margins',
        'knockout-binding-typeahead',
        'knockout-binding-attr',
        'knockout-binding-style',
        'knockout-binding-options',
        'knockout-binding-wizardPanel',
        'knockout-binding-carousel',
        'knockout-binding-scrollPosition',
        'knockout-binding-scrollTopAccordion',
        'knockout-binding-scrollTop',
        'knockout-binding-profileIconStatus',
        'knockout-binding-datepicker',
        'knockout-binding-fadeIf',
        'knockout-binding-tooltip',
        'knockout-binding-transaction-steps'];
    var usedComponents = ['knockout-component-modal',
        'knockout-component-captcha',
        'knockout-component-hcaptcha',
        'knockout-component-quicknavigationlinks-panel'];
    var usedExtenders = ['knockout-async',
        'knockout-ajaxValidator',
        'knockout-i18n',
        'knockout-computedArray',
        'knockout-validation-resources',
        'knockout-extender-resettable',
        'knockout-extender-MappingName',
        'knockout-extender-SubscribeWhenValid'];
    var usedDataTypes = [];
    var jQueryPlugins = [];

    if (Modernizr.touch) {
        jQueryPlugins.push('jquery-touch');
    }

    define('core', ['utils', 'icUtils', 'knockout', 'analytics-google'].concat(appModules).concat(usedDataTypes).concat(usedBindings).concat(usedComponents).concat(usedExtenders).concat(jQueryPlugins), function () {
    });

    var jsonPrefix = 'json!Scripts/lib/i18n/cultures/',
        i18nDeps = [
            'configuration',
            'globalize-knockout',
            jsonPrefix + 'core.json',
            'globalize-number',
            'globalize-plural',
            'globalize-currency',
            'globalize-date'];

    define('i18n', i18nDeps, function (config, g, localeData) {
        g.load(localeData);
        return g;
    });

})();;
if (typeof (BotDetect) == "undefined") { // start single inclusion guard

    BotDetect = function (captchaId, instanceId, inputId, autoFocusInput, autoClearInput, autoUppercaseInput, autoReloadExpiredImage, autoReloadPeriod, autoReloadTimeout, soundStartDelay, limitSoundRegeneration) {
        this.Id = captchaId;
        this.InstanceId = instanceId;

        // Captcha image properties
        var imageId = captchaId + "_CaptchaImage";
        this.Image = document.getElementById(imageId);
        this.ImagePlaceholder = this.Image.parentNode;

        this.ControlsDisabled = false;

        // check for Captcha Reload icon presence
        var reloadLinkId = captchaId + "_ReloadLink";
        var reloadLink = document.getElementById(reloadLinkId);
        if (reloadLink) {
            // show Captcha Reload icon
            reloadLink.style.cssText = 'display: inline-block !important';

            // init reloading elements
            this.NewImage = null;
            this.ProgressIndicator = null;
            this.ReloadTimer = null;
            this.ReloadTimerTicks = 0;

            // Captcha image auto-reloading
            this.AutoReloadPeriod = Math.max((autoReloadPeriod - 10), 10) * 1000;
            this.AutoReloadTimeout = autoReloadTimeout * 1000;
            this.AutoReloadExpiredImage = autoReloadExpiredImage;
            this.AutoReloadPeriodSum = 0;
            this.AutoReloading = false;
            if (autoReloadExpiredImage) {
                if (this.AutoReloadTimer) { clearTimeout(this.AutoReloadTimer); }
                var self = this;
                this.AutoReloadTimer = setTimeout(
                  function () {
                      clearTimeout(self.AutoReloadTimer);
                      if (self.AutoReloadPeriodSum >= self.AutoReloadTimeout) { self.DisableControls(); self.SessionExpired = true; return; }
                      self.AutoReloading = true;
                      self.ReloadImage();
                      self.AutoReloading = false;
                      self.AutoReloadPeriodSum += self.AutoReloadPeriod;
                      self = null;
                  },
                  self.AutoReloadPeriod
                );
            }
        }

        // pre-load disabled reload icon
        var reloadIcon = document.getElementById(this.Id + "_ReloadIcon");
        if (reloadIcon) {
            this.ReloadIconSrc = document.getElementById(this.Id + "_ReloadIcon").src;
            this.DisabledReloadIconSrc = null;
            var preloadedReloadIcon = document.createElement('img');
            var self2 = this;
            preloadedReloadIcon.onload = function () {
                self2.DisabledReloadIconSrc = this.src;
                self2 = null;
            };
            preloadedReloadIcon.src = this.ReloadIconSrc.replace('ReloadIcon', 'DisabledReloadIcon');
        }

        // Captcha sound properties
        this.SoundStartDelay = soundStartDelay;
        this.LimitSoundRegeneration = limitSoundRegeneration;
        this.SoundPlayed = false;
        this.SoundPlayDelayed = false;
        var soundLinkId = captchaId + "_SoundLink";
        var soundFullUrlId = captchaId + "_SoundFullUrl";
        var soundLink = document.getElementById(soundLinkId);
        if (soundLink) {
            this.SoundUrl = soundLink.href;
        }
        var soundFullUrl = document.getElementById(soundFullUrlId);
        if (soundFullUrl) {
            this.soundFullUrl = soundFullUrl.href;
        }
        var soundPlaceholderId = captchaId + "_AudioPlaceholder";
        this.SoundPlaceholder = document.getElementById(soundPlaceholderId);

        // pre-load disabled sound icon
        var soundIcon = document.getElementById(this.Id + "_SoundIcon");
        if (soundIcon) {
            this.SoundIconSrc = document.getElementById(this.Id + "_SoundIcon").src;
            this.DisabledSoundIconSrc = null;
            var preloadedSoundIcon = document.createElement('img');
            var self3 = this;
            preloadedSoundIcon.onload = function () {
                self3.DisabledSoundIconSrc = this.src;
                self3 = null;
            };
            preloadedSoundIcon.src = this.SoundIconSrc.replace('SoundIcon', 'DisabledSoundIcon');
        }

        // Captcha input textbox properties
        this.ValidationUrl = this.Image.src.replace('get=image', 'get=validationResult');

        // Captcha help link properties
        this.FollowHelpLink = true;

        // Captcha code user input element registration, helpers & processing
        if (!inputId) return;
        this.InputId = inputId;
        var input = document.getElementById(inputId);
        if (!input) return;

        input.Captcha = this; // allow access to the BotDetect object via the input element
        this.ValidationResult = false; // used for Ajax validation

        // automatic input processing
        this.AutoFocusInput = autoFocusInput;
        this.AutoClearInput = autoClearInput;
        if (autoUppercaseInput) {
            input.style.textTransform = 'uppercase';
        }
    };

    BotDetect.Init = function (captchaId, instanceId, inputId, autoFocusInput, autoClearInput, autoUppercaseInput, autoReloadExpiredImage, autoReloadPeriod, autoReloadTimeout, soundStartDelay, limitSoundRegeneration) {
        var inputIdString = null;
        if (inputId) {
            inputIdString = "'" + inputId + "'";
        }

        var actualInitialization = new Function("if (document.getElementById('" + captchaId + "_CaptchaImage')) { window['" + captchaId + "'] = new BotDetect('" + captchaId + "', '" + instanceId + "', " + inputIdString + ", " + autoFocusInput + ", " + autoClearInput + ", " + autoUppercaseInput + ", " + autoReloadExpiredImage + ", " + autoReloadPeriod + ", " + autoReloadTimeout + ", " + soundStartDelay + ", " + limitSoundRegeneration + "); window['" + captchaId + "'].PostInit(); }");

        if ((typeof (Sys) != "undefined") && (typeof (Sys.Application) != "undefined")) {
            // ASP.NET Ajax initialization
            Sys.Application.add_load(actualInitialization);
        } else if (typeof (window.jQuery) != "undefined") {
            // jQuery initalization
            jQuery(actualInitialization);
        } else {
            // regular initialization
            BotDetect.RegisterHandler(window, 'domready', actualInitialization, false);
        }

        // back button image reload to avoid cache issues
        if (window.opera) {
            BotDetect.RegisterHandler(window, 'popstate', function (e) { window[captchaId].ReloadImage(); }, false);
        } else if (window.chrome) {
            BotDetect.RegisterHandler(window, 'domready', function (e) { var el = document.getElementById("LBD_BackWorkaround_" + captchaId); if (el.value == "0") { el.value = "1"; } else { el.value = "0"; window[captchaId].ReloadImage(); } }, false);
        } else { // firefox & safari
            BotDetect.RegisterHandler(window, 'pageshow', function (e) { var el = document.getElementById("LBD_BackWorkaround_" + captchaId); if (el.value == "0") { el.value = "1"; } else { window[captchaId].ReloadImage(); } }, false);
        }
    };


    // constants
    BotDetect.ReloadTimerMaxTicks = 100;
    BotDetect.ReloadTimerDelay = 250;
    BotDetect.MillisecondsInAMinute = 60000;
    BotDetect.AjaxTimeout = 10000;
    BotDetect.MinSoundCooldown = 2000;


    // CAPTCHA image reloading
    BotDetect.prototype.ReloadImage = function () {
        if (this.Image && !this.ReloadInProgress && !this.SessionExpired && (!this.ControlsDisabled || this.SoundPlayDelayed)) {
            this.ReloadInProgress = true;
            this.DisableControls();
            this.ProgressIndicator = document.createElement('span');
            this.ProgressIndicator.className = 'LBD_ProgressIndicator';
            this.ProgressIndicator.appendChild(document.createTextNode('.'));
            this.PreReloadImage();

            var imageUrl = BotDetect.UpdateTimestamp(this.Image.src);
            this.InitNewImage(imageUrl);

            this.ImagePlaceholder.innerHTML = '';
            this.ImagePlaceholder.appendChild(this.ProgressIndicator);

            this.ShowProgress();
        }
    };

    BotDetect.prototype.InitNewImage = function (imageUrl) {
        this.NewImage = document.createElement('img');
        var self = this;
        this.NewImage.onload = function () {
            if (self.NewImage && self.ImagePlaceholder && self.ProgressIndicator) {
                self.ImagePlaceholder.innerHTML = '';
                self.ImagePlaceholder.appendChild(self.NewImage);
                self.Image = self.NewImage;
                self.ProgressIndicator = null;
                self.PostReloadImage();
                self = null;
            }
        };
        this.NewImage.id = this.Image.id;
        this.NewImage.alt = this.Image.alt;
        this.NewImage.src = imageUrl;
    };

    BotDetect.prototype.ShowProgress = function () {
        if (this.ProgressIndicator && (this.ReloadTimerTicks < BotDetect.ReloadTimerMaxTicks)) {
            this.ReloadTimerTicks = this.ReloadTimerTicks + 1;
            this.UpdateProgressIndicator();
            var self = this;
            this.ReloadTimer = setTimeout(function () { self.ShowProgress(); self = null; }, BotDetect.ReloadTimerDelay);
        } else {
            clearTimeout(this.ReloadTimer);
            this.ReloadTimerTicks = 0;
            this.ReloadInProgress = false;
        }
    };

    BotDetect.prototype.UpdateProgressIndicator = function () {
        if (0 == this.ProgressIndicator.childNodes.length) {
            this.ProgressIndicator.appendChild(document.createTextNode('.'));
            return;
        }
        if (0 === this.ReloadTimerTicks % 5) {
            this.ProgressIndicator.firstChild.nodeValue = '.';
        } else {
            this.ProgressIndicator.firstChild.nodeValue = this.ProgressIndicator.firstChild.nodeValue + '.';
        }
    };


    // CAPTCHA sound playing
    BotDetect.prototype.PlaySound = function () {
        if (!document.getElementById || this.SoundPlayingInProgess || (this.ControlsDisabled && !this.SoundPlayDelayed)) { return; }

        this.DisableControls();

        //if (this.LimitSoundRegeneration && !BotDetect.SoundReplaySupported()) {
        //    // reload the captcha image and play the new sound
        //    if (this.SoundPlayed) {
        //        this.SoundPlayDelayed = true;
        //        this.ReloadImage();
        //        return;
        //    }
        //}

        this.SoundPlayingInProgess = true;

        if (BotDetect.UseHtml5Audio()) { // html5 audio
            var self = this;
            var sound = document.getElementById('LBD_CaptchaSoundAudio_' + this.Id);
            if (sound) { // replay existing audio, with the correct delay
                sound.currentTime = 0;

                this.SoundStartDelayTimer = setTimeout(
                  function () {
                      if (self) {
                          clearTimeout(self.SoundStartDelayTimer);
                          self.PrePlaySound();
                          var sound = document.getElementById('LBD_CaptchaSoundAudio_' + self.Id);
                          sound.play();
                      }
                  },
                  this.SoundStartDelay
                );

            } else { // play new audio
                this.SoundPlaceholder.innerHTML = '';
                var soundUrl = this.SoundUrl;
                soundUrl = BotDetect.UpdateTimestamp(soundUrl);
                soundUrl = BotDetect.DetectSsl(soundUrl);
                sound = new Audio(soundUrl);
                sound.id = 'LBD_CaptchaSoundAudio_' + this.Id;
                sound.type = 'audio/wav';
                sound.autobuffer = false;
                sound.loop = false;
                sound.autoplay = false;
                sound.preload = 'auto';
                this.SoundPlaceholder.appendChild(sound);

                sound.load();
                BotDetect.RegisterHandler( // start counting the starting delay only when the sound is loaded
                  sound,
                  'canplay',
                  function () {
                      if (self) {
                          self.SoundStartDelayTimer = setTimeout(
                            function () {
                                clearTimeout(self.SoundStartDelayTimer);
                                self.PrePlaySound();
                                var sound = document.getElementById('LBD_CaptchaSoundAudio_' + self.Id);
                                sound.play();
                            },
                            this.SoundStartDelay
                          );
                      }
                  },
                  false
                );
            }

            // enable controls & other after-play cleanup
            BotDetect.RegisterHandler(
              sound,
              'ended',
              function () {
                  if (self) {
                      var sound = document.getElementById('LBD_CaptchaSoundAudio_' + self.Id);
                      if (sound.duration == 1) { // Android 4.0.4 issue
                          sound.play();
                      } else {
                          self.SoundPlayingInProgess = false;
                          self.EnableControls();
                          self = null;
                      }
                  }
              },
              false
            );

        } else { // xhtml embed + object
            this.SoundPlaceholder.innerHTML = '';
            var self = this;
            this.SoundStartDelayTimer = setTimeout(
              function () {
                  clearTimeout(self.SoundStartDelayTimer);
                  self.PrePlaySound();
                  self.StartXhtmlSoundPlayback();
              },
              this.SoundStartDelay
            );
        }

        this.SoundPlayed = true;
    };


    BotDetect.prototype.StartXhtmlSoundPlayback = function () {
        var soundUrl = this.soundFullUrl;
        soundUrl = BotDetect.UpdateTimestamp(soundUrl);
        soundUrl = BotDetect.DetectSsl(soundUrl);

        var objectSrc = "<object id='LBD_CaptchaSoundObject_" + this.Id + "' classid='clsid:22D6F312-B0F6-11D0-94AB-0080C74C7E95' height='0' width='0' style='width:0; height:0;'><param name='AutoStart' value='1' /><param name='Volume' value='0' /><param name='PlayCount' value='1' /><param name='FileName' value='" + soundUrl + "' /><embed id='LBD_CaptchaSoundEmbed' src='" + soundUrl + "' autoplay='true' hidden='true' volume='100' type='" + BotDetect.GetMimeType() + "' style='display:inline;' /></object>";

        this.SoundPlaceholder.innerHTML = objectSrc;

        var self = this;
        this.SoundCooldownTimer = setTimeout(
          function () {
              if (self) {
                  clearTimeout(self.SoundCooldownTimer);
                  self.SoundPlayingInProgess = false;
                  self.EnableControls();
                  self = null;
              }
          },
          BotDetect.MinSoundCooldown
        );
    };


    // input element access
    BotDetect.prototype.GetInputElement = function () {
        return document.getElementById(this.InputId);
    };

    // CAPTCHA Ajax validation
    BotDetect.prototype.Validate = function () {
        if (BotDetect.AjaxError) { return true; } // temporary to allow full form post
        var input = this.GetInputElement();
        if (!input || !input.value || input.value.length < 0) {
            this.AjaxValidationFailed();
            return false;
        }
        if (!this.ValidationResult) {
            this.PreAjaxValidate();
            this.StartValidation();
        }
        return this.ValidationResult;
    };

    BotDetect.prototype.StartValidation = function () {
        var input = this.GetInputElement();
        var url = this.ValidationUrl + '&i=' + input.value;
        var self = this;
        var callback = function (y) {
            clearTimeout(self.AjaxTimer);
            if (200 != y.status) { self.AjaxValidationError(); self = null; return; }
            var validationResult = false;
            var parsed = BotDetect.ParseJson(y.responseText);
            if (parsed) {
                validationResult = parsed;
            }
            self.EndValidation(validationResult);
            self = null;
        }
        this.AjaxTimer = setTimeout(self.AjaxValidationError, BotDetect.AjaxTimeout);
        BotDetect.Get(url, callback);
    };

    BotDetect.prototype.EndValidation = function (result) {
        if (result) {
            this.ValidationResult = true;
            this.AjaxValidationPassed();
        } else {
            this.AjaxValidationFailed();
        }
    };

    BotDetect.ParseJson = function (jsonString) {
        var resultObj = null;
        if ("undefined" != typeof (JSON) && "function" == typeof (JSON.parse)) {
            resultObj = JSON.parse(jsonString);
        }
        if (!resultObj) {
            resultObj = eval('(' + jsonString + ')');
        }
        return resultObj;
    };


    // custom CAPTCHA events

    BotDetect.prototype.PostInit = function () {
    };

    BotDetect.prototype.PreReloadImage = function () {
        this.ClearInput();
        this.FocusInput();
    };

    BotDetect.prototype.PostReloadImage = function () {
        this.ValidationUrl = this.Image.src.replace('get=image', 'get=validationResult');

        if (this.AutoReloadExpiredImage) {
            if (this.AutoReloadTimer) { clearTimeout(this.AutoReloadTimer); }
            var self = this;
            this.AutoReloadTimer = setTimeout(
              function () {
                  clearTimeout(self.AutoReloadTimer);
                  if (self.AutoReloadPeriodSum >= self.AutoReloadTimeout) { self.DisableControls(); self.SessionExpired = true; return; }
                  self.AutoReloading = true;
                  self.ReloadImage();
                  self.AutoReloading = false;
                  self.AutoReloadPeriodSum += self.AutoReloadPeriod;
                  self = null;
              },
              self.AutoReloadPeriod
            );
        }

        if (this.SoundIconSrc) {
            this.SoundPlaceholder.innerHTML = '';
            this.SoundPlayed = false;
            if (this.SoundPlayDelayed) {
                this.PlaySound();
                this.SoundPlayDelayed = false;
            } else {
                this.EnableControls();
            }
        } else {
            this.EnableControls();
        }
    };

    BotDetect.prototype.PrePlaySound = function () {
        this.FocusInput();
    };

    BotDetect.prototype.OnHelpLinkClick = function () {
    };

    BotDetect.prototype.PreAjaxValidate = function () {
    };

    BotDetect.prototype.AjaxValidationFailed = function () {
        this.ReloadImage();
    };

    BotDetect.prototype.AjaxValidationPassed = function () {
    };

    BotDetect.prototype.AjaxValidationError = function () {
        BotDetect.Xhr().abort();
        BotDetect.AjaxError = true;
    };

    BotDetect.RegisterCustomHandler = function (eventName, userHandler) {
        var oldHandler = BotDetect.prototype[eventName];
        BotDetect.prototype[eventName] = function () {
            oldHandler.call(this);
            userHandler.call(this);
        }
    };

    // input processing
    BotDetect.prototype.FocusInput = function () {
        var input = this.GetInputElement();
        if (!this.AutoFocusInput || !input) return;
        if (this.AutoReloading) return;
        input.focus();
    };

    BotDetect.prototype.ClearInput = function () {
        var input = this.GetInputElement();
        if (!this.AutoClearInput || !input) return;
        input.value = '';
    };


    // helpers

    BotDetect.UpdateTimestamp = function (url) {
        var i = url.indexOf('&d=');
        if (-1 !== i) {
            url = url.substring(0, i);
        }
        return url + '&d=' + BotDetect.GetTimestamp();
    };

    BotDetect.GetTimestamp = function () {
        var d = new Date();
        var t = d.getTime() + (d.getTimezoneOffset() * BotDetect.MillisecondsInAMinute);
        return t;
    };

    BotDetect.DetectSsl = function (url) {
        var i = url.indexOf('&e=');
        if (-1 !== i) {
            var len = url.length;
            url = url.substring(0, i) + url.substring(i + 4, len);
        }
        if (document.location.protocol === "https:") {
            url = url + '&e=1';
        }
        return url;
    };

    BotDetect.GetMimeType = function () {
        var mimeType = "audio/x-wav";
        return mimeType;
    };

    BotDetect.UseHtml5Audio = function () {
        var html5SoundSupported = false;
        if (BotDetect.DetectAndroid() || BotDetect.DetectIOS()) {
            html5SoundSupported = true;  // Android says it can't play audio even when it can; assuming iOS uses Html5 simplifies further browser checks
        } else {
            var browserCompatibilityCheck = document.createElement('audio');
            html5SoundSupported = (
              !!(browserCompatibilityCheck.canPlayType) &&
              !!(browserCompatibilityCheck.canPlayType("audio/wav")) &&
              !BotDetect.DetectIncompatibleAudio() // some browsers say they support the audio even when they have issues playing it
            );
        }
        return html5SoundSupported;
    };

    BotDetect.DetectIncompatibleAudio = function () {
        return BotDetect.DetectFirefox3() || BotDetect.DetectSafariSsl();
    };

    BotDetect.DetectAndroid = function () {
        var detected = false;
        if (navigator && navigator.userAgent) {
            var matches = navigator.userAgent.match(/Linux; U; Android/);
            if (matches) {
                detected = true;
            }
        }
        return detected;
    };

    BotDetect.DetectIOS = function () {
        var detected = false;
        if (navigator && navigator.userAgent) {
            var matches = navigator.userAgent.match(/like Mac OS/);
            if (matches) {
                detected = true;
            }
        }
        return detected;
    };

    BotDetect.DetectFirefox3 = function () {
        var detected = false;
        if (navigator && navigator.userAgent) {
            var matches = navigator.userAgent.match(/(Firefox)\/(3\.6\.[^;\+,\/\s]+)/);
            if (matches) {
                detected = true;
            }
        }
        return detected;
    };

    BotDetect.DetectSafariSsl = function () {
        var detected = false;
        if (navigator && navigator.userAgent) {
            var matches = navigator.userAgent.match(/Safari/);
            if (matches) {
                matches = navigator.userAgent.match(/Chrome/);
                if (!matches && document.location.protocol === "https:") {
                    detected = true;
                }
            }
        }
        return detected;
    };

    BotDetect.DetectAndroidBelow41 = function () {
        var detected = false;
        if (navigator && navigator.userAgent) {
            var i = navigator.userAgent.indexOf("Android");
            if (i >= 0) {
                var v = parseFloat(navigator.userAgent.slice(i + 8));
                if (v < 4.1) {
                    detected = true;
                }
            }
        }
        return detected;
    }

    BotDetect.SoundReplaySupported = function () {
        return (BotDetect.UseHtml5Audio() &&
                    !BotDetect.DetectAndroidBelow41());
    };

    BotDetect.prototype.DisableControls = function () {
        this.ControlsDisabled = true;
        this.DisableReloadIcon();
        this.DisableSoundIcon();
    }

    BotDetect.prototype.EnableControls = function () {
        this.ControlsDisabled = false;
        this.EnableReloadIcon();
        this.EnableSoundIcon();
    }

    BotDetect.prototype.DisableReloadIcon = function () {
        if (this.ReloadIconSrc) {
            if (this.DisabledReloadIconSrc) {
                document.getElementById(this.Id + "_ReloadIcon").src = this.DisabledReloadIconSrc;
            }
        }
    };

    BotDetect.prototype.EnableReloadIcon = function () {
        if (this.ReloadIconSrc) {
            if (this.DisabledReloadIconSrc) {
                document.getElementById(this.Id + "_ReloadIcon").src = this.ReloadIconSrc;
            }
        }
    };

    BotDetect.prototype.DisableSoundIcon = function () {
        if (this.SoundIconSrc) {
            if (this.DisabledSoundIconSrc) {
                document.getElementById(this.Id + "_SoundIcon").src = this.DisabledSoundIconSrc;
            }
        }
    };

    BotDetect.prototype.EnableSoundIcon = function () {
        if (this.SoundIconSrc) {
            if (this.DisabledSoundIconSrc) {
                document.getElementById(this.Id + "_SoundIcon").src = this.SoundIconSrc;
            }
        }
    };

    // standard events & handlers
    BotDetect.RegisterHandler = function (target, eventType, functionRef, capture) {
        // special case
        if (eventType == "domready") {
            BotDetect.RegisterDomReadyHandler(functionRef);
            return;
        }
        // normal event registration
        if (typeof target.addEventListener != "undefined") {
            target.addEventListener(eventType, functionRef, capture);
        } else if (typeof target.attachEvent != "undefined") {
            var functionString = eventType + functionRef;
            target["e" + functionString] = functionRef;
            target[functionString] = function (event) {
                if (typeof event == "undefined") {
                    event = window.event;
                }
                target["e" + functionString](event);
            };
            target.attachEvent("on" + eventType, target[functionString]);
        } else {
            eventType = "on" + eventType;
            if (typeof target[eventType] == "function") {
                var oldListener = target[eventType];
                target[eventType] = function () {
                    oldListener();
                    return functionRef();
                };
            } else {
                target[eventType] = functionRef;
            }
        }
    };

    // earlier than window.load, if possible
    BotDetect.RegisterDomReadyHandler = function (functionRef) {
        if (document.addEventListener) {
            document.addEventListener("DOMContentLoaded",
              function () {
                  document.removeEventListener("DOMContentLoaded", arguments.callee, false);
                  functionRef();
              },
              false
            );
            return;
        }
        else if (document.attachEvent) {
            var called = false;
            document.attachEvent("onreadystatechange",
              function () {
                  if (document.readyState === "complete") {
                      document.detachEvent("onreadystatechange", arguments.callee);
                      functionRef();
                      called = true;
                  }
              }
            );
            if (document.documentElement.doScroll && window == window.top) {
                (function () {
                    if (called) return;
                    try {
                        document.documentElement.doScroll("left");
                    } catch (error) {
                        setTimeout(arguments.callee, 1);
                        return;
                    }
                    functionRef();
                    called = true;
                })();
            }
            return;
        } else {
            BotDetect.RegisterHandler(window, 'load', functionRef, false);
        }
    };


    // Ajax helper
    BotDetect.Xhr = function () {
        var x = null;
        try { x = new XMLHttpRequest(); return x; } catch (e) { }
        try { x = new ActiveXObject('MSXML2.XMLHTTP.5.0'); return x; } catch (e) { }
        try { x = new ActiveXObject('MSXML2.XMLHTTP.4.0'); return x; } catch (e) { }
        try { x = new ActiveXObject('MSXML2.XMLHTTP.3.0'); return x; } catch (e) { }
        try { x = new ActiveXObject('MSXML2.XMLHTTP'); return x; } catch (e) { }
        try { x = new ActiveXObject('Microsoft.XMLHTTP'); return x; } catch (e) { }
        return x;
    };

    BotDetect.Get = function (url, callback) {
        BotDetect.AjaxError = false;
        var x = BotDetect.Xhr();
        if (x && 0 == x.readyState) {
            x.onreadystatechange = function () {
                if (4 == x.readyState) {
                    callback(x);
                }
            }
            x.open('GET', url, true);
            x.send();
        }
    };

} // end single inclusion guard

// required for ASP.NET Ajax compatibility
if ((typeof (Sys) != "undefined") && (typeof (Sys.Application) != "undefined")) {
    Sys.Application.notifyScriptLoaded();
};
define('BrowserPopup-Helper', ['messenger'], function(messenger) {
    var showBrowserPopup = function(versions) {
        var result = getBrowser();
        // Ignore blank user agents
        if (result.n === "e") return;
        // Ignore bot spiders
        if (result.n === "b") return;
        // Don't show for mobile browsers
        if (result.n === "m") return;
        // Check browser versions for browsers that we support
        if (result.n === "c" && result.v >= versions.c) return;
        if (result.n === "i" && result.v >= versions.i) return;
        if (result.n === "s" && result.v >= versions.s) return;
        if (result.n === "f" && result.v >= versions.f) return;

        var browserModal = document.getElementById("unsupportedBrowserModal");
        var browserModalClose = document.getElementById("browserModalClose");

        // Toggle Modal Open / Close for Responsive
        if (browserModal && browserModalClose) {
            browserModal.style.display = "block";

            browserModal.classList.add("in");
            document.documentElement.classList.add("modal-open");

            browserModalClose.addEventListener("click", function() {
                browserModal.classList.remove("in");
                document.documentElement.classList.remove("modal-open");
                browserModal.style.zIndex = "-1";
            });
        }

        // if older version or a different browser show popup
        //var window = $('#PopupWindow');
        //window.find('.t-window-content').width(750).height(400);
        //window.data('tWindow').center().content($('#PopupContent').html()).open();

        googleAnalytics.trackEvent("BrowserPopup", "LightBox", "Open");
    };

    //browser-update.org notification script, <browser-update.org>
    //Copyright (c) 2007-2014, MIT Style License <browser-update.org/LICENSE.txt>
    var getBrowser = function() {
        var n;
        var ua = navigator.userAgent;
        // if user agent is blank, do not do any checks
        if (!ua) return { n: "e", v: 0 }
        var names = {
            i: 'Internet Explorer',
            f: 'Firefox',
            o: 'Opera',
            s: 'Apple Safari',
            n: 'Netscape Navigator',
            c: "Chrome",
            x: "Other",
            m: "Mobile",
            b: "Bot",
            "e": "Empty"
        };
        // if it's a bot, ignore it
        if (/bot/i.test(ua)) n = "b";
        // Firt of all, check if it's a mobile browser.
        else if (
            /android|bb\d+|meego\).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od|ad)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino|blackberry|android|phone|opera mini|moblin|android|mobile|symbian/i
                .test(ua)) n = "m";
        else if (
            /bot|googlebot|facebook|slurp|wii|silk|blackberry|maxthon|maxton|mediapartners|dolfin|dolphin|adsbot|silk|android|phone|bingbot|google web preview|like firefox|chromeframe|seamonkey|opera mini|min|meego|netfront|moblin|maemo|arora|camino|flot|k-meleon|fennec|kazehakase|galeon|android|mobile|iphone|ipod|ipad|epiphany|rekonq|symbian|webos/i
                .test(ua)) n = "x";
        else if (/Trident.*rv:(\d+\.\d+)/i.test(ua)) n = "i";
        else if (/Trident.(\d+\.\d+)/i.test(ua)) n = "io";
        else if (/MSIE.(\d+\.\d+)/i.test(ua)) n = "i";
        else if (/OPR.(\d+\.\d+)/i.test(ua)) n = "o";
        else if (/Chrome.(\d+\.\d+)/i.test(ua)) n = "c";
        else if (/Firefox.(\d+\.\d+)/i.test(ua)) n = "f";
        else if (/Version.(\d+.\d+).{0,10}Safari/i.test(ua)) n = "s";
        else if (/Safari.(\d+)/i.test(ua)) n = "so";
        else if (/Opera.*Version.(\d+\.\d+)/i.test(ua)) n = "o";
        else if (/Opera.(\d+\.?\d+)/i.test(ua)) n = "o";
        else if (/Netscape.(\d+)/i.test(ua)) n = "n";
        else return { n: "x", v: 0, t: names[n] };

        var v = parseFloat(RegExp.$1);
        var donotnotify = false;
        //do not notify ver old systems since their is no up-to-date browser available
        if (/windows.nt.5.0|windows.nt.4.0|windows.98|os x 10.4|os x 10.5|os x 10.3|os x 10.2/.test(ua))
            donotnotify = "oldOS";

        //do not notify firefox ESR
        if (n == "f" && Math.round(v) == 24)
            donotnotify = "ESR";
        //do not notify opera 12 on linux since it is the latest version
        if (/linux|x11|unix|bsd/.test(ua) && n == "o" && v > 12)
            donotnotify = "Opera12Linux";

        if (n == "x") return { n: "x", v: v || 0, t: names[n], donotnotify: donotnotify };


        if (n == "so") {
            v = ((v < 100) && 1.0) ||
                ((v < 130) && 1.2) ||
                ((v < 320) && 1.3) ||
                ((v < 520) && 2.0) ||
                ((v < 524) && 3.0) ||
                ((v < 526) && 3.2) ||
                4.0;
            n = "s";
        }
        if (n == "i" && v == 7 && window.XDomainRequest) {
            v = 8;
        }
        if (n == "io") {
            n = "i";
            if (v > 6) v = 11;
            else if (v > 5) v = 10;
            else if (v > 4) v = 9;
            else if (v > 3.1) v = 8;
            else if (v > 3) v = 7;
            else v = 9;
        }
        return { n: n, v: v, t: names[n] + " " + v, donotnotify: donotnotify };
    };

    return {
        showBrowserPopup: showBrowserPopup,
        getBrowser: getBrowser
    };
});;
define('CommonModels', ['knockout', 'globalize-knockout'], function (ko, globalize) {

    var MenuGroup = (function () {
        var ctor = function MenuGroup(name, requiresAuth, links, cbVisible) {
            this.name = ko.observable(name);
            this.requiresAuth = ko.observable(!!requiresAuth);
            this.menuItems = ko.observableArray(links);
            this.chromeMenuItems = ko.observableArray(links);

            if(!(cbVisible && typeof (cbVisible) == 'function')) {
                cbVisible = function() { return true; };
            }
            this.isVisible = ko.computed(cbVisible, this);
        };

        return ctor;
    })();

    var Link = (function () {
        var ctor = function Link(url, text, icon, requiresAuth, target, key, cbVisible) {
            this.url = ko.observable(url);
            this.title = ko.observable(text);
            this.icon = ko.observable(icon || '');
            this.requiresAuth = ko.observable(!!requiresAuth);
            this.target = ko.observable(target || '_self');
            this.key = ko.observable(key || '');

            if (!(cbVisible && typeof (cbVisible) == 'function')) {
                cbVisible = function () { return true; };
            }
            this.isVisible = ko.computed(cbVisible, this);

            // Used for GA4 tracking.
            // We should use 'key' in the Link()
            // We set the 'id' attr in the html code using trackingId
            this.id = setGA4Id("Link", this.key());                      
            this.trackingId = ko.observable(this.id);
        };

        return ctor;
    })();

    var ActionLink = (function () {
        var ctor = function Link(url, text, icon, message, requiresAuth, target, info) {
            this.url = ko.observable(url);
            this.title = ko.observable(text);
            this.icon = ko.observable(icon || '');
            this.requiresAuth = ko.observable(!!requiresAuth);
            this.target = ko.observable(target || '_self');
            this.message = ko.observable(message);
            this.info = ko.observable(info);

            // Used for GA4 tracking.
            // We should use 'message' in the ActionLink()
            // We set the 'id' attr in the html code using trackingId
            this.id = setGA4Id("ActionLink", this.message());
            this.trackingId = ko.observable(this.id);
        };

        return ctor;
    })();

    var Money = (function () {
        var ctor = function Money(currency, value) {

            this.currency = ko.observable(currency || globalize.defaultCurrency());
            this.value = ko.numberObservable(value, 0);

            if (currency && currency != globalize.defaultCurrency()) {
                //show currency code if it is not consistent
                this.forceCode = true;
            }
		
            this.add = function (other) {
                if (!this.currency()) {
                    return new Money(other.currency(), other.value());
                }
                if (other.currency() != this.currency() && this.value() ) {
                    throw new Error("Cannot add different currencies");
                }
                return new Money(other.currency(), this.value() + other.value());
            };

            this.mult = function (multiplier) {
                return new Money(this.currency(), this.value() * multiplier);
            };

            this.toString = ko.computed(function () {
                return globalize.locale() ? globalize.formatCurrency(this.value(), this.currency()) : this.value();
            }, this);

        };

        return ctor;
    })();

    var ActionMenu = (function () {
        var ctor = function Link(holdingKey, url, title, message, requiresAuth, target, info) {
            this.holdingKey = ko.observable(holdingKey);
            this.url = ko.observable(url);
            this.title = ko.observable(title);
            this.requiresAuth = ko.observable(!!requiresAuth);
            this.target = ko.observable(target || '_self');
            this.message = ko.observable(message);
            this.info = ko.observable(info);

            // Used for GA4 tracking.
            // We should use 'title' in the ActionMenu()
            // We set the 'id' attr in the html code using trackingId
            this.id = setGA4Id("ActionMenu", this.title());
            this.trackingId = ko.observable(this.id);            
        };

        return ctor;
    })();

    function setGA4Id(linkType, id) {
        this.trackingId = '';

        switch (linkType) {
            case 'ActionMenu': {
                this.trackingId = 'action-menu-idUnknown';
            }
            case 'Link': {
                this.trackingId = 'link-idUnknown';
            }
            default: {
                this.trackingId = 'action-link-idUnknown';
            }
        }       

        if (id !== undefined && id !== null && id !== '') {
            // replace '#', '/' and spaces with empty string
            this.trackingId = id.replace(/#/g, '').replace(/\//g, '-').replace(/\s/g, '');
        }
       
        return this.trackingId;
    }

    return {
        Money: Money,
        Link: Link,
        ActionLink: ActionLink,
        MenuGroup: MenuGroup,
        ActionMenu: ActionMenu
    };
});;
(function () {

    var global = this || (0, eval)('this'),
    document = global['document'],
    moduleName = 'contentExplorer-templates',
    dependencies = ['jQuery'];

    var moduleDance = function (factory) {
        // Module systems magic dance.

        if (typeof define === "function" && define["amd"]) {
            define(moduleName, dependencies.concat('exports'), factory);
        } else {
            // using explicit <script> tags with no loader
            global.CPU = global.CPU || {};
            global.CPU.contextExplorerTemplates = factory($);
        }
    };

    var factory = function ($) {

        // template="investor2-template"
        var investorResource = function (locale, queryXML, results) {

            /*
             *  Sample Query XML                                    ╒═══ {locale}
                <content-query template="investor2-resource" lang="en-au" appcode="INVCEN" url="/Investor/Home/Index" content-status="draft">
                  <content-query>
                    <qualifier name="resource-group" value="Home-Navigation" />                         <== {resource-group}
                    <qualifier name="country-code" value="AU" />
                  </content-query>
                </content-query>

             *  Sample Query Result XML
                <investor2-resource id="{DC0FBF10-6051-416A-AC63-3E5FCE306833}" label="Existing User Login Button Label" xml:lang="en" version="1" status="checkedout">
                    <resource-key label="Key"><![CDATA[ExistingUserLoginButtonLabel]]></resource-key>   <== {key}
                    <resource-value label="Value"><![CDATA[Existing user login]]></resource-value>
                </investor2-resource>
            */

            var resourceGroupMatcher = /name="resource-group" value="([^"]+)/,
                resourceKeyName = /resource-key label="Key"><!\[CDATA\[([^\]]+)/,
                resourceGroup = queryXML.match(resourceGroupMatcher);

            if (!resourceGroup) {
                console.warn('Missing resource group from investor2-template XML');
                console.warn(queryXML);
                return [];
            }

            return results.map(function (result) {
                return {
                    key: 'res:' + locale + ':' + resourceGroup[1] + ':' + result.xml.match(resourceKeyName)[1],
                    url: result.url
                };

            });

        };

        var investorHomePage = function (locale, queryXML, results) {

            /*
             *  Sample Query XML                                    ╒═══ {locale}
                <content-query template="investor-mobile-homepage" lang="en-au" appcode="INVCEN" url="/Investor/Home/Index" content-status="draft">
                    <qualifier name="country-code" value="AU" />
                </content-query>

             *  Sample Query Result XML
                <investor-mobile-homepage id="{0E312109-5EAD-4892-B02E-1491D73DA88D}" label="Investor Centre Mobile Home Page (AU)" xml:lang="en" version="1" status="checkedout">
                    <header label="Header"><![CDATA[Your share portfolio, on your mobile.]]></header>
                    <background-image width="414" height="673" align="absbottom" alt="Investor Centre" label="Background Image">
                        <document-id>{B3E95549-CD78-4438-AB5C-F835DCCC0B37}</document-id>
                        <document-size>64908</document-size>
                        <document-mime-type>image/jpeg</document-mime-type>
                    </background-image>
                    <hero-link-title label="Hero Link Title"><![CDATA[Learn More]]></hero-link-title>
                    <hero-link-url label="Hero Link Url"><![CDATA[#Home/Tour]]></hero-link-url>
                    <link-1-title label="Link 1 Title"><![CDATA[Log in to Investor Centre Mobile]]></link-1-title>
                    <link-1-url label="Link 1 Url"><![CDATA[system-login]]></link-1-url>
                    <link-2-title label="Link 2 Title"><![CDATA[Or go to the full website to register]]></link-2-title>
                    <link-2-url label="Link 2 Url"><![CDATA[system-fullsite]]></link-2-url>
                    <link-3-title label="Link 3 Title"><![CDATA[]]></link-3-title>
                    <link-3-url label="Link 3 Url"><![CDATA[]]></link-3-url>
                    <link-4-title label="Link 4 Title"><![CDATA[]]></link-4-title>
                    <link-4-url label="Link 4 Url"><![CDATA[]]></link-4-url>
                    <full-site-title label="Full Site Title"><![CDATA[Visit full Investor Center website]]></full-site-title>
                    <full-site-url label="Full Site Url"><![CDATA[system-fullsite]]></full-site-url>
                </investor-mobile-homepage>
            */

            var elementLabelMatcher = /([\w-]+) label/g,
                elementNameMatcher = /[^ ]+/;
                

            // Expect results to have length of 1
            if (results.length !== 1) {
                console.warn('Unexpect result XML for investor-mobile-homepage');
                console.warn(results);
                return [];
            }

            var result = results[0],
                labels = result.xml.match(elementLabelMatcher);

            return labels.map(function (resultItem) {
                return {
                    key: 'res:' + locale + ':mobile/homepage:' + resultItem.match(elementNameMatcher)[0],
                    url: result.url
                };
            });

        };

        var investorLink = function (locale, queryXML, results) {

            /*
             *  Sample Query XML                               ╒═══ {locale}
                <content-query template="investor-link" lang="en-au" appcode="INVCEN" url="/Investor/" content-status="draft">
                  <qualifier name="country-code" value="AU" />
                  <element name="link-id" value="PrivacyPolicy" />                  <== {resource-group}
                </content-query>

             *  Sample Query Result XML
                <investor-link id="{227FB8E8-313B-42E4-9237-CC8B8CE0C968}" label="AU Privacy Policy" xml:lang="en" version="2" status="active">
                  <link-id label="Link ID"><![CDATA[PrivacyPolicy]]></link-id>
                  <link-label label="Link Label"><![CDATA[Privacy Policy]]></link-label>
                  <url label="Url"><![CDATA[http://www.computershare.com/au/help/Pages/privacy-policies.aspx]]></url>
                </investor-link>
            */

            var linkIdMatcher = /name="link-id" value="([^"]+)/,
                linkIdGroup = queryXML.match(linkIdMatcher);
                

            // Expect results to have length of 1
            if (results.length !== 1) {
                console.warn('Unexpect result XML for investor-link');
                console.warn(results);
                return [];
            }

            var result = results[0];

            return [{
                key: 'res:' + locale + ':investor/link:' + linkIdGroup[1],
                url: result.url
            }];

        };

        var investorCentrePanel = function (locale, queryXML, results) {

            /*
             *  Sample Query XML                                      ╒═══ {locale}
                <content-query template="investorcentre-panel" lang="en-au" appcode="INVCEN" url="/Investor/Contact/Success" cache="false" content-status="draft">
                  <qualifier name="country-code" value="AU" />
                  <element name="panel-id" value="EnquirySuccessMessage" />         <== {resource-group}
                </content-query>

             *  Sample Query Result XML
                <investorcentre-panel id="{DFD43249-3D17-4BCF-BA55-BD1F228A6EFE}" label="Contact Enquiry Success Message" xml:lang="en" version="1" status="checkedout">
                  <panel-id label="Panel Id"><![CDATA[EnquirySuccessMessage]]></panel-id>
                  <panel-xhtml label="Panel XHTML">
                    <xhtml>Your enquiry has been successfully submitted and you should receive a response within 5 working days.</xhtml>
                  </panel-xhtml>
                </investorcentre-panel>
            */

            var panelIdMatcher = /name="panel-id" value="([^"]+)/,
                panelIdGroup = queryXML.match(panelIdMatcher);


            // Expect results to have length of 1
            if (results.length !== 1) {
                console.warn('Unexpect result XML for investorcentre-panel');
                console.warn(results);
                return [];
            }

            var result = results[0];

            return [{
                key: 'res:' + locale + ':investorcentre/panel:' + panelIdGroup[1],
                url: result.url
            }];

        };

        var investorMobileImage = function (locale, queryXML, results) {

            /*
             *  Sample Query XML                                         ╒═══ {locale}
                <content-query template="investor-mobile-image" lang="en-au" appcode="INVCEN" url="/Investor/" content-status="draft">
                  <qualifier name="country-code" value="AU" />
                  <element name="code" value="ComputershareLogo" />
                </content-query>

             *  Sample Query Result XML
                <investor-mobile-image id="{54CC53F5-64E6-4D97-B44A-7331937C4D10}" label="Computershare Logo" xml:lang="en" version="1" status="checkedout">
                  <code label="Code"><![CDATA[ComputershareLogo]]></code>
                  <image width="121" height="48" align="absbottom" alt="Computershare" label="Image">
                    <document-id>{208D22D1-D95C-4273-88D4-3F036BAD3CF3}</document-id>
                    <document-size>3219</document-size>
                    <document-mime-type>image/png</document-mime-type>
                  </image>
                </investor-mobile-image>
            */

            var codeMatcher = /name="code" value="([^"]+)/,
                codeGroup = queryXML.match(codeMatcher);


            // Expect results to have length of 1
            if (results.length !== 1) {
                console.warn('Unexpect result XML for investor-mobile-image');
                console.warn(results);
                return [];
            }

            var result = results[0];

            return [{
                key: 'res:' + locale + ':investor/image:' + codeGroup[1],
                    url: result.url
                }];

        };

        var investorResponsiveImage = function (locale, queryXML, results) {

            /*
             *  Sample Query XML                                         ╒═══ {locale}
                <content-query template="investor-responsive-image" lang="en-au" appcode="INVCEN" url="/Investor/" content-status="draft">
                  <qualifier name="country-code" value="AU" />
                  <element name="code" value="HomePageBackgroundImage" />
                </content-query>

             *  Sample Query Result XML
                <investor-responsive-image id="{54CC53F5-64E6-4D97-B44A-7331937C4D10}" label="Home Page Background Image" xml:lang="en" version="1" status="checkedout">
                  <code label="Code"><![CDATA[HomePageBackgroundImage]]></code>
                  <image-large width="121" height="48" align="absbottom" alt="" label="Image">
                    <document-id>{208D22D1-D95C-4273-88D4-3F036BAD3CF3}</document-id>
                    <document-size>3219</document-size>
                    <document-mime-type>image/png</document-mime-type>
                  </image-large>
                  <image-medium width="121" height="48" align="absbottom" alt="" label="Image">
                    <document-id>{208D22D1-D95C-4273-88D4-3F036BAD3CF3}</document-id>
                    <document-size>3219</document-size>
                    <document-mime-type>image/png</document-mime-type>
                  </image-medium>
                </investor-responsive-image>
            */

            var codeMatcher = /name="code" value="([^"]+)/,
                codeGroup = queryXML.match(codeMatcher);


            // Expect results to have length of 1
            if (results.length !== 1) {
                console.warn('Unexpect result XML for investor-responsive-image');
                console.warn(results);
                return [];
            }

            var result = results[0];

            return [{
                key: 'res:' + locale + ':investor/responsiveImage:' + codeGroup[1],
                    url: result.url
                }];

        };

        var investorResponsiveExclusionList = function(locale, queryXML, results) {
            /*
             Sample Query result
                <content>
                   <investor-responsive-url-exclusion-list id="{C63524C8-6AC9-4DE7-961B-B261C2F9B1A8}" label="Investor Centre Trade URL Exclusion" xml:lang="en" version="1" status="active">
                      <relative-url label="Relative URL">/investor/trade</relative-url>
                   </investor-responsive-url-exclusion-list>
                   <investor-responsive-url-exclusion-list id="{764AE757-1C2F-4FE9-A310-9947BC8288C4}" label="Investor Centre URL Exclusion Campaign EComms AU" xml:lang="en" version="1" status="active">
                      <relative-url label="Relative URL">/investor/wizard/comms/</relative-url>
                      <parameter-key label="Parameter Key">issuerid</parameter-key>
                   </investor-responsive-url-exclusion-list>
                   <investor-responsive-url-exclusion-list id="{CFF8EDCF-34A4-4F61-B4E1-4865D6AB59A8}" label="Investor Centre URL Exclusion Landing" xml:lang="en" version="1" status="active">
                      <relative-url label="Relative URL">/investor</relative-url>
                      <parameter-key label="Parameter Key">landing</parameter-key>
                      <parameter-value label="Parameter Value">y</parameter-value>
                   </investor-responsive-url-exclusion-list>
                </content>
             */

            return results.map(function (result) {
                var k = result.xml.match(/parameter-key label="Parameter Key"><!\[CDATA\[([^\]]+)/),
                    v = result.xml.match(/parameter-value label="Parameter Value"><!\[CDATA\[([^\]]+)/);
                
                return {
                    relativeUrl: result.xml.match(/relative-url label="Relative URL"><!\[CDATA\[([^\]]+)/)[1],
                    parameterKey: (k && k.length && k[1]) || null,
                    parameterValue: (v && v.length && v[1]) || null,
                    url: result.url
                }
            });
        }

        return {
            'investor2-resource': investorResource,
            'investor-mobile-homepage': investorHomePage,
            'investor-link': investorLink,
            'investorcentre-panel': investorCentrePanel,
            'investor-mobile-image': investorMobileImage,
            'investor-responsive-image': investorResponsiveImage,
            'investor-responsive-url-exclusion-list': investorResponsiveExclusionList
        }
    };

    moduleDance(factory);
})();;
(function () {

    var global = this || (0, eval)('this'),
    document = global['document'],
    moduleName = 'contentExplorer',
    dependencies = ['knockout', 'ajax', 'messenger', 'configuration', 'jQuery', 'cookies', 'knockout-binding-resourceText', 'InvestorResources', 'contentExplorer-templates'];

    var moduleDance = function (factory) {
        // Module systems magic dance.

        if (typeof define === "function" && define["amd"]) {
            define(moduleName, dependencies.concat('exports'), factory);
        } else {
            // using explicit <script> tags with no loader
            global.CPU = global.CPU || {};
            factory($, global.CPU.ajax, global.CPU.messenger, global.CPU.configuration, $, undefined, global.CPU.contextExplorerTemplates, global.CPU.contentExplorer = {});
        }
    };

    var factory = function (ko, ajax, messenger, configuration, $, cookies, resourceTextBinding, investorResources, contextExplorerTemplates, contentExplorer) {

        // Add a zIndex fn to jQuery - taken from jQuery UI
        if (!$.fn.zIndex) {
            $.fn.zIndex = function (zIndex) {
                if (zIndex !== undefined) {
                    return this.css("zIndex", zIndex);
                }

                if (this.length) {
                    var elem = $(this[0]), position, value;
                    while (elem.length && elem[0] !== document) {
                        // Ignore z-index if position is set to a value where z-index is ignored by the browser
                        // This makes behavior of this function consistent across browsers
                        // WebKit always returns auto if the element is positioned
                        position = elem.css("position");
                        if (position === "absolute" || position === "relative" || position === "fixed") {
                            // IE returns 0 when zIndex is not specified
                            // other browsers return a string
                            // we ignore the case of nested elements with an explicit value of 0
                            // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
                            value = parseInt(elem.css("zIndex"), 10);
                            if (!isNaN(value) && value !== 0) {
                                return value;
                            }
                        }
                        elem = elem.parent();
                    }
                }

                return 0;
            };
        }
        var currentKey = 0;
        var queryQueue = [];

        var isContentQuery = false;

        contentExplorer.data = ko.observableArray();
        contentExplorer.ceData = ko.observable();

        var ceCookieHandler = (function() {

            var showcedetail,
                showce,
                contentStatus,
                cacheStatus;

            var writeCookie = function(reload) {
                cookies.setItem('ContentAccess', 'showcedetail=' + showcedetail + '&showce=' + showce + '&contentstatus=' + contentStatus + '&cache=' + cacheStatus);

                if (reload) {
                    messenger.publish('system-suppressAjaxErrors', true);
                    window.location.reload();
                }
            }

            var cookieValue = cookies.getItem('ContentAccess');

            if (cookieValue) {
                showcedetail = (cookieValue.match(/showcedetail=(true|false)/) || ['', ''])[1];
                showce = (cookieValue.match(/showce=(true|false)/) || ['', ''])[1];
                contentStatus = (cookieValue.match(/contentstatus=(draft|committed)/) || ['', ''])[1];
                cacheStatus = (cookieValue.match(/cache=(valid|invalid)/) || ['', ''])[1];
            }

            if (!showcedetail || !showce || !contentStatus) {
                showcedetail = showcedetail || 'true';
                showce = showce || 'true';
                contentStatus = contentStatus || 'draft';
                cacheStatus = cacheStatus || 'valid';

                writeCookie(false);
            }

            return { 
                contentStatus : ko.computed({
                    read: function() {
                        return contentStatus;
                    },
                    write: function(value) {
                        if ( value !== 'draft' && value !== 'committed'){
                            throw new Error('Unsupported ContentStatus value: ' + value);
                        }

                        if (value !== contentStatus) {
                            contentStatus = value;
                            writeCookie(true);
                        }
                    }
                }),
                cacheStatus: ko.computed({
                    read: function () {
                        return cacheStatus;
                    },
                    write: function (value) {
                        if (value !== 'valid' && value !== 'invalid') {
                            throw new Error('Unsupported CacheStatus value: ' + value);
                        }

                        if (value !== cacheStatus) {
                            cacheStatus = value;
                            writeCookie(true);
                        }
                    }
                })

            }; 
            
        })();

        contentExplorer.isEnabled = ko.computed({
            read: function () {
                var setting = cookies.getItem('ContentAccess');
                return setting && /showcedetail\=true/.test(setting);
            },
            write: function (value) {
                cookies.setItem('ContentAccess', 'showcedetail=' + (value ? 'true' : 'false') + '&showce=' + (value ? 'true' : 'false') + '&contentstatus=');

                // Need to toggle a complete refresh
                //messenger.publish('system-suppressAjaxErrors', true);
                //global.location.reload();
            }
        });

        if (!cookies.getItem('ContentAccess')) {
            contentExplorer.isEnabled = true;
        }

        contentExplorer.contentStatus = ceCookieHandler.contentStatus;
        contentExplorer.cacheStatus = ceCookieHandler.cacheStatus;

        var mergeResourceData = function (resourceEntries) {

            // Read now so we can manipulate the data once, then update the observable once.
            var existingData = contentExplorer.data(),
                ceData = contentExplorer.ceData();

            while (resourceEntries.length > 0) {
                var entry = resourceEntries.pop(),
                    foundEntry = existingData.find(function (item) {
                        return item.Key === entry.Key && item.ResourceKey === entry.ResourceKey;
                    });

                if (!foundEntry)
                    existingData.push(entry);
                else if (!foundEntry.ResourceKey) {
                    foundEntry.ResourceKey = entry.ResourceKey;
                };
            }

            if (ceData) {
                // Go through all the resourceEntries looking for matching resource keys
                existingData.forEach(function (item) {
                    if (!item.Url) {
                        if (item.Key) {
                            if (ceData[item.Key]) {
                                item.Url = ceData[item.Key];
                            }
                        }
                    }
                });
            }

            contentExplorer.data.notifySubscribers(existingData);

        };

        var extractAndMergeQueryData = function ($content) {

            /*
             * #ContextExplorer
             *   #ContentPanel
             *     #TreeMenuPanel
             *       ul.filetree
             *         li.closed           [1..n]
             *           span.folder
             *             a href=queryId
             *           ul
             *             li              [1..n]
             *               span.file
             *                 a href=queryResultId
             *     #ContentDetailPanel
             *       #queryId              [1..n]
             *         ul
             *           div.xmlcode
             *       #queryResultId        [1..n]
             *         a href=webContentUrl                                                             <== {editUrl}
             *         ul
             *           div.xmlcode
             */

            /*
             *  Sample Query XML                            ╒═══ {locale}
                <content-query template="{templateName}" lang="en-au" appcode="INVCEN" url="/Investor/Home/Index" content-status="draft">
                  <content-query>
                     ...
                  </content-query>
                </content-query>

            */

            // Build a map of resourceKeys to WCAdmin edit urls
            // [ { key: "res:{locale}:{resource-group}:{key}", url: {editUrl}, ...]

            var matchQueryId = /ceQ\d+/,
                matchQueryResultId = /ceQR\d+/,
                templateName = /template="([^"]+)/,
                resourceGroupName = /name="resource-group" value="([^"]+)/,
                localeName = /lang="([^"]+)/,
                resourceKeyName = /resource-key label="Key"><!\[CDATA\[([^\]]+)/;

            // Find all queries
            var queryMap = $content.find('#ContentPanel ul.filetree li.closed').toArray().reduce(function (result, item) {

                var $item = $(item);
                // Extract queryId from onclick function text
                var queryId = $item.find('span.folder a').attr('onclick').match(matchQueryId).toString();

                // Get the xml text from the query's detail section
                var queryXml = $content.find('#ContentDetailPanel #' + queryId + ' .xmlcode').text();

                var templateType = queryXml.match(templateName)[1],
                    templateProcessor = contextExplorerTemplates[templateType];

                if (!templateProcessor) {
                    console.warn('Content template ' + templateType + ' did not have a processor');
                    return result;
                }

                var locale = queryXml.match(localeName)[1].replace(/-\w+/, function (match) { return match.toUpperCase(); });

                var results = $item.find('span.file a').toArray().map(function(resultItem) {
                    var $resultItem = $(resultItem),
                        queryResultId = $resultItem.attr('onclick').match(matchQueryResultId).toString(),
                        // Find the query Result's detail section
                        $queryResultData = $content.find('#ContentDetailPanel #' + queryResultId),
                        // Get the xml content
                        queryResultXml = $queryResultData.find('.xmlcode').text();

                    return { 
                        url: $queryResultData.find('a.EditContent').attr('href'),
                        xml: $queryResultData.find('.xmlcode').text()
                    };
                });
                Array.prototype.push.apply(result, templateProcessor(locale, queryXml, results));

                return result;
            }, []);

            var existingCEData = contentExplorer.ceData() || {};

            // Add key-url pair to the controlExplorer's dictionary if it's missing
            queryMap.forEach(function (item) {
                if (!existingCEData[item.key]) {
                    existingCEData[item.key] = item.url;
                }
            });

            contentExplorer.ceData(existingCEData);
        }

        messenger.subscribe('system-loadTemplate', function (data) {

            if (!data) {
                return;
            }

            // Extract WCA path data
            var $content = investorResources.loadResourceContent(data).find('span');

            var resourceEntries = $content.toArray().map(function (element) {
                return {
                    Key: element.getAttribute('data-wcapath'),
                    ResourceKey: element.getAttribute('data-resourcepath'),
                    Value: element.innerHTML
                }
            });

            // Extract contentExplorerStream data
            if (typeof data === 'string') {
                startPos = data.indexOf('<div id="contentExplorerResult"');

                if (!~startPos) {
                    return data;
                }

                var startCEdiv = data.indexOf('<div id="ContentExplorer');

                if (!!~startCEdiv) {
                    // Found tag.  Extract all content
                    endPos = data.indexOf('</body>', startPos) + '</body>'.length;
                    content = data.substring(startCEdiv, endPos);

                    $content = $(content);

                    extractAndMergeQueryData($content);

                    // Remove content panel stuff from template
                    endPos = data.indexOf('</div>', endPos) + '</div>'.length;

                    data = data.substring(0, startPos) + data.substring(endPos);
                }
            } else {
                $content = $(data).find('#ContentExplorer');

                if ($content.length > 0) {
                    extractAndMergeQueryData($content);
                    $content.remove();
                }
            }

            mergeResourceData(resourceEntries);
            return data;

        }, contentExplorer);

        contentExplorer.toggleCE = function (model, event) {
            contentExplorer.showResourceContent(!contentExplorer.showResourceContent());
            event.stopImmediatePropagation();
            return false;
        };

        contentExplorer.toggleContentStatus = function () {
            if (contentExplorer.contentStatus() === 'committed') {
                contentExplorer.contentStatus('draft');
            } else {
                contentExplorer.contentStatus('committed');
            }
            event.stopImmediatePropagation();
            return false;
        };

        contentExplorer.toggleCacheStatus = function () {
            if (contentExplorer.cacheStatus() === 'invalid') {
                contentExplorer.cacheStatus('valid');
            } else {
                contentExplorer.cacheStatus('invalid');
            }
            event.stopImmediatePropagation();
            return false;
        };

        contentExplorer.contentStatusDisplay = ko.computed(function () {
            return contentExplorer.contentStatus().replace(/^\w/, function (match) { return match.toUpperCase(); });
        });

        contentExplorer.cacheStatusDisplay = ko.computed(function () {
            return 'Cache';
        });

        contentExplorer.toggleDisplayOptions = function (model, event) {
            contentExplorer.showOptions(!contentExplorer.showOptions());
            event.stopImmediatePropagation();
            return false;
        };

        contentExplorer.showResourceContent = ko.observable(false);
        contentExplorer.showOptions = ko.observable(false);

        contentExplorer.wcaEditOnClick = function (model, event) {
            $('#wcaEditLink').attr('href', event.target.getAttribute('data-href'));

            $('#wcaEditLink')[0].click();
            event.stopImmediatePropagation();
            return false;
        }

        var $document = $(document),
            $body = $(document.body),
            uid = 0;

        $document.ready(function () {

            var closeCE = '<span class="ceClose switch cpuicon cpuicon-cancel" data-bind="click: toggleDisplayOptions"></span>';
            var cacheHtml = '<div class="switch" data-bind="click: toggleCacheStatus"><input id="chkIsCacheEnabled" type="checkbox" data-bind="checked: cacheStatus() == \'valid\'" class="input-toggle input-toggle-round"><label for="chkIsCacheEnabled"><span data-bind="text: cacheStatusDisplay"></span></label></div>';
            var statusHtml = '<div class="switch" data-bind="click: toggleContentStatus"><input id="chkIsDraft" type="checkbox" data-bind="checked: contentStatus() !== \'committed\'" class="input-toggle input-toggle-round"><label for="chkIsDraft"><span data-bind="text: contentStatusDisplay"></span></label></div>';
            var highlightHtml = '<div class="switch" data-bind="click: toggleCE"><input id="chkHighlight" type="checkbox" data-bind="checked: showResourceContent" class="input-toggle input-toggle-round"><label for="chkHighlight"><span>Edit</span></label></div>';
            var wcAnchor = '<a id="wcaEditLink" target="_blank" href="#"></a>';
            $(document.body).append('<!-- ko blockContext: {} --><div id="ceSection"><div id="ceIcon" class="ceIcon-enabled" data-bind="click: toggleDisplayOptions, css: {\'ceIcon-active\': showOptions, \'ceInspectEnabled\': showResourceContent }"><span class="toggleIcon cpuicon cpuicon-forms"></span>' + closeCE + cacheHtml + statusHtml + highlightHtml + '</div>' + wcAnchor + '<div id="editContainer" data-bind="visible: showResourceContent"></div></div><!-- /ko -->');

            ko.applyBindings(contentExplorer, document.getElementById('ceSection'));

            var oldBinding = ko.bindingHandlers['resourceText'].update;

            var toggleCssClass = function (element, name, value) {
                value = !!ko.unwrap(value);

                // I'd like to use classList but not all browsers follow spec and honour the second parameter
                //if (element.classList) {
                //    element.classList.toggle(name, value);
                //} else {
                    $(element).toggleClass(name, value);
                //}
            }

            ko.bindingHandlers['resourceText'].update = function (element, valueAccessor, allBindings, viewModel, bindingContext) {

                // Clean up old
                var $element = $(element);
                var oldKey = element.getAttribute('data-edit-uid');

                if (oldKey) {
                    clearTimeout($document.find('span.wcaEditLink[data-edit-uid="' + oldKey + '"]').tooltip('destroy').remove().attr('data-timeoutId'));
                }

                var key = ko.unwrap(valueAccessor());

                toggleCssClass(element, 'wcaHighlight', contentExplorer.showResourceContent);
                element.setAttribute('data-resourceKey', key);

                oldBinding(element, valueAccessor, allBindings, viewModel, bindingContext);

                if (contentExplorer.showResourceContent()) {
                    var resourceInfo = findResourceKeyInfo(element);

                    if (!resourceInfo || !resourceInfo.resourceEntry || !resourceInfo.resourceEntry.Url) {
                        return;
                    }

                    buildAndPositionEditElement($element, uid++, key, resourceInfo);
                    //$element.after('<span class="wcaEditLink cpuicon cpuicon-settings" data-bind="click: wcaEditOnClick" data-toggle="tooltip" data-resourceKey="' + key + '" data-href="' + resourceInfo.resourceEntry.Url + '"></span>');
                    //var $editLink = $element.siblings('span.wcaEditLink[data-resourceKey="' + key + '"]')
                    //contentExplorer.enableTooltip($editLink)
                    //ko.applyBindingsToNode($editLink[0], { click: contentExplorer.wcaEditOnClick });
                }
            };

            // If the page was loaded with content Explorer turned on, load the data
            var initialCE = $document.find('#ContentExplorer');

            if (initialCE.length > 0) {
                extractAndMergeQueryData(initialCE);
                initialCE.remove();
            }
        });

        var buildAndPositionEditElement = function ($sourceElement, instanceUid, key, resourceInfo) {
            var html = '<span class="wcaEditLink cpuicon cpuicon-triangle-top" data-bind="click: wcaEditOnClick" data-toggle="tooltip" data-edit-uid="' + instanceUid + '" data-resourceKey="' + key + '" data-href="' + resourceInfo.resourceEntry.Url + '"></span>',
                $editContainer = $body.find('#editContainer');

            $editContainer.append(html);

            var $newElement = $editContainer.find('span[data-edit-uid="' + instanceUid + '"]');
            contentExplorer.enableTooltip($newElement);

            var timeoutId = setInterval(function () { 
                var position = $sourceElement[0].getBoundingClientRect();
                var zIndex = $sourceElement.zIndex();
                $newElement.css({ position: 'absolute', top: position.top + window.scrollY, left: position.left, zIndex: zIndex + 1 });
            }, 500);

            $newElement.attr('data-timeoutId', timeoutId);
            ko.applyBindingsToNode($newElement[0], { click: contentExplorer.wcaEditOnClick });
        }

        var findResourceKeyInfo = function (element) {
            var key = element.getAttribute('data-resourcekey');

            var resourceEntry = contentExplorer.data.find(function (item) {
                return item.ResourceKey === key;
            });

            return {
                key: key,
                resourceEntry: resourceEntry
            };
        }

        var formatWCAKey = function (text) {

            if (!text) {
                return '';
            }

            var info = text.split(':');

            return 'Culture: ' + info[1] + '<br />Group: ' + info[2] + '<br />Key: ' + info[3];
        };

        contentExplorer.enableTooltip = function ($element) {

            $element.tooltip({
                container: 'body',
                placement: 'auto',
                html: true,
                title: function (element) {

                    var resourceInfo = findResourceKeyInfo(this),
                        key = resourceInfo.key,
                        resourceEntry = resourceInfo.resourceEntry;

                    var tooltipText = key + (resourceEntry ? ('<br />' + formatWCAKey(resourceEntry.Key)) : '');

                    return tooltipText;
                },
                template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner tooltip-inner-wca"></div></div>'
            });
        };


    };

    moduleDance(factory);
})();;
define('Cordova-Helper', ['messenger'], function (messenger) {

    var dateMonthsToString = [
        "Jan", "Feb", "Mar", "Apr", "May", "Jun",
        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
    ];

    var getExportPdfFileName = function (pdfType) {
        var now = new Date();

        var dateString = now.getDate() + "-" + dateMonthsToString[now.getMonth()] + "-" + now.getFullYear();
        var timeString = now.getHours() + "-" + now.getMinutes() + "-" + now.getSeconds();

        return pdfType + " " + dateString + " " + timeString;
    };

    var getFile = function(url, fileName, fileMIMEType) {
        var fileExt = ".";
        switch (fileMIMEType) {
        case "text/csv":
            fileExt = fileExt + "csv";
            break;
        case "application/pdf":
        default:
            fileExt = fileExt + "pdf";
            break;
        }

        fileName = fileName + fileExt;

        window.requestFileSystem(LocalFileSystem.PERSISTENT,
            0,
            function(fs) {

                fs.root.getFile(fileName,
                    { create: true, exclusive: false },
                    function(fileEntry) {
                        var oReq = new XMLHttpRequest();

                        // Make sure you add the domain name to the Content-Security-Policy <meta> element.
                        oReq.open("GET", url, true);

                        // Define how you want the XHR data to come back
                        oReq.responseType = "blob";

                        oReq.onload = function(oEvent) {
                            var blob = oReq.response; // Note: not oReq.responseText

                            console.log(oReq);
                            console.log(blob);

                            if (blob) {
                                fileEntry.createWriter(function(fileWriter) {
                                    fileWriter.write(blob);
                                });

                                var filePath = fileEntry.toURL();

                                cordova.plugins.fileOpener2.showOpenWithDialog(
                                    filePath,
                                    fileMIMEType,
                                    {
                                        error: function(e) {
                                            console.log('Error status: ' + e.status + ' - Error message: ' + e.message);
                                        },
                                        success: function() {
                                            console.log('file opened successfully');
                                        }
                                    }
                                );

                            } else console.error('we didnt get an XHR response!');
                        };
                        oReq.send(null);
                    },
                    function(err) { console.error('error getting file! ' + err); });

            },
            function(err) { console.error('error getting persistent fs! ' + err); });
    };

    var showDownloadRequestModal = function() {
        messenger.call('modal-show',
            {
                titleSelector: 'CPU/DownloadAlert/DownloadAlertHeader',
                contentSelector: 'CPU/DownloadAlert/AlertText',
                okOptions: 'CPU/DownloadAlert/AlertOkButton',
                icon: 'alert',
                modalBehaviour: { keyboard: false }
            }).then(function(result) {
            this.modalVisible = false;
            if (result === 'ok') return;
        }.bind(this));
    };

    return {
        getFile: getFile,
        getExportPdfFileName: getExportPdfFileName,
        showDownloadRequestModal: showDownloadRequestModal
    };
});;
define('EComms-WithMobile', ['knockout'], function (ko) {

	var WithMobile = (function () {

		var ctor = function WithMobile(alertsMessages) {
			// resource strings for alerts++
			this.alertsMessages = ko.observable(alertsMessages)

			this.mobileCountryCallingCode = ko.observable();
			this.mobileSubscriberNumber = ko.observable();

			this.mobileErrors = ko.validation.group([this.mobileSubscriberNumber])

			this.previousCountryCode = ko.observable('');
			this.mobileNationalNumber = ko.observable("");
			this.warningInvalidPhone = ko.observable("");
			this.previousMobileSubscriberNumber = ko.observable();
			this.selectedPrefix = ko.observable("").resettable();
			this.hasValidationIssues = ko.observable(false)
			this.hasWarning = ko.observable(false);

			this.phoneCountryCodeList = ko.observable();
			this.prevalidateStep = this.prevalidateStep.bind(this);
			this.promptUserOn = this.promptUserOn.bind(this);
			this.proceed = this.proceed.bind(this);
			this.cleanMobileNumber = this.cleanMobileNumber.bind(this);
			this.skipPhoneValidation = this.skipPhoneValidation.bind(this);
			this.validateMobileNumber = this.validateMobileNumber.bind(this);
			this.isBlankSubscriberNumber = this.isBlankSubscriberNumber.bind(this);
			this.setPhoneCountryCodeOptionDisable = this.setPhoneCountryCodeOptionDisable.bind(this);
			this.submitPhone = this.submitPhone.bind(this);

			this.init = this.init.bind(this);
			this.addValidation = this.addValidation.bind(this);
			this.onCountryChange = this.onCountryChange.bind(this);
			this.onSubscriberNumberChange = this.onSubscriberNumberChange.bind(this);


			this.subscriptions = [
				this.selectedPrefix.subscribe(this.onCountryChange, this),
				this.mobileSubscriberNumber.subscribe(this.onSubscriberNumberChange, this)
			];

			this.extractCountryCode = function (prefix) {
				return prefix.split("-")[0]
			}

			this.countryCode = ko.computed(function () {
				if (this.selectedPrefix())
					return this.extractCountryCode(this.selectedPrefix())
				else
					return "";
			}, this);
			this.countryCallingCode = ko.computed(function () {
				if (this.selectedPrefix())
					return this.selectedPrefix().split('-')[1];
				else
					return "";
			}, this);
			this.isCountrySelected = ko.computed(function () {
				return !!this.selectedPrefix()
			}, this);

			this.validatePhoneService = null;
		};

		ctor.prototype.isBlankSubscriberNumber = function () {
			return (!this.mobileSubscriberNumber() || this.mobileSubscriberNumber() === "")
		}

		ctor.prototype.prevalidateStep = function () {

			this.warningInvalidPhone();

			if (!this.mobileSubscriberNumber.isValid()) {
				return this.promptUserOn('mobile_subscriber_fix');
			}

			var isBlankNumber = this.isBlankSubscriberNumber();
			if (this.isCountrySelected() && isBlankNumber) {
				return this.promptUserOn('incomplete_mobile_number')
			}

			if (!this.isCountrySelected() && !isBlankNumber) {
				return this.promptUserOn('incomplete_country_code')
			}

			return true;
		}

		// (STOP AND then) prompt user on (action or solution) 
        ctor.prototype.promptUserOn = function (action, data) {
            // store estimated national number
            this.mobileNationalNumber(data.nationalNumber)
			if (action === 'mobile_subscriber_fix') {
				this.mobileErrors.showAllMessages();
			}
			else if (action === 'incomplete_mobile_number') {
				this.warningInvalidPhone(this.alertsMessages()[action])
				this.hasWarning(true)
			}
			else if (action === 'incomplete_country_code') {
				this.warningInvalidPhone(this.alertsMessages()[action])
				this.hasWarning(true)
			}
			else if (action === 'has_validation_issues') {
				this.warningInvalidPhone(this.alertsMessages()[action]);
				this.hasWarning(true)
				this.hasValidationIssues(true)
				this.previousMobileSubscriberNumber(data.phone);
				this.previousCountryCode(data.countryCode)
			} else if (action === 'invalid_calling_country_code') {
				this.warningInvalidPhone(this.alertsMessages()[action]);
				this.hasWarning(true)
				this.previousMobileSubscriberNumber(data.phone);
				this.previousCountryCode(data.countryCode)
				this.hasValidationIssues(false)
			}

			return false;
		}

		ctor.prototype.proceed = function (action, data) {
            if (action === 'bypass_validation_issues') {
                // if estimated guess exists, use it
                var compiledNumber = this.mobileNationalNumber()
                    ?? this.previousMobileSubscriberNumber();
                this.mobileNationalNumber(compiledNumber)
			}
			else if (action === 'mobile_number_ok') {
				this.hasWarning(false);
				this.hasValidationIssues(false)
				this.mobileNationalNumber(data.nationalNumber)
				this.previousMobileSubscriberNumber(data.phone)
				this.previousCountryCode(data.countryCode)
			}

			return true
		}

		ctor.prototype.removeSeparators = function (phoneNo) {
			if (!phoneNo) return phoneNo;

			var isIE11 = !!window.MSInputMethodContext && !!document.documentMode;
			if (isIE11) {
				return phoneNo.replace(/-/g, '').replace(/ /g, '');
			}
			else {
				return phoneNo.replaceAll("-", "").replaceAll(" ", "");
			}
		}

		ctor.prototype.cleanMobileNumber = function () {
			return this.removeSeparators(this.mobileSubscriberNumber());
		}

		ctor.prototype.skipPhoneValidation = function () {
			var isBlankNumber = (!this.mobileSubscriberNumber() || this.mobileSubscriberNumber() === "")
			if (!this.isCountrySelected() && isBlankNumber) {
				return this.proceed('mobile_not_supplied')
			}

			var phone = this.cleanMobileNumber();
			var isPhoneInputUnmodified = this.countryCode() === this.previousCountryCode() && phone === this.previousMobileSubscriberNumber();

			if (isPhoneInputUnmodified && this.hasValidationIssues()) {
				return this.proceed('bypass_validation_issues', phone)
			}
			else {
				return false;
			}
		}

		ctor.prototype.validateMobileNumber = function (phone) {
			this.mobileNationalNumber();

			var mobileCode = this.countryCode()
			var inputData = {
				PhoneNumber: phone,
				CountryCode: mobileCode,
			}

			return this.validatePhoneService(inputData).showLoading()
				.then(function (data) {
					if (!data.IsValidNumber) {
						return this.promptUserOn('has_validation_issues',
							{
								phone,
                                countryCode: mobileCode,
                                nationalNumber: data.NationalNumber
							})
					}
					if (!data.IsValidCountryCode) {
						return this.promptUserOn('invalid_calling_country_code',
							{
								phone,
								countryCode: mobileCode
							})
					}

					return this.proceed('mobile_number_ok',
						{
							phone,
							nationalNumber: data.NationalNumber,
							countryCode: mobileCode
						});
				}.bind(this));

		}

		ctor.prototype.init = function (service, mobileNationalNumber, mobileSelectedPrefix, phoneCountryCodeList, mobileSubscriberNumber) {
			this.validatePhoneService = service;
			this.mobileNationalNumber(mobileNationalNumber || undefined);

            if (!!mobileSubscriberNumber) {
				// so validation only occurs once when moving back and forth in wizard
                this.mobileSubscriberNumber(mobileSubscriberNumber)
                this.previousMobileSubscriberNumber(mobileSubscriberNumber)
			}

			this.phoneCountryCodeList(phoneCountryCodeList.map((item) => {
				return {
					selected: item.Selected,
					text: item.Text,
					value: item.Value,
					disabled: item.Disabled
				};
			}));

			this.selectedPrefix(mobileSelectedPrefix || undefined);

			if (!!mobileNationalNumber && !!mobileSelectedPrefix) {
				// so validation only occurs once when moving back and forth in wizard
				this.previousCountryCode(this.extractCountryCode(mobileSelectedPrefix))
			}
		};

		ctor.prototype.addValidation = function (required) {
			this.mobileSubscriberNumber.extend({
				maxLength: 15,
				pattern: {
					params: /^[0-9- ]{8,15}$/,
					message: this.alertsMessages()['phone_error_message']
				},
			});
			if (required) {
				this.mobileSubscriberNumber.extend({
					required: {
						message: this.alertsMessages()['phone_required_error_message']
					},
				});
            }
		};

		ctor.prototype.onCountryChange = function () {
			this.hasWarning(false);
			if (this.selectedPrefix()) {
				this.mobileCountryCallingCode(this.countryCallingCode());
			}
		}
		ctor.prototype.onSubscriberNumberChange = function () {
			// reset if blank only
			if (this.isBlankSubscriberNumber()) {
				this.mobileNationalNumber("")
			}
			this.hasValidationIssues(false)
			this.hasWarning(false)
			this.warningInvalidPhone()
		}

		ctor.prototype.dispose = function () {
			if (this.subscriptions) {
				while (this.subscriptions.length > 0) {
					this.subscriptions.pop().dispose();
				};
			};
		};

		ctor.prototype.submitPhone = function (callback) {
			var phoneNumber = this.cleanMobileNumber();
			return this.validateMobileNumber(phoneNumber)
				.then(function (status) {
					if (status) {
						return callback();
					}

					return false;
				})
		}

		ctor.prototype.handleWithMobile = function (onSubmit) {
			if (!this.prevalidateStep())
				return false;

			if (this.skipPhoneValidation()) {
				return onSubmit();
			}
			else {
				return this.submitPhone(onSubmit);
			}
		}



		ctor.prototype.setPhoneCountryCodeOptionDisable = function (option, item) {
			if (item) {
				ko.applyBindingsToNode(option, { disable: item.disabled }, item);
			}
		} 

		return ctor;
	})();

	return WithMobile;
});;

define('InvestorAjax', ['ajax', 'messenger'], function (ajax, messenger) {

    ajax.promises.fn.showLoading = function () {
        messenger.publish('modal-showLoading', this);
        return this;
    }
});;
define('InvestorCentre', ['configuration', 'knockout', 'globalize-knockout', 'routing', 'InvestorHeader', 'InvestorSession', 'InvestorModals', 'InvestorModals-Autocomplete', 'resources', 'ajax', 'core', 'messenger'],
    function (config, ko, globalize, routing, InvestorHeader, InvestorSession, InvestorModals, AutoComplete, resources, ajax, core, messenger) {
        var checkOption = function (value, defaultValue) {
            return value === undefined ? defaultValue : value;
        };
        var router = routing.router;
        var Application = (function () {
            var ctor = function Application() {
                this.header = new InvestorHeader();
                this.initializeExternalUrlHandling();

                this.identity = {
                    firstName: ko.observable(),
                    surname: ko.observable(),
                    lastLogin: ko.observable(),
                    roles: ko.observable(),
                    isHoldingAssociatedWithMembershipAccount: ko.observable(),
                    isNonMember: ko.observable(),
                    acceptedTnC: ko.observable(true),
                    isDeceased: ko.observable(false),
                    hasNoAccounts: ko.observable(false),
                    isLoggedInToWrongCountry: ko.observable(false),
                    isAllCompaniesTerminated: ko.observable(false),
                    isFirstLogin: ko.observable(),
                    showNewMessageNotificationOpt: ko.observable(true),
                    newMessageCount: ko.observable(),
                    antiForgeryToken: ko.observable(),
                    isMFARequired: ko.observable(false)
                };
                this.showRegulatoryDisclaimer = ko.computed(function () {
                    return config.showRegulatoryDisclaimer;
                }, this);

                this.showCopyright = ko.computed(function () {
                    return config.showCopyright;
                }, this);

                this.showTimeout = ko.observable(false);
                this.isIncompleteUser = ko.computed(function () {
                    return config.isIncompleteUser;
                }, this);
                this.enableBigMobile = ko.computed(function () {
                    return config.enableBigMobile;
                }, this);

                this.identity.isAuthenticated = ko.computed(function () {
                    return !!this.identity.firstName();

                }, this);
                this.identity.showTimeout = ko.computed(function () {
                    if (this.identity.isNonMember()) {
                        return !!this.identity.isNonMember();
                    }
                    else {
                        if (this.showTimeout()) {
                            return !!this.showTimeout();
                        }
                    }
                }, this);

                messenger.subscribe('menu-options', function (data) {
                    this.showTimeout(data.showTimeout);
                }, this);

                this.modals = new InvestorModals();
                this.modalsAutocomplete = new AutoComplete();
                this.investorSession = new InvestorSession(config.sessionOptions, this.identity);
                if (config.enableConsoleLogging) {
                    this.investorSession.interceptConsole();
                }

                this.isAuthorized = this.isAuthorized.bind(this);
                this.onMyProfile = this.onMyProfile.bind(this);
                this.onModalOk = this.onModalOk.bind(this);
                this.onMyProfile = this.onMyProfile.bind(this);
                this.isAuthorized = this.isAuthorized.bind(this);

                messenger.subscribe('onMyProfileClick', this.onMyProfile, this);
                messenger.subscribe('maskCredentials', this.replaceAt, this);
            };

            // This is to accomodate the ICApp's handling of external urls.
            // Listen for every click under to handle external urls, and intercept them.
            // Currently only for Oceania Region
            ctor.prototype.initializeExternalUrlHandling = function () {
                if (config.initExternalUrlsForApp) {
                    $("body").on("click",
                        "a[target='_system'], a[target='_blank']",
                        function (e) {
                            if (config.isCordova) {
                                e.preventDefault();
                                window.open(e.currentTarget.href, "_system");
                            }
                        });
                }
            };

            // Mask the account number
            ctor.prototype.replaceAt = function (options) {
                var string = options.actualString;
                var index = options.index;
                var replacementString = options.replacementString;
                return string.substr(0, index) + replacementString + string.substr(index + replacementString.length);
            }

            ctor.prototype.onModalOk = function (options) {
                messenger.call('modal-show', {
                    titleSelector: resources.getResource('CPU/Error/AccessDenied'),
                    contentSelector: resources.getResource(options.contentSelector),
                    cancelOptions: 'CPU/Common/Cancel',
                    okOptions: options.okOptions,
                    modalBehaviour: { keyboard: false }
                }).then(function (result) {
                    this.modalVisible = false;
                    if (result === 'ok') {
                        messenger.publish("system-logout", options.redirectTo);
                    }
                    return false;
                }.bind(this));
            };

            ctor.prototype.onMyProfile = function () {
                if (this.identity.isHoldingAssociatedWithMembershipAccount() && this.identity.isNonMember()) {
                    this.onModalOk({
                        contentSelector: 'CPU/Error/MemberLoginText',
                        okOptions: 'CPU/Error/MemberLoginButtonText',
                        redirectTo: config.loginUrl
                    });
                    return false;
                }
                if (this.identity.isHoldingAssociatedWithMembershipAccount() || this.identity.isNonMember()) {
                    this.onModalOk({
                        contentSelector: 'CPU/Error/RegisterText',
                        okOptions: 'CPU/Error/ResisterButtonText',
                        redirectTo: config.createLoginUrl
                    });
                    return false;
                }
                router.routeTo(undefined, {
                    controller: 'MyProfile'
                });
            };

            ctor.prototype.isAuthorized = function (value) {
                var title = value().substring(value().lastIndexOf('/') + 1).toLowerCase();
                if (!this.identity.roles()) { return false; }
                switch (title.toLowerCase()) {
                    case 'documents':
                        title = 'statements';
                        break;
                    case 'activity':
                        title = 'accounthistory';
                        break;
                }

                //.includes function is not working in IE. Using IndexOf Function Instead.
                return (this.identity.roles().toLowerCase().indexOf(title) === -1 ? false : true);
            };

            ctor.prototype.init = function (locale, initialResources) {

                var registerFunctions = config.wizardControllers.map(function (controller) {

                    config.resolveBundle(controller, 'Index').then(function (name) {

                        var key = controller + '-Index';
                        ko.components.register(key, {
                            viewModel: { require: name },
                            template: '<!-- ko if: currentStep -->' +
                                '<div data-bind="component: {name: \'' +
                                controller +
                                '-ForStep-\' + currentStep(), params: {data: $data}}"></div>' +
                                '<!-- /ko -->'
                            /*'<h1>' + controller + '</h1>' +
                                '<pre data-bind="text: JSON.stringify(model(), undefined, \' \')"></pre>'*/
                        });
                    });
                });

                Promise.all(registerFunctions);

                // inspect and initialize the globalization system
                globalize.locale(locale);
                if (!globalize.defaultCurrency)
                    globalize.defaultCurrency = ko.observable(); //from scripts/lib/Framework/resources.js superceded by RWF.resources

                ko.applyBindings(this);

                this.header.redirectToDesktop(ko.bootstrap.currentBreakpointName());

                var isWizardController = function (params) {
                    return params && params.controller && !!~config.wizardControllers.indexOf(params.controller);
                };

                var isContactController = function (params) {
                    return params && /^contact$/i.test(params.controller);
                };

                var wizardRouteStatePresent = function (title, context, lastState /*last, title, context*/) {
                    if (lastState.title !== title) {
                        return false;
                    }

                    if (!lastState.context.params.id && context.params.id) {
                        lastState.context.params.id = context.params.id;
                    }

                    return lastState.context.params.id === context.params.id;
                };

                router.register({
                    view: '.main-view',
                    defaults: {
                        controller: 'RestrictedAccess',
                        action: 'WrongCountry'
                    },
                    routePattern: '#.+',
                    isDefault: true,
                    constraint: function () { return this.identity.isLoggedInToWrongCountry(); }.bind(this)
                });

                router.register({
                    view: '.main-view',
                    defaults: {
                        controller: 'RestrictedAccess',
                        action: 'NoAccounts'
                    },
                    routePattern: '#.+',
                    isDefault: true,
                    constraint: function () { return this.identity.hasNoAccounts(); }.bind(this)
                });

                router.register({
                    view: '.main-view',
                    defaults: {
                        controller: 'RestrictedAccess',
                        action: 'Deceased'
                    },
                    routePattern: '#.+',
                    isDefault: true,
                    constraint: function () { return this.identity.isDeceased(); }.bind(this)
                });

                router.register({
                    view: '.main-view',
                    defaults: {
                        controller: 'RestrictedAccess',
                        action: 'NoAccounts'
                    },
                    routePattern: '#.+',
                    isDefault: true,
                    constraint: function () { return this.identity.isAllCompaniesTerminated(); }.bind(this)
                });

                router.register({
                    view: '.main-view',
                    defaults: {
                        controller: 'TermsAndConditions',
                        action: 'Agree'
                    },
                    routePattern: '#.+',
                    isDefault: true,
                    constraint: function (routeParams, currentRouteUrl) {

                        // See also Computershare.Web.Investor.Presentation.Home.TermsAndConditionsActionFilter
                        var urlExceptions = [
                            '/Investor/#Registration',
                            '/Investor/#TermsAndConditions',
                            '/Investor/#Welcome',
                            '/Investor/#ClassifyUser',
                            '/Investor/#Mobile'
                        ];

                        if (currentRouteUrl) {
                            var urlException = urlExceptions.find(function (element) {
                                return currentRouteUrl.substring(0, element.length) === element;
                            });

                            if (urlException !== undefined) return false;
                        }
                        // if user is non member then we don't want them to accept updated terms and conditions; so returns false.
                        if (this.identity.isNonMember()) { return false; }
                        //If user is incomplete i.e Account set up is complete but member id is not assigned then we don't want to perform this check; so returns false.
                        if (this.isIncompleteUser()) { return false; }
                        return !this.identity.acceptedTnC();
                    }.bind(this)
                });

                router.register({
                    view: '.main-view',
                    componentName: 'wizard',
                    defaults: {
                        controller: 'Home',
                        action: 'Index'
                    },
                    routes: [
                        {
                            routePattern: '#:controller/:id',
                            isDefault: false
                        }, {
                            routePattern: "#:controller",
                            isDefault: false
                        }
                    ],
                    constraint: function (params) {
                        // Check if the URL is #Registration and redirect to Home
                        if (config.enablePing && params.controller === "Registration") {
                            window.location.hash = "#Home";
                            return false; // Prevent the original route from being activated
                        }
                        return isWizardController(params);
                    },
                    suppressAnalytics: true,
                    isRouterStatePresent: wizardRouteStatePresent
                });

                router.register({
                    view: '.main-view',
                    defaults: {
                        controller: 'Contact',
                        action: 'Enquiry'
                    },
                    routes: [{
                        routePattern: '#:controller/:action',
                        isDefault: false
                    }, {
                        routePattern: "#:controller",
                        isDefault: false
                    }
                    ],
                    constraint: isContactController
                });

                router.register({
                    view: '.main-view',
                    defaults: {
                        controller: 'Home',
                        action: 'Index'
                    },
                    routes: [{
                        routePattern: '#:controller/:action',
                        isDefault: false
                    }, {
                        routePattern: "#:controller",
                        isDefault: false
                    }, {
                        routePattern: '',
                        isDefault: false
                    },
                    {
                        routePattern: '#',
                        isDefault: true
                    }
                    ]

                });

                router.register({
                    view: '.main-view',
                    defaults: {
                        controller: 'MyProfile',
                        action: 'Index',
                        id: ''
                    },
                    routes: [{
                        routePattern: '#MyProfile/Index/:id',
                        isDefault: false
                    }],
                    isRouterStatePresent: function () {
                        return false;
                    }
                });

                // For sms opt out myprofile
                router.register({
                    view: '.main-view',
                    defaults: {
                        controller: 'MyProfile',
                        action: 'SmsOptOut'
                    },
                    routes: [{
                        routePattern: '#:controller/:action/:id',
                        isDefault: true
                    }, {
                        routePattern: "#:controller",
                        isDefault: false
                    }
                    ],
                    constraint: isContactController
                });

                // Wait until cldr to initialize before the router 
                var waitForCldr = function () {
                    if (globalize.cldr) {
                        router.run(config);
                    } else {
                        setTimeout(waitForCldr, 5);
                    }
                }

                waitForCldr();
            };

            Array.prototype.descSort = function (options) {
                if (!options) {
                    this.sort(function (item1, item2) {
                        if (item1.toLowerCase() > item2.toLowerCase()) {
                            return -1;
                        }
                        if (item1.toLowerCase() < item2.toLowerCase()) {
                            return 1;
                        }
                        return 0;
                    });
                } else {
                    this.sort(function (item1, item2) {
                        if (ko.unwrap(item1[options.propKey]).toLowerCase() > ko.unwrap(item2[options.propKey]).toLowerCase()) {
                            return -1;
                        }
                        if (ko.unwrap(item1[options.propKey]).toLowerCase() < ko.unwrap(item2[options.propKey]).toLowerCase()) {
                            return 1;
                        }
                        return 0;
                    });
                }
            };
            Array.prototype.ascSort = function (options) {
                if (!options) {
                    this.sort(function (item1, item2) {
                        if (item1.toLowerCase() > item2.toLowerCase()) {
                            return 1;
                        }
                        if (item1.toLowerCase() < item2.toLowerCase()) {
                            return -1;
                        }
                        return 0;
                    });
                } else {
                    this.sort(function (item1, item2) {
                        if (ko.unwrap(item1[options.propKey]).toLowerCase() > ko.unwrap(item2[options.propKey]).toLowerCase()) {
                            return 1;
                        }
                        if (ko.unwrap(item1[options.propKey]).toLowerCase() < ko.unwrap(item2[options.propKey]).toLowerCase()) {
                            return -1;
                        }
                        return 0;
                    });
                }
            };

            return ctor;
        })();

        return new Application();
    });;
define('InvestorHeader', ['knockout', 'configuration', 'resources', 'routing', 'CommonModels', 'messenger', 'ajax','InvestorCentre'],
    function (ko, configuration, resources, routing, commonModels, messenger, ajax, investorCentre) {

        var checkOption = function (value, defaultValue) {
            return value === undefined ? defaultValue : value;
        };

        var InvestorHeader = (function () {
            var ctor = function InvestorHeader() {

                this.subscriptions = [];
                this.bootstrapSubscriptions = [];
                this.navShowClass = ko.observable();
                this.menuItems = ko.observableArray();
                this.menuGroups = ko.observableArray();
                this.showOverlay = ko.observable(false);
                this.chromeMenuItems = ko.observableArray();
                this.bootstrapSubscriptions.push(ko.bootstrap.currentBreakpointName.subscribe(this.onBreakpointChange, this));

                // Force computed observables to always notify subscribers and ensure updates no more than once per 50-millisecond period
                this.menuPosition = ko.observable(0).extend({ notify: 'always', rateLimit: 50 });

                this.options = ko.observable({
                    subtitle: '',
                    showMain: true,
                    showLogo: true,
                    showMenu: true,
                    showBack: false,
                    isWizard: false,
                    showModal: false,
                    fullScreen: false,
                    backBehaviour: 'back',
                    enforceBSDMobile: false,
                    restrictedAccess: false,
                    routingParams: undefined,
                    isTransparentHeader: false,
                    title: (ko.bootstrap.currentBreakpointName() === 'xs' ? 'CPU/applicationName-xs' : 'CPU/applicationName'),
                    showFooterMFA: false
                });

                //Set desktop overlay class
                this.desktopOverlayCss = ko.observable();
                messenger.subscribe('menu-options', function (options) {
                    options.showMenu = checkOption(options.showMenu, true);
                    options.showBack = checkOption(options.showBack, false);
                    options.isWizard = checkOption(options.isWizard, false);
                    options.activeMenu = checkOption(options.activeMenu, '');
                    options.showModal = checkOption(options.showModal, false);
                    options.fullScreen = checkOption(options.fullScreen, false);
                    options.backBehaviour = checkOption(options.backBehaviour, 'back');
                    options.routingParams = checkOption(options.routingParams, undefined);
                    options.restrictedAccess = checkOption(options.restrictedAccess, false);
                    options.isTransparentHeader = checkOption(options.isTransparentHeader, false);
                    options.showFooterMFA = checkOption(options.showFooterMFA, false);
                    this.options(options);
                }, this);

                // Hide the menu if visible whenever the url changes
                // This can happen if the user uses the back button
                // when the menu is visible.
                messenger.subscribe('router-urlActivated', function () {
                    //TODO: Get Rid of Outer If once Mobile has been discontinued
                    if (configuration.enableResponsive === true) {
                        if (!this.navbarButton.hasClass('collapsed')) {
                            this.navbarButton.click();
                        }
                    }
                }, this);

                this.authenticatedItems = ko.computedArray(function () {
                    return this.menuItems.filter(function (item) { return item.requiresAuth(); });
                }, this);

                this.commonMenuItems = ko.computedArray(function () {
                    return this.menuItems.filter(function (item) { return !item.requiresAuth(); });
                }, this);

                this.primaryMenuItems = ko.computed(function () {
                    return this.authenticatedItems().slice(0, 5); //why is this limited??!
                }, this);
                this.secondaryMenuItems = ko.computed(function () {
                    return this.authenticatedItems.slice(1);
                }, this);

                this.logOutUrl = new commonModels.Link(configuration.logoutUrl, 'CPU/Menu/Logout');
                this.logInUrl = new commonModels.Link(configuration.loginUrl, 'CPU/Menu/Login');

                // NavBar section

                this.cssHeaderBar = ko.computed(function () {
                    if (this.options().enforceBSDMobile) {
                        return 'navbar-bsd';
                    }
                    if (this.options().showMain) {
                        if (this.options().isTransparentHeader && this.options().fullScreen) {
                            return 'navbar-purple-bg navbar-transparent-bg containerFull';
                        } else return 'navbar-purple-bg';
                    } else {
                        return 'navbar-purple-bg';
                    }
                    //return this.options().showMain ? 'navbar-white-bg' : 'navbar-purple-bg';
                }, this);

                this.enforceBSDMobile = ko.computed(function () {
                    var options = this.options();
                    if (options.enforceBSDMobile) {
                        $('.canvas').addClass('canvas-bsd');
                    }

                }, this);

                this.title = ko.computed(function () {
                    var options = this.options();

                    if (options.showLogo === true && (options.subtitle !== undefined || options.subtitle === '')) {
                        return ko.unwrap(resources.getResource('CPU/applicationName')); //if subtitle provided, force 'Investor Center' as title
                    }

                    return options.title ? ko.unwrap(resources.getResource(options.title)) : '';
                }, this);

                this.subtitle = ko.computed(function () {
                    var options = this.options();

                    if (options.subtitle === undefined) {
                        return '';
                    }

                    return options.subtitle.indexOf('/') !== -1 ? ko.unwrap(resources.getResource(options.subtitle)) : options.subtitle; //TODO: this check should be revised to only use webcontent, but for quick mocks allow straight text
                }, this);

                this.showMenu = ko.computed(function () {
                    return !this.options().showModal && this.options().showMenu;
                }, this);

                this.restrictedAccess = ko.computed(function () {
                    return this.options().restrictedAccess;
                }, this);

                this.showFooterMFA = ko.computed(function () {
                    return this.options().showFooterMFA;
                }, this);

                this.actionGlyph = ko.computed(function () {
                    var options = this.options();
                    return options.showBack ? 'cpuicon-arrow-left' : options.showModal ? 'cpuicon-arrow-left' : '';
                }, this);

                this.cssTitleBar = ko.computed(function () {
                    var options = this.options();

                    var cssNames = [];
                    cssNames.push(options.showMain || options.showLogo ? 'navbar-logo-visible' : 'navbar-logo-hidden');

                    if (options.showBack || options.showModal) {
                        cssNames.push('navbar-showBack');
                    }

                    return cssNames.toString().replace(/,/g, ' ');
                }, this);

                // Event handlers
                this.goBack = this.goBack.bind(this);
                this.onNavShow = this.onNavShow.bind(this);
                this.getCountries = this.getCountries.bind(this);
                this.loadCountries = this.loadCountries.bind(this);
                this.bindCountries = this.bindCountries.bind(this);
                this.onLogoutSelected = this.onLogoutSelected.bind(this);
                this.redirectToDesktop = this.redirectToDesktop.bind(this);
                this.onBreakpointChange = this.onBreakpointChange.bind(this);
                this.onMenuItemSelected = this.onMenuItemSelected.bind(this);
                this.onFooterItemSelected = this.onFooterItemSelected.bind(this);
                this.onChromeMenuItemSelected = this.onChromeMenuItemSelected.bind(this);
                this.GetNewMessageCountAndNotificationOpt = this.GetNewMessageCountAndNotificationOpt.bind(this);

            /*
               Added Investor RS Variables below this line 
            */
            this.countries = ko.observableArray();
            this.selectedCountry = ko.observable();
            this.footerItems = ko.observableArray();
            this.leftMenuItems = ko.observableArray();
            this.isCordova = ko.observable(configuration.isCordova);
            this.appVersion = ko.observable(configuration.appVersion);
            this.enableBuyStockDirectNA = ko.observable(configuration.enableBuyStockDirectNA);
            this.enableBeneficiaryNA = ko.observable(configuration.enableBeneficiaryNA);
            this.enableMultiAccBeneficiaries = ko.observable(configuration.enableMultiAccBeneficiaries);
            this.enableGiftTransferNA = ko.observable(configuration.enableGiftTransferNA);
            this.loadCountries = this.loadCountries.bind(this);
            
            this.loadCountries();

                this.isBSD = ko.computed(function () {
                    return this.options().enforceBSDMobile;
                }, this);

                this.subscriptions.push(this.isBSD.subscribe(this.loadCountries));

                this.countrySelectEnabled = ko.computed(function () {
                    return !this.isCordova() && !this.options().isWizard;
                }, this);

                /*
                   Added Investor RS Variables Above this line 
                */


            };
            // gets new messages count
            ctor.prototype.GetNewMessageCountAndNotificationOpt = function () {
                return ajax.postJSON(configuration.baseUrl + 'Messages/GetNewMessageCountAndNotificationOpt');
            };
            // Event handlers
            ctor.prototype.onNavShow = function () {
                if (this.navShowClass()) {
                    this.navShowClass('');
                    if (!configuration.enableResponsive) {
                        this.showOverlay(false);
                    }
                } else {
                    this.navShowClass('navbar-visible');
                    if (!configuration.enableResponsive) {
                        this.showOverlay(true);
                    }
                }

                // Force scroll to the top
                this.menuPosition(0);

                return true;
            };
            ctor.prototype.onMenuItemSelected = function (menuItem) {
                this.navbarButton.click();
                if (menuItem.message) {
                    messenger.publish(ko.unwrap(menuItem.message));
                    return false;       // Cancel the event so it doesn't allow anchor to change the URL
                }

                return true;
            };
            ctor.prototype.onChromeMenuItemSelected = function (chromeMenuItem) {
                this.navbarButton.click();
                if (chromeMenuItem.message) {
                    messenger.publish(ko.unwrap(chromeMenuItem.message));
                    return false;       // Cancel the event so it doesn't allow anchor to change the URL
                }

                return true;
            };
            ctor.prototype.goBack = function () {
                var options = this.options();
                if (options.backBehaviour === 'close') {
                    window.close();
                } else {
                    var routingParams = options.routingParams;
                    if (routingParams === undefined) {
                        routing.router.navigateBack();
                    } else {
                        routing.router.routeTo(undefined, routingParams);
                    }
                }
                return true;
            };
            ctor.prototype.redirectToDesktop = function (currentBreakPoint) {
                if (configuration.onResizeRedirectToDesktop) {
                    if (!configuration.isTabletEnabled) {
                        if (currentBreakPoint !== 'xs') {
                            this.desktopOverlayCss('overlayDesktop');
                            messenger.call('modal-show', {
                                icon: 'alert',
                                modalBehaviour: { keyboard: false },
                                okOptions: 'CPU/Session/ContinueButton',
                                titleSelector: 'CPU/Common/AccessFullSite',
                                contentSelector: 'CPU/Common/IncorrectViewPoint'
                            }).then(function (result) {
                                this.modalVisible = false;
                                if (result === 'ok') {
                                    window.location = 'Mobile\\ToDesktop';
                                }
                            }.bind(this));
                        }
                    }
                }
            };
            //Redirect to Desktop on Sm/Md breakpoints for NA
            ctor.prototype.onBreakpointChange = function (currentBreakPoint) {
                this.redirectToDesktop(currentBreakPoint);
            };
            ctor.prototype.dispose = function () {
                while (this.bootstrapSubscriptions.length > 0) {
                    this.bootstrapSubscriptions.pop().dispose();
                };
                while (this.subscriptions.length > 0) {
                    this.subscriptions.pop().dispose();
                }
            };
            /**
               Added Investor RS Methods below this line 
            */
            ctor.prototype.loadCountries = function () {
                // dont want to perform this ajax call if i am an incomplete user
                if (!configuration.isIncompleteUser) {
                    this.getCountries().showLoading().then(this.bindCountries);
                }
            }
            ctor.prototype.bindCountries = function (data) {
                this.countries.removeAll();

                if (this.options().enforceBSDMobile) {
                    for (var i = 0; i < data.Countries.length; i++) {
                        var country = data.Countries[i];
                        var cc = country.CountryCode.toLowerCase();
                        var lang = country.LanguageCode.toLowerCase();

                        if (cc === 'ca' || cc === 'us') {
                            country.DisplayText = country.CountryName +
                                (country.LanguageCount !== 1 ? ' (' + country.LanguageName + ')' : '');
                            this.countries.push(country);
                        }
                    }
                } else {
                    this.countries(data.Countries.map(function (item) {
                        item.DisplayText =
                            item.CountryName + (item.LanguageCount !== 1 ? ' (' + item.LanguageName + ')' : '');
                        return item;
                    }));
                }

                var countrySelected = ko.utils.arrayFirst(this.countries(), function (country) {
                    return country.Selected;
                });

                this.selectedCountry(countrySelected);
            };
            ctor.prototype.getCountries = function () {
                return ajax.postJSON(configuration.baseUrl + 'Country/GetCountries');
            };
            ctor.prototype.onFooterItemSelected = function (footerItem) {
                if (footerItem.message) {
                    messenger.publish(ko.unwrap(footerItem.message));
                    return false;       // Cancel the event so it doesn't allow anchor to change the URL
                }
                return true;
            };
            ctor.prototype.onLogoutSelected = function () {
                messenger.publish('system-logout-notice');
                return false;
            };

            /**
               Added Investor RS Methods Above this line 
            */

            return ctor;
        })();

        return InvestorHeader;
    }
);
;
define('InvestorResources', ['messenger', 'resources'], function (messenger, resources) {

    var textProp = ('innerText' in document.createElement('span')) ? 'innerText' : 'textContent';
    var loadResourceContent = function (data) {

        if (typeof data === "string") {
            var startRes = data.indexOf('<div id="resources"'),
                endRes = data.indexOf('</div>', data.indexOf('<!--endResources-->', startRes)) + 6,
                resContent = data.substring(startRes, endRes);
        
            return $(resContent);
        }

        var $resources = $(data).children('#resources');

        return $resources.length > 0 ? $resources : $(data).find('#resources');
    };

    messenger.subscribe('system-loadTemplate', function (data) {

        if (!data) { return }

        var $resContent = loadResourceContent(data).find('span'),
            elements = Array.prototype.slice.call($resContent, 0),
            resourceData = {};

        elements.reduce(function (prev, curr) {

            var currTextProp = curr.getAttribute('data-type') === 'html' ? 'innerHTML' : textProp;

            curr.getAttribute('data-resourcepath').match(/[^/]+/g).reduce(function (prevPath, currPath, index, array) {
                prevPath[currPath] = (index === array.length - 1) ? curr[currTextProp] : (prevPath[currPath] || {});
                return prevPath[currPath];
            }, resourceData);

            return prev;
        }, resourceData);

        resources.setResources(resourceData);

        return data;
    });

    return {
        loadResourceContent: loadResourceContent
    };
});;
define('InvestorSession', ['knockout', 'configuration', 'resources', 'routing', 'messenger', 'ajax', 'globalize', 'LogService'],
    function (ko, configuration, resources, routing, messenger, ajax, globalize, logService) {
        'use strict';

        var consts = {
            millisecondsInSecond: 1000,
            millisecondsInMinute: 1000 * 60,
            secondsInMinute: 60
        };

        var InvestorSession = (function () {

            // Get the raw value of any midnight in the user's local time.
            // <trivialFact>If the user's system is set to UTC then this value will be zero</trivialFact>
            var baseDate = (new Date(1970, 0, 1, 0, 0, 0, 0)).valueOf();

            var getSeconds = function (value) {
                return Math.max(Math.floor((value / consts.millisecondsInSecond) % consts.secondsInMinute), 0);
            }

            var appendQueryString = function (url, paramName, paramValue) {

                var parts = [url, !~url.indexOf('?') ? '?' : '&', paramName, '=', encodeURIComponent(paramValue)];

                return parts.join('');
            }

            var ctor = function InvestorSession(options, identity) {

                this.options = options;
                this.identity = identity;
                this.now = Date.now();

                this.options.interval = this.options.interval * consts.millisecondsInSecond;
                this.options.warningTime = this.options.warningTime * consts.millisecondsInMinute;
                this.options.actionTime = this.options.actionTime * consts.millisecondsInMinute;

                this.timeout = ko.observable(this.options.actionTime);
                this.consoleMessages = {
                    log: [],
                    info: [],
                    warn: [],
                    error: [],
                    debug: []
                };

                // Formatted mm:ss of time remaining.  Used in session timeout modal and also (if not prod) displayed in footer.
                this.timeRemaining = ko.computed(function () {
                    // Wait for the locale system to be initialised.
                    // "ms" is the Globalize's formatCode for time in minutes and seconds
                    return globalize.locale() && globalize.formatDate(new Date(baseDate + this.timeout()), { skeleton: "ms" });
                }, this);

                this.modalVisible = false;
                //this.pageTitle = ko.observable(document.title);

                //only start focussing inner elements once the first page has loaded
                this.hasFirstPageLoaded = ko.observable(false);
                this.canFocusElements = function () {
                    if (this.hasFirstPageLoaded()) {
                        return true;
                    } else {
                        this.hasFirstPageLoaded(true);
                        return false;
                    }
                };

                this.a11yAnnouncement = ko.observable();

                this.setLoadedMessage = function () {
                    this.a11yAnnouncement('Page has loaded');
                    var local = this;
                    setTimeout(function () {
                        local.a11yAnnouncement('');
                    }, 100);
                };

                this.setLoadingMessage = function () {
                    this.a11yAnnouncement('Page loading');
                    var local = this;
                    setTimeout(function () {
                        local.a11yAnnouncement('');
                    }, 100);
                };


                this.loadingAnouncement = function (message) {
                    this.a11yAnnouncement(message + 'loading');
                    var local = this;
                    setTimeout(function () {
                        local.a11yAnnouncement('');
                    }, 60);
                };

                this.loadedAnnouncement = function (message) {
                    this.a11yAnnouncement(message + 'loaded');
                    var local = this;
                    setTimeout(function () {
                        local.a11yAnnouncement('');
                    }, 60);
                };

                this.skipToMain = function () {
                    var element = document.getElementById('mainwrap');
                    element.scrollIntoView(true);
                    $(element).find('.panel-heading h2').focus();
                }
                messenger.subscribe('router-urlActivated', function (url) {
                    this.setLoadingMessage();
                }, this);

                messenger.subscribe('onViewModelLoaded', function (data) {
                    var title = resources.getResource('CPU/applicationName')();
                    if (data.pageTitle) {
                        title = data.pageTitle() + ' | ' + title;
                    } else {
                        title = resources.getResource('CPU/Body.Master/InvestorCentreSiteTitle')();
                    }
                    document.title = title;
                    //this.setTitle(data.pageTitle);
                    messenger.publish('router-urlActivated', data.pageTitle ? data.pageTitle() : title);
                    this.setLoadedMessage();
                }, this);

                messenger.subscribe('ajax-send', function () {
                    this.now = Date.now();
                }, this);

                messenger.subscribe('error-ajaxError', this.onAjaxError, this);
                messenger.subscribe('system-login', this.doLogin, this);
                messenger.subscribe('system-logout', this.doLogout, this);
                messenger.subscribe('system-fullsite', this.switchToFullSite, this);
                messenger.subscribe('system-employeesite', this.gotoEmployeeOnline, this);
                messenger.subscribe('system-buystockdirect', this.gotoBuyStockDirect, this);
                messenger.subscribe('system-addBeneficiary', this.gotoAddBeneficiary, this);
                messenger.subscribe('system-virtualAgent', this.gotoVirtualAgent, this);
                messenger.subscribe('system-privacy-policy', this.doPrivacyPolicy, this);
                messenger.subscribe('system-logout-to-page', this.logoutToPage, this);
                messenger.subscribe('system-logout-redirect', this.logoutAndRedirect, this);
                messenger.subscribe('system-logout-notice', this.logoutNotice, this);
                messenger.subscribe('system-error', this.logError, this);
                messenger.subscribe('system-registration', this.doRegistration, this);
                messenger.subscribe('system-goBackHome', this.goBackHome, this);
                messenger.subscribe('display-termsAndConditions', this.onTermsAndConditionsClick, this);
                messenger.subscribe('cancel-transaction', this.onCancelTransaction, this);
                messenger.subscribe('cancel-verification', this.cancelverification, this);

                this.identity.isAuthenticated.subscribe(this.onAuthenticationUpdate, this);
                this.onAuthenticationUpdate(this.identity.isAuthenticated());

                this.identity.showTimeout.subscribe(this.onAuthenticationUpdate, this);
                this.onAuthenticationUpdate(this.identity.showTimeout());


                this.onCountrySelected = this.onCountrySelected.bind(this);
                this.onCancelTransaction = this.onCancelTransaction.bind(this);
                this.showTermsAndConditions = this.showTermsAndConditions.bind(this);
                this.onTermsAndConditionsClick = this.onTermsAndConditionsClick.bind(this);

                messenger.subscribe('router-urlActivated', function (data) {
                    try {
                        if (window.lpTag) {
                            window.lpTag.newPage(window.location.href);
                        }
                    } catch (e) {
                        console.error(e);
                    }
                }, this);
                messenger.subscribe('announcement-loading', function (data) {
                    this.loadingAnouncement(data.message);
                }, this);
                messenger.subscribe('announcement-loaded', function (data) {
                    this.loadedAnnouncement(data.message);
                }, this);
            };
            ctor.prototype.goBackHome = function () {
                if (this.identity.isAuthenticated() || this.identity.isNonMember()) {
                    routing.router.navigateBack();
                } else {
                    routing.router.routeTo(undefined, {
                        controller: 'Home',
                        action: 'Index'
                    });
                }
            }
            ctor.prototype.onTermsAndConditionsClick = function (data) {
                data = data || {};
                if (!data.title) {
                    data.title = 'CPU/Common/TermsAndConditionsHeader';
                }
                if (!data.termsAndConditions) {
                    ajax.postJSON(configuration.baseUrl + 'TermsAndConditions/GetTermsAndConditions').then(function (result) {
                        data.termsAndConditions = result.Body;
                        this.showTermsAndConditions(data);
                    }.bind(this));
                } else {
                    this.showTermsAndConditions(data);
                }
                return false;
            };
            ctor.prototype.showTermsAndConditions = function (data) {
                messenger.publish('modal-show', {
                    titleSelector: data.title,
                    contentSelector: data.termsAndConditions,
                    okOptions: 'CPU/Common/Close',
                    modalBehaviour: {
                        keyboard: true
                    }
                });
            };
            ctor.prototype.onCancelTransaction = function (wizard, options) {
                var titleString = 'CPU/Registration/RegistrationTitle';
                var contentString = 'CPU/Registration/CancelText';
                var cancelOptions = 'CPU/Common/Cancel';
                var okOptions = 'CPU/Common/Continue';

                if (configuration.enableResponsive) {
                    titleString = 'CPU/Common/Cancel';
                    contentString = 'CPU/Common/TransactionCancelText';
                    cancelOptions = 'CPU/Common/No';
                    okOptions = 'CPU/Common/Yes';
                }

                messenger.call('modal-show', {
                    titleSelector: titleString,
                    contentSelector: contentString,
                    cancelOptions: cancelOptions,
                    okOptions: okOptions,
                    icon: 'alert',
                    modalBehaviour: {
                        keyboard: false
                    }
                }).then(function (result) {
                    this.modalVisible = false;
                    if (result === 'ok') {
                        //if (wizard) {
                        //    if (wizard.stepCallbacks['Cancel']) {
                        //        wizard.service.setState(wizard.service.Actions.cancel);
                        //    }
                        //}
                        if (options) {
                            if (options.topic) {
                                var isComponentResolved = messenger.call(options.topic);
                                if (isComponentResolved !== true) {
                                    routing.router.routeTo(undefined, {
                                        controller: 'Portfolio',
                                        action: 'Index'
                                    });
                                }
                                return false;
                            }
                            routing.router.routeTo(undefined, options);
                            return false;
                        }
                        routing.router.routeTo(undefined, {
                            controller: 'Home',
                            action: 'Index'
                        });
                        return false;
                    }
                }.bind(this));

                return false;
            };
            ctor.prototype.interceptConsole = function () {
                var methodsToIntercept = ['log', 'error', 'warn', 'info', 'debug'];
                // Some IE versions console are not really javascript functions per se.
                if (window.console && typeof window.console.log === 'object') {
                    return;
                }

                methodsToIntercept.forEach(function (name) {
                    var oldMethod = window.console && window.console[name];

                    // WinPhone 7.x doesn't have a console, so they dropped the javascript accessor as well.
                    if (!window.console) {
                        window.console = {};
                    }
                    window.console[name] = function () {
                        this.consoleMessages[name].push(Array.prototype.slice.call(arguments));

                        if (oldMethod) {
                            oldMethod.apply(window.console, arguments);
                        }
                    }.bind(this);
                }.bind(this));
            };
            ctor.prototype.onAuthenticationUpdate = function (value) {
                if (value && !this.intervalId) {
                    this.intervalId = setInterval(this.onTimerTick.bind(this), this.options.interval);
                }
                if (!value && this.intervalId) {
                    clearInterval(this.intervalId);
                    this.intervalId = undefined;
                }
            };
            ctor.prototype.keepAlive = function () {
                return ajax.postJSON(configuration.keepAlive);
            };
            ctor.prototype.onTimerTick = function () {
                var elapsedTime = Date.now() - this.now; // in milliseconds.
                this.timeout(Math.max(0, this.options.actionTime - elapsedTime)); //Remaining

                // Extra callback from the setInterval or not reached warning time... do nothing
                if (!this.intervalId || elapsedTime < this.options.warningTime) {
                    return;
                }

                if (elapsedTime >= this.options.actionTime) {
                    this.doLogout();
                    return;
                }

                if (elapsedTime < this.options.actionTime && !this.modalVisible) {
                    this.modalVisible = true;

                    var modalTitle = resources.getResource('CPU/Session/TimeoutHeader'),
                        modalContent = ko.computed(function () {
                            return '<p>' + ko.unwrap(resources.getResource('CPU/Session/SessionTimeoutText')) + '</p><p>' + ko.unwrap(resources.getResource('CPU/Session/SessionTimeoutCountdownText')) + '{mm:ss}</p>';
                        });

                    // Show model dialog
                    var modalContentWithTimer = ko.computed(function () {
                        return ko.unwrap(modalContent).replace('{mm:ss}', this.timeRemaining());
                    }, this);

                    messenger.call('modal-show', {
                        titleSelector: modalTitle,
                        contentSelector: modalContentWithTimer,
                        cancelOptions: 'CPU/Session/ContinueButton',
                        okOptions: 'CPU/Session/LogoutButton',
                        icon: 'alert',
                        modalBehaviour: { keyboard: false }
                    }).then(function (result) {
                        this.modalVisible = false;
                        if (result === 'ok') {
                            this.doLogout();
                        } else {
                            // this will do an ajax keep alive which in turn re-triggers the ajax send message
                            this.keepAlive();
                        }
                    }.bind(this));

                    return;
                }
            };
            ctor.prototype.onAjaxError = function (error) {
                // If the response is unauthorised initiate a login
                // This could either be the user hitting a secured page whilst not be logging
                // in, order the identity has timed out server side
                switch (error.responseCode) {
                    case 401:
                        messenger.publish('system-login', error.url);

                        break;

                    case 412: // StepUp required.  Change the browser URL so the FAM can redirect
                    case 369: // Exclusion list, use desktop route, Add currentBreakpoint for promo existing check
                        var url = appendQueryString(error.url, 'bypassSPA', 'true') + '&breakpoint=' + ko.bootstrap.currentBreakpointName();
                        messenger.publish('modal-showLoading', new Promise(function (resolve, reject) { })); // keep the spinner up until 
                        routing.router.navigateTo(url);

                        break;

                    case 200:
                        messenger.publish('system-suppressAjaxErrors', true);
                        error.responseText = error.responseText.replace('wizard%2fTaxCertificate%2f', '%23MyProfile%3ftargetController%3dTaxCertificate%26id%3d');
                        $('body').html(error.responseText);
                        break;

                    case 370: // client side route redirect
                        var redirectTo = error.responseHeaders['x-redirectto'] || error.responseHeaders['location'];
                        if (!redirectTo) {
                            if (console && console.debug) {
                                console.debug(error.responseHeaders);
                            }
                            throw new Error('Unable to resolve redirect location from response headers');
                        }

                        messenger.publish('system-suppressAjaxErrors', true);
                        redirectTo = configuration.baseUrl + '#' + redirectTo.replace(configuration.baseUrl, '');
                        routing.router.navigateTo(redirectTo);

                        break;

                    default:
                        routing.router.routeTo(undefined, { controller: "Error", reason: error.responseCode, message: error.message });
                }
            };
            ctor.prototype.logError = function (error) {
                logService.logError(error.title, error.data);
            }
            /* LogoutToPage - Allow logout to alternate logout location */
            ctor.prototype.logoutToPage = function (url) {
                var modalTitle = resources.getResource('CPU/Session/LogoutHeader');
                var modalContent = resources.getResource('CPU/Session/LogoutText');

                this.modalVisible = true;
                messenger.call('modal-show', {
                    titleSelector: modalTitle,
                    contentSelector: modalContent,
                    cancelOptions: 'CPU/Common/Cancel',
                    okOptions: 'CPU/Session/LogoutButton',
                    modalBehaviour: { keyboard: false }
                }).then(function (result) {

                    this.modalVisible = false;

                    if (result === 'ok') {
                        this.doLogout(url);
                    }

                    return false;
                }.bind(this));

                // Return false here to cancel any event in progress, in case we're wired to a click handler of an anchor
                return false;
            };
            /* LogoutAndRedirect - for some reason this is Country Region-related instead of just offering an alternate logout location */
            ctor.prototype.logoutAndRedirect = function (url) {
                var modalTitle = resources.getResource('CPU/Session/ChangeRegionLogoutHeader');
                var modalContent = resources.getResource('CPU/Session/ChangeRegionLogoutText');

                this.modalVisible = true;
                messenger.call('modal-show', {
                    titleSelector: modalTitle,
                    contentSelector: modalContent,
                    cancelOptions: 'CPU/Common/Cancel',
                    okOptions: 'CPU/Session/LogoutButton',
                    modalBehaviour: { keyboard: false }
                }).then(function (result) {
                    this.modalVisible = false;
                    if (result === 'ok') {
                        this.doLogout(url);
                    }
                    return false;
                }.bind(this));

                // Return false here to cancel any event in progress, in case we're wired to a click handler of an anchor
                return false;
            };
            ctor.prototype.cancelverification = function () {
                var modalTitle = resources.getResource('CPU/Common/Cancel');
                var modalContent = resources.getResource('CPU/MultiFactorAuthentication/VerifyCancelText');

                this.modalVisible = true;
                messenger.call('modal-show', {
                    titleSelector: modalTitle,
                    contentSelector: modalContent,
                    cancelOptions: 'CPU/Common/No',
                    okOptions: 'CPU/Common/Yes',
                    modalBehaviour: { keyboard: false }
                }).then(function (result) {
                    this.modalVisible = false;
                    if (result === 'ok') {
                        messenger.publish('analytics-trackEvent', { category: '2FactorAuth', action: 'Cancel_Click', label: 'Cancel button', value: null });
                        var baseUrl = routing.router.routeFor({ controller: 'Summary', action: 'Index' });
                        routing.router.navigateTo(baseUrl);
                    }
                    return false;
                }.bind(this));

                // Return false here to cancel any event in progress, in case we're wired to a click handler of an anchor
                return false;
            };
            ctor.prototype.logoutNotice = function () {
                var modalTitle = resources.getResource('CPU/Session/LogoutHeader');
                var modalContent = resources.getResource('CPU/Session/LogoutText');

                this.modalVisible = true;
                messenger.call('modal-show', {
                    titleSelector: modalTitle,
                    contentSelector: modalContent,
                    cancelOptions: 'CPU/Common/Cancel',
                    okOptions: 'CPU/Session/LogoutButton',
                    modalBehaviour: { keyboard: false }
                }).then(function (result) {
                    this.modalVisible = false;
                    if (result === 'ok') {
                        this.doLogout();
                    }
                    return false;
                }.bind(this));

                // Return false here to cancel any event in progress, in case we're wired to a click handler of an anchor
                return false;
            };
            ctor.prototype.switchToFullSite = function () {
                var modalTitle = resources.getResource('CPU/Session/FullSiteHeader');
                var modalContent = resources.getResource('CPU/Session/FullSiteContent');

                this.modalVisible = true;
                messenger.call('modal-show', {
                    titleSelector: modalTitle,
                    contentSelector: modalContent,
                    cancelOptions: 'CPU/Common/Cancel',
                    okOptions: 'CPU/Common/Continue',
                    modalBehaviour: { keyboard: false }
                }).then(function (result) {
                    this.modalVisible = false;

                    if (result === 'ok') {
                        window.location = configuration.fullSiteUrl;
                    }

                }.bind(this));

                // Return false here to cancel any event in progress, in case we're wired to a click handler of an anchor
                return false;
            };
            ctor.prototype.gotoBuyStockDirect = function () {
                var modalTitle = resources.getResource('CPU/Session/FullSiteHeader');
                var modalContent = resources.getResource('CPU/Session/FullSiteContent');

                this.modalVisible = true;
                messenger.call('modal-show', {
                    titleSelector: modalTitle,
                    contentSelector: modalContent,
                    cancelOptions: 'CPU/Common/Cancel',
                    okOptions: 'CPU/Common/Continue',
                    modalBehaviour: { keyboard: false }
                }).then(function (result) {
                    this.modalVisible = false;

                    if (result === 'ok') {
                        window.location = configuration.buyStockDirectSiteUrl;
                    }

                }.bind(this));

                return false;
            };
            ctor.prototype.gotoAddBeneficiary = function () {
                var modalTitle = resources.getResource('CPU/Session/FullSiteHeader');
                var modalContent = resources.getResource('CPU/Session/FullSiteContent');

                this.modalVisible = true;
                messenger.call('modal-show', {
                    titleSelector: modalTitle,
                    contentSelector: modalContent,
                    cancelOptions: 'CPU/Common/Cancel',
                    okOptions: 'CPU/Common/Continue',
                    modalBehaviour: { keyboard: false }
                }).then(function (result) {
                    this.modalVisible = false;

                    if (result === 'ok') {
                        window.location = configuration.addBeneficiarySiteUrl;
                    }

                }.bind(this));

                return false;
            };
            ctor.prototype.gotoVirtualAgent = function (searchText) {
                var url = configuration.virtualAgentUrl.replace(/&amp;/g, '&') + "&usertext=" + encodeURIComponent(searchText || '');
                window.open(url, "virtualagent");
                return false;
            };
            ctor.prototype.gotoEmployeeOnline = function () {
                var modalTitle = resources.getResource('CPU/Session/EmployeeSiteHeader');
                var modalContent = resources.getResource('CPU/Session/EmployeeSiteText');

                this.modalVisible = true;
                messenger.call('modal-show', {
                    titleSelector: modalTitle,
                    contentSelector: modalContent,
                    cancelOptions: 'CPU/Common/Cancel',
                    okOptions: 'CPU/Common/Continue',
                    modalBehaviour: { keyboard: false }
                }).then(function (result) {
                    this.modalVisible = false;

                    if (result === 'ok') {
                        window.location = configuration.employeeSiteUrl;
                    }

                }.bind(this));

                return false;
            };
            ctor.prototype.doPrivacyPolicy = function () {
                var modalTitle = resources.getResource('CPU/Session/PrivacyPolicyHeader');
                var modalContent = resources.getResource('CPU/Session/PrivacyPolicyContent');
                this.modalVisible = true;
                messenger.call('modal-show', {
                    titleSelector: modalTitle,
                    contentSelector: modalContent,
                    cancelOptions: 'CPU/Common/Cancel',
                    okOptions: 'CPU/Common/Continue',
                    okHref: configuration.privacyPolicyUrl,
                    okTarget: '_blank',
                    modalBehaviour: { keyboard: false }
                }).then(function (result) {
                    this.modalVisible = false;

                    if (result === 'ok') {
                        $('.modal.dialog').modal('hide');
                        //window.open(configuration.privacyPolicyUrl, '_blank');
                        if (configuration.isCordova) {
                            cordova.InAppBrowser.open(configuration.privacyPolicyUrl, '_system');
                        }
                    }
                }.bind(this));
                return false;
            };
            ctor.prototype.doLogout = function (url) {
                if (configuration.enableSurveyGenesys) {
                    closeSurveyMessenger(); //closes survey messenger if opened
                }

                clearInterval(this.intervalId);
                this.intervalId = undefined;
                routing.router.stop();
                var logoutUrl = configuration.logoutUrl;
                if (url) {
                    logoutUrl = logoutUrl + "?url=" + encodeURIComponent(url);
                }
                window.location = logoutUrl;
            };
            ctor.prototype.doLogin = function (returnUrl) {
                if (/\/welcome\/failed$/i.test(returnUrl)) { // if returnUrl ends with /welcome/failed (case insensitive)
                    window.location = returnUrl + "?breakpoint=" + ko.bootstrap.currentBreakpointName() + '&bypassSPA=true';
                }
                else {
                    window.location = configuration.loginUrl + "?breakpoint=" + ko.bootstrap.currentBreakpointName();
                }
            };
            ctor.prototype.doRegistration = function () {
                window.location = configuration.createLoginUrl + "?breakpoint=" + ko.bootstrap.currentBreakpointName();
            };
            //Logs out user if they select a new country rather than same country, different language
            ctor.prototype.onCountrySelected = function (selectedCountry) {
                // Stop the routing engine so that same region can redirect.              
                if (selectedCountry) {

                    //do not logout within the same country
                    if (configuration.countryContext === selectedCountry.CountryCode) {
                        //TODO: this functionality changed due to UserPrefereces reloading page for same country
                        //window.location = selectedCountry.RedirectUrl;
                    }
                    else {
                        if (this.identity.isAuthenticated()) {
                            messenger.publish('system-logout-redirect', selectedCountry.RedirectUrl);
                            return false;
                        }
                    }
                    routing.router.stop();
                }
                return true;
            };
            return ctor;

        })();

        return InvestorSession;
    });;
define('LogService', ['configuration', 'knockout', 'globalize'], function (configuration, ko, globalize) {


    var Audit = (function () {
        var ctor = function Audit(logArea, scenario, action, success, targetType, data) {
            this.logArea = ko.observable(logArea);
            this.scenario = ko.observable(scenario);
            this.action = ko.observable(action);
            this.success = ko.observable(success);
            this.targetType = ko.observable(targetType);
            this.data = ko.observable(data);
        };

        return ctor;
    })();

    var auditModel = (function() {
        var ctor = function (logArea, scenario, action, targetType, success, data) {
            this.success = success;
            this.logArea = logArea;
            this.targetType = targetType;
            this.scenario = scenario;
            this.action = action;
            this.data = data;
        }

        return ctor;
    })();

    var auditCategory = function() {
        return{
            error : "error",
            infomation : "information",
            audit : "audit"
        }
    };

    function postAjax(data, url) {
        $.ajax({
            type: "POST",
            url: url,
            data: data
        });
    }


    return {
        logError: function (title, data) {
            //postAjax({ title: title, data: data, category: auditCategory.error }, configuration.logErrorUrl);
        },
        logInformation : function(title, data) {
            postAjax({ title: title, data: data, category: auditCategory.infomation }, configuration.logErrorUrl);
        },
        logAudit: function (logArea, scenario, action, targetType, success, data) {
            //var auditData = new auditModel(logArea, scenario, action, targetType, success, data);
            //postAjax(auditData, configuration.logAuditUrl);
        }
    };
});;
define('InvestorModals-Autocomplete', ['configuration', 'knockout', 'jQuery', 'i18n', 'routing', 'InvestorHeader', 'resources', 'messenger', 'utils'], function (config, ko, $, globalize, routing, InvestorHeader, resources, messenger, utils) {

    var ModalsAutoComplete = (function () {
        var ctor = function ModalsAutoComplete() {
            this.init = this.init.bind(this);
            this.modalActive = false;
        };

        ctor.prototype.init = function (rootElement) {

            this.$element = $(rootElement);
            this.$autocomplete = this.$element.find('.modal.autocomplete');

            messenger.subscribe('modal-autocomplete', function (options) {

                var _this = this;
                var promise = new Promise(function (resolve, reject) {

                    var model = new AutoCompleteModel(options, resolve);

                    // We need to clone the dropdown nodes as it is hard to clean up
                    // in a reusable way.
                    var $ddInstance = _this.$autocomplete.clone();
                    $ddInstance.appendTo(_this.$element);

                    ko.applyBindings(model, $ddInstance[0]);
                    
                    $ddInstance.modal();
                   
                    $ddInstance.one('shown.bs.modal', function () {
                        $ddInstance.find('input.tt-query').focus();
                    });

                    $ddInstance.one('hidden.bs.modal', function () {
                        ko.cleanNode($ddInstance);
                        $ddInstance.remove();
                    });

                    //Hack for ie9mobile                   
                    if ($('html').hasClass('ie9mobile')) {
                        window.scrollTo(0, 0);
                    }

                });


                return promise;

            }, this);
        };

        ctor.prototype.resourceOrText = function (value) {
            var isResource = /^CPU\/.+/;
            if (ko.isObservable(value)) {
                value = value();
            }

            return ko.unwrap(typeof value === 'string' && isResource.test(value) ? resources.getResource(value) : value);
        };

        return ctor;
    })();

    var AutoCompleteModel = (function () {

        var highlighterResult = function (textToMatch, textSelector, matchOptions, item) {

            var text = textSelector(item);
            var replacerRegex = new RegExp(matchOptions && matchOptions.wordBoundaries ? '\\b' + textToMatch : textToMatch, 'gi');
            
            return text.replace(replacerRegex, function (value) {
                return '<strong>' + value + '</strong>';
            });
        }.curry();

        var delayBy = function (delayMillis) {
            var timeoutId = undefined;
            var delayPromise = new Promise(function(resolve, reject) {

                timeoutId = setTimeout(resolve, delayMillis);
            });

            delayPromise.cancel = function () {
                clearTimeout(timeoutId);
            };

            return delayPromise;
        }


        var ctor = function AutoCompleteModel(options, onResolve) {

            var onCancel = undefined;

            this.value = ko.observable();
            this.displayedResults = ko.observableArray([]);

            this.options = options;
            // Setup the selector functions -- note the functions are curried
            var textSelector = options.textSelector;
            var valueSelector = options.valueSelector;

            this.isRetrievingData = ko.observable(false);
            this.hasNoResults = ko.observable(false);

            this.results = ko.asyncComputedArray(function () {

                this.hasNoResults(false);
                var value = this.value();
                if (!value) {
                    return Promise.resolve([]);
                }

                if (onCancel) {
                    onCancel();
                }

                var promise = delayBy(300);
                onCancel = promise.cancel;

                return promise
                    .then(function () {
                        var lookupPromise = options.lookupSource(value);
                        onCancel = lookupPromise.cancel;
                        this.isRetrievingData(true);
                        return lookupPromise;
                    }.bind(this))
                    .then(function (data) {

                        var highlighter = highlighterResult(value, options.textSelector, options.optionsHighlight);
                        //  Clear the cancelation as have a result
                        onCancel = undefined;

                        this.isRetrievingData(false);

                        this.hasNoResults(!data || data.length === 0);

                        return data.map(function (item) {
                            return {
                                Text: options.textSelector(item),
                                Value: options.valueSelector(item),
                                resultWithHighlight: highlighter(item)
                            };
                        });
                    }.bind(this));

            }, this);

            this.results.subscribe(function (value) {             
                this.displayedResults(value);
            }, this);

            this.value.subscribe(function () {
                this.displayedResults([]);
            }, this, 'beforeChange');

            this.hint = ko.computed(function () {
                var value = this.value(),
                    results = this.displayedResults();

                if (results.length > 0) {
                    var textFirstResult = textSelector(results[0]);
                    if ( new RegExp('^' + value, 'i').test(textFirstResult)){
                        return value + textFirstResult.slice(value.length);
                    }
                }

                return ( !value && options.placeholder) ? ko.unwrap(options.placeholder) : value;

            }, this);

            this.isPlaceholderShown = ko.computed(function () {
                return this.hint() === ko.unwrap(options.placeholder);
            }, this);

            this.onEnter = function (target) {
                if (this.results().length > 0) {
                    // click the first result - Need to do this to get the modal to dismiss
                    $(target).parents('.modal-body').find('.selectionItem:first').click();
                }
            }.bind(this);

            this.onSelectItem = function (item) {
                onResolve(item.Value);
            };
        };

        return ctor;
    })();

    return ModalsAutoComplete;
});;
define('InvestorModals', ['configuration', 'knockout', 'jQuery', 'i18n', 'routing', 'InvestorHeader', 'resources', 'messenger'], function (config, ko, $, globalize, routing, InvestorHeader, resources, messenger) {

    var Modals = (function () {
        var ctor = function Modals() {
            this.init = this.init.bind(this);

            this.title = ko.observable();
            this.titleText = ko.computed(function () {
                return this.resourceOrText(this.title());
            }, this);

            this.content = ko.observable();
            this.contentHtml = ko.computed(function () {
                return this.resourceOrText(this.content());
            }, this);

            this.cancelOptions = ko.observable();
            this.cancelVisible = ko.observable(true);
            this.cancelText = ko.computed(function () {
                return this.resourceOrText(this.cancelOptions());
            }, this);

            this.okOptions = ko.observable();
            this.okVisible = ko.observable(true);
            this.okText = ko.computed(function () {
                return this.resourceOrText(this.okOptions());
            }, this);
            this.okHref = ko.observable(undefined);
            this.okTarget = ko.observable();

            this.icon = ko.observable();
            this.iconGlyph = ko.computed(function () {
                return this.icon() ? 'cpuicon-' + this.icon() : '';
            }, this);

            this.modalActive = false;

            this.onComplete = undefined;
            this.onClose = this.onClose.bind(this);
            this.onCancel = this.onCancel.bind(this);
            this.onOk = this.onOk.bind(this);
            this.handleResponse = this.handleResponse.bind(this);

            this.loaderCount = 0;
        };

        ctor.prototype.init = function (rootElement) {

            this.$element = $(rootElement);
            this.$modal = this.$element.find('.modal.dialog');
            this.$loader = this.$element.find('.modal.loader');
            this.$dropdown = this.$element.find('.modal.dropdown');
            this.$component = this.$element.find('.modal.modal-component');



            messenger.subscribe('modal-show', function (options) {

                return new Promise(function (resolve, reject) {

                    this.onComplete = resolve;
                    this.runModal(options.name, options.titleSelector, options.contentSelector, options.cancelOptions, options.okOptions, options.icon, options.modalBehaviour, options.okHref, options.okTarget);
                }.bind(this));
            }, this);

            messenger.subscribe('modal-showComponent', function(options) {
                return new Promise(function (resolve, reject) {
                    //lock scrolling while modal visible
                    $('body').css('overflow','hidden');
                    $('body').css('position','relative');
                    this.onComplete = resolve;
                    this.runComponent(options);
                }.bind(this));
            }, this);

            messenger.subscribe('modal-getLinkText', function (options) {

                var $rootElement = this.$element.find('#modal-' + options.name);

                return $rootElement.find(options.linkSelector).text();
            }, this);

            messenger.subscribe('modal-showLoading', function (options) {
                if (++this.loaderCount === 1) {
                    this.$loader.find('.modal-backdrop').remove(); //remove backdrop for current loader instance
                    this.$loader.modal();
                }

                var completeLoader = function () {

                    // Set a tiny delay to avoid concurrent, but discrete, show loading calls
                    // from running multiple loading modals
                    setTimeout(function () {
                        if (--this.loaderCount === 0) {
                            $(".modal-backdrop").remove(); // cleanup
                            this.$loader.modal('hide');
                        }

                    }.bind(this), 10);
                }.bind(this);

                // Treat both success and failure scenarios as the same.
                options.then(completeLoader, completeLoader);

            }, this);

            messenger.subscribe('modal-dropdown', function (options) {

                var _this = this;
                var promise = new Promise(function (resolve, reject) {

                    //
                    var onSelectItem = function (item) {
                        //_this.$dropdown.modal('hide');
                        resolve(item);
                    };

                    var isItemSelected = function (item) {
                        //_this.$dropdown.modal('hide');
                        return options.valueTarget() === item;
                    };

                    var model = {
                        data: options,
                        isItemSelected: isItemSelected,
                        onSelectItem: onSelectItem
                    };

                    // We need to clone the dropdown nodes as it is hard to clean up
                    // in a reusable way.
                    var $ddInstance = _this.$dropdown.clone();
                    $ddInstance.appendTo(_this.$element);

                    ko.applyBindings(model, $ddInstance[0]);
                    $ddInstance.modal();

                    $ddInstance.one('hidden.bs.modal', function () {
                        ko.cleanNode($ddInstance);
                        $ddInstance.remove();
                    });

                });


                return promise;

            }, this);
        };

        ctor.prototype.onClose = function() {
            return this.handleResponse('close');
        };

        ctor.prototype.onCancel = function () {
            return this.handleResponse('cancel');
        };

        ctor.prototype.onOk = function () {
            return this.handleResponse('ok');
        };

        ctor.prototype.handleResponse = function (response) {
            this.onComplete(response);
            this.onComplete = undefined;
            this.modalActive = false;

            return true;
        };

        ctor.prototype.resourceOrText = function (value) {
            var isResource = /^CPU\/.+/;
            if (ko.isObservable(value)) {
                value = value();
            }

            return ko.unwrap(typeof value === 'string' && isResource.test(value) ? resources.getResource(value) : value);
        };

        ctor.prototype.runComponent = function(options) {

            var model = options;
            var shouldLoad = true;

            var isSelector = /^[#\.].+/,
                $rootElement = this.$element.find('#modal-' + options.componentData.name);
            options.titleText = this.resourceOrText(isSelector.test(options.titleSelector) ? $rootElement.find(options.titleSelector).text() : options.titleSelector);

            // We need to clone the component nodes as it is hard to clean up
            // in a reusable way.
            var $componentInstance = this.$component.clone();
            $componentInstance.appendTo(this.$element);

            ko.applyBindings(model, $componentInstance[0]);

            // If option.showAfter is loaded then the OnLoad function must return a promise
            var messageName = options.showAfter === 'loaded' ? 'component-viewModelLoaded' : 'component-activated';

            if (options.showAfter === 'loaded') {
                options.componentData.params._ensureOnLoadPromise = true;
            }

            var hideAllModalsSubscription = messenger.subscribe('modal-hideAllModals', function () {
                if (this.modalActive) {
                    $componentInstance.trigger('hidden.bs.modal');
                } else {
                    shouldLoad = false;
                }
            }, this);
            
            // Attach an event for when modal dialogs are closed via the title or (if allowed) click outside the modal box.
            $componentInstance.one('hidden.bs.modal', function () {
                    $('body').css('overflow','visible');
                    $('body').css('position','initial');
            }.bind(this));

            var subscription = messenger.subscribe(messageName, function (componentName) {

                var cleanUpCallback = function() {
                    ko.cleanNode($componentInstance);
                    $componentInstance.remove();
                    hideAllModalsSubscription.dispose();

                    if (this.modalActive) {
                        this.onOk();
                    };
                }.bind(this);

                if (componentName !== options.componentData.name) {
                    return;
                }

                // In the event the hide all modal is called before the component has had
                // time to finish loading, prevent the modal from being loaded at all.
                if (!shouldLoad) {
                    cleanUpCallback();
                    return;
                }

                subscription.dispose();

                setTimeout(function () {
                    $componentInstance.modal();
                    this.modalActive = true;
                    $componentInstance.one('hidden.bs.modal', cleanUpCallback);
                }, 20);

            }, this);
        };

        ctor.prototype.runModal = function (name, titleSelector, contentSelector, cancelOptions, okOptions, icon, options, href, target) {

            // Locate content
            var isSelector = /^[#\.].+/,
                $rootElement = this.$element.find('#modal-' + name),
                titleText = isSelector.test(titleSelector) ? $rootElement.find(titleSelector).text() : titleSelector,
                contentHtml = isSelector.test(contentSelector) ? $rootElement.find(contentSelector).html() : contentSelector,
                returnFocusEl = document.activeElement;
            this.title(titleText);
            this.content(contentHtml);
            this.icon(icon);
            this.cancelOptions(cancelOptions);
            this.cancelVisible(!!cancelOptions);
            this.okOptions(okOptions);
            this.okVisible(!!okOptions);
            this.okHref(href);
            this.okTarget(target);

            this.$modal.modal(options);

            this.modalActive = true;

            // Attach an event for when modal dialogs are closed via the title or (if allowed) click outside the modal box.
            this.$modal.one('hidden.bs.modal', function () {
                // If we haven't closed via the buttons, treat it as a cancel ( if 2 buttons shown ) or ok (if 1 button shown).
                if (this.modalActive) {
                    if (this.cancelVisible()) {
                        this.onCancel();
                    } else {
                        this.onOk();
                    }
                };
                returnFocusEl.focus();
            }.bind(this));
        };

        return ctor;
    })();

    return Modals;
});;
define('PortfolioSortableTable-Helper', ['configuration', 'resources'], function (config, resources) {
    // Note: This is made specifically for Portfolio / Summary / Investment held elsewhere tables

    var sortConfig = {
        selectedHeadingColor: '#7d236f',
        defaultHeadingColor: '#000000',
        order: {
            ascending: 'asc',
            descending: 'desc'
        },
        sessionStorageKey: {
            mobile: "mSortPreference",
            desktop: "dSortPreference"
        },
        holdingValue: {
            all: 'all',
            managed: 'managed',
            external: 'external'
        },
        compareValue: {
            ticker: 'ticker',
            quantity: 'quantity',
            price: 'marketDisplayPrice',
            marketValue: 'totalValue'
        }
    };

    // Options for Select Lists on mobile devices
    var sortByOptions = {
        holdings: [
            { Text: resources.getResource('CPU/Portfolio/ManagedHoldingsLabel'), value: sortConfig.holdingValue.managed },
            { Text: resources.getResource('CPU/Portfolio/ExternalHoldingsLabel'), value: sortConfig.holdingValue.external },
            { Text: resources.getResource('CPU/Portfolio/AllGridLabel'), value: sortConfig.holdingValue.all },
        ],
        headers: [
            { Text: resources.getResource('CPU/Portfolio/HoldingsLabel'), value: sortConfig.compareValue.ticker },
            { Text: resources.getResource('CPU/Portfolio/QauntityLabel'), value: sortConfig.compareValue.quantity },
            { Text: resources.getResource('CPU/Portfolio/MarketValueLabel'), value: sortConfig.compareValue.marketValue }
        ],
        sortType: [
            { Text: resources.getResource('CPU/Portfolio/SortOrderAscending'), value: sortConfig.order.ascending },
            { Text: resources.getResource('CPU/Portfolio/SortOrderDescending'), value: sortConfig.order.descending }
        ]
    };

    var comparers = {
        bySecondarySortTotalValue: function (first, second) {
            if (first.totalValue.value() === second.totalValue.value()) {
                return first.ticker().localeCompare(second.ticker());
            }
        },
        bySecondarySortQuantity: function (first, second) {
            if (first.quantity() === second.quantity()) {
                return first.ticker().localeCompare(second.ticker());
            }
        },
        byTotalValue: function (sortOrder) {
            return function (first, second) {
                return sortOrder !== sortConfig.order.ascending ? second.totalValue.value() - first.totalValue.value() : first.totalValue.value() - second.totalValue.value();
            }
        },
        byTicker: function (sortOrder) {
            return function (first, second) {
                return sortOrder !== sortConfig.order.ascending ? second.ticker().localeCompare(first.ticker()) : first.ticker().localeCompare(second.ticker());
            }
        },
        byQuantity: function (sortOrder) {
            return function (first, second) {
                return sortOrder !== sortConfig.order.ascending ? second.quantity() - first.quantity() : first.quantity() - second.quantity();
            }
        },
        byMarketPrice: function (sortOrder) {
            return function (first, second) {
                return sortOrder !== sortConfig.order.ascending ? second.price.value() - first.price.value() : first.price.value() - second.price.value();
            }
        },
    };

    var reloadSort = function (list) {
        var sortingPreferenceDesktop = JSON.parse(sessionStorage.getItem(sortConfig.sessionStorageKey.desktop)) || {};
        var sortingPreferenceMobile = JSON.parse(sessionStorage.getItem(sortConfig.sessionStorageKey.mobile)) || {};

        if (window.innerWidth > 768) {
            if (!$.isEmptyObject(sortingPreferenceDesktop) && sortingPreferenceDesktop.external) {
                this.sortByColumn(sortingPreferenceDesktop.external.sortColumn, sortingPreferenceDesktop.external.sortOrder, list)
            }
        } else {
            if (!$.isEmptyObject(sortingPreferenceMobile)) {
                this.sortByColumn(sortingPreferenceMobile.sortColumn, sortingPreferenceMobile.sortOrder, list)
            }
        }
    };

    // Sort the actual account lists by column and order
    var sortByColumn = function (sortColumn, sortOrder, list) {
        switch (sortColumn) {
            case sortConfig.compareValue.ticker:
                list.sort(comparers.byTicker(sortOrder));
                break;
            case sortConfig.compareValue.quantity:
                list.sort(comparers.byQuantity(sortOrder));
                list.sort(comparers.bySecondarySortQuantity);
                break;
            case sortConfig.compareValue.price:
                list.sort(comparers.byMarketPrice(sortOrder));
                break;
            case sortConfig.compareValue.marketValue:
                list.sort(comparers.byTotalValue(sortOrder));
                list.sort(comparers.bySecondarySortTotalValue);
                break;
            default:
                break;
        }
    };

    // Sort account lists based on holdings option for dropdown
    var determineMobileSortColumn = function (holding, sortColumn, sortOrder, accountLists) {
        switch (holding) {
            case sortConfig.holdingValue.all:
                this.sortByColumn(sortColumn, sortOrder, accountLists.managed);
                this.sortByColumn(sortColumn, sortOrder, accountLists.external);
                break;
            case sortConfig.holdingValue.managed:
                this.sortByColumn(sortColumn, sortOrder, accountLists.managed);
                break;
            case sortConfig.holdingValue.external:
                this.sortByColumn(sortColumn, sortOrder, accountLists.external);
                break;
            default:
                break;
        }
    }

    // Desktop functionality onclick event
    var sortAccountList = function (e, list, xsOptions) {
        if (config.enableSortableTable) {
            var sortOrder = e.currentTarget.dataset.sortOrder;
            var sortColumn = e.currentTarget.dataset.sortColumn;
            var holdingType = e.currentTarget.dataset.holdingType;
            var sortingPreferenceDesktop = JSON.parse(sessionStorage.getItem(sortConfig.sessionStorageKey.desktop)) || {};
            var sortingPreferenceMobile = JSON.parse(sessionStorage.getItem(sortConfig.sessionStorageKey.mobile)) || {};

            this.sortByColumn(sortColumn, sortOrder, list);
            this.toggleSortOrder(e.currentTarget, sortOrder);
            this.setSortedColumnElement(e.currentTarget, sortColumn);

            this.saveDesktopSortPreference(sortingPreferenceDesktop, holdingType, sortColumn, sortOrder);
            this.triggerDesktopToMobileBinding(sortingPreferenceDesktop, sortingPreferenceMobile, holdingType, sortColumn, sortOrder, xsOptions);
        }
    };

    // Mobile dropdown sort functionality onclick event
    var sortAccountListByDropdown = function (options) {
        var sortingPreferenceMobile = JSON.parse(sessionStorage.getItem(sortConfig.sessionStorageKey.mobile)) || {};
        var sortingPreferenceDesktop = JSON.parse(sessionStorage.getItem(sortConfig.sessionStorageKey.desktop)) || {};

        this.determineMobileSortColumn(options.holding, options.sortColumn, options.sortOrder, options.accountLists);
        this.saveMobileSortPreference(sortingPreferenceMobile, options.holding, options.sortColumn, options.sortOrder);

        // Trigger binding to desktop for any browser resize
        this.triggerMobileToDesktopBinding(sortingPreferenceDesktop, options.holding, options.sortColumn, options.sortOrder);
    }

    // Set which column is currently sorted (Desktop)
    var setSortedColumnElement = function (target, sortType) {
        target.style.color = sortConfig.selectedHeadingColor;

        $('.' + target.dataset.holdingType + '-holding-sortable.sortable').each(function (_, element) {
            if (element.dataset.sortColumn !== sortType) {
                element.style.color = sortConfig.defaultHeadingColor;

                var glyphIcons = $(element).find('.glyphicon');
                $(glyphIcons[0]).addClass('hidden');
                $(glyphIcons[1]).addClass('hidden');

                element.dataset.sortOrder = sortConfig.order.ascending;
            }
        });
    };

    // Alter the sortable glyphicon based on sort order (Desktop)
    var toggleSortOrder = function (target, sortOrder) {
        var glyphIcons = $(target).find('.glyphicon');

        if (sortOrder === sortConfig.order.ascending) {
            target.dataset.sortOrder = sortConfig.order.descending;
            $(glyphIcons[0]).removeClass('hidden');
            $(glyphIcons[1]).addClass('hidden');
        } else {
            target.dataset.sortOrder = sortConfig.order.ascending;
            $(glyphIcons[0]).addClass('hidden');
            $(glyphIcons[1]).removeClass('hidden');
        }
    };

    // Set mobile dropdown items
    var setMobileSelectedOptions = function (selectedHolding, sortColumn, sortOrder, xsOptions) {
        xsOptions().holding(sortByOptions.holdings.filter(function (holding) {
            return selectedHolding === holding.value;
        })[0]);

        xsOptions().sortColumn(sortByOptions.headers.filter(function (header) {
            return sortColumn === header.value;
        })[0]);

        xsOptions().sortOrder(sortByOptions.sortType.filter(function (sortType) {
            return sortOrder === sortType.value;
        })[0]);
    };

    // Set desktop sort preferences from session storage
    var setDesktopSavedSortPreference = function (key, list) {
        var sortingPreference = JSON.parse(sessionStorage.getItem(sortConfig.sessionStorageKey.desktop)) || {};

        if (!$.isEmptyObject(sortingPreference) && sortingPreference[key]) {
            var sortColumn = sortingPreference[key].sortColumn;
            var sortOrder = sortingPreference[key].sortOrder;
            var target = document.querySelector("." + key + "-holding-sortable[data-sort-column=" + sortColumn + "]");
            if (target == null) return;
            target.style.color = sortConfig.selectedHeadingColor;

            this.sortByColumn(sortColumn, sortOrder, list);
            this.toggleSortOrder(target, sortOrder);
        } else {
            var target = document.querySelector("." + key + "-holding-sortable[data-sort-column='ticker']");
            target.style.color = sortConfig.selectedHeadingColor;
            this.toggleSortOrder(target, sortConfig.order.ascending);

            saveDesktopSortPreference(sortingPreference, sortConfig.holdingValue.managed, sortConfig.compareValue.ticker, sortConfig.order.ascending);

            saveDesktopSortPreference(sortingPreference, sortConfig.holdingValue.external, sortConfig.compareValue.ticker, sortConfig.order.ascending);
        }
    };

    // Set mobile sort preferences from session storage
    var setMobileSavedSortPreference = function (xsOptions, accountLists) {
        var sortingPreference = JSON.parse(sessionStorage.getItem(sortConfig.sessionStorageKey.mobile)) || {};

        if (!$.isEmptyObject(sortingPreference)) {
            xsOptions().holding(sortByOptions.holdings.filter(function (holding) {
                return sortingPreference.holding === holding.value;
            })[0]);

            xsOptions().sortColumn(sortByOptions.headers.filter(function (header) {
                return sortingPreference.sortColumn === header.value;
            })[0]);

            xsOptions().sortOrder(sortByOptions.sortType.filter(function (sortType) {
                return sortingPreference.sortOrder === sortType.value;
            })[0]);

            this.determineMobileSortColumn(sortingPreference.holding, sortingPreference.sortColumn, sortingPreference.sortOrder, accountLists);
        } else {
            xsOptions().holding(sortByOptions.headers[0]);
            xsOptions().sortColumn(sortByOptions.headers[0]);
            xsOptions().sortOrder(sortByOptions.headers[0]);

            saveMobileSortPreference(sortingPreference, sortConfig.holdingValue.managed, sortConfig.compareValue.ticker, sortConfig.order.ascending);
        }
    };

    // Save desktop sort preferences to session storage
    var saveDesktopSortPreference = function (sortingPreference, holdingType, sortColumn, sortOrder) {
        if (!$.isEmptyObject(sortingPreference) && sortingPreference[holdingType]) {
            sortingPreference[holdingType].sortOrder = sortOrder;
            sortingPreference[holdingType].sortColumn = sortColumn;
        } else {
            sortingPreference[holdingType] = {
                sortOrder: sortOrder,
                sortColumn: sortColumn
            };
        }

        sessionStorage.setItem(sortConfig.sessionStorageKey.desktop, JSON.stringify(sortingPreference));
    };

    // Save mobile sort preferences to session storage
    var saveMobileSortPreference = function (sortingPreference, holding, sortColumn, sortOrder) {
        if (!$.isEmptyObject(sortingPreference)) {
            sortingPreference.holding = holding;
            sortingPreference.sortColumn = sortColumn;
            sortingPreference.sortOrder = sortOrder;
        } else {
            sortingPreference = {
                holding: holding,
                sortOrder: sortOrder,
                sortColumn: sortColumn
            };
        }

        sessionStorage.setItem(sortConfig.sessionStorageKey.mobile, JSON.stringify(sortingPreference));
    };

    // Two way binding for desktop to mobile
    var triggerDesktopToMobileBinding = function (sortingPreferenceDesktop, sortingPreferenceMobile, holding, sortColumn, sortOrder, xsOptions) {
        if (!$.isEmptyObject(sortingPreferenceDesktop)) {
            var hasManagedAndExternal = sortingPreferenceDesktop[sortConfig.holdingValue.managed] && sortingPreferenceDesktop[sortConfig.holdingValue.external];

            var equalColumnAndOrder = sortingPreferenceDesktop.external.sortColumn === sortingPreferenceDesktop.managed.sortColumn && sortingPreferenceDesktop.external.sortOrder === sortingPreferenceDesktop.managed.sortOrder;

            var bindedHolding = hasManagedAndExternal && equalColumnAndOrder ? sortConfig.holdingValue.all : holding;

            this.saveMobileSortPreference(sortingPreferenceMobile, bindedHolding, sortColumn, sortOrder)
            this.setMobileSelectedOptions(bindedHolding, sortColumn, sortOrder, xsOptions);
        }
    };

    // Two way binding for mobile to desktop
    var triggerMobileToDesktopBinding = function (sortingPreference, holding, sortColumn, sortOrder) {
        var target = {
            managed: document.querySelector(".managed-holding-sortable[data-sort-column=" + sortColumn + "]"),
            external: document.querySelector(".external-holding-sortable[data-sort-column=" + sortColumn + "]")
        };

        switch (holding) {
            case sortConfig.holdingValue.all:
                saveDesktopSortPreference(sortingPreference, sortConfig.holdingValue.managed, sortColumn, sortOrder);
                this.setSortedColumnElement(target.managed, sortColumn);
                this.toggleSortOrder(target.managed, sortOrder);

                saveDesktopSortPreference(sortingPreference, sortConfig.holdingValue.external, sortColumn, sortOrder);
                this.setSortedColumnElement(target.external, sortColumn);
                this.toggleSortOrder(target.external, sortOrder);
                break;
            case sortConfig.holdingValue.managed:
                saveDesktopSortPreference(sortingPreference, sortConfig.holdingValue.managed, sortColumn, sortOrder);
                this.setSortedColumnElement(target.managed, sortColumn);
                this.toggleSortOrder(target.managed, sortOrder);
                break;
            case sortConfig.holdingValue.external:
                saveDesktopSortPreference(sortingPreference, sortConfig.holdingValue.external, sortColumn, sortOrder);
                this.setSortedColumnElement(target.external, sortColumn);
                this.toggleSortOrder(target.external, sortOrder);
                break;
            default:
                break;
        }
    };

    return {
        sortByColumn: sortByColumn,
        sortAccountList: sortAccountList,
        sortAccountListByDropdown: sortAccountListByDropdown,
        setSortedColumnElement: setSortedColumnElement,
        toggleSortOrder: toggleSortOrder,
        sortByOptions: sortByOptions,
        determineMobileSortColumn: determineMobileSortColumn,
        setMobileSelectedOptions: setMobileSelectedOptions,
        triggerDesktopToMobileBinding: triggerDesktopToMobileBinding,
        triggerMobileToDesktopBinding: triggerMobileToDesktopBinding,
        setDesktopSavedSortPreference: setDesktopSavedSortPreference,
        setMobileSavedSortPreference: setMobileSavedSortPreference,
        saveDesktopSortPreference: saveDesktopSortPreference,
        saveMobileSortPreference: saveMobileSortPreference,
        reloadSort: reloadSort,
        sortConfig: sortConfig
    };
});;
define('WizardController', ['knockout', 'routing'], function (ko, routing) {


});;
