PageSourceSearch

https://www.servwise.com/home/templates/orderforms/swstandard_cart/js/scripts.js?v=2a285f

js servwise.com collected 2026-10-10 02:02:24 UTC 130,233 bytes, 3,498 lines download raw bytes

vendor: 11,760 bytes, lines 1-409
1/*!
2 * iCheck v1.0.2, http://git.io/arlzeA
3 * ===================================
4 * Powerful jQuery and Zepto plugin for checkboxes and radio buttons customization
5 *
6 * (c) 2013 Damir Sultanov, http://fronteed.com
7 * MIT Licensed
8 */
9
10(function($) {
11
12  // Cached vars
13  var _iCheck = 'iCheck',
14    _iCheckHelper = _iCheck + '-helper',
15    _checkbox = 'checkbox',
16    _radio = 'radio',
17    _checked = 'checked',
18    _unchecked = 'un' + _checked,
19    _disabled = 'disabled',a
20    _determinate = 'determinate',
21    _indeterminate = 'in' + _determinate,
22    _update = 'update',
23    _type = 'type',
24    _click = 'click',
25    _touch = 'touchbegin.i touchend.i',
26    _add = 'addClass',
27    _remove = 'removeClass',
28    _callback = 'trigger',
29    _label = 'label',
30    _cursor = 'cursor',
31    _mobile = /ipad|iphone|ipod|android|blackberry|windows phone|opera mini|silk/i.test(navigator.userAgent);
32
33  // Plugin init
34  $.fn[_iCheck] = function(options, fire) {
35
36    // Walker
37    var handle = 'input[type="' + _checkbox + '"], input[type="' + _radio + '"]',
38      stack = $(),
39      walker = function(object) {
40        object.each(function() {
41          var self = $(this);
42
43          if (self.is(handle)) {
44            stack = stack.add(self);
45          } else {
46            stack = stack.add(self.find(handle));
47          }
48        });
49      };
50
51    // Check if we should operate with some method
52    if (/^(check|uncheck|toggle|indeterminate|determinate|disable|enable|update|destroy)$/i.test(options)) {
53
54      // Normalize method's name
55      options = options.toLowerCase();
56
57      // Find checkboxes and radio buttons
58      walker(this);
59
60      return stack.each(function() {
61        var self = $(this);
62
63        if (options == 'destroy') {
64          tidy(self, 'ifDestroyed');
65        } else {
66          operate(self, true, options);
67        }
68
69        // Fire method's callback
70        if ($.isFunction(fire)) {
71          fire();
72        }
73      });
74
75    // Customization
76    } else if (typeof options == 'object' || !options) {
77
78      // Check if any options were passed
79      var settings = $.extend({
80          checkedClass: _checked,
81          disabledClass: _disabled,
82          indeterminateClass: _indeterminate,
83          labelHover: true
84        }, options),
85
86        selector = settings.handle,
87        hoverClass = settings.hoverClass || 'hover',
88        focusClass = settings.focusClass || 'focus',
89        activeClass = settings.activeClass || 'active',
90        labelHover = !!settings.labelHover,
91        labelHoverClass = settings.labelHoverClass || 'hover',
92
93        // Setup clickable area
94        area = ('' + settings.increaseArea).replace('%', '') | 0;
95
96      // Selector limit
97      if (selector == _checkbox || selector == _radio) {
98        handle = 'input[type="' + selector + '"]';
99      }
100
101      // Clickable area limit
102      if (area < -50) {
103        area = -50;
104      }
105
106      // Walk around the selector
107      walker(this);
108
109      return stack.each(function() {
110        var self = $(this);
111
112        // If already customized
113        tidy(self);
114
115        var node = this,
116          id = node.id,
117
118          // Layer styles
119          offset = -area + '%',
120          size = 100 + (area * 2) + '%',
121          layer = {
122            position: 'absolute',
123            top: offset,
124            left: offset,
125            display: 'block',
126            width: size,
127            height: size,
128            margin: 0,
129            padding: 0,
130            background: '#fff',
131            border: 0,
132            opacity: 0
133          },
134
135          // Choose how to hide input
136          hide = _mobile ? {
137            position: 'absolute',
138            visibility: 'hidden'
139          } : area ? layer : {
140            position: 'absolute',
141            opacity: 0
142          },
143
144          // Get proper class
145          className = node[_type] == _checkbox ? settings.checkboxClass || 'i' + _checkbox : settings.radioClass || 'i' + _radio,
146
147          // Find assigned labels
148          label = $(_label + '[for="' + id + '"]').add(self.closest(_label)),
149
150          // Check ARIA option
151          aria = !!settings.aria,
152
153          // Set ARIA placeholder
154          ariaID = _iCheck + '-' + Math.random().toString(36).substr(2,6),
155
156          // Parent & helper
157          parent = '<div class="' + className + '" ' + (aria ? 'role="' + node[_type] + '" ' : ''),
158          helper;
159
160        // Set ARIA "labelledby"
161        if (aria) {
162          label.each(function() {
163            parent += 'aria-labelledby="';
164
165            if (this.id) {
166              parent += this.id;
167            } else {
168              this.id = ariaID;
169              parent += ariaID;
170            }
171
172            parent += '"';
173          });
174        }
175
176        // Wrap input
177        parent = self.wrap(parent + '/>')[_callback]('ifCreated').parent().append(settings.insert);
178
179        // Layer addition
180        helper = $('<ins class="' + _iCheckHelper + '"/>').css(layer).appendTo(parent);
181
182        // Finalize customization
183        self.data(_iCheck, {o: settings, s: self.attr('style')}).css(hide);
184        !!settings.inheritClass && parent[_add](node.className || '');
185        !!settings.inheritID && id && parent.attr('id', _iCheck + '-' + id);
186        parent.css('position') == 'static' && parent.css('position', 'relative');
187        operate(self, true, _update);
188
189        // Label events
190        if (label.length) {
191          label.on(_click + '.i mouseover.i mouseout.i ' + _touch, function(event) {
192            var type = event[_type],
193              item = $(this);
194
195            // Do nothing if input is disabled
196            if (!node[_disabled]) {
197
198              // Click
199              if (type == _click) {
200                if ($(event.target).is('a')) {
201                  return;
202                }
203                operate(self, false, true);
204
205              // Hover state
206              } else if (labelHover) {
207
208                // mouseout|touchend
209                if (/ut|nd/.test(type)) {
210                  parent[_remove](hoverClass);
211                  item[_remove](labelHoverClass);
212                } else {
213                  parent[_add](hoverClass);
214                  item[_add](labelHoverClass);
215                }
216              }
217
218              if (_mobile) {
219                event.stopPropagation();
220              } else {
221                return false;
222              }
223            }
224          });
225        }
226
227        // Input events
228        self.on(_click + '.i focus.i blur.i keyup.i keydown.i keypress.i', function(event) {
229          var type = event[_type],
230            key = event.keyCode;
231
232          // Click
233          if (type == _click) {
234            return false;
235
236          // Keydown
237          } else if (type == 'keydown' && key == 32) {
238            if (!(node[_type] == _radio && node[_checked])) {
239              if (node[_checked]) {
240                off(self, _checked);
241              } else {
242                on(self, _checked);
243              }
244            }
245
246            return false;
247
248          // Keyup
249          } else if (type == 'keyup' && node[_type] == _radio) {
250            !node[_checked] && on(self, _checked);
251
252          // Focus/blur
253          } else if (/us|ur/.test(type)) {
254            parent[type == 'blur' ? _remove : _add](focusClass);
255          }
256        });
257
258        // Helper events
259        helper.on(_click + ' mousedown mouseup mouseover mouseout ' + _touch, function(event) {
260          var type = event[_type],
261
262            // mousedown|mouseup
263            toggle = /wn|up/.test(type) ? activeClass : hoverClass;
264
265          // Do nothing if input is disabled
266          if (!node[_disabled]) {
267
268            // Click
269            if (type == _click) {
270              operate(self, false, true);
271
272            // Active and hover states
273            } else {
274
275              // State is on
276              if (/wn|er|in/.test(type)) {
277
278                // mousedown|mouseover|touchbegin
279                parent[_add](toggle);
280
281              // State is off
282              } else {
283                parent[_remove](toggle + ' ' + activeClass);
284              }
285
286              // Label hover
287              if (label.length && labelHover && toggle == hoverClass) {
288
289                // mouseout|touchend
290                label[/ut|nd/.test(type) ? _remove : _add](labelHoverClass);
291              }
292            }
293
294            if (_mobile) {
295              event.stopPropagation();
296            } else {
297              return false;
298            }
299          }
300        });
301      });
302    } else {
303      return this;
304    }
305  };
306
307  // Do something with inputs
308  function operate(input, direct, method) {
309    var node = input[0],
310      state = /er/.test(method) ? _indeterminate : /bl/.test(method) ? _disabled : _checked,
311      active = method == _update ? {
312        checked: node[_checked],
313        disabled: node[_disabled],
314        indeterminate: input.attr(_indeterminate) == 'true' || input.attr(_determinate) == 'false'
315      } : node[state];
316
317    // Check, disable or indeterminate
318    if (/^(ch|di|in)/.test(method) && !active) {
319      on(input, state);
320
321    // Uncheck, enable or determinate
322    } else if (/^(un|en|de)/.test(method) && active) {
323      off(input, state);
324
325    // Update
326    } else if (method == _update) {
327
328      // Handle states
329      for (var each in active) {
330        if (active[each]) {
331          on(input, each, true);
332        } else {
333          off(input, each, true);
334        }
335      }
336
337    } else if (!direct || method == 'toggle') {
338
339      // Helper or label was clicked
340      if (!direct) {
341        input[_callback]('ifClicked');
342      }
343
344      // Toggle checked state
345      if (active) {
346        if (node[_type] !== _radio) {
347          off(input, state);
348        }
349      } else {
350        on(input, state);
351      }
352    }
353  }
354
355  // Add checked, disabled or indeterminate state
356  function on(input, state, keep) {
357    var node = input[0],
358      parent = input.parent(),
359      checked = state == _checked,
360      indeterminate = state == _indeterminate,
361      disabled = state == _disabled,
362      callback = indeterminate ? _determinate : checked ? _unchecked : 'enabled',
363      regular = option(input, callback + capitalize(node[_type])),
364      specific = option(input, state + capitalize(node[_type]));
365
366    // Prevent unnecessary actions
367    if (node[state] !== true) {
368
369      // Toggle assigned radio buttons
370      if (!keep && state == _checked && node[_type] == _radio && node.name) {
371        var form = input.closest('form'),
372          inputs = 'input[name="' + node.name + '"]';
373
374        inputs = form.length ? form.find(inputs) : $(inputs);
375
376        inputs.each(function() {
377          if (this !== node && $(this).data(_iCheck)) {
378            off($(this), state);
379          }
380        });
381      }
382
383      // Indeterminate state
384      if (indeterminate) {
385
386        // Add indeterminate state
387        node[state] = true;
388
389        // Remove checked state
390        if (node[_checked]) {
391          off(input, _checked, 'force');
392        }
393
394      // Checked or disabled state
395      } else {
396
397        // Add checked or disabled state
398        if (!keep) {
399          node[state] = true;
400        }
401
402        // Remove indeterminate state
403        if (checked && node[_indeterminate]) {
404          off(input, _indeterminate, false);
405        }
406      }
407
408      // Trigger callbacks
409      callbacks(input, checked, state, keep);
410    }
411
412    // Add proper cursor
413    if (node[_disabled] && !!option(input, _cursor, true)) {
414      parent.find('.' + _iCheckHelper).css(_cursor, 'default');
415    }
416
417    // Add state class
418    parent[_add](specific || option(input, state) || '');
419
420    // Set ARIA attribute
421    if (!!parent.attr('role') && !indeterminate) {
422      parent.attr('aria-' + (disabled ? _disabled : _checked), 'true');
423    }
424
425    // Remove regular state class
426    parent[_remove](regular || option(input, callback) || '');
427  }
428
429  // Remove checked, disabled or indeterminate state
430  function off(input, state, keep) {
431    var node = input[0],
432      parent = input.parent(),
433      checked = state == _checked,
434      indeterminate = state == _indeterminate,
435      disabled = state == _disabled,
436      callback = indeterminate ? _determinate : checked ? _unchecked : 'enabled',
437      regular = option(input, callback + capitalize(node[_type])),
438      specific = option(input, state + capitalize(node[_type]));
439
440    // Prevent unnecessary actions
441    if (node[state] !== false) {
442
443      // Toggle state
444      if (indeterminate || !keep || keep == 'force') {
445        node[state] = false;
446      }
447
448      // Trigger callbacks
449      callbacks(input, checked, callback, keep);
450    }
451
452    // Add proper cursor
453    if (!node[_disabled] && !!option(input, _cursor, true)) {
454      parent.find('.' + _iCheckHelper).css(_cursor, 'pointer');
455    }
456
457    // Remove state class
458    parent[_remove](specific || option(input, state) || '');
459
460    // Set ARIA attribute
461    if (!!parent.attr('role') && !indeterminate) {
462      parent.attr('aria-' + (disabled ? _disabled : _checked), 'false');
463    }
464
465    // Add regular state class
466    parent[_add](regular || option(input, callback) || '');
467  }
468
469  // Remove all traces
470  function tidy(input, callback) {
471    if (input.data(_iCheck)) {
472
473      // Remove everything except input
474      input.parent().html(input.attr('style', input.data(_iCheck).s || ''));
475
476      // Callback
477      if (callback) {
478        input[_callback](callback);
479      }
480
481      // Unbind events
482      input.off('.i').unwrap();
483      $(_label + '[for="' + input[0].id + '"]').add(input.closest(_label)).off('.i');
484    }
485  }
486
487  // Get some option
488  function option(input, state, regular) {
489    if (input.data(_iCheck)) {
490      return input.data(_iCheck).o[state + (regular ? '' : 'Class')];
491    }
492  }
493
494  // Capitalize some string
495  function capitalize(string) {
496    return string.charAt(0).toUpperCase() + string.slice(1);
497  }
498
499  // Executable handlers
500  function callbacks(input, checked, callback, keep) {
501    if (!keep) {
502      if (checked) {
503        input[_callback]('ifToggled');
504      }
505
506      input[_callback]('ifChanged')[_callback]('if' + capitalize(callback));
507    }
508  }
509})(window.jQuery || window.Zepto);
510
511/**
512 * WHMCS core JS library reference
513 *
514 * @copyright Copyright (c) WHMCS Limited 2005-2017
515 * @license http://www.whmcs.com/license/ WHMCS Eula
516 */
517
518(function (window, factory) {
519    if (typeof window.WHMCS !== 'object') {
520        window.WHMCS = factory;
521    }
522}(
523    window,
524    {
525        hasModule: function (name) {
526            return (typeof WHMCS[name] !== 'undefined'
527                && Object.getOwnPropertyNames(WHMCS[name]).length > 0);
528        },
529        loadModule: function (name, module) {
530            if (this.hasModule(name)) {
531                return;
532            }
533
534            WHMCS[name] = {};
535            if (typeof module === 'function') {
536                (module).apply(WHMCS[name]);
537            } else {
538                for (var key in module) {
539                    if (module.hasOwnProperty(key)) {
540                        WHMCS[name][key] = {};
541                        (module[key]).apply(WHMCS[name][key]);
542                    }
543                }
544            }
545        }
546    }
547));
548
549jQuery(document).ready(function() {
550    jQuery(document).on('click', '.disable-on-click', function () {
551        jQuery(this).addClass('disabled');
552
553        if (jQuery(this).hasClass('spinner-on-click')) {
554            var icon = $(this).find('i.fas,i.far,i.fal,i.fab');
555
556            jQuery(icon)
557                .removeAttr('class')
558                .addClass('fas fa-spinner fa-spin');
559        }
560    });
561});
562
563function scrollToGatewayInputError() {
564    var displayError = jQuery('.gateway-errors,.assisted-cc-input-feedback').first(),
565        frm = displayError.closest('form');
566    if (!frm) {
567        frm = jQuery('form').first();
568    }
569    frm.find('button[type="submit"],input[type="submit"]')
570        .prop('disabled', false)
571        .removeClass('disabled')
572        .find('i.fas,i.far,i.fal,i.fab')
573        .removeAttr('class')
574        .addClass('fas fa-arrow-circle-right')
575        .find('span').toggleClass('hidden');
576
577    if (displayError.length) {
578        jQuery('html, body').animate(
579            {
580                scrollTop: displayError.offset().top - 50
581            },
582            500
583        );
584    }
585}
586
587/**
588 * WHMCS authentication module
589 *
590 * @copyright Copyright (c) WHMCS Limited 2005-2017
591 * @license http://www.whmcs.com/license/ WHMCS Eula
592 */
593
594(function(module) {
595    if (!WHMCS.hasModule('authn')) {
596        WHMCS.loadModule('authn', module);
597    }
598})({
599provider: function () {
600    var callbackFired = false;
601
602    /**
603     * @return {jQuery}
604     */
605    this.feedbackContainer = function () {
606        return jQuery(".providerLinkingFeedback");
607    };
608
609    /**
610     * @returns {jQuery}
611     */
612    this.btnContainer = function () {
613        return jQuery(".providerPreLinking");
614    };
615
616    this.feedbackMessage = function (context) {
617        if (typeof context === 'undefined') {
618            context = 'complete_sign_in';
619        }
620        var msgContainer = jQuery('p.providerLinkingMsg-preLink-' + context);
621        if (msgContainer.length) {
622            return msgContainer.first().html();
623        }
624
625        return '';
626    };
627
628    this.showProgressMessage = function(callback) {
629        this.feedbackContainer().fadeIn('fast', function () {
630            if (typeof callback === 'function' && !callbackFired) {
631                callbackFired = true;
632                callback();
633            }
634        });
635    };
636
637    this.preLinkInit = function (callback) {
638        var icon = '<i class="fas fa-fw fa-spinner fa-spin"></i> ';
639
640        this.feedbackContainer()
641            .removeClass('alert-danger alert-success')
642            .addClass('alert alert-info')
643            .html(icon + this.feedbackMessage())
644            .hide();
645
646        var btnContainer = this.btnContainer();
647        if (btnContainer.length) {
648            if (btnContainer.data('hideOnPrelink')) {
649                var self = this;
650                btnContainer.fadeOut('false', function ()
651                {
652                    self.showProgressMessage(callback)
653                });
654            } else if (btnContainer.data('disableOnPrelink')) {
655                btnContainer.find('.btn').addClass('disabled');
656                this.showProgressMessage(callback);
657            } else {
658                this.showProgressMessage(callback);
659            }
660        } else {
661            this.showProgressMessage(callback);
662        }
663    };
664
665    this.displayError = function (provider, errorCondition, providerErrorText){
666        jQuery('#providerLinkingMessages .provider-name').html(provider);
667
668        var feedbackMsg = this.feedbackMessage('connect_error');
669        if (errorCondition) {
670            var errorMsg = this.feedbackMessage(errorCondition);
671            if (errorMsg) {
672                feedbackMsg = errorMsg
673            }
674        }
675
676        if (providerErrorText && $('.btn-logged-in-admin').length > 0) {
677            feedbackMsg += ' Error: ' + providerErrorText;
678        }
679
680        this.feedbackContainer().removeClass('alert-info alert-success')
681            .addClass('alert alert-danger')
682            .html(feedbackMsg).slideDown();
683    };
684
685    this.displaySuccess = function (data, context, provider) {
686        var icon = provider.icon;
687        var htmlTarget = context.htmlTarget;
688        var targetLogin = context.targetLogin;
689        var targetRegister = context.targetRegister;
690        var displayName = provider.name;
691        var feedbackMsg = '';
692
693        switch (data.result) {
694            case "logged_in":
695            case "2fa_needed":
696                feedbackMsg = this.feedbackMessage('2fa_needed');
697                this.feedbackContainer().removeClass('alert-danger alert-warning alert-success')
698                    .addClass('alert alert-info')
699                    .html(feedbackMsg);
700
701                window.location = data.redirect_url
702                    ? decodeURIComponent(data.redirect_url)
703                    : decodeURIComponent(context.redirectUrl);
704
705                break;
706
707            case "linking_complete":
708                var accountInfo = '';
709                if (data.remote_account.email) {
710                    accountInfo = data.remote_account.email;
711                } else {
712                    accountInfo = data.remote_account.firstname + " " + data.remote_account.lastname;
713                }
714
715                accountInfo = accountInfo.trim();
716
717                feedbackMsg = this.feedbackMessage('linking_complete').trim().replace(':displayName', displayName);
718                if (accountInfo) {
719                    feedbackMsg = feedbackMsg.replace(/\.$/, ' (' + accountInfo + ').');
720                }
721
722                this.feedbackContainer().removeClass('alert-danger alert-warning alert-info')
723                    .addClass('alert alert-success')
724                    .html(icon + feedbackMsg);
725                break;
726
727            case "login_to_link":
728                if (htmlTarget === targetLogin) {
729                    feedbackMsg = this.feedbackMessage('login_to_link-signin-required');
730                    this.feedbackContainer().removeClass('alert-danger alert-success alert-info')
731                        .addClass('alert alert-warning')
732                        .html(icon + feedbackMsg);
733                } else {
734                    var emailField = jQuery("input[name=email]");
735                    var firstNameField = jQuery("input[name=firstname]");
736                    var lastNameField = jQuery("input[name=lastname]");
737
738                    if (emailField.val() === "") {
739                        emailField.val(data.remote_account.email);
740                    }
741
742                    if (firstNameField.val() === "") {
743                        firstNameField.val(data.remote_account.firstname);
744                    }
745
746                    if (lastNameField.val() === "") {
747                        lastNameField.val(data.remote_account.lastname);
748                    }
749
750                    if (htmlTarget === targetRegister) {
751                        if (typeof WHMCS.client.registration === 'object') {
752                            WHMCS.client.registration.prefillPassword();
753                        }
754                        feedbackMsg = this.feedbackMessage('login_to_link-registration-required');
755                        this.feedbackContainer().fadeOut('slow', function () {
756                            $(this).removeClass('alert-danger alert-success alert-info')
757                                .addClass('alert alert-warning')
758                                .html(icon + feedbackMsg).fadeIn('fast');
759                        });
760
761                    } else {
762                        // this is checkout
763                        if (typeof WHMCS.client.registration === 'object') {
764                            WHMCS.client.registration.prefillPassword();
765                        }
766
767                        var self = this;
768                        this.feedbackContainer().each(function (i, el) {
769                            var container = $(el);
770                            var linkContext = container.siblings('div .providerPreLinking').data('linkContext');
771
772                            container.fadeOut('slow', function () {
773                                if (linkContext === 'checkout-new') {
774                                    feedbackMsg = self.feedbackMessage('checkout-new');
775                                } else {
776                                    feedbackMsg = self.feedbackMessage('login_to_link-signin-required');
777                                }
778                                container.removeClass('alert-danger alert-success alert-info')
779                                    .addClass('alert alert-warning')
780                                    .html(icon + feedbackMsg).fadeIn('fast');
781                            });
782                        });
783                    }
784                }
785
786                break;
787
788            case "other_user_exists":
789                feedbackMsg = this.feedbackMessage('other_user_exists');
790                this.feedbackContainer().removeClass('alert-info alert-success')
791                    .addClass('alert alert-danger')
792                    .html(icon + feedbackMsg).slideDown();
793                break;
794
795            case "already_linked":
796                feedbackMsg = this.feedbackMessage('already_linked');
797                this.feedbackContainer().removeClass('alert-info alert-success')
798                    .addClass('alert alert-danger')
799                    .html(icon + feedbackMsg).slideDown();
800                break;
801
802            default:
803                feedbackMsg = this.feedbackMessage('default');
804                this.feedbackContainer().removeClass('alert-info alert-success')
805                    .addClass('alert alert-danger')
806                    .html(icon + feedbackMsg).slideDown();
807                break;
808        }
809    };
810
811    this.signIn = function (config, context, provider, providerDone, providerError) {
812        jQuery.ajax(config).done(function(data) {
813            providerDone();
814            WHMCS.authn.provider.displaySuccess(data, context, provider);
815            var table = jQuery('#tableLinkedAccounts');
816            if (table.length) {
817                WHMCS.ui.dataTable.getTableById('tableLinkedAccounts').ajax.reload();
818            }
819        }).error(function() {
820            providerError();
821            WHMCS.authn.provider.displayError();
822        });
823    };
824
825    return this;
826}});
827
828/**
829 * WHMCS client module
830 *
831 * @copyright Copyright (c) WHMCS Limited 2005-2017
832 * @license http://www.whmcs.com/license/ WHMCS Eula
833 */
834(function(module) {
835    if (!WHMCS.hasModule('client')) {
836        WHMCS.loadModule('client', module);
837    }
838})({
839registration: function () {
840    this.prefillPassword = function (params) {
841        params = params || {};
842        if (typeof params.hideContainer === 'undefined') {
843            var id = (jQuery('#inputSecurityQId').attr('id')) ? '#containerPassword' : '#containerNewUserSecurity';
844            params.hideContainer = jQuery(id);
845            params.hideInputs = true;
846        } else if (typeof params.hideContainer === 'string' && params.hideContainer.length) {
847            params.hideContainer = jQuery(params.hideContainer);
848        }
849
850        if (typeof params.form === 'undefined') {
851            params.form = {
852                password: [
853                    {id: 'inputNewPassword1'},
854                    {id: 'inputNewPassword2'}
855                ]
856            };
857        }
858
859        var prefillFunc = function () {
860            var $randomPasswd = WHMCS.utils.simpleRNG();
861            for (var i = 0, len = params.form.password.length; i < len; i++) {
862                jQuery('#' + params.form.password[i].id)
863                    .val($randomPasswd).trigger('keyup');
864            }
865        };
866
867        if (params.hideInputs) {
868            params.hideContainer.slideUp('fast', prefillFunc);
869        } else {
870            prefillFunc();
871        }
872    };
873
874    return this;
875}});
876
877/**
878 * WHMCS HTTP module
879 *
880 * @copyright Copyright (c) WHMCS Limited 2005-2018
881 * @license http://www.whmcs.com/license/ WHMCS Eula
882 */
883(function(module) {
884    if (!WHMCS.hasModule('http')) {
885        WHMCS.loadModule('http', module);
886    }
887})({
888jqClient: function () {
889    _getSettings = function (url, data, success, dataType)
890    {
891        if (typeof url === 'object') {
892            /*
893                Settings may be the only argument
894             */
895            return url;
896        }
897
898        if (typeof data === 'function') {
899            /*
900                If 'data' is omitted, 'success' will come in its place
901             */
902            success = data;
903            data = null;
904        }
905
906        return {
907            url: url,
908            data: data,
909            success: success,
910            dataType: dataType
911        };
912    };
913
914    /**
915     * @param url
916     * @param data
917     * @param success
918     * @param dataType
919     * @returns {*}
920     */
921    this.get = function (url, data, success, dataType)
922    {
923        return WHMCS.http.client.request(
924            jQuery.extend(
925                _getSettings(url, data, success, dataType),
926                {
927                    type: 'GET'
928                }
929            )
930        );
931    };
932
933    /**
934     * @param url
935     * @param data
936     * @param success
937     * @param dataType
938     * @returns {*}
939     */
940    this.post = function (url, data, success, dataType)
941    {
942        return WHMCS.http.client.request(
943            jQuery.extend(
944                _getSettings(url, data, success, dataType),
945                {
946                    type: 'POST'
947                }
948            )
949        );
950    };
951
952    /**
953     * @param options
954     * @returns {*}
955     */
956    this.jsonGet = function (options) {
957        options = options || {};
958        this.get(options.url, options.data, function(response) {
959            if (response.warning) {
960                console.log('[WHMCS] Warning: ' + response.warning);
961                if (typeof options.warning === 'function') {
962                    options.warning(response.warning);
963                }
964            } else if (response.error) {
965                console.log('[WHMCS] Error: ' + response.error);
966                if (typeof options.error === 'function') {
967                    options.error(response.error);
968                }
969            } else {
970                if (typeof options.success === 'function') {
971                    options.success(response);
972                }
973            }
974        }, 'json').error(function(xhr, errorMsg){
975            console.log('[WHMCS] Error: ' + errorMsg);
976            if (typeof options.fail === 'function') {
977                options.fail(errorMsg);
978            }
979        }).always(function() {
980            if (typeof options.always === 'function') {
981                options.always();
982            }
983        });
984    };
985
986    /**
987     * @param options
988     * @returns {*}
989     */
990    this.jsonPost = function (options) {
991        options = options || {};
992        this.post(options.url, options.data, function(response) {
993            if (response.warning) {
994                console.log('[WHMCS] Warning: ' + response.warning);
995                if (typeof options.warning === 'function') {
996                    options.warning(response.warning);
997                }
998            } else if (response.error) {
999                console.log('[WHMCS] Error: ' + response.error);
1000                if (typeof options.error === 'function') {
1001                    options.error(response.error);
1002                }
1003            } else {
1004                if (typeof options.success === 'function') {
1005                    options.success(response);
1006                }
1007            }
1008        }, 'json').error(function(xhr, errorMsg){
1009            console.log('[WHMCS] Error: ' + errorMsg);
1010            if (typeof options.fail === 'function') {
1011                options.fail(errorMsg);
1012            }
1013        }).always(function() {
1014            if (typeof options.always === 'function') {
1015                options.always();
1016            }
1017        });
1018    };
1019
1020    return this;
1021},
1022
1023client: function () {
1024    var methods = ['get', 'post', 'put', 'delete'];
1025    var client = this;
1026
1027    _beforeRequest = function (settings)
1028    {
1029        /*
1030            Enforcing dataType was found to break many invocations expecting HTML back.
1031            If/when those are refactored, this may be uncommented to enforce a safer
1032            data transit.
1033         */
1034       
1034 /*if (typeof settings.dataType === 'undefined') {
1035            settings.dataType = 'json';
1036        }*/
1037
1038        if (typeof settings.type === 'undefined') {
1039            // default request type is GET
1040            settings.type = 'GET';
1041        }
1042
1043        /*
1044            Add other preprocessing here if required
1045         */
1046
1047        return settings;
1048    };
1049
1050    this.request = function (settings)
1051    {
1052        settings = _beforeRequest(settings || {});
1053        return jQuery.ajax(settings);
1054    };
1055
1056    /*
1057        Create shortcut methods for methods[] array above
1058     */
1059    jQuery.each(methods, function(index, method) {
1060        client[method] = (function(method, client) {
1061            return function (settings)
1062            {
1063                settings = settings || {};
1064
1065                settings.type = method.toUpperCase();
1066
1067                return client.request(settings);
1068            }
1069        })(method, client);
1070    });
1071
1072    return this;
1073}
1074
1075});
1076
1077/**
1078 * WHMCS UI module
1079 *
1080 * @copyright Copyright (c) WHMCS Limited 2005-2017
1081 * @license http://www.whmcs.com/license/ WHMCS Eula
1082 */
1083(function(module) {
1084    if (!WHMCS.hasModule('ui')) {
1085        WHMCS.loadModule('ui', module);
1086    }
1087})({
1088/**
1089 * Confirmation PopUp
1090 */
1091confirmation: function () {
1092
1093    /**
1094     * @type {Array} Registered confirmation root selectors
1095     */
1096    var toggles = [];
1097
1098    /**
1099     * Register/Re-Register all confirmation elements with jQuery
1100     * By default all elements of data toggle "confirmation" will be registered
1101     *
1102     * @param {(string|undefined)} rootSelector
1103     * @return {Array} array of registered toggles
1104     */
1105    this.register = function (rootSelector) {
1106        if (typeof rootSelector === 'undefined') {
1107            rootSelector = '[data-toggle=confirmation]';
1108        }
1109        if (toggles.indexOf(rootSelector) < 0) {
1110            toggles.push(rootSelector);
1111        }
1112
1113        jQuery(rootSelector).confirmation({
1114            rootSelector: rootSelector
1115        });
1116
1117        return toggles;
1118    };
1119
1120    return this;
1121},
1122
1123/**
1124 * Data Driven Table
1125 */
1126dataTable: function () {
1127
1128    /**
1129     * @type {{}}
1130     */
1131    this.tables = {};
1132
1133    /**
1134     * Register all tables on page with the class "data-driven"
1135     */
1136    this.register = function () {
1137        var self = this;
1138        jQuery('table.data-driven').each(function (i, table) {
1139            self.getTableById(table.id, undefined);
1140        });
1141    };
1142
1143    /**
1144     * Get a table by id; create table object on fly as necessary
1145     *
1146     * @param {string} id
1147     * @param {({}|undefined)} options
1148     * @returns {DataTable}
1149     */
1150    this.getTableById = function (id, options) {
1151        var self = this;
1152        var el = jQuery('#' + id);
1153        if (typeof self.tables[id] === 'undefined') {
1154            if (typeof options === 'undefined') {
1155                options = {
1156                    dom: '<"listtable"ift>pl',
1157                    paging: false,
1158                    lengthChange: false,
1159                    searching: false,
1160                    ordering: true,
1161                    info: false,
1162                    autoWidth: true,
1163                    language: {
1164                        emptyTable: (el.data('lang-empty-table')) ? el.data('lang-empty-table') : "No records found"
1165                    }
1166                };
1167            }
1168            var ajaxUrl = el.data('ajax-url');
1169            if (typeof ajaxUrl !== 'undefined') {
1170                options.ajax = {
1171                    url: ajaxUrl
1172                };
1173            }
1174            var dom = el.data('dom');
1175            if (typeof dom !== 'undefined') {
1176                options.dom = dom;
1177            }
1178            var searching = el.data('searching');
1179            if (typeof searching !== 'undefined') {
1180                options.searching = searching;
1181            }
1182            var responsive = el.data('responsive');
1183            if (typeof responsive !== 'undefined') {
1184                options.responsive = responsive;
1185            }
1186            var ordering = el.data('ordering');
1187            if (typeof ordering !== 'undefined') {
1188                options["ordering"] = ordering;
1189            }
1190            var order = el.data('order');
1191            if (typeof order !== 'undefined' && order) {
1192                options["order"] = order;
1193            }
1194            var colCss = el.data('columns');
1195            if (typeof colCss !== 'undefined' && colCss) {
1196                options["columns"] = colCss;
1197            }
1198            var autoWidth = el.data('auto-width');
1199            if (typeof autoWidth !== 'undefined') {
1200                options["autoWidth"] = autoWidth;
1201            }
1202            var paging = el.data('paging');
1203            if (typeof paging !== 'undefined') {
1204                options["paging"] = paging;
1205            }
1206            var lengthChange = el.data('length-change');
1207            if (typeof lengthChange !== 'undefined') {
1208                options["lengthChange"] = lengthChange;
1209            }
1210            var pageLength = el.data('page-length');
1211            if (typeof pageLength !== 'undefined') {
1212                options["pageLength"] = pageLength;
1213            }
1214
1215            self.tables[id] = self.initTable(el, options);
1216        } else if (typeof options !== 'undefined') {
1217            var oldTable = self.tables[id];
1218            var initOpts = oldTable.init();
1219            var newOpts = jQuery.extend( initOpts, options);
1220            oldTable.destroy();
1221            self.tables[id] = self.initTable(el, newOpts);
1222        }
1223
1224        return self.tables[id];
1225    };
1226
1227    this.initTable = function (el, options) {
1228        var table = el.DataTable(options);
1229        var self = this;
1230        if (el.data('on-draw')) {
1231            table.on('draw.dt', function (e, settings) {
1232                var namedCallback = el.data('on-draw');
1233                if (typeof window[namedCallback] === 'function') {
1234                    window[namedCallback](e, settings);
1235                }
1236            });
1237        } else if (el.data('on-draw-rebind-confirmation')) {
1238            table.on('draw.dt', function (e) {
1239                self.rebindConfirmation(e);
1240            });
1241        }
1242
1243        return table;
1244    };
1245
1246    this.rebindConfirmation = function (e) {
1247        var self = this;
1248        var tableId = e.target.id;
1249        var toggles = WHMCS.ui.confirmation.register();
1250        for(var i = 0, len = toggles.length; i < len; i++ ) {
1251            jQuery(toggles[i]).on(
1252                'confirmed.bs.confirmation',
1253                function (e)
1254                {
1255                    e.preventDefault();
1256                    WHMCS.http.jqClient.post(
1257                        jQuery(e.target).data('target-url'),
1258                        {
1259                            'token': csrfToken
1260                        }
1261                    ).done(function (data)
1262                    {
1263                        if (data.status === 'success' || data.status === 'okay') {
1264                            self.getTableById(tableId, undefined).ajax.reload();
1265                        }
1266                    });
1267
1268                }
1269            );
1270        }
1271    };
1272
1273    return this;
1274},
1275
1276clipboard: function() {
1277    this.copy = function(e) {
1278        e.preventDefault();
1279
1280        var trigger = $(e.currentTarget);
1281        var contentElement = $(trigger).data('clipboard-target');
1282        var container = $(contentElement).parent();
1283
1284        try {
1285            var tempElement = $('<textarea>')
1286                .css('position', 'fixed')
1287                .css('opacity', '0')
1288                .css('width', '1px')
1289                .css('height', '1px')
1290                .val($(contentElement).val());
1291
1292            container.append(tempElement);
1293            tempElement.focus().select();
1294            document.execCommand('copy');
1295        } finally {
1296            tempElement.remove();
1297        }
1298
1299        trigger.tooltip({
1300            trigger: 'click',
1301            placement: 'bottom'
1302        });
1303        WHMCS.ui.toolTip.setTip(trigger, 'Copied!');
1304        WHMCS.ui.toolTip.hideTip(trigger);
1305    };
1306
1307    return this;
1308},
1309
1310/**
1311 * ToolTip and Clipboard behaviors
1312 */
1313toolTip: function () {
1314    this.setTip = function (btn, message) {
1315        var tip = btn.data('bs.tooltip');
1316        if (tip.hoverState !== 'in') {
1317            tip.hoverState = 'in';
1318        }
1319        btn.attr('data-original-title', message);
1320        tip.show();
1321
1322        return tip;
1323    };
1324
1325    this.hideTip = function (btn) {
1326        return setTimeout(function() {
1327            btn.data('bs.tooltip').hide()
1328        }, 2000);
1329    }
1330},
1331
1332jsonForm: function() {
1333    this.managedElements = 'input,textarea,select';
1334
1335    this.initFields = function (form) {
1336        var self = this;
1337        $(form).find(self.managedElements).each(function () {
1338            var field = this;
1339
1340            $(field).on('keypress change', function () {
1341                if (self.fieldHasError(field)) {
1342                    self.clearFieldError(field);
1343                }
1344            });
1345        });
1346    };
1347
1348    this.init = function (form) {
1349        var self = this;
1350
1351        self.initFields(form);
1352
1353        $(form).on('submit', function(e) {
1354            e.preventDefault();
1355            e.stopPropagation();
1356
1357            self.clearErrors(form);
1358
1359            var formModal = $(form).parents('.modal[role="dialog"]').first();
1360
1361            if ($(formModal).length) {
1362                $(formModal).on('show.bs.modal hidden.bs.modal', function() {
1363                    self.clearErrors(form);
1364                });
1365
1366                /*
1367                 * Make this optional if the form is used for editing
1368                 */
1369                $(formModal).on('show.bs.modal', function() {
1370                    $(form)[0].reset();
1371                });
1372            }
1373
1374            WHMCS.http.client.post({
1375                url: $(form).attr('action'),
1376                data: $(form).serializeArray(),
1377            })
1378                .done(function (response) {
1379                    self.onSuccess(form, response);
1380                })
1381                .fail(function (jqXHR) {
1382                    self.onError(form, jqXHR);
1383                })
1384                .always(function (data) {
1385                    self.onRequestComplete(form, data);
1386                });
1387        });
1388    };
1389
1390    this.initAll = function () {
1391        var self = this;
1392
1393        $('form[data-role="json-form"]').each(function() {
1394            var formElement = this;
1395            self.init(formElement);
1396        });
1397    };
1398
1399    this.markFieldErrors = function (form, fields)
1400    {
1401        var self = this;
1402        var errorMessage = null;
1403        var field, fieldLookup;
1404
1405        for (var fieldName in fields) {
1406            if (fields.hasOwnProperty(fieldName)) {
1407                errorMessage = fields[fieldName];
1408            }
1409
1410            fieldLookup = self.managedElements.split(',').map(function(element) {
1411                return element + '[name="' + fieldName + '"]';
1412            }).join(',');
1413
1414            field = $(form).find(fieldLookup);
1415
1416            if (errorMessage) {
1417                $(field).parents('.form-group').addClass('has-error');
1418                $(field).attr('title', errorMessage);
1419                $(field).tooltip();
1420            }
1421        }
1422
1423        $(form).find('.form-group.has-error input[title]').first().tooltip('show');
1424    };
1425
1426    this.fieldHasError = function (field) {
1427        return $(field).parents('.form-group').hasClass('has-error');
1428    };
1429
1430    this.clearFieldError = function (field) {
1431        $(field).tooltip('destroy');
1432        $(field).parents('.form-group').removeClass('has-error');
1433    };
1434
1435    this.onSuccess = function (form, response) {
1436        var formOnSuccess = $(form).data('on-success');
1437
1438        if (typeof formOnSuccess === 'function') {
1439            formOnSuccess(response.data);
1440        }
1441    };
1442
1443    this.onError = function (form, jqXHR) {
1444        if (jqXHR.responseJSON && jqXHR.responseJSON.fields && typeof jqXHR.responseJSON.fields === 'object') {
1445            this.markFieldErrors(form, jqXHR.responseJSON.fields);
1446        } else {
1447            // TODO: replace with client-accessible generic error messaging
1448            console.log('Unknown error - please try again later.');
1449        }
1450
1451        var formOnError = $(form).data('on-error');
1452
1453        if (typeof formOnError === 'function') {
1454            formOnError(jqXHR);
1455        }
1456    };
1457
1458    this.clearErrors = function (form) {
1459        var self = this;
1460
1461        $(form).find(self.managedElements).each(function () {
1462            self.clearFieldError(this);
1463        })
1464    };
1465
1466    this.onRequestComplete = function (form, data) {
1467        // implement as needed
1468    };
1469
1470    return this;
1471},
1472
1473effects: function () {
1474    this.errorShake = function (element) {
1475        /**
1476         * Shake effect without jQuery UI inspired by Hiren Patel | ninty9notout:
1477         * @see https://github.com/ninty9notout/jquery-shake/blob/51f3dcf625970c78505bcac831fd9e28fc85d374/jquery.ui.shake.js
1478         */
1479        options = options || {};
1480        var options = $.extend({
1481            direction: "left",
1482            distance: 8,
1483            times: 3,
1484            speed: 90
1485        }, options);
1486
1487        return element.each(function () {
1488            var el = $(this), props = {
1489                position: el.css("position"),
1490                top: el.css("top"),
1491                bottom: el.css("bottom"),
1492                left: el.css("left"),
1493                right: el.css("right")
1494            };
1495
1496            el.css("position", "relative");
1497
1498            var ref = (options.direction === "up" || options.direction === "down") ? "top" : "left";
1499            var motion = (options.direction === "up" || options.direction === "left") ? "pos" : "neg";
1500
1501            var animation = {}, animation1 = {}, animation2 = {};
1502            animation[ref] = (motion === "pos" ? "-=" : "+=") + options.distance;
1503            animation1[ref] = (motion === "pos" ? "+=" : "-=") + options.distance * 2;
1504            animation2[ref] = (motion === "pos" ? "-=" : "+=") + options.distance * 2;
1505
1506            el.animate(animation, options.speed);
1507            for (var i = 1; i < options.times; i++) {
1508                el.animate(animation1, options.speed).animate(animation2, options.speed);
1509            }
1510
1511            el.animate(animation1, options.speed).animate(animation, options.speed / 2, function () {
1512                el.css(props);
1513            });
1514        });
1515    };
1516
1517}
1518});
1519
1520/**
1521 * Form module
1522 *
1523 * @copyright Copyright (c) WHMCS Limited 2005-2017
1524 * @license http://www.whmcs.com/license/ WHMCS Eula
1525 */
1526(function(module) {
1527    if (!WHMCS.hasModule('form')) {
1528        WHMCS.loadModule('form', module);
1529    }
1530})(
1531function () {
1532    this.checkAllBound = false;
1533
1534    this.register = function () {
1535        if (!this.checkAllBound) {
1536            this.bindCheckAll();
1537            this.checkAllBound = true;
1538        }
1539    };
1540
1541    this.bindCheckAll = function ()
1542    {
1543        var huntSelector = '.btn-check-all';
1544        jQuery(huntSelector).click(function (e) {
1545            var btn = jQuery(e.target);
1546            var targetInputs = jQuery(
1547                '#' + btn.data('checkbox-container') + ' input[type="checkbox"]'
1548            );
1549            if (btn.data('btn-check-toggle')) {
1550                // one control that changes
1551                var textDeselect = 'Deselect All';
1552                var textSelect = 'Select All';
1553                if (btn.data('label-text-deselect')) {
1554                    textDeselect = btn.data('label-text-deselect');
1555                }
1556                if (btn.data('label-text-select')) {
1557                    textSelect = btn.data('label-text-select');
1558                }
1559
1560                if (btn.hasClass('toggle-active')) {
1561                    targetInputs.prop('checked',false);
1562                    btn.text(textSelect);
1563                    btn.removeClass('toggle-active');
1564                } else {
1565                    targetInputs.prop('checked',true);
1566                    btn.text(textDeselect);
1567                    btn.addClass('toggle-active');
1568                }
1569            } else {
1570                // two controls that are static
1571                if (btn.data('btn-toggle-on')) {
1572                    targetInputs.prop('checked',true);
1573                } else {
1574                    targetInputs.prop('checked',false);
1575                }
1576            }
1577        });
1578    };
1579
1580    this.reloadCaptcha = function (element)
1581    {
1582        if (!element) {
1583            element = jQuery('#inputCaptchaImage');
1584        }
1585
1586        var src = jQuery(element).data('src');
1587        jQuery(element).attr('src', src + '?nocache=' + (new Date()).getTime());
1588    };
1589
1590    return this;
1591});
1592
1593/**
1594 * reCaptcha module
1595 *
1596 * @copyright Copyright (c) WHMCS Limited 2005-2018
1597 * @license http://www.whmcs.com/license/ WHMCS Eula
1598 */
1599var recaptchaLoadComplete = false;
1600
1601(function(module) {
1602    if (!WHMCS.hasModule('recaptcha')) {
1603        WHMCS.loadModule('recaptcha', module);
1604    }
1605})(
1606    function () {
1607
1608        this.register = function () {
1609            if (recaptchaLoadComplete) {
1610                return;
1611            }
1612            var postLoad = [];
1613            var recaptchaForms = jQuery(".btn-recaptcha").parents('form');
1614            recaptchaForms.each(function (i, el){
1615                if (typeof recaptchaSiteKey === 'undefined') {
1616                    console.log('Recaptcha site key not defined');
1617                    return;
1618                }
1619                var frm = jQuery(el);
1620                var btnRecaptcha = frm.find(".btn-recaptcha");
1621                var isInvisible = btnRecaptcha.hasClass('btn-recaptcha-invisible'),
1622                    required = (typeof requiredText !== 'undefined') ? requiredText : 'Required';
1623
1624                // if no recaptcha element, make one
1625                var recaptchaContent = frm.find("#divDynamicRecaptcha .g-recaptcha"),
1626                    recaptchaElement = frm.find('.recaptcha-container'),
1627                    appendElement = frm;
1628
1629                if (recaptchaElement.length) {
1630                    appendElement = recaptchaElement;
1631                }
1632                if (!recaptchaContent.length) {
1633                    appendElement.append('<div id="divDynamicRecaptcha" class="g-recaptcha" data-toggle="tooltip" data-placement="bottom" data-trigger="manual" title="' + required + '"></div>');
1634                    recaptchaContent = appendElement.find("#divDynamicRecaptcha");
1635                }
1636                // propagate invisible recaptcha if necessary
1637                if (isInvisible) {
1638                    if (recaptchaContent.data('size') !== 'invisible') {
1639                        recaptchaContent.attr('data-size', 'invisible');
1640                    }
1641                } else {
1642                    recaptchaContent.hide()
1643                }
1644
1645                // ensure site key is available to grecaptcha
1646                recaptchaContent.attr('data-sitekey', recaptchaSiteKey);
1647
1648
1649                // alter form to work around JS behavior on .submit() when there
1650                // there is an input with the name 'submit'
1651                var btnSubmit = frm.find("input[name='submit']");
1652                if (btnSubmit.length) {
1653                    var action = frm.prop('action');
1654                    frm.prop('action', action + '&submit=1');
1655                    btnSubmit.remove();
1656                }
1657
1658                // make callback for grecaptcha to invoke after
1659                // injecting token & make it known via data-callback
1660                var funcName = 'recaptchaCallback' + i;
1661                window[funcName] = function () {
1662                    if (isInvisible) {
1663                        frm.submit();
1664                    }
1665                };
1666                recaptchaContent.attr('data-callback', funcName);
1667
1668                // setup an on form submit event to ensure that we
1669                // are allowing required field validation to occur before
1670                // we do the invisible recaptcha checking
1671                if (isInvisible) {
1672                    frm.on('submit', function (event) {
1673                        if (!grecaptcha.getResponse().trim()) {
1674                            event.preventDefault();
1675                            grecaptcha.execute();
1676                        }
1677                    });
1678                } else {
1679                    postLoad.push(function () {
1680                        recaptchaContent.slideDown('fast', function() {
1681                            // just in case there's a delay in DOM; rare
1682                            recaptchaContent.find(':first').addClass('center-block');
1683                        });
1684                    });
1685                    postLoad.push(function() {
1686                        recaptchaContent.find(':first').addClass('center-block');
1687                    });
1688                }
1689            });
1690
1691            // fetch/invoke the grecaptcha lib
1692            if (recaptchaForms.length) {
1693                var gUrl = "https://www.google.com/recaptcha/api.js";
1694                jQuery.getScript(gUrl, function () {
1695                    for(var i = postLoad.length -1; i >= 0 ; i--){
1696                        postLoad[i]();
1697                    }
1698                });
1699            }
1700            recaptchaLoadComplete = true;
1701        };
1702
1703        return this;
1704    });
1705
1706/**
1707 * General utilities module
1708 *
1709 * @copyright Copyright (c) WHMCS Limited 2005-2017
1710 * @license http://www.whmcs.com/license/ WHMCS Eula
1711 */
1712(function(module) {
1713    if (!WHMCS.hasModule('utils')) {
1714        WHMCS.loadModule('utils', module);
1715    }
1716})(
1717function () {
1718    /**
1719     * Not crypto strong; server-side must discard for
1720     * something with more entropy; the value is sufficient
1721     * for strong client-side validation check
1722     */
1723    this.simpleRNG = function () {
1724        var chars = './$_-#!,^*()|';
1725        var r = 0;
1726        for (var i = 0; r < 3; i++) {
1727            r += Math.floor((Math.random() * 10) / 2);
1728        }
1729        r = Math.floor(r);
1730        var s = '';
1731        for (var x = 0; x < r; x++) {
1732            v = (Math.random() + 1).toString(24).split('.')[1];
1733            if ((Math.random()) > 0.5) {
1734                s += btoa(v).substr(0,4)
1735            } else {
1736                s += v
1737            }
1738
1739            if ((Math.random()) > 0.5) {
1740                s += chars.substr(
1741                    Math.floor(Math.random() * 13),
1742                    1
1743                );
1744            }
1745        }
1746
1747        return s;
1748    };
1749
1750    this.getRouteUrl = function (path) {
1751        return whmcsBaseUrl + "/index.php?rp=" + path;
1752    };
1753
1754    this.validateBaseUrl = function() {
1755        if (typeof window.whmcsBaseUrl === 'undefined') {
1756            console.log('Warning: The WHMCS Base URL definition is missing '
1757                + 'from your active template. Please refer to '
1758                + 'https://docs.whmcs.com/WHMCS_Base_URL_Template_Variable '
1759                + 'for more information and details of how to resolve this '
1760                + 'warning.');
1761            window.whmcsBaseUrl = this.autoDetermineBaseUrl();
1762            window.whmcsBaseUrlAutoSet = true;
1763        } else if (window.whmcsBaseUrl === ''
1764            && typeof window.whmcsBaseUrlAutoSet !== 'undefined'
1765            && window.whmcsBaseUrlAutoSet === true
1766        ) {
1767            window.whmcsBaseUrl = this.autoDetermineBaseUrl();
1768        }
1769    };
1770
1771    this.autoDetermineBaseUrl = function() {
1772        var windowLocation = window.location.href;
1773        var phpExtensionLocation = -1;
1774
1775        if (typeof windowLocation !== 'undefined') {
1776            phpExtensionLocation = windowLocation.indexOf('.php');
1777        }
1778
1779        if (phpExtensionLocation === -1) {
1780            windowLocation = jQuery('#Primary_Navbar-Home a').attr('href');
1781            if (typeof windowLocation !== 'undefined') {
1782                phpExtensionLocation = windowLocation.indexOf('.php');
1783            }
1784        }
1785
1786        if (phpExtensionLocation !== -1) {
1787            windowLocation = windowLocation.substring(0, phpExtensionLocation);
1788            var lastTrailingSlash = windowLocation.lastIndexOf('/');
1789            if (lastTrailingSlash !== false) {
1790                return windowLocation.substring(0, lastTrailingSlash);
1791            }
1792        }
1793
1794        return '';
1795    };
1796
1797    this.normaliseStringValue = function(status) {
1798        return status ? status.toLowerCase().replace(/\s/g, '-') : '';
1799    };
1800
1801    this.generatePassword = function(len) {
1802        var charset = this.getPasswordCharacterSet();
1803        var result = "";
1804        for (var i = 0; len > i; i++)
1805            result += charset[this.randomInt(charset.length)];
1806        return result;
1807    };
1808    this.getPasswordCharacterSet = function() {
1809        var rawCharset = '0123456789'
1810            + 'abcdefghijklmnopqrstuvwxyz'
1811            + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
1812            + '!#$%()*+,-.:;=@_|{ldelim}{rdelim}~';
1813
1814        // Parse UTF-16, remove duplicates, convert to array of strings
1815        var charset = [];
1816        for (var i = 0; rawCharset.length > i; i++) {
1817            var c = rawCharset.charCodeAt(i);
1818            if (0xD800 > c || c >= 0xE000) {  // Regular UTF-16 character
1819                var s = rawCharset.charAt(i);
1820                if (charset.indexOf(s) == -1)
1821                    charset.push(s);
1822                continue;
1823            }
1824            if (0xDC00 > c ? rawCharset.length > i + 1 : false) {  // High surrogate
1825                var d = rawCharset.charCodeAt(i + 1);
1826                if (d >= 0xDC00 ? 0xE000 > d : false) {  // Low surrogate
1827                    var s = rawCharset.substring(i, i + 2);
1828                    i++;
1829                    if (charset.indexOf(s) == -1)
1830                        charset.push(s);
1831                    continue;
1832                }
1833            }
1834            throw "Invalid UTF-16";
1835        }
1836        return charset;
1837    };
1838    this.randomInt = function(n) {
1839        var x = this.randomIntMathRandom(n);
1840        x = (x + this.randomIntBrowserCrypto(n)) % n;
1841        return x;
1842    };
1843    this.randomIntMathRandom = function(n) {
1844        var x = Math.floor(Math.random() * n);
1845        if (0 > x || x >= n)
1846            throw "Arithmetic exception";
1847        return x;
1848    };
1849    this.randomIntBrowserCrypto = function(n) {
1850        var cryptoObject = null;
1851
1852        if ("crypto" in window)
1853            cryptoObject = crypto;
1854        else if ("msCrypto" in window)
1855            cryptoObject = msCrypto;
1856        else
1857            return 0;
1858
1859        if (!("getRandomValues" in cryptoObject) || !("Uint32Array" in window) || typeof Uint32Array != "function")
1860            cryptoObject = null;
1861
1862        if (cryptoObject == null)
1863            return 0;
1864
1865        // Generate an unbiased sample
1866        var x = new Uint32Array(1);
1867        do cryptoObject.getRandomValues(x);
1868        while (x[0] - x[0] % n > 4294967296 - n);
1869        return x[0] % n;
1870    };
1871
1872    return this;
1873});
1874
1875WHMCS.utils.validateBaseUrl();
1876
1877if (typeof localTrans === 'undefined') {
1878    localTrans = function (phraseId, fallback)
1879    {
1880        if (typeof _localLang !== 'undefined') {
1881            if (typeof _localLang[phraseId] !== 'undefined') {
1882                if (_localLang[phraseId].length > 0) {
1883                    return _localLang[phraseId];
1884                }
1885            }
1886        }
1887
1888        return fallback;
1889    }
1890}
1891
1892var domainLookupCallCount,
1893    checkoutForm,
1894    furtherSuggestions;
1895
1896jQuery(document).ready(function(){
1897
1898    jQuery('#order-standard_cart').find('input').not('.no-icheck').iCheck({
1899        inheritID: true,
1900        checkboxClass: 'icheckbox_square-blue',
1901        radioClass: 'iradio_square-blue',
1902        increaseArea: '20%'
1903    });
1904
1905    jQuery('.mc-promo .header').click(function(e) {
1906        e.preventDefault();
1907        if (jQuery(e.target).is('.btn, .btn span,.btn .fa')) {
1908            return;
1909        }
1910        jQuery(this).parent().find('.rotate').toggleClass('down');
1911        jQuery(this).parent().find('.body').slideToggle('fast');
1912    });
1913    jQuery('.mc-promos.viewcart .mc-promo:first-child .header').click();
1914
1915    var cardNumber = jQuery('#inputCardNumber'),
1916        existingCvv = jQuery('#inputCardCVV2');
1917    if (cardNumber.length) {
1918        cardNumber.payment('formatCardNumber');
1919        jQuery('#inputCardCVV').payment('formatCardCVC');
1920        jQuery('#inputCardStart').payment('formatCardExpiry');
1921        jQuery('#inputCardExpiry').payment('formatCardExpiry');
1922    }
1923    if (existingCvv.length) {
1924        existingCvv.payment('formatCardCVC');
1925    }
1926
1927    var $orderSummaryEl = jQuery("#orderSummary");
1928    if ($orderSummaryEl.length) {
1929        var offset = jQuery("#scrollingPanelContainer").parent('.row').offset();
1930        var maxTopOffset = jQuery("#scrollingPanelContainer").parent('.row').outerHeight() - 35;
1931        var topPadding = 190;
1932        jQuery(window).resize(function() {
1933            offset = jQuery("#scrollingPanelContainer").parent('.row').offset();
1934            maxTopOffset = jQuery("#scrollingPanelContainer").parent('.row').outerHeight() - 35;
1935            repositionScrollingSidebar();
1936        });
1937        jQuery(window).scroll(function() {
1938            repositionScrollingSidebar();
1939        });
1940        repositionScrollingSidebar();
1941    }
1942
1943    function repositionScrollingSidebar() {
1944        if (jQuery("#scrollingPanelContainer").css('float') != 'left') {
1945            $orderSummaryEl.stop().css('margin-top', '0');
1946            return false;
1947        }
1948        var heightOfOrderSummary =  $orderSummaryEl.outerHeight();
1949        var offsetTop = 0;
1950        if (typeof offset !== "undefined") {
1951            offsetTop = offset.top +50;
1952        }
1953        var newTopOffset = jQuery(window).scrollTop() - offsetTop + topPadding;
1954        if (newTopOffset > maxTopOffset - heightOfOrderSummary) {
1955            newTopOffset = maxTopOffset - heightOfOrderSummary;
1956        }
1957        if (jQuery(window).scrollTop() > (offsetTop - 220)) {
1958            $orderSummaryEl.stop().animate({
1959                marginTop: newTopOffset
1960            });
1961        } else {
1962            $orderSummaryEl.stop().animate({
1963                marginTop: 0
1964            });
1965        }
1966    }
1967
1968    jQuery("#frmConfigureProduct").submit(function(e) {
1969        e.preventDefault();
1970
1971        var button = jQuery('#btnCompleteProductConfig');
1972
1973        var btnOriginalText = jQuery(button).html();
1974        jQuery(button).find('i').removeClass('fa-arrow-circle-right').addClass('fa-spinner fa-spin');
1975        WHMCS.http.jqClient.post("cart.php", 'ajax=1&a=confproduct&' + jQuery("#frmConfigureProduct").serialize(),
1976            function(data) {
1977                if (data) {
1978                    jQuery("#btnCompleteProductConfig").html(btnOriginalText);
1979                    jQuery("#containerProductValidationErrorsList").html(data);
1980                    jQuery("#containerProductValidationErrors").removeClass('hidden').show();
1981                    // scroll to error container if below it
1982                    if (jQuery(window).scrollTop() > jQuery("#containerProductValidationErrors").offset().top) {
1983                        jQuery('html, body').scrollTop(jQuery("#containerProductValidationErrors").offset().top - 15);
1984                    }
1985                } else {
1986                    window.location = 'cart.php?a=confdomains';
1987                }
1988            }
1989        );
1990    });
1991
1992    jQuery("#productConfigurableOptions").on('ifChecked', 'input', function() {
1993        recalctotals();
1994    });
1995    jQuery("#productConfigurableOptions").on('ifUnchecked', 'input', function() {
1996        recalctotals();
1997    });
1998    jQuery("#productConfigurableOptions").on('change', 'select', function() {
1999        recalctotals();
2000    });
2001
2002    jQuery(".addon-products").on('click', '.panel-addon', function(e) {
2003        e.preventDefault();
2004        var $activeAddon = jQuery(this);
2005        if ($activeAddon.hasClass('panel-addon-selected')) {
2006            $activeAddon.find('input[type="checkbox"]').iCheck('uncheck');
2007        } else {
2008            $activeAddon.find('input[type="checkbox"]').iCheck('check');
2009        }
2010    });
2011    jQuery(".addon-products").on('ifChecked', '.panel-addon input', function(event) {
2012        var $activeAddon = jQuery(this).parents('.panel-addon');
2013        $activeAddon.addClass('panel-addon-selected');
2014        $activeAddon.find('input[type="checkbox"]').iCheck('check');
2015        $activeAddon.find('.panel-add').html('<i class="fas fa-shopping-cart"></i> '+localTrans('addedToCartRemove', 'Added to Cart (Remove)'));
2016        recalctotals();
2017    });
2018    jQuery(".addon-products").on('ifUnchecked', '.panel-addon input', function(event) {
2019        var $activeAddon = jQuery(this).parents('.panel-addon');
2020        $activeAddon.removeClass('panel-addon-selected');
2021        $activeAddon.find('input[type="checkbox"]').iCheck('uncheck');
2022        $activeAddon.find('.panel-add').html('<i class="fas fa-plus"></i> '+localTrans('addToCart', 'Add to Cart'));
2023        recalctotals();
2024    });
2025
2026    jQuery("#frmConfigureProduct").on('ifChecked', '.addon-selector', function(event) {
2027        recalctotals();
2028    });
2029
2030    if (jQuery(".domain-selection-options input:checked").length == 0) {
2031        var firstInput = jQuery(".domain-selection-options input:first");
2032
2033        jQuery(firstInput).iCheck('check');
2034        jQuery(firstInput).parents('.option').addClass('option-selected');
2035    }
2036    jQuery("#domain" + jQuery(".domain-selection-options input:checked").val()).show();
2037    jQuery(".domain-selection-options input").on('ifChecked', function(event){
2038        jQuery(".domain-selection-options .option").removeClass('option-selected');
2039        jQuery(this).parents('.option').addClass('option-selected');
2040        jQuery(".domain-input-group").hide();
2041        jQuery("#domain" + jQuery(this).val()).show();
2042    });
2043
2044    jQuery('#frmProductDomain').submit(function (e) {
2045        e.preventDefault();
2046
2047        var btnSearchObj = jQuery(this).find('button[type="submit"]'),
2048            domainSearchResults = jQuery("#DomainSearchResults"),
2049            spotlightTlds = jQuery('#spotlightTlds'),
2050            suggestions = jQuery('#domainSuggestions'),
2051            btnDomainContinue = jQuery('#btnDomainContinue'),
2052            domainoption = jQuery(".domain-selection-options input:checked").val(),
2053            sldInput = jQuery("#" + domainoption + "sld"),
2054            sld = sldInput.val(),
2055            tld = '',
2056            pid = jQuery('#frmProductDomainPid').val(),
2057            tldInput = '';
2058
2059        if (domainoption == 'incart') {
2060            sldInput = jQuery("#" + domainoption + "sld option:selected");
2061            sld = sldInput.text();
2062        } else if (domainoption == 'subdomain') {
2063            tldInput = jQuery("#" + domainoption + "tld option:selected");
2064            tld = tldInput.text();
2065        } else {
2066            tldInput = jQuery("#" + domainoption + "tld");
2067            tld = tldInput.val();
2068            if (sld && !tld) {
2069                tldInput.tooltip('show');
2070                tldInput.focus();
2071                return false;
2072            }
2073            if (tld.substr(0, 1) != '.') {
2074                tld = '.' + tld;
2075            }
2076        }
2077        if (!sld) {
2078            sldInput.tooltip('show');
2079            sldInput.focus();
2080            return false;
2081        }
2082
2083        sldInput.tooltip('hide');
2084        if (tldInput.length) {
2085            tldInput.tooltip('hide');
2086        }
2087
2088        jQuery('input[name="domainoption"]').iCheck('disable');
2089        domainLookupCallCount = 0;
2090        btnSearchObj.attr('disabled', 'disabled').addClass('disabled');
2091
2092        jQuery('.domain-lookup-result').addClass('hidden');
2093        jQuery('#primaryLookupResult div').hide();
2094        jQuery('#primaryLookupResult').find('.register-price-label').show().end()
2095            .find('.transfer-price-label').addClass('hidden');
2096
2097        jQuery('.domain-lookup-register-loader').hide();
2098        jQuery('.domain-lookup-transfer-loader').hide();
2099        jQuery('.domain-lookup-other-loader').hide();
2100        if (domainoption == 'register') {
2101            jQuery('.domain-lookup-register-loader').show();
2102        } else if (domainoption == 'transfer') {
2103            jQuery('.domain-lookup-transfer-loader').show();
2104        } else {
2105            jQuery('.domain-lookup-other-loader').show();
2106        }
2107
2108        jQuery('.domain-lookup-loader').show();
2109        suggestions.find('li').addClass('hidden').end()
2110            .find('.clone').remove().end();
2111        jQuery('div.panel-footer.more-suggestions').addClass('hidden')
2112            .find('a').removeClass('hidden').end()
2113            .find('span.no-more').addClass('hidden');
2114        jQuery('.btn-add-to-cart').removeAttr('disabled')
2115            .find('span').hide().end()
2116            .find('span.to-add').show();
2117        btnDomainContinue.addClass('hidden').attr('disabled', 'disabled');
2118
2119        if (domainoption != 'register') {
2120            spotlightTlds.hide();
2121            jQuery('.suggested-domains').hide();
2122        }
2123
2124        if (!domainSearchResults.is(":visible")) {
2125            domainSearchResults.hide().removeClass('hidden').fadeIn();
2126        }
2127
2128        if (domainoption == 'register') {
2129            jQuery('.suggested-domains').hide().removeClass('hidden').fadeIn('fast');
2130            spotlightTlds.hide().removeClass('hidden').fadeIn('fast');
2131            jQuery('#resultDomainOption').val(domainoption);
2132            var lookup = WHMCS.http.jqClient.post(
2133                    WHMCS.utils.getRouteUrl('/domain/check'),
2134                    {
2135                        token: csrfToken,
2136                        type: 'domain',
2137                        domain: sld + tld,
2138                        sld: sld,
2139                        tld: tld,
2140                        source: 'cartAddDomain'
2141                    },
2142                    'json'
2143                ),
2144                spotlight = WHMCS.http.jqClient.post(
2145                    WHMCS.utils.getRouteUrl('/domain/check'),
2146                    {
2147                        token: csrfToken,
2148                        type: 'spotlight',
2149                        domain: sld + tld,
2150                        sld: sld,
2151                        tld: tld,
2152                        source: 'cartAddDomain'
2153                    },
2154                    'json'
2155                ),
2156                suggestion = WHMCS.http.jqClient.post(
2157                    WHMCS.utils.getRouteUrl('/domain/check'),
2158                    {
2159                        token: csrfToken,
2160                        type: 'suggestions',
2161                        domain: sld + tld,
2162                        sld: sld,
2163                        tld: tld,
2164                        source: 'cartAddDomain'
2165                    },
2166                    'json'
2167                );
2168
2169            // primary lookup handler
2170            lookup.done(function (data) {
2171                jQuery.each(data.result, function(index, domain) {
2172                    var pricing = null,
2173                        result = jQuery('#primaryLookupResult'),
2174                        available = result.find('.domain-available'),
2175                        availablePrice = result.find('.domain-price'),
2176                        unavailable = result.find('.domain-unavailable'),
2177                        invalid= result.find('.domain-invalid'),
2178                        contactSupport = result.find('.domain-contact-support'),
2179                        resultDomain = jQuery('#resultDomain'),
2180                        resultDomainPricing = jQuery('#resultDomainPricingTerm'),
2181                        error = result.find('.domain-error');
2182                    result.removeClass('hidden').show();
2183                    jQuery('.domain-lookup-primary-loader').hide();
2184                    if (!data.result.error && domain.isValidDomain) {
2185                        error.hide();
2186                        pricing = domain.pricing;
2187                        if (domain.isAvailable && typeof pricing !== 'string') {
2188                            if (domain.preferredTLDNotAvailable) {
2189                                unavailable.show().find('strong').html(domain.originalUnavailableDomain);
2190                            }
2191                            contactSupport.hide();
2192                            available.show().find('strong').html(domain.domainName);
2193                            availablePrice.show().find('span.price').html(pricing[Object.keys(pricing)[0]].register).end()
2194                                .find('button').attr('data-domain', domain.idnDomainName);
2195                            resultDomain.val(domain.domainName);
2196                            resultDomainPricing.val(Object.keys(pricing)[0]).attr('name', 'domainsregperiod[' + domain.domainName +']');
2197
2198                            btnDomainContinue.removeAttr('disabled');
2199                        } else {
2200                            unavailable.show().find('strong').html(domain.domainName);
2201                            contactSupport.hide();
2202                            if (typeof pricing === 'string' && pricing == 'ContactUs') {
2203                                contactSupport.show();
2204                            }
2205                        }
2206                    } else {
2207                        var invalidLength = invalid.find('span.domain-length-restrictions'),
2208                            done = false,
2209                            reg = /<br\s*\/>/,
2210                            errors = [];
2211                        invalidLength.hide();
2212                        error.hide();
2213                        if (domain.minLength > 0 && domain.maxLength > 0) {
2214                            invalidLength.find('.min-length').html(domain.minLength).end()
2215                                .find('.max-length').html(domain.maxLength).end();
2216                            invalidLength.show();
2217                        } else if (data.result.error) {
2218                            if (!data.result.error.match(reg)) {
2219                                error.text(data.result.error);
2220                            } else {
2221                                error.text('');
2222                                errors = data.result.error.split(reg);
2223                                for(var i=0; i < errors.length; i++) {
2224                                    var errorMsg = errors[i];
2225                                    if (errorMsg.length) {
2226                                        if (error.text()) {
2227                                            // only add line break if there is
2228                                            // multiple lines of text
2229                                            error.append('<br />');
2230                                        }
2231                                        error.append(jQuery('<span></span>').text(errorMsg));
2232                                    }
2233                                }
2234                            }
2235                            error.show();
2236                            done = true;
2237                        }
2238                        if (!done) {
2239                            invalid.show();
2240                        }
2241                    }
2242
2243
2244                });
2245            }).always(function() {
2246                hasProductDomainLookupEnded(3, btnSearchObj);
2247            });
2248
2249            // spotlight lookup handler
2250            spotlight.done(function(data) {
2251                if (typeof data != 'object' || data.result.length == 0 || data.result.error) {
2252                    jQuery('.domain-lookup-spotlight-loader').hide();
2253                    return;
2254                }
2255                jQuery.each(data.result, function(index, domain) {
2256                    var tld = domain.tldNoDots,
2257                        pricing = domain.pricing,
2258                        result = jQuery('#spotlight' + tld + ' .domain-lookup-result');
2259                    jQuery('.domain-lookup-spotlight-loader').hide();
2260                    result.find('button').addClass('hidden').end();
2261                    if (domain.isValidDomain) {
2262                        if (domain.isAvailable && typeof pricing !== 'string') {
2263                            result
2264                                .find('span.available').html(pricing[Object.keys(pricing)[0]].register).removeClass('hidden').end()
2265                                .find('button.btn-add-to-cart')
2266                                .attr('data-domain', domain.idnDomainName)
2267                                .removeClass('hidden');
2268
2269                            result.find('button.domain-contact-support').addClass('hidden').end();
2270                        } else {
2271                            if (typeof pricing === 'string') {
2272                                if (pricing == '') {
2273                                    result.find('button.unavailable').removeClass('hidden').end();
2274                                } else {
2275                                    result.find('button.domain-contact-support').removeClass('hidden').end();
2276                                }
2277                                result.find('span.available').addClass('hidden').end();
2278                            } else {
2279                                result.find('button.unavailable').removeClass('hidden').end();
2280                                result.find('span.available').addClass('hidden').end();
2281                            }
2282                        }
2283                    } else {
2284                        result.find('button.invalid.hidden').removeClass('hidden').end()
2285                            .find('span.available').addClass('hidden').end()
2286                            .find('button').not('button.invalid').addClass('hidden');
2287                    }
2288                    result.removeClass('hidden');
2289                });
2290            }).always(function() {
2291                hasProductDomainLookupEnded(3, btnSearchObj);
2292            });
2293
2294            // suggestions lookup handler
2295            suggestion.done(function (data) {
2296                if (typeof data != 'object' || data.result.length == 0 || data.result.error) {
2297                    jQuery('.suggested-domains').fadeOut('fast', function() {
2298                        jQuery(this).addClass('hidden');
2299                    });
2300                    return;
2301                } else {
2302                    jQuery('.suggested-domains').removeClass('hidden');
2303                }
2304                var suggestionCount = 1;
2305                jQuery.each(data.result, function(index, domain) {
2306                    var tld = domain.tld,
2307                        pricing = domain.pricing;
2308                    suggestions.find('li:first').clone(true, true).appendTo(suggestions);
2309                    var newSuggestion = suggestions.find('li.domain-suggestion').last();
2310                    newSuggestion.addClass('clone')
2311                        .find('span.domain').html(domain.sld).end()
2312                        .find('span.extension').html('.' + tld).end();
2313
2314                    if (typeof pricing === 'string') {
2315                        newSuggestion.find('button.btn-add-to-cart').remove();
2316                        if (pricing != '') {
2317                            newSuggestion.find('button.domain-contact-support').removeClass('hidden').end()
2318                                .find('span.price').hide();
2319                        } else {
2320                            newSuggestion.remove();
2321                        }
2322                    } else {
2323                        newSuggestion.find('button.btn-add-to-cart').attr('data-domain', domain.idnDomainName).end()
2324                            .find('span.price').html(pricing[Object.keys(pricing)[0]].register).end();
2325                    }
2326
2327                    if (suggestionCount <= 10) {
2328                        newSuggestion.removeClass('hidden');
2329                    }
2330                    suggestionCount++;
2331                    if (domain.group) {
2332                        newSuggestion.find('span.promo')
2333                            .addClass(domain.group)
2334                            .html(domain.group.toUpperCase())
2335                            .removeClass('hidden')
2336                            .end();
2337                    }
2338                    furtherSuggestions = suggestions.find('li.domain-suggestion.clone.hidden').length;
2339                    if (furtherSuggestions > 0) {
2340                        jQuery('div.more-suggestions').removeClass('hidden');
2341                    }
2342                });
2343                jQuery('.domain-lookup-suggestions-loader').hide();
2344                jQuery('#domainSuggestions').removeClass('hidden');
2345            }).always(function() {
2346                hasProductDomainLookupEnded(3, btnSearchObj);
2347            });
2348        } else if (domainoption == 'transfer') {
2349            jQuery('#resultDomainOption').val(domainoption);
2350            var transfer = WHMCS.http.jqClient.post(
2351                WHMCS.utils.getRouteUrl('/domain/check'),
2352                {
2353                    token: csrfToken,
2354                    type: 'transfer',
2355                    domain: sld + tld,
2356                    sld: sld,
2357                    tld: tld,
2358                    source: 'cartAddDomain'
2359                },
2360                'json'
2361            );
2362
2363            transfer.done(function (data) {
2364                if (typeof data != 'object' || data.result.length == 0) {
2365                    jQuery('.domain-lookup-primary-loader').hide();
2366                    return;
2367                }
2368                var result = jQuery('#primaryLookupResult'),
2369                    transfereligible = result.find('.transfer-eligible'),
2370                    transferPrice = result.find('.domain-price'),
2371                    transfernoteligible = result.find('.transfer-not-eligible'),
2372                    resultDomain = jQuery('#resultDomain'),
2373                    resultDomainPricing = jQuery('#resultDomainPricingTerm');
2374                if (Object.keys(data.result).length === 0) {
2375                    jQuery('.domain-lookup-primary-loader').hide();
2376                    result.removeClass('hidden').show();
2377                    transfernoteligible.show();
2378                }
2379                jQuery.each(data.result, function(index, domain) {
2380                    var pricing = domain.pricing;
2381                    jQuery('.domain-lookup-primary-loader').hide();
2382                    result.removeClass('hidden').show();
2383                    if (domain.isRegistered) {
2384                        transfereligible.show();
2385                        transferPrice.show().find('.register-price-label').hide().end()
2386                            .find('.transfer-price-label').removeClass('hidden').show().end()
2387                            .find('span.price').html(pricing[Object.keys(pricing)[0]].transfer).end()
2388                            .find('button').attr('data-domain', domain.idnDomainName);
2389                        resultDomain.val(domain.domainName);
2390                        resultDomainPricing.val(Object.keys(pricing)[0]).attr('name', 'domainsregperiod[' + domain.domainName +']');
2391                        btnDomainContinue.removeAttr('disabled');
2392                    } else {
2393                        transfernoteligible.show();
2394                    }
2395                });
2396            }).always(function() {
2397                hasProductDomainLookupEnded(1, btnSearchObj);
2398            });
2399        } else if (domainoption == 'owndomain' || domainoption == 'subdomain' || domainoption == 'incart') {
2400
2401            var otherDomain = WHMCS.http.jqClient.post(
2402                WHMCS.utils.getRouteUrl('/domain/check'),
2403                {
2404                    token: csrfToken,
2405                    type: domainoption,
2406                    pid: pid,
2407                    domain: sld + tld,
2408                    sld: sld,
2409                    tld: tld,
2410                    source: 'cartAddDomain'
2411                },
2412                'json'
2413            );
2414
2415            otherDomain.done(function(data) {
2416                if (typeof data != 'object' || data.result.length == 0) {
2417                    jQuery('.domain-lookup-subdomain-loader').hide();
2418                    return;
2419                }
2420                jQuery.each(data.result, function(index, result) {
2421                    if (result.status === true) {
2422                        window.location = 'cart.php?a=confproduct&i=' + result.num;
2423                    } else {
2424                        jQuery('.domain-lookup-primary-loader').hide();
2425                        if (typeof result === 'string') {
2426                            jQuery('#primaryLookupResult').removeClass('hidden').show().find('.domain-error')
2427                                .text(result)
2428                                .show();
2429                        } else {
2430                            jQuery('#primaryLookupResult').removeClass('hidden').show().find('.domain-invalid').show();
2431                        }
2432                    }
2433                });
2434
2435            }).always(function(){
2436                hasProductDomainLookupEnded(1, btnSearchObj);
2437            });
2438        }
2439
2440        btnDomainContinue.removeClass('hidden');
2441    });
2442
2443    jQuery("#btnAlreadyRegistered").click(function() {
2444        jQuery("#containerNewUserSignup").slideUp('', function() {
2445            jQuery("#containerExistingUserSignin").hide().removeClass('hidden').slideDown('', function() {
2446                jQuery("#inputCustType").val('existing');
2447                jQuery("#btnAlreadyRegistered").fadeOut('', function() {
2448                    jQuery("#btnNewUserSignup").removeClass('hidden').fadeIn();
2449                });
2450            });
2451        });
2452        jQuery("#containerNewUserSecurity").hide();
2453        if (jQuery("#stateselect").attr('required')) {
2454            jQuery("#stateselect").removeAttr('required').addClass('requiredAttributeRemoved');
2455        }
2456        jQuery('.marketing-email-optin').slideUp();
2457    });
2458
2459    jQuery("#btnNewUserSignup").click(function() {
2460        jQuery("#containerExistingUserSignin").slideUp('', function() {
2461            jQuery("#containerNewUserSignup").hide().removeClass('hidden').slideDown('', function() {
2462                jQuery("#inputCustType").val('new');
2463                if (jQuery("#passwdFeedback").html().length == 0) {
2464                    jQuery("#containerNewUserSecurity").show();
2465                }
2466                jQuery("#btnNewUserSignup").fadeOut('', function() {
2467                    jQuery("#btnAlreadyRegistered").removeClass('hidden').fadeIn();
2468                });
2469            });
2470            jQuery('.marketing-email-optin').slideDown();
2471        });
2472        if (jQuery("#stateselect").hasClass('requiredAttributeRemoved')) {
2473            jQuery("#stateselect").attr('required', 'required').removeClass('requiredAttributeRemoved');
2474        }
2475    });
2476
2477    var existingCards = jQuery('.existing-card'),
2478        cvvFieldContainer = jQuery('#cvv-field-container'),
2479        existingCardContainer = jQuery('#existingCardsContainer'),
2480        newCardInfo = jQuery('#newCardInfo'),
2481        newCardSaveSettings = jQuery('#newCardSaveSettings'),
2482        inputNoStoreContainer = jQuery('#inputNoStoreContainer'),
2483        existingCardInfo = jQuery('#existingCardInfo'),
2484        newCardOption = jQuery('#new'),
2485        creditCardInputFields = jQuery('#creditCardInputFields');
2486
2487    existingCards.on('ifChecked', function(event) {
2488        newCardSaveSettings.slideUp().find('input').attr('disabled', 'disabled');
2489        if (jQuery('.payment-methods:checked').data('remote-inputs') === 1) {
2490            return;
2491        }
2492
2493        newCardInfo.slideUp().find('input').attr('disabled', 'disabled');
2494        existingCardInfo.slideDown().find('input').removeAttr('disabled');
2495    });
2496    newCardOption.on('ifChecked', function(event) {
2497        newCardSaveSettings.slideDown().find('input').removeAttr('disabled');
2498        if (jQuery('.payment-methods:checked').data('remote-inputs') === 1) {
2499            return;
2500        }
2501
2502        newCardInfo.slideDown().find('input').removeAttr('disabled');
2503        existingCardInfo.slideUp().find('input').attr('disabled', 'disabled');
2504    });
2505
2506    if (!existingCards.length) {
2507        existingCardInfo.slideUp().find('input').attr('disabled', 'disabled');
2508    }
2509
2510    jQuery(".payment-methods").on('ifChecked', function(event) {
2511        if (jQuery(this).hasClass('is-credit-card')) {
2512            var gatewayPaymentType = jQuery(this).data('payment-type'),
2513                gatewayModule = jQuery(this).val(),
2514                showLocal = jQuery(this).data('show-local'),
2515                relevantMethods = [];
2516            if (gatewayPaymentType === 'RemoteCreditCard') {
2517                inputNoStoreContainer.hide().find('input').prop('disabled', 'disabled');
2518            } else {
2519                if (!(inputNoStoreContainer.is(':visible'))) {
2520                    inputNoStoreContainer.show().find('input').removeProp('disabled');
2521                }
2522            }
2523
2524            existingCards.each(function(index) {
2525                var paymentType = jQuery(this).data('payment-type'),
2526                    paymentModule = jQuery(this).data('payment-gateway'),
2527                    payMethodId = jQuery(this).val();
2528
2529                var paymentTypeMatch = (paymentType === gatewayPaymentType);
2530
2531                var paymentModuleMatch = false;
2532                if (gatewayPaymentType === 'RemoteCreditCard') {
2533                    // only show remote credit cards that belong to the selected gateway
2534                    paymentModuleMatch = (paymentModule === gatewayModule);
2535                } else if (gatewayPaymentType === 'CreditCard') {
2536                    // any local credit card can be used with any credit card gateway
2537                    paymentModuleMatch = true;
2538                }
2539
2540                if (showLocal && paymentType === 'CreditCard') {
2541                    paymentTypeMatch = true;
2542                    paymentModuleMatch = true;
2543                }
2544
2545                var payMethodElements = jQuery('[data-paymethod-id="' + payMethodId + '"]');
2546
2547                if (paymentTypeMatch && paymentModuleMatch) {
2548                    jQuery(payMethodElements).show();
2549                    relevantMethods.push(this);
2550                } else {
2551                    jQuery(payMethodElements).hide();
2552                }
2553            });
2554
2555            var enabledRelevantMethods = relevantMethods.filter(function (item) {
2556                return ! jQuery(item).attr('disabled');
2557            });
2558
2559            if (enabledRelevantMethods.length > 0) {
2560                var defaultId = null;
2561                jQuery.each(enabledRelevantMethods, function(index, value) {
2562                    var jQueryElement = jQuery(value),
2563                        order = parseInt(jQueryElement.data('order-preference'), 10);
2564                    if ((defaultId === null) || (order < defaultId)) {
2565                        defaultId = jQueryElement.val();
2566                        if (order === 0) {
2567                            return false;
2568                        }
2569                    }
2570                });
2571                if (defaultId === null) {
2572                    defaultId = 'new';
2573                }
2574
2575                jQuery.each(enabledRelevantMethods, function(index, value) {
2576                    var jQueryElement = jQuery(value);
2577                    if (jQueryElement.val() === defaultId) {
2578                        jQueryElement.iCheck('check');
2579                        return false;
2580                    }
2581                });
2582
2583                existingCardContainer.show();
2584                existingCardInfo.removeClass('hidden').show().find('input').removeAttr('disabled');
2585            } else {
2586                jQuery(newCardOption).iCheck('check');
2587                existingCardContainer.hide();
2588                existingCardInfo.hide().find('input').attr('disabled', 'disabled');
2589            }
2590
2591            if (!creditCardInputFields.is(":visible")) {
2592                creditCardInputFields.hide().removeClass('hidden').slideDown();
2593            }
2594        } else {
2595            creditCardInputFields.slideUp();
2596        }
2597    });
2598
2599    // make sure relevant payment methods are displayed for the pre-selected gateway
2600    jQuery(".payment-methods:checked").trigger('ifChecked');
2601
2602    jQuery('.cc-input-container .paymethod-info').click(function() {
2603        var payMethodId = $(this).data('paymethod-id');
2604        var input = jQuery('input[name="ccinfo"][value=' + payMethodId + ']:not(:disabled)');
2605
2606        if (input.length > 0) {
2607            input.iCheck('check');
2608        }
2609    });
2610
2611    jQuery("#inputDomainContact").on('change', function() {
2612        if (this.value == "addingnew") {
2613            jQuery("#domainRegistrantInputFields").hide().removeClass('hidden').slideDown();
2614        } else {
2615            jQuery("#domainRegistrantInputFields").slideUp();
2616        }
2617    });
2618
2619    if (typeof registerFormPasswordStrengthFeedback == 'function') {
2620        jQuery("#inputNewPassword1").keyup(registerFormPasswordStrengthFeedback);
2621    } else {
2622        jQuery("#inputNewPassword1").keyup(function ()
2623        {
2624            passwordStrength = getPasswordStrength(jQuery(this).val());
2625            if (passwordStrength >= 75) {
2626                textLabel = langPasswordStrong;
2627                cssClass = 'success';
2628            } else
2629                if (passwordStrength >= 30) {
2630                    textLabel = langPasswordModerate;
2631                    cssClass = 'warning';
2632                } else {
2633                    textLabel = langPasswordWeak;
2634                    cssClass = 'danger';
2635                }
2636            jQuery("#passwordStrengthTextLabel").html(langPasswordStrength + ': ' + passwordStrength + '% ' + textLabel);
2637            jQuery("#passwordStrengthMeterBar").css(
2638                'width',
2639                passwordStrength + '%'
2640            ).attr('aria-valuenow', passwordStrength);
2641            jQuery("#passwordStrengthMeterBar").removeClass(
2642                'progress-bar-success progress-bar-warning progress-bar-danger').addClass(
2643                'progress-bar-' + cssClass);
2644        });
2645    }
2646
2647    jQuery('#inputDomain').on('shown.bs.tooltip', function () {
2648        setTimeout(function(input) {
2649            input.tooltip('hide');
2650        },
2651            5000,
2652            jQuery(this)
2653        );
2654    });
2655
2656    jQuery('#frmDomainChecker').submit(function (e) {
2657        e.preventDefault();
2658
2659        var frmDomain = jQuery('#frmDomainChecker'),
2660            inputDomain = jQuery('#inputDomain'),
2661            suggestions = jQuery('#domainSuggestions'),
2662            reCaptchaContainer = jQuery('#divDynamicRecaptcha'),
2663            captcha = jQuery('#inputCaptcha');
2664
2665        domainLookupCallCount = 0;
2666
2667        // check a domain has been entered
2668        if (!inputDomain.val()) {
2669            inputDomain.tooltip('show');
2670            inputDomain.focus();
2671            return;
2672        }
2673
2674        inputDomain.tooltip('hide');
2675
2676        if (jQuery('#captchaContainer').length) {
2677            validate_captcha(frmDomain);
2678            return;
2679        }
2680
2681        reCaptchaContainer.tooltip('hide');
2682        captcha.tooltip('hide');
2683
2684        // disable repeat submit and show loader
2685        jQuery('#btnCheckAvailability').attr('disabled', 'disabled').addClass('disabled');
2686        jQuery('.domain-lookup-result').addClass('hidden');
2687        jQuery('.domain-lookup-loader').show();
2688
2689        // reset elements
2690        suggestions.find('li').addClass('hidden').end();
2691        suggestions.find('.clone').remove().end();
2692        jQuery('div.panel-footer.more-suggestions').addClass('hidden')
2693            .find('a').removeClass('hidden').end()
2694            .find('span.no-more').addClass('hidden');
2695        jQuery('.btn-add-to-cart').removeAttr('disabled')
2696            .find('span').hide().end()
2697            .find('span.to-add').show();
2698        jQuery('.suggested-domains').hide().removeClass('hidden').fadeIn('fast');
2699
2700        // fade in results
2701        if (!jQuery('#DomainSearchResults').is(":visible")) {
2702            jQuery('.domain-pricing').hide();
2703            jQuery('#DomainSearchResults').hide().removeClass('hidden').fadeIn();
2704        }
2705
2706        var lookup = WHMCS.http.jqClient.post(
2707                WHMCS.utils.getRouteUrl('/domain/check'),
2708                frmDomain.serialize() + '&type=domain',
2709                'json'
2710            ),
2711            spotlight = WHMCS.http.jqClient.post(
2712                WHMCS.utils.getRouteUrl('/domain/check'),
2713                frmDomain.serialize() + '&type=spotlight',
2714                'json'
2715            ),
2716            suggestion = WHMCS.http.jqClient.post(
2717                WHMCS.utils.getRouteUrl('/domain/check'),
2718                frmDomain.serialize() + '&type=suggestions',
2719                'json'
2720            );
2721
2722        // primary lookup handler
2723        lookup.done(function (data) {
2724            if (typeof data != 'object' || data.result.length == 0) {
2725                jQuery('.domain-lookup-primary-loader').hide();
2726                return;
2727            }
2728            jQuery.each(data.result, function(index, domain) {
2729                var pricing = null,
2730                    result = jQuery('#primaryLookupResult'),
2731                    available = result.find('.domain-available'),
2732                    availablePrice = result.find('.domain-price'),
2733                    contactSupport = result.find('.domain-contact-support'),
2734                    unavailable = result.find('.domain-unavailable'),
2735                    invalid = result.find('.domain-invalid'),
2736                    error = result.find('.domain-error');
2737                jQuery('.domain-lookup-primary-loader').hide();
2738                result.find('.btn-add-to-cart').removeClass('checkout');
2739                result.removeClass('hidden').show();
2740                if (!data.result.error && domain.isValidDomain) {
2741                    pricing = domain.pricing;
2742                    unavailable.hide();
2743                    contactSupport.hide();
2744                    invalid.hide();
2745                    error.hide();
2746                    if (domain.isAvailable && typeof pricing !== 'string') {
2747                        if (domain.preferredTLDNotAvailable) {
2748                            unavailable.show().find('strong').html(domain.originalUnavailableDomain);
2749                        }
2750                        available.show().find('strong').html(domain.domainName);
2751                        availablePrice.show().find('span.price').html(pricing[Object.keys(pricing)[0]].register).end()
2752                            .find('button').attr('data-domain', domain.idnDomainName);
2753                    } else {
2754                        available.hide();
2755                        availablePrice.hide();
2756                        contactSupport.hide();
2757                        unavailable.show().find('strong').html(domain.domainName);
2758                        if (typeof pricing === 'string' && pricing == 'ContactUs') {
2759                            contactSupport.show();
2760                        }
2761                    }
2762                } else {
2763                    available.hide();
2764                    availablePrice.hide();
2765                    unavailable.hide();
2766                    contactSupport.hide();
2767                    invalid.hide();
2768                    error.hide();
2769                    var invalidLength = invalid.find('span.domain-length-restrictions'),
2770                        done = false,
2771                        reg = /<br\s*\/>/,
2772                        errors = [];
2773                    invalidLength.hide();
2774                    if (domain.minLength > 0 && domain.maxLength > 0) {
2775                        invalidLength.find('.min-length').html(domain.minLength).end()
2776                            .find('.max-length').html(domain.maxLength).end();
2777                        invalidLength.show();
2778                    } else if (data.result.error) {
2779                        if (!data.result.error.match(reg)) {
2780                            error.text(data.result.error);
2781                        } else {
2782                            error.text('');
2783                            errors = data.result.error.split(reg);
2784                            for(var i=0; i < errors.length; i++) {
2785                                var errorMsg = errors[i];
2786                                if (errorMsg.length) {
2787                                    if (error.text()) {
2788                                        // only add line break if there is
2789                                        // multiple lines of text
2790                                        error.append('<br />');
2791                                    }
2792                                    error.append(jQuery('<span></span>').text(errorMsg));
2793                                }
2794                            }
2795                        }
2796                        error.show();
2797                        done = true;
2798                    }
2799                    if (!done) {
2800                        invalid.show();
2801                    }
2802                }
2803
2804            });
2805        }).always(function() {
2806            hasDomainLookupEnded();
2807        });
2808
2809        // spotlight lookup handler
2810        spotlight.done(function(data) {
2811            if (typeof data != 'object' || data.result.length == 0 || data.result.error) {
2812                jQuery('.domain-lookup-spotlight-loader').hide();
2813                return;
2814            }
2815            jQuery.each(data.result, function(index, domain) {
2816                var tld = domain.tldNoDots,
2817                    pricing = domain.pricing,
2818                    result = jQuery('#spotlight' + tld + ' .domain-lookup-result');
2819                jQuery('.domain-lookup-spotlight-loader').hide();
2820                result.find('button').addClass('hidden').end();
2821                if (domain.isValidDomain) {
2822                    if (domain.isAvailable && typeof pricing !== 'string') {
2823                        result.find('button.unavailable').addClass('hidden').end()
2824                            .find('button.invalid').addClass('hidden').end()
2825                            .find('span.available').html(pricing[Object.keys(pricing)[0]].register).removeClass('hidden').end()
2826                            .find('button').not('button.unavailable').not('button.invalid')
2827                            .attr('data-domain', domain.idnDomainName)
2828                            .removeClass('hidden');
2829
2830                        result.find('button.domain-contact-support').addClass('hidden').end();
2831                    } else {
2832                        if (typeof pricing === 'string') {
2833                            if (pricing == '') {
2834                                result.find('button.unavailable').removeClass('hidden').end();
2835                            } else {
2836                                result.find('button.domain-contact-support').removeClass('hidden').end();
2837                            }
2838                            result.find('button.invalid').addClass('hidden').end();
2839                            result.find('span.available').addClass('hidden').end();
2840                        } else {
2841                            result.find('button.invalid').addClass('hidden').end()
2842                                .find('button.unavailable').removeClass('hidden').end()
2843                                .find('span.available').addClass('hidden').end();
2844                        }
2845                    }
2846                } else {
2847                    result.find('button.invalid.hidden').removeClass('hidden').end()
2848                        .find('span.available').addClass('hidden').end()
2849                        .find('button').not('button.invalid').addClass('hidden');
2850                }
2851                result.removeClass('hidden');
2852            });
2853        }).always(function() {
2854            hasDomainLookupEnded();
2855        });
2856
2857        // suggestions lookup handler
2858        suggestion.done(function (data) {
2859            if (typeof data != 'object' || data.result.length == 0 || data.result.error) {
2860                jQuery('.suggested-domains').fadeOut('fast', function() {
2861                    jQuery(this).addClass('hidden');
2862                });
2863                return;
2864            } else {
2865                jQuery('.suggested-domains').removeClass('hidden');
2866            }
2867            var suggestionCount = 1;
2868            jQuery.each(data.result, function(index, domain) {
2869                var tld = domain.tld,
2870                    pricing = domain.pricing;
2871                suggestions.find('li:first').clone(true, true).appendTo(suggestions);
2872                var newSuggestion = suggestions.find('li.domain-suggestion').last();
2873                newSuggestion.addClass('clone')
2874                    .find('span.domain').html(domain.sld).end()
2875                    .find('span.extension').html('.' + tld).end();
2876
2877                if (typeof pricing === 'string') {
2878                    newSuggestion.find('button.btn-add-to-cart').remove();
2879                    if (pricing != '') {
2880                        newSuggestion.find('button.domain-contact-support').removeClass('hidden').end()
2881                            .find('span.price').hide();
2882                    } else {
2883                        newSuggestion.remove();
2884                    }
2885                } else {
2886                    newSuggestion.find('button.btn-add-to-cart').attr('data-domain', domain.idnDomainName).end()
2887                        .find('span.price').html(pricing[Object.keys(pricing)[0]].register).end();
2888                }
2889                if (suggestionCount <= 10) {
2890                    newSuggestion.removeClass('hidden');
2891                }
2892                suggestionCount++;
2893                if (domain.group) {
2894                    newSuggestion.find('span.promo')
2895                        .addClass(domain.group)
2896                        .removeClass('hidden')
2897                        .end();
2898                    newSuggestion.find('span.sales-group-' + domain.group)
2899                        .removeClass('hidden')
2900                        .end();
2901                }
2902                furtherSuggestions = suggestions.find('li.domain-suggestion.clone.hidden').length;
2903                if (furtherSuggestions > 0) {
2904                    jQuery('div.more-suggestions').removeClass('hidden');
2905                }
2906            });
2907            jQuery('.domain-lookup-suggestions-loader').hide();
2908            jQuery('#domainSuggestions').removeClass('hidden');
2909        }).always(function() {
2910            hasDomainLookupEnded();
2911        });
2912    });
2913
2914    jQuery('.btn-add-to-cart').on('click', function() {
2915        if (jQuery(this).hasClass('checkout')) {
2916            window.location = 'cart.php?a=confdomains';
2917            return;
2918        }
2919        var domain = jQuery(this).attr('data-domain'),
2920            buttons = jQuery('button[data-domain="' + domain + '"]'),
2921            whois = jQuery(this).attr('data-whois'),
2922            isProductDomain = jQuery(this).hasClass('product-domain'),
2923            btnDomainContinue = jQuery('#btnDomainContinue'),
2924            resultDomain = jQuery('#resultDomain'),
2925            resultDomainPricing = jQuery('#resultDomainPricingTerm');
2926
2927        buttons.attr('disabled', 'disabled').each(function() {
2928            jQuery(this).css('width', jQuery(this).outerWidth());
2929        });
2930
2931        var sideOrder =
2932            ((jQuery(this).parents('.spotlight-tlds').length > 0)
2933            ||
2934            (jQuery(this).parents('.suggested-domains').length > 0)) ? 1 : 0;
2935
2936        var addToCart = WHMCS.http.jqClient.post(
2937            window.location.pathname,
2938            {
2939                a: 'addToCart',
2940                domain: domain,
2941                token: csrfToken,
2942                whois: whois,
2943                sideorder: sideOrder
2944            },
2945            'json'
2946        ).done(function (data) {
2947            buttons.find('span.to-add').hide();
2948            if (data.result == 'added') {
2949                buttons.find('span.added').show().end();
2950                if (!isProductDomain) {
2951                    buttons.removeAttr('disabled').addClass('checkout');
2952                }
2953                if (resultDomain.length && !resultDomain.val()) {
2954                    resultDomain.val(domain);
2955                    resultDomainPricing.val(data.period).attr('name', 'domainsregperiod[' + domain +']');
2956                    if (btnDomainContinue.length > 0 && btnDomainContinue.is(':disabled')) {
2957                        btnDomainContinue.removeAttr('disabled');
2958                    }
2959                }
2960                jQuery('#cartItemCount').html(data.cartCount);
2961            } else {
2962                buttons.find('span.unavailable').show();
2963            }
2964        });
2965    });
2966
2967    jQuery('#frmDomainTransfer').submit(function (e) {
2968        e.preventDefault();
2969
2970        var frmDomain = jQuery('#frmDomainTransfer'),
2971        transferButton = jQuery('#btnTransferDomain'),
2972            inputDomain = jQuery('#inputTransferDomain'),
2973            authField = jQuery('#inputAuthCode'),
2974            domain = inputDomain.val(),
2975            authCode = authField.val(),
2976            redirect = false,
2977            reCaptchaContainer = jQuery('#divDynamicRecaptcha'),
2978            captcha = jQuery('#inputCaptcha');
2979
2980        if (!domain) {
2981            inputDomain.tooltip('show');
2982            inputDomain.focus();
2983            return false;
2984        }
2985
2986        inputDomain.tooltip('hide');
2987
2988        if (jQuery('#captchaContainer').length) {
2989            validate_captcha(frmDomain);
2990            return;
2991        }
2992
2993        reCaptchaContainer.tooltip('hide');
2994        captcha.tooltip('hide');
2995
2996        transferButton.attr('disabled', 'disabled').addClass('disabled')
2997            .find('span').hide().removeClass('hidden').end()
2998            .find('.loader').show();
2999
3000        WHMCS.http.jqClient.post(
3001            frmDomain.attr('action'),
3002            frmDomain.serialize(),
3003            null,
3004            'json'
3005        ).done(function (data) {
3006            if (typeof data != 'object') {
3007                transferButton.find('span').hide().end()
3008                    .find('#addToCart').show().end()
3009                    .removeAttr('disabled').removeClass('disabled');
3010                return false;
3011            }
3012            var result = data.result;
3013
3014            if (result == 'added') {
3015                window.location = 'cart.php?a=confdomains';
3016                redirect = true;
3017            } else {
3018                if (result.isRegistered == true) {
3019                    if (result.epp == true && !authCode) {
3020                        authField.tooltip('show');
3021                        authField.focus();
3022                    }
3023                } else {
3024                    jQuery('#transferUnavailable').html(result.unavailable)
3025                        .hide().removeClass('hidden').fadeIn('fast', function() {
3026                            setTimeout(function(input) {
3027                                    input.fadeOut('fast');
3028                                },
3029                                3000,
3030                                jQuery(this)
3031                            );
3032                        }
3033                    );
3034                }
3035            }
3036        }).always(function () {
3037            if (redirect == false) {
3038                transferButton.find('span').hide().end()
3039                    .find('#addToCart').show().end()
3040                    .removeAttr('disabled').removeClass('disabled');
3041            }
3042        });
3043
3044    });
3045
3046    jQuery("#btnEmptyCart").click(function() {
3047        jQuery('#modalEmptyCart').modal('show');
3048    });
3049
3050    jQuery("#cardType li a").click(function (e) {
3051        e.preventDefault();
3052        jQuery("#selectedCardType").html(jQuery(this).html());
3053        jQuery("#cctype").val(jQuery('span.type', this).html().trim());
3054    });
3055
3056    jQuery(document).on('click', '.domain-contact-support', function(e) {
3057        e.preventDefault();
3058
3059        var child = window.open();
3060        child.opener = null;
3061        child.location = 'submitticket.php';
3062    });
3063
3064    jQuery('#frmConfigureProduct input:visible, #frmConfigureProduct select:visible').first().focus();
3065    jQuery('#frmProductDomain input[type=text]:visible').first().focus();
3066    jQuery('#frmDomainChecker input[type=text]:visible').first().focus();
3067    jQuery('#frmDomainTransfer input[type=text]:visible').first().focus();
3068
3069    jQuery('.mc-promo .btn-add').click(function(e) {
3070        var self = jQuery(this);
3071        self.attr('disabled', 'disabled')
3072            .find('span.arrow i').removeClass('fa-chevron-right').addClass('fa-spinner fa-spin');
3073        WHMCS.http.jqClient.post(
3074            window.location.pathname,
3075            {
3076                'a': 'addUpSell',
3077                'product_key': self.data('product-key'),
3078                'token': csrfToken
3079            },
3080            function (data) {
3081                if (typeof data.modal !== 'undefined') {
3082                    openModal(
3083                        data.modal,
3084                        '',
3085                        data.modalTitle,
3086                        '',
3087                        '',
3088                        data.modalSubmit,
3089                        data.modelSubmitId
3090                    );
3091                    return;
3092                }
3093                window.location.reload(true);
3094            },
3095            'json'
3096        );
3097    });
3098
3099    jQuery(document).on('click', '#btnAddUpSell', function(e) {
3100        needRefresh = true;
3101    });
3102
3103    var useFullCreditOnCheckout = jQuery('#iCheck-useFullCreditOnCheckout'),
3104        skipCreditOnCheckout = jQuery('#iCheck-skipCreditOnCheckout');
3105
3106    useFullCreditOnCheckout.on('ifChecked', function() {
3107        var radio = jQuery('#useFullCreditOnCheckout'),
3108            selectedPaymentMethod = jQuery('input[name="paymentmethod"]:checked'),
3109            isCcSelected = selectedPaymentMethod.hasClass('is-credit-card'),
3110            firstNonCcGateway = jQuery('input[name="paymentmethod"]')
3111            .not(jQuery('input.is-credit-card[name="paymentmethod"]'))
3112            .first(),
3113            container = jQuery('#paymentGatewaysContainer'),
3114            ccInputFields = jQuery('#creditCardInputFields');
3115        if (radio.prop('checked')) {
3116            if (isCcSelected && firstNonCcGateway.length !== 0) {
3117                firstNonCcGateway.iCheck('check');
3118                ccInputFields.slideUp();
3119                container.slideUp();
3120            } else if (isCcSelected && !container.is(":visible")) {
3121                ccInputFields.slideDown();
3122                container.slideDown();
3123            }
3124        }
3125    });
3126
3127    skipCreditOnCheckout.on('ifChecked', function() {
3128        var selectedPaymentMethod = jQuery('input[name="paymentmethod"]:checked'),
3129            isCcSelected = selectedPaymentMethod.hasClass('is-credit-card'),
3130            container = jQuery('#paymentGatewaysContainer');
3131        if (!container.is(":visible")) {
3132            container.slideDown();
3133            if (isCcSelected) {
3134                jQuery('#creditCardInputFields').slideDown();
3135            }
3136        }
3137    });
3138
3139    if (jQuery('#applyCreditContainer').data('apply-credit') === 1 && useFullCreditOnCheckout.length) {
3140        skipCreditOnCheckout.iCheck('check');
3141        useFullCreditOnCheckout.iCheck('check');
3142    }
3143
3144    jQuery('#domainRenewals').find('span.added').hide().end().find('span.to-add').find('i').hide();
3145    jQuery('.btn-add-renewal-to-cart').on('click', function() {
3146        var self = jQuery(this),
3147            domainId = self.data('domain-id'),
3148            period = jQuery('#renewalPricing' + domainId).val();
3149
3150        if (self.hasClass('checkout')) {
3151            window.location = 'cart.php?a=view';
3152            return;
3153        }
3154
3155        self.attr('disabled', 'disabled').each(function() {
3156            jQuery(this).find('i').fadeIn('fast').end().css('width', jQuery(this).outerWidth());
3157        });
3158
3159        WHMCS.http.jqClient.post(
3160            WHMCS.utils.getRouteUrl('/cart/domain/renew/add'),
3161            {
3162                domainId: domainId,
3163                period: period,
3164                token: csrfToken
3165            },
3166            null,
3167            'json'
3168        ).done(function (data) {
3169            self.find('span.to-add').hide();
3170            if (data.result === 'added') {
3171                self.find('span.added').show().end().find('i').fadeOut('fast').css('width', self.outerWidth());
3172            }
3173            recalculateRenewalTotals();
3174        });
3175    });
3176    jQuery(document).on('submit', '#removeRenewalForm', function(e) {
3177        e.preventDefault();
3178
3179        WHMCS.http.jqClient.post(
3180            whmcsBaseUrl + '/cart.php',
3181            jQuery(this).serialize() + '&ajax=1'
3182        ).done(function(data) {
3183            var domainId = data.i,
3184                button = jQuery('#renewDomain' + domainId);
3185
3186            button.attr('disabled', 'disabled').each(function() {
3187                jQuery(this).find('span.added').hide().end()
3188                    .removeClass('checkout').find('span.to-add').show().end().removeAttr('disabled');
3189                jQuery(this).css('width', jQuery(this).outerWidth());
3190            });
3191
3192        }).always(function () {
3193            jQuery('#modalRemoveItem').modal('hide');
3194            recalculateRenewalTotals();
3195        });
3196    });
3197
3198    jQuery('.select-renewal-pricing').on('change', function() {
3199        var self = jQuery(this),
3200            domainId = self.data('domain-id'),
3201            button = jQuery('#renewDomain' + domainId);
3202
3203        button.attr('disabled', 'disabled').each(function() {
3204            jQuery(this).css('width', jQuery(this).outerWidth());
3205            jQuery(this).find('span.added').hide().end()
3206                .removeClass('checkout').find('span.to-add').show().end().removeAttr('disabled');
3207        });
3208    });
3209
3210    jQuery('#domainRenewalFilter').on('keyup', function() {
3211        var inputText = jQuery(this).val().toLowerCase();
3212        jQuery('#domainRenewals').find('div.domain-renewal').filter(function() {
3213            jQuery(this).toggle(jQuery(this).data('domain').toLowerCase().indexOf(inputText) > -1);
3214        });
3215    });
3216
3217    checkoutForm = jQuery('#frmCheckout');
3218    if (checkoutForm.length) {
3219        checkoutForm.on('submit', validateCheckoutCreditCardInput);
3220    }
3221
3222    if (existingCardContainer.is(':visible')) {
3223        newCardInfo.hide();
3224    }
3225});
3226//checkoutForm
3227function validateCheckoutCreditCardInput(e)
3228{
3229    var newOrExisting = jQuery('input[name="ccinfo"]:checked').val(),
3230        submitButton = checkoutForm.find('*[type="submit"]'),
3231        cardType = null,
3232        submit = true,
3233        selectedPaymentMethod = checkoutForm.find('input[name="paymentmethod"]:checked'),
3234        isCreditCardGateway = selectedPaymentMethod.hasClass('is-credit-card'),
3235        isRemoteCard = selectedPaymentMethod.data('payment-type') === 'RemoteCreditCard',
3236        cardNumber = jQuery('#inputCardNumber');
3237
3238    checkoutForm.find('.form-group').removeClass('has-error');
3239    checkoutForm.find('.field-error-msg').hide();
3240
3241    if (isCreditCardGateway && !isRemoteCard) {
3242        var cvvField = checkoutForm.find('#inputCardCVV2');
3243
3244        if (newOrExisting === 'new') {
3245            cvvField = checkoutForm.find('#inputCardCVV');
3246
3247            cardType = jQuery.payment.cardType(checkoutForm.find('#inputCardNumber').val());
3248            if (!jQuery.payment.validateCardNumber(checkoutForm.find('#inputCardNumber').val()) || cardNumber.hasClass('unsupported')) {
3249                var error = cardNumber.data('message-invalid');
3250                if (cardNumber.hasClass('unsupported')) {
3251                    error = cardNumber.data('message-unsupported');
3252                }
3253                checkoutForm.find('#inputCardNumber').setInputError(error).showInputError();
3254                submit = false;
3255            }
3256            if (
3257                !jQuery.payment.validateCardExpiry(
3258                    checkoutForm.find('#inputCardExpiry').payment('cardExpiryVal')
3259                )
3260            ) {
3261                checkoutForm.find('#inputCardExpiry').showInputError();
3262                submit = false;
3263            }
3264        }
3265        if (!jQuery.payment.validateCardCVC(cvvField.val(), cardType)) {
3266            cvvField.showInputError();
3267            submit = false;
3268        }
3269        if (!submit) {
3270            submitButton.prop('disabled', false)
3271                .removeClass('disabled')
3272                .find('i')
3273                .removeAttr('class')
3274                .addClass('fas fa-arrow-circle-right');
3275            e.preventDefault();
3276        }
3277    }
3278}
3279
3280function hasDomainLookupEnded() {
3281    domainLookupCallCount++;
3282    if (domainLookupCallCount == 3) {
3283        jQuery('#btnCheckAvailability').removeAttr('disabled').removeClass('disabled');
3284    }
3285}
3286
3287function hasProductDomainLookupEnded(total, button) {
3288    domainLookupCallCount++;
3289    if (domainLookupCallCount == total) {
3290        button.removeAttr('disabled').removeClass('disabled');
3291        jQuery('input[name="domainoption"]').iCheck('enable');
3292    }
3293}
3294
3295function domainGotoNextStep() {
3296    jQuery("#domainLoadingSpinner").show();
3297    jQuery("#frmProductDomainSelections").submit();
3298}
3299
3300function removeItem(type, num) {
3301    jQuery('#inputRemoveItemType').val(type);
3302    jQuery('#inputRemoveItemRef').val(num);
3303    jQuery('#modalRemoveItem').modal('show');
3304}
3305
3306function updateConfigurableOptions(i, billingCycle) {
3307
3308    WHMCS.http.jqClient.post("cart.php", 'a=cyclechange&ajax=1&i='+i+'&billingcycle='+billingCycle,
3309        function(data) {
3310            jQuery("#productConfigurableOptions").html(jQuery(data).find('#productConfigurableOptions').html());
3311            jQuery('input').iCheck({
3312                inheritID: true,
3313                checkboxClass: 'icheckbox_square-blue',
3314                radioClass: 'iradio_square-blue',
3315                increaseArea: '20%'
3316            });
3317        }
3318    );
3319    recalctotals();
3320
3321}
3322
3323function recalctotals() {
3324    if (!jQuery("#orderSummaryLoader").is(":visible")) {
3325        jQuery("#orderSummaryLoader").fadeIn('fast');
3326    }
3327
3328    var thisRequestId = Math.floor((Math.random() * 1000000) + 1);
3329    window.lastSliderUpdateRequestId = thisRequestId;
3330
3331    var post = WHMCS.http.jqClient.post("cart.php", 'ajax=1&a=confproduct&calctotal=true&'+jQuery("#frmConfigureProduct").serialize());
3332    post.done(
3333        function(data) {
3334            if (thisRequestId == window.lastSliderUpdateRequestId) {
3335                jQuery("#producttotal").html(data);
3336            }
3337        }
3338    );
3339    post.always(
3340        function() {
3341            jQuery("#orderSummaryLoader").delay(500).fadeOut('slow');
3342        }
3343    );
3344}
3345
3346function recalculateRenewalTotals() {
3347    if (!jQuery("#orderSummaryLoader").is(":visible")) {
3348        jQuery("#orderSummaryLoader").fadeIn('fast');
3349    }
3350
3351    var thisRequestId = Math.floor((Math.random() * 1000000) + 1);
3352    window.lastSliderUpdateRequestId = thisRequestId;
3353
3354    WHMCS.http.jqClient.get(
3355        WHMCS.utils.getRouteUrl('/cart/domain/renew/calculate')
3356    ).done(function(data) {
3357        if (thisRequestId === window.lastSliderUpdateRequestId) {
3358            jQuery("#producttotal").html(data.body);
3359        }
3360    }).always(
3361        function() {
3362            jQuery("#orderSummaryLoader").delay(500).fadeOut('slow');
3363        }
3364    );
3365}
3366
3367function selectDomainPricing(domainName, price, period, yearsString, suggestionNumber) {
3368    jQuery("#domainSuggestion" + suggestionNumber).iCheck('check');
3369    jQuery("[name='domainsregperiod[" + domainName + "]']").val(period);
3370    jQuery("[name='" + domainName + "-selected-price']").html('<b class="glyphicon glyphicon-shopping-cart"></b>'
3371        + ' ' + period + ' ' + yearsString + ' @ ' + price);
3372}
3373
3374function selectDomainPeriodInCart(domainName, price, period, yearsString) {
3375    var loader = jQuery("#orderSummaryLoader");
3376    if (loader.hasClass('hidden')) {
3377        loader.hide().removeClass('hidden').fadeIn('fast');
3378    }
3379    jQuery("[name='" + domainName + "Pricing']").html(period + ' ' + yearsString + ' <span class="caret"></span>');
3380    jQuery("[name='" + domainName + "Price']").html(price);
3381    var update = WHMCS.http.jqClient.post(
3382        window.location.pathname,
3383        {
3384            domain: domainName,
3385            period: period,
3386            a: 'updateDomainPeriod',
3387            token: csrfToken
3388        }
3389    );
3390    update.done(
3391        function(data) {
3392            data.domains.forEach(function(domain) {
3393                jQuery("[name='" + domain.domain + "Price']").parent('div').find('.renewal-price').html(
3394                    domain.prefixedRenewPrice + domain.shortRenewalYearsLanguage
3395                ).end();
3396            });
3397            jQuery('#subtotal').html(data.subtotal);
3398            if (data.promotype) {
3399                jQuery('#discount').html(data.discount);
3400            }
3401            if (data.taxrate) {
3402                jQuery('#taxTotal1').html(data.taxtotal);
3403            }
3404            if (data.taxrate2) {
3405                jQuery('#taxTotal2').html(data.taxtotal2);
3406            }
3407
3408            var recurringSpan = jQuery('#recurring');
3409
3410            recurringSpan.find('span:visible').not('span.cost').fadeOut('fast').end();
3411
3412            if (data.totalrecurringannually) {
3413                jQuery('#recurringAnnually').fadeIn('fast').find('.cost').html(data.totalrecurringannually);
3414            }
3415
3416            if (data.totalrecurringbiennially) {
3417                jQuery('#recurringBiennially').fadeIn('fast').find('.cost').html(data.totalrecurringbiennially);
3418            }
3419
3420            if (data.totalrecurringmonthly) {
3421                jQuery('#recurringMonthly').fadeIn('fast').find('.cost').html(data.totalrecurringmonthly);
3422            }
3423
3424            if (data.totalrecurringquarterly) {
3425                jQuery('#recurringQuarterly').fadeIn('fast').find('.cost').html(data.totalrecurringquarterly);
3426            }
3427
3428            if (data.totalrecurringsemiannually) {
3429                jQuery('#recurringSemiAnnually').fadeIn('fast').find('.cost').html(data.totalrecurringsemiannually);
3430            }
3431
3432            if (data.totalrecurringtriennially) {
3433                jQuery('#recurringTriennially').fadeIn('fast').find('.cost').html(data.totalrecurringtriennially);
3434            }
3435
3436            jQuery('#totalDueToday').html(data.total);
3437        }
3438    );
3439    update.always(
3440        function() {
3441            loader.delay(500).fadeOut('slow').addClass('hidden').show();
3442        }
3443    );
3444}
3445
3446function loadMoreSuggestions()
3447{
3448    var suggestions = jQuery('#domainSuggestions'),
3449        suggestionCount;
3450
3451    for (suggestionCount = 1; suggestionCount <= 10; suggestionCount++) {
3452        if (furtherSuggestions > 0) {
3453            suggestions.find('li.domain-suggestion.hidden.clone:first').not().hide().removeClass('hidden').slideDown();
3454            furtherSuggestions = suggestions.find('li.domain-suggestion.clone.hidden').length;
3455        } else {
3456            jQuery('div.more-suggestions').find('a').addClass('hidden').end().find('span.no-more').removeClass('hidden');
3457            return;
3458        }
3459    }
3460}
3461
3462function validate_captcha(form)
3463{
3464    var reCaptcha = jQuery('#g-recaptcha-response'),
3465        reCaptchaContainer = jQuery('#divDynamicRecaptcha'),
3466        captcha = jQuery('#inputCaptcha');
3467
3468    if (reCaptcha.length && !reCaptcha.val()) {
3469        reCaptchaContainer.tooltip('show');
3470        return false;
3471    }
3472
3473    if (captcha.length && !captcha.val()) {
3474        captcha.tooltip('show');
3475        return false;
3476    }
3477
3478    var validate = WHMCS.http.jqClient.post(
3479        form.attr('action'),
3480        form.serialize() + '&a=validateCaptcha',
3481        null,
3482        'json'
3483    );
3484
3485    validate.done(function(data) {
3486        if (data.error) {
3487            jQuery('#inputCaptcha').attr('data-original-title', data.error).tooltip('show');
3488            if (captcha.length) {
3489                jQuery('#inputCaptchaImage').replaceWith(
3490                    '<img id="inputCaptchaImage" src="' + whmcsBaseUrl + 'includes/verifyimage.php" align="middle" />'
3491                );
3492            }
3493        } else {
3494            jQuery('#captchaContainer').remove();
3495            form.trigger('submit');
3496        }
3497    });
3498}

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