PageSourceSearch

https://nic.ua/cache/js/dd7e2ec.js?version=v354

js nic.ua collected 2026-10-09 21:28:59 UTC 37,341 bytes, 1,106 lines download raw bytes

1/*!
2 * mustache.js - Logic-less {{mustache}} templates with JavaScript
3 * http://github.com/janl/mustache.js
4 */
5
6/*global define: false*/
7
8(function (global, factory) {
9  if (typeof exports === "object" && exports) {
10    factory(exports); // CommonJS
11  } else if (typeof define === "function" && define.amd) {
12    define(['exports'], factory); // AMD
13  } else {
14    factory(global.Mustache = {}); // <script>
15  }
16}(this, function (mustache) {
17
18  var Object_toString = Object.prototype.toString;
19  var isArray = Array.isArray || function (object) {
20    return Object_toString.call(object) === '[object Array]';
21  };
22
23  function isFunction(object) {
24    return typeof object === 'function';
25  }
26
27  function escapeRegExp(string) {
28    return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
29  }
30
31  // Workaround for https://issues.apache.org/jira/browse/COUCHDB-577
32  // See https://github.com/janl/mustache.js/issues/189
33  var RegExp_test = RegExp.prototype.test;
34  function testRegExp(re, string) {
35    return RegExp_test.call(re, string);
36  }
37
38  var nonSpaceRe = /\S/;
39  function isWhitespace(string) {
40    return !testRegExp(nonSpaceRe, string);
41  }
42
43  var entityMap = {
44    "&": "&amp;",
45    "<": "&lt;",
46    ">": "&gt;",
47    '"': '&quot;',
48    "'": '&#39;',
49    "/": '&#x2F;'
50  };
51
52  function escapeHtml(string) {
53    return String(string).replace(/[&<>"'\/]/g, function (s) {
54      return entityMap[s];
55    });
56  }
57
58  var whiteRe = /\s*/;
59  var spaceRe = /\s+/;
60  var equalsRe = /\s*=/;
61  var curlyRe = /\s*\}/;
62  var tagRe = /#|\^|\/|>|\{|&|=|!/;
63
64  /**
65   * Breaks up the given `template` string into a tree of tokens. If the `tags`
66   * argument is given here it must be an array with two string values: the
67   * opening and closing tags used in the template (e.g. [ "<%", "%>" ]). Of
68   * course, the default is to use mustaches (i.e. mustache.tags).
69   *
70   * A token is an array with at least 4 elements. The first element is the
71   * mustache symbol that was used inside the tag, e.g. "#" or "&". If the tag
72   * did not contain a symbol (i.e. {{myValue}}) this element is "name". For
73   * all text that appears outside a symbol this element is "text".
74   *
75   * The second element of a token is its "value". For mustache tags this is
76   * whatever else was inside the tag besides the opening symbol. For text tokens
77   * this is the text itself.
78   *
79   * The third and fourth elements of the token are the start and end indices,
80   * respectively, of the token in the original template.
81   *
82   * Tokens that are the root node of a subtree contain two more elements: 1) an
83   * array of tokens in the subtree and 2) the index in the original template at
84   * which the closing tag for that section begins.
85   */
86  function parseTemplate(template, tags) {
87    if (!template)
88      return [];
89
90    var sections = [];     // Stack to hold section tokens
91    var tokens = [];       // Buffer to hold the tokens
92    var spaces = [];       // Indices of whitespace tokens on the current line
93    var hasTag = false;    // Is there a {{tag}} on the current line?
94    var nonSpace = false;  // Is there a non-space char on the current line?
95
96    // Strips all whitespace tokens array for the current line
97    // if there was a {{#tag}} on it and otherwise only space.
98    function stripSpace() {
99      if (hasTag && !nonSpace) {
100        while (spaces.length)
101          delete tokens[spaces.pop()];
102      } else {
103        spaces = [];
104      }
105
106      hasTag = false;
107      nonSpace = false;
108    }
109
110    var openingTagRe, closingTagRe, closingCurlyRe;
111    function compileTags(tags) {
112      if (typeof tags === 'string')
113        tags = tags.split(spaceRe, 2);
114
115      if (!isArray(tags) || tags.length !== 2)
116        throw new Error('Invalid tags: ' + tags);
117
118      openingTagRe = new RegExp(escapeRegExp(tags[0]) + '\\s*');
119      closingTagRe = new RegExp('\\s*' + escapeRegExp(tags[1]));
120      closingCurlyRe = new RegExp('\\s*' + escapeRegExp('}' + tags[1]));
121    }
122
123    compileTags(tags || mustache.tags);
124
125    var scanner = new Scanner(template);
126
127    var start, type, value, chr, token, openSection;
128    while (!scanner.eos()) {
129      start = scanner.pos;
130
131      // Match any text between tags.
132      value = scanner.scanUntil(openingTagRe);
133
134      if (value) {
135        for (var i = 0, valueLength = value.length; i < valueLength; ++i) {
136          chr = value.charAt(i);
137
138          if (isWhitespace(chr)) {
vendor: 6,990 bytes, lines 139-414
139            spaces.push(tokens.length);
140          } else {
141            nonSpace = true;
142          }
143
144          tokens.push([ 'text', chr, start, start + 1 ]);
145          start += 1;
146
147          // Check for whitespace on the current line.
148          if (chr === '\n')
149            stripSpace();
150        }
151      }
152
153      // Match the opening tag.
154      if (!scanner.scan(openingTagRe))
155        break;
156
157      hasTag = true;
158
159      // Get the tag type.
160      type = scanner.scan(tagRe) || 'name';
161      scanner.scan(whiteRe);
162
163      // Get the tag value.
164      if (type === '=') {
165        value = scanner.scanUntil(equalsRe);
166        scanner.scan(equalsRe);
167        scanner.scanUntil(closingTagRe);
168      } else if (type === '{') {
169        value = scanner.scanUntil(closingCurlyRe);
170        scanner.scan(curlyRe);
171        scanner.scanUntil(closingTagRe);
172        type = '&';
173      } else {
174        value = scanner.scanUntil(closingTagRe);
175      }
176
177      // Match the closing tag.
178      if (!scanner.scan(closingTagRe))
179        throw new Error('Unclosed tag at ' + scanner.pos);
180
181      token = [ type, value, start, scanner.pos ];
182      tokens.push(token);
183
184      if (type === '#' || type === '^') {
185        sections.push(token);
186      } else if (type === '/') {
187        // Check section nesting.
188        openSection = sections.pop();
189
190        if (!openSection)
191          throw new Error('Unopened section "' + value + '" at ' + start);
192
193        if (openSection[1] !== value)
194          throw new Error('Unclosed section "' + openSection[1] + '" at ' + start);
195      } else if (type === 'name' || type === '{' || type === '&') {
196        nonSpace = true;
197      } else if (type === '=') {
198        // Set the tags for the next time around.
199        compileTags(value);
200      }
201    }
202
203    // Make sure there are no open sections when we're done.
204    openSection = sections.pop();
205
206    if (openSection)
207      throw new Error('Unclosed section "' + openSection[1] + '" at ' + scanner.pos);
208
209    return nestTokens(squashTokens(tokens));
210  }
211
212  /**
213   * Combines the values of consecutive text tokens in the given `tokens` array
214   * to a single token.
215   */
216  function squashTokens(tokens) {
217    var squashedTokens = [];
218
219    var token, lastToken;
220    for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
221      token = tokens[i];
222
223      if (token) {
224        if (token[0] === 'text' && lastToken && lastToken[0] === 'text') {
225          lastToken[1] += token[1];
226          lastToken[3] = token[3];
227        } else {
228          squashedTokens.push(token);
229          lastToken = token;
230        }
231      }
232    }
233
234    return squashedTokens;
235  }
236
237  /**
238   * Forms the given array of `tokens` into a nested tree structure where
239   * tokens that represent a section have two additional items: 1) an array of
240   * all tokens that appear in that section and 2) the index in the original
241   * template that represents the end of that section.
242   */
243  function nestTokens(tokens) {
244    var nestedTokens = [];
245    var collector = nestedTokens;
246    var sections = [];
247
248    var token, section;
249    for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
250      token = tokens[i];
251
252      switch (token[0]) {
253      case '#':
254      case '^':
255        collector.push(token);
256        sections.push(token);
257        collector = token[4] = [];
258        break;
259      case '/':
260        section = sections.pop();
261        section[5] = token[2];
262        collector = sections.length > 0 ? sections[sections.length - 1][4] : nestedTokens;
263        break;
264      default:
265        collector.push(token);
266      }
267    }
268
269    return nestedTokens;
270  }
271
272  /**
273   * A simple string scanner that is used by the template parser to find
274   * tokens in template strings.
275   */
276  function Scanner(string) {
277    this.string = string;
278    this.tail = string;
279    this.pos = 0;
280  }
281
282  /**
283   * Returns `true` if the tail is empty (end of string).
284   */
285  Scanner.prototype.eos = function () {
286    return this.tail === "";
287  };
288
289  /**
290   * Tries to match the given regular expression at the current position.
291   * Returns the matched text if it can match, the empty string otherwise.
292   */
293  Scanner.prototype.scan = function (re) {
294    var match = this.tail.match(re);
295
296    if (!match || match.index !== 0)
297      return '';
298
299    var string = match[0];
300
301    this.tail = this.tail.substring(string.length);
302    this.pos += string.length;
303
304    return string;
305  };
306
307  /**
308   * Skips all text until the given regular expression can be matched. Returns
309   * the skipped string, which is the entire tail if no match can be made.
310   */
311  Scanner.prototype.scanUntil = function (re) {
312    var index = this.tail.search(re), match;
313
314    switch (index) {
315    case -1:
316      match = this.tail;
317      this.tail = "";
318      break;
319    case 0:
320      match = "";
321      break;
322    default:
323      match = this.tail.substring(0, index);
324      this.tail = this.tail.substring(index);
325    }
326
327    this.pos += match.length;
328
329    return match;
330  };
331
332  /**
333   * Represents a rendering context by wrapping a view object and
334   * maintaining a reference to the parent context.
335   */
336  function Context(view, parentContext) {
337    this.view = view == null ? {} : view;
338    this.cache = { '.': this.view };
339    this.parent = parentContext;
340  }
341
342  /**
343   * Creates a new context using the given view with this context
344   * as the parent.
345   */
346  Context.prototype.push = function (view) {
347    return new Context(view, this);
348  };
349
350  /**
351   * Returns the value of the given name in this context, traversing
352   * up the context hierarchy if the value is absent in this context's view.
353   */
354  Context.prototype.lookup = function (name) {
355    var cache = this.cache;
356
357    var value;
358    if (name in cache) {
359      value = cache[name];
360    } else {
361      var context = this, names, index;
362
363      while (context) {
364        if (name.indexOf('.') > 0) {
365          value = context.view;
366          names = name.split('.');
367          index = 0;
368
369          while (value != null && index < names.length)
370            value = value[names[index++]];
371        } else {
372          value = context.view[name];
373        }
374
375        if (value != null)
376          break;
377
378        context = context.parent;
379      }
380
381      cache[name] = value;
382    }
383
384    if (isFunction(value))
385      value = value.call(this.view);
386
387    return value;
388  };
389
390  /**
391   * A Writer knows how to take a stream of tokens and render them to a
392   * string, given a context. It also maintains a cache of templates to
393   * avoid the need to parse the same template twice.
394   */
395  function Writer() {
396    this.cache = {};
397  }
398
399  /**
400   * Clears all cached templates in this writer.
401   */
402  Writer.prototype.clearCache = function () {
403    this.cache = {};
404  };
405
406  /**
407   * Parses and caches the given `template` and returns the array of tokens
408   * that is generated from the parse.
409   */
410  Writer.prototype.parse = function (template, tags) {
411    var cache = this.cache;
412    var tokens = cache[template];
413
414    if (tokens == null)
415      tokens = cache[template] = parseTemplate(template, tags);
416
417    return tokens;
418  };
419
420  /**
421   * High-level method that is used to render the given `template` with
422   * the given `view`.
423   *
424   * The optional `partials` argument may be an object that contains the
425   * names and templates of partials that are used in the template. It may
426   * also be a function that is used to load partial templates on the fly
427   * that takes a single argument: the name of the partial.
428   */
429  Writer.prototype.render = function (template, view, partials) {
430    var tokens = this.parse(template);
431    var context = (view instanceof Context) ? view : new Context(view);
432    return this.renderTokens(tokens, context, partials, template);
433  };
434
435  /**
436   * Low-level method that renders the given array of `tokens` using
437   * the given `context` and `partials`.
438   *
439   * Note: The `originalTemplate` is only ever used to extract the portion
440   * of the original template that was contained in a higher-order section.
441   * If the template doesn't use higher-order sections, this argument may
442   * be omitted.
443   */
444  Writer.prototype.renderTokens = function (tokens, context, partials, originalTemplate) {
445    var buffer = '';
446
447    // This function is used to render an arbitrary template
448    // in the current context by higher-order sections.
449    var self = this;
450    function subRender(template) {
451      return self.render(template, context, partials);
452    }
453
454    var token, value;
455    for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
456      token = tokens[i];
457
458      switch (token[0]) {
459      case '#':
460        value = context.lookup(token[1]);
461
462        if (!value)
463          continue;
464
465        if (isArray(value)) {
466          for (var j = 0, valueLength = value.length; j < valueLength; ++j) {
467            buffer += this.renderTokens(token[4], context.push(value[j]), partials, originalTemplate);
468          }
469        } else if (typeof value === 'object' || typeof value === 'string') {
470          buffer += this.renderTokens(token[4], context.push(value), partials, originalTemplate);
471        } else if (isFunction(value)) {
472          if (typeof originalTemplate !== 'string')
473            throw new Error('Cannot use higher-order sections without the original template');
474
475          // Extract the portion of the original template that the section contains.
476          value = value.call(context.view, originalTemplate.slice(token[3], token[5]), subRender);
477
478          if (value != null)
479            buffer += value;
480        } else {
481          buffer += this.renderTokens(token[4], context, partials, originalTemplate);
482        }
483
484        break;
485      case '^':
486        value = context.lookup(token[1]);
487
488        // Use JavaScript's definition of falsy. Include empty arrays.
489        // See https://github.com/janl/mustache.js/issues/186
490        if (!value || (isArray(value) && value.length === 0))
491          buffer += this.renderTokens(token[4], context, partials, originalTemplate);
492
493        break;
494      case '>':
495        if (!partials)
496          continue;
497
498        value = isFunction(partials) ? partials(token[1]) : partials[token[1]];
499
500        if (value != null)
501          buffer += this.renderTokens(this.parse(value), context, partials, value);
502
503        break;
504      case '&':
505        value = context.lookup(token[1]);
506
507        if (value != null)
508          buffer += value;
509
510        break;
511      case 'name':
512        value = context.lookup(token[1]);
513
514        if (value != null)
515          buffer += mustache.escape(value);
516
517        break;
518      case 'text':
519        buffer += token[1];
520        break;
521      }
522    }
523
524    return buffer;
525  };
526
527  mustache.name = "mustache.js";
528  mustache.version = "0.8.1";
529  mustache.tags = [ "{{", "}}" ];
530
531  // All high-level mustache.* functions use this writer.
532  var defaultWriter = new Writer();
533
534  /**
535   * Clears all cached templates in the default writer.
536   */
537  mustache.clearCache = function () {
538    return defaultWriter.clearCache();
539  };
540
541  /**
542   * Parses and caches the given template in the default writer and returns the
543   * array of tokens it contains. Doing this ahead of time avoids the need to
544   * parse templates on the fly as they are rendered.
545   */
546  mustache.parse = function (template, tags) {
547    return defaultWriter.parse(template, tags);
548  };
549
550  /**
551   * Renders the `template` with the given `view` and `partials` using the
552   * default writer.
553   */
554  mustache.render = function (template, view, partials) {
555    return defaultWriter.render(template, view, partials);
556  };
557
558  // This is here for backwards compatibility with 0.4.x.
559  mustache.to_html = function (template, view, partials, send) {
560    var result = mustache.render(template, view, partials);
561
562    if (isFunction(send)) {
563      send(result);
564    } else {
565      return result;
566    }
567  };
568
569  // Export the escaping function so that the user may override it.
570  // See https://github.com/janl/mustache.js/issues/244
571  mustache.escape = escapeHtml;
572
573  // Export these mainly for testing, but also for advanced usage.
574  mustache.Scanner = Scanner;
575  mustache.Context = Context;
576  mustache.Writer = Writer;
577
578}));
579
580var optionTemplate = '<option value="{{handle}}">{{name}}</option>';
581$(document).ready(function () {
582    var body = $('body');
583    /**
584     * Submit cart step processing
585     */
586    body.on('click', '#checkout-submit', function (event) {
587        if (!getBasicParam('isAuthorized')) {
588            var loginForm = $('#js-modal-login');
589            event.preventDefault();
590            $.magnificPopup.open({
591                items: {src: '#js-modal-login'},
592                type: 'inline',
593                mainClass: 'modal-perspective',
594                removalDelay: 350,
595                midClick: true,
596                callbacks: {
597                    close: function () {
598                        loginForm.find('input[name="nextUrl"]').remove();
599                    }
600                }
601            });
602            loginForm.find('form').append('<input type="hidden" name="nextUrl" value="' +
603                Routing.generate('checkout_cart', {'skip': true}) + '"/>');
604
605            return false;
606        }
607    });
608
609    /**
610     * Process questionnaire form, perform post request to add new nic handle for user
611     */
612    body.on('submit', '.questionnaire-form', function (event) {
613        event.preventDefault();
614        var thisElement = $(this);
615        $.post({
616            url: Routing.generate('add_nic_handle'),
617            data: thisElement.serialize(),
618            dataType: 'json'
619        }).success(function (response) {
620            if(thisElement.parents('.domain-contact-wrapper').length){
621                thisElement.parents('.domain-contact-wrapper').find('.text-error').hide();
622            }
623            var template = $('#new-contact-template').html();
624            var block = Mustache.render(template, response.data);
625            var descriptionContainer = $('#description-container');
626            descriptionContainer.append(block);
627            var select = thisElement.parent().prev().find('select');
628            select.append(
629                Mustache.render(optionTemplate, {handle: response.data.handle, name: response.data.formattedName})
630            );
631            select.val(response.data.handle);
632            contactFormDecorator(select);
633            initSelect2();
634        }).fail(function (xhr) {
635            var data = xhr.responseJSON;
636            var inputs = thisElement.find('input');
637            inputs.removeClass('form-control-error');
638            var errorWrappers = inputs.siblings('.text-error');
639            errorWrappers.text('');
640            errorWrappers.hide();
641            for (var i = 0; i < data.errorList.length; i++) {
642                var input = thisElement.find('input[name="baseQuestionnaire[' +
643                    data.errorList[i].field + ']"]');
644                input.addClass('form-control-error');
645                var errorWrapper = input.siblings('.text-error');
646                errorWrapper.show();
647                errorWrapper.html(data.errorList[i].errors);
648            }
649        });
650    });
651
652    body.find('.domain-contact-select .select-custom').prop('disabled', false);
653
654    /**
655     * Clear questionnaire form
656     */
657    body.on('click', '.questionnaire-form .link-btn a', function (event) {
658        event.preventDefault();
659        if($(event.target).parents('.domain-contact-wrapper').length){
660            $(event.target).parents('.domain-contact-wrapper').find('.text-error').hide();
661        }
662        var form = $(this).parent().parent().parent();
663        form.find('.text-error').hide();
664        form.find('input').removeClass('form-control-error');
665        form[0].reset();
666        var select = form.parent().prev().find('select');
667        select.val(select.find('option:first').val());
668        initSelect2();
669        contactFormDecorator(select);
670    });
671
672    /**
673     * Remove validation errors
674     */
675    body.on('keyup', '.questionnaire-form input, .single-questionnaire input, form[name="companyContactForm"] input, ' +
676        '#trademark-form input', function () {
677        removeError($(this));
678    });
679
680    body.on('change', '.form-control-fulldate-day', function() {
681        if ($(this).val().length === 1) {
682            $(this).val('0'+$(this).val());
683        }
684    });
685
686    body.on('keyup, change', '.date-pick-widget input, .date-pick-widget select', function (event) {
687        var parent = $(this).parent();
688        var target = $(parent.data('target'));
689        target.val(
690            parent.find('input[data-type="year"]').val() + '-' +
691            parent.find('select').val() + '-' +
692            parent.find('input[data-type="day"]').val()
693        );
694    });
695    $.each(body.find('.date-pick-widget'), function (key, value) {
696        var $value = $(value);
697        var target = $($value.data('target'));
698        if (target.val().length > 0) {
699            var data = target.val().split('-');
700            $value.find('input[data-type="year"]').val(data[0]);
701            $value.find('select').val(data[1]);
702            $value.find('input[data-type="day"]').val(data[2]);
703        }
704    });
705
706    /**
707     * Hide flash message
708     */
709    body.on('click', '.notify-remover', function (event) {
710        event.preventDefault();
711        $(this).parent.hide();
712    });
713
714    /**
715     * Process bonus forms
716     */
717    body.on('submit', '.bonus-form', function (event) {
718        event.preventDefault();
719        $('#bonus-form-submit').prop("disabled", true);
720        var thisElement = $(this);
721        var formData = thisElement.serialize();
722        $.post({
723            url: Routing.generate('bonus_payment'),
724            data: formData,
725            dataType: 'json'
726        }).success(function (data) {
727            if (data.success) {
728                thisElement.parent().remove();
729                var spanList = $('span.payment-span');
730                var currency = $('#invoice-currency').val();
731                $('.bonus-error-container').hide();
732                $.each(spanList, function (key, value) {
733                    $(value).html(
734                        numberToCurrency(data.invoiceAmt, $(value).data('currency'), currency)
735                    );
736                });
737                $('.receipt-header div.text-large strong:last').html(
738                    numberToCurrency(data.invoiceAmt, currency, currency)
739                );
740                var successWrapper = $('#bonus-success-box');
741                successWrapper.show();
742                successWrapper.find('#payment-success').html(
743                    numberToCurrency(data.amount, currency, currency, true)
744                );
745                successWrapper.find('#account-balance').html(
746                    numberToCurrency(data.balance, currency, currency, true)
747                );
748                $('#contacts-submit p.text-error').val('');
749            } else {
750                $('.bonus-error-container').show();
751                $('.bonus-error-container .error-wrapper').html(data.error);
752                thisElement.find('.text-muted').addClass('text-error');
753                $('#bonus-form-submit').prop('disabled', false);
754            }
755        })
756    });
757
758    body.on('change', 'select.acc-switcher', function () {
759        var container = $($(this).data('form'));
760        var currency = container.find('input[name="currency"]');
761        var option = $(this).find(':selected');
762        $('.formatted-value-container').html(option.data('formatted-value'));
763        if (option.data('formatted-credit-value') != undefined) {
764            var creditContainer = $('.formatted-credit-value-container');
765            if (option.data('credit-value') > 0) {
766                creditContainer.html(option.data('formatted-credit-value'));
767                creditContainer.parent().parent().show();
768            } else {
769                creditContainer.parent().parent().hide();
770            }
771        }
772        if ($(this).data('max-payment') != undefined) {
773            var value = null;
774            if ($(this).data('max-payment') < option.data('value')) {
775                value = $(this).data('max-payment');
776            } else {
777                value = option.data('value');
778            }
779            container.find('input[name="amount"]').val(value);
780        }
781    });
782
783    body.on('click', '.bonus-hider', function (event) {
784        event.preventDefault();
785        $(this).parent().hide();
786        $('.bonus-opener-container').show();
787        var amount = 1;
788        if (getCookie('bonus_hidden') !== false) {
789            amount = parseInt(getCookie('bonus_hidden')) + 1;
790        }
791        setCookie('bonus_hidden', amount, {expires: 86400 * 30});
792    });
793
794    body.on('click', '.bonus-opener', function (event) {
795        event.preventDefault();
796        $('.bonus-opener-container').hide();
797        $('.bonus-container').show();
798    });
799
800    /**
801     * Partial payment
802     */
803    body.on('submit', '#partial-payment-form', function (event) {
804        event.preventDefault();
805        var thisElement = $(this);
806        var input = thisElement.find('input[name="amount"]');
807        var currency = thisElement.find('input[name="currency"]');
808        if (input.val() > 0) {
809            input.removeClass('form-control-error');
810            $.post({
811                url: thisElement.attr('action'),
812                data: thisElement.serialize(),
813                dataType: 'json'
814            }).success(function (response) {
815                if (response.success) {
816                    var ul = thisElement.parent().parent().siblings('ul');
817                    ul.find('li:first').hide();
818                    ul.find('li:last').show();
819                    ul.find('li:last strong:first').html(response.currency);
820                    $('.js-checkout-pay-by-parts').hide();
821                    var spanList = $('span.payment-span');
822                    $.each(spanList, function (key, value) {
823                        $(value).html(
824                            numberToCurrency(input.val(), $(value).data('currency'), currency.val())
825                        );
826                    });
827                } else {
828                    input.addClass('form-control-error');
829                }
830            });
831        } else {
832            input.addClass('form-control-error');
833        }
834    });
835
836
837    /**
838     * Step "Owner'sContacts" - process select changing
839     */
840    body.on('change', 'select.select-custom', function () {
841        contactFormDecorator($(this));
842        var selectList = $('select.select-custom');
843        selectList.find('option:disabled').prop('disabled', false);
844        var targetValue = '';
845        $.each(selectList, function (key, value) {
846            value = $(value);
847            var selectedValues = [value];
848            do {
849                var targetSelect = $('select.select-custom[data-type="' + value.val() + '"]');
850                if (targetSelect.length > 0) {
851                    selectedValues.push(targetSelect);
852                    targetValue = targetSelect.val();
853                }
854                value = targetSelect;
855            } while (targetSelect.length > 0);
856            for (var i = 0; i < selectedValues.length; i++) {
857                var select = selectedValues.pop();
858                $.each(selectedValues, function (k, v) {
859                    select.find('option[value="' + $(v).data('type') + '"]').prop('disabled', true);
860                });
861            }
862        });
863        initSelect2();
864    });
865
866    /**
867     * Process form data in Owner'sContacts step
868     */
869    body.on('submit', '#contacts-submit', function (event) {
870        var thisElement = $(this);
871        var inputs = thisElement.find('input');
872        $.each(inputs, function (key, value) {
873            if ($(value).attr('name') === 'contacts[payer]') {
874                var result = false;
875                var innerInput = $(value);
876                do {
877                    if (innerInput !== undefined) {
878                        result = innerInput.val();
879                    }
880                    innerInput =  $('input[name="contacts['+ innerInput.val() + ']"]');
881                } while (innerInput[0] !== undefined);
882                if (result === DEFAULT_NIC_HANDLE) {
883                    event.preventDefault();
884                    var errorWrapper = thisElement.find('p.text-error');
885                    errorWrapper.html(getTranslation('__Payer_nic_handle_error'));
886                    errorWrapper.show();
887                    return false;
888                }
889            }
890            value = $(value).val();
891            if (value === undefined || ['new', 'show_contacts'].indexOf(value) >= 0 || value.length < 1) {
892                event.preventDefault();
893                var errorWrapper = thisElement.find('p.text-error');
894                if (value === 'show_contacts') {
895                    errorWrapper.html(getTranslation('__Invalid_contacts_value'));
896                } else {
897                    errorWrapper.html(getTranslation('__Submit_contacts_error'));
898                }
899                errorWrapper.show();
900                return false;
901            }
902        });
903    });
904
905    /**
906     * Trademark input toggle
907     */
908    body.on('click', '#trademark-form input[type="checkbox"]', function () {
909        var form = $('#trademark-form');
910        var targetInput = $(this).parent().parent().siblings('input');
911        if ($(this).prop('checked') === true) {
912            targetInput.show();
913        } else {
914            targetInput.hide();
915        }
916        var similarInputs = form.find('input[type="text"]:visible');
917        if (similarInputs.length < 1) {
918            $('#trademark-submit').hide();
919            $('.hidden-trademark-contact').show();
920        } else {
921            $('#trademark-submit').show();
922            $('.hidden-trademark-contact').hide();
923        }
924    });
925
926    /**
927     * Trademark form preSubmitProcessing, validation
928     */
929    body.on('submit', '#trademark-form', function (event) {
930        var thisElement = $(this);
931        var similarInputs = thisElement.find('input[type="text"]:visible');
932        var error = getTranslation('__Trademark_required_error');
933        var resultData = [];
934        $.each(similarInputs, function (key, value) {
935            var $value = $(value);
936            if ($value.val().length > 1) {
937                removeError($value);
938                resultData.push({
939                    domain: $value.data('domain'),
940                    trademark: ($value.val().length() > 0) ? $value.val() : false
941                });
942                return;
943            }
944            addError($value, error);
945            event.preventDefault();
946        });
947    });
948    $.each($('.js-tooltip-with-content'), function (key, value) {
949        var val = $(value).siblings('.tooltip-data-container').html().trim();
950        $(value).tooltipster({
951            theme: 'tooltipster-light',
952            interactive: 'true',
953            maxWidth: 340,
954            content: val
955        });
956    });
957
958    //preload cart list content
959    $('#content-loader').show();
960    $('.cart-list-data').empty();
961    $.ajax({
962            type: "GET",
963            url: Routing.generate('checkout_cart_list')
964        })
965        .done(function (data) {
966            $('#content-loader').hide();
967            $('.cart-list-data').append(data.body);
968            removeCardTableEmptyLines();
969            //activate tooltips
970            var tips = $('.js-tooltip');
971            $.each(tips, function (key, value) {
972                var object = $(value);
973                var theme = 'tooltipster-light';
974                var options = {
975                    theme: theme,
976                    interactive: true,
977                    content: $($(object.data('target')).html())
978                };
979                if (is_touch_device()) {
980                    options = {
981                        theme: theme,
982                        interactive: true,
983                        trigger: 'click',
984                        content: $($(object.data('target')).html())
985                    }
986                };
987                object.tooltipster(options);
988            });
989
990            if (data.discount_clear) {
991                discount = false;
992            }
993            refreshTotalPrice(discount);
994        });
995
996    body.on('change', 'select.card-select', function (e) {
997        var option = $(this).find('option:selected');
998        var target = $($(this).data('target'));
999        if (option.data('extra') === 'new') {
1000            target.show();
1001        } else {
1002            target.hide();
1003        }
1004    });
1005
1006    $('#select_default_contact').val('show_contacts').change();
1007});
1008
1009function is_touch_device() {
1010  return !!('ontouchstart' in window);
1011}
1012/**
1013 * Process improved select info data
1014 */
1015function contactFormDecorator(select) {
1016    var descriptionContainer = $('#description-container');
1017    var newFormWrapper = select.parent().parent().parent().next();
1018    newFormWrapper.hide();
1019    switch (select.val()) {
1020        case 'new' :
1021            newFormWrapper.show();
1022            break;
1023        case 'show_contacts' :
1024            var errorWrapper = select.siblings('p.text-error');
1025            var selectList = $('select.select-custom');
1026            selectList.find('option[value="show_contacts"]').text(getTranslation('__Checkout_contacts_loader'));
1027            initSelect2(select);
1028            $.get({
1029                url: Routing.generate('user_handles'),
1030                dataType: 'json'
1031            }).success(function (response) {
1032                var template = $('#new-contact-template').html();
1033                var renderResult = '<optgroup label="' + getTranslation('__Checkout_regular_optgroup') + '">';
1034                var containerAppendData = '';
1035                $.each(response.data.regular, function (k, v) {
1036                    renderResult += Mustache.render(optionTemplate, {handle: v.handle, name: v.formattedName});
1037                    containerAppendData += Mustache.render(template, v);
1038                });
1039                renderResult += '</optgroup><optgroup label="' + getTranslation('__Checkout_legal_optgroup') + '">';
1040                $.each(response.data.org, function (k, v) {
1041                    renderResult += Mustache.render(optionTemplate, {handle: v.handle, name: v.formattedName});
1042                    containerAppendData += Mustache.render(template, v);
1043                });
1044                renderResult += '</optgroup>';
1045                selectList.find('optgroup[data-type="additional"]').remove();
1046                $.each(selectList, function (k, v) {
1047                    var select = $(v);
1048                    select.addClass('select-custom-with-search');
1049                    if (select.attr('id') === 'select_default_contact') {
1050                        select.prepend(renderResult);
1051                    } else {
1052                        select.append(renderResult);
1053                    }
1054                });
1055                descriptionContainer.append(containerAppendData);
1056                select.val(select.find('option:first').val());
1057                initSelect2(select);
1058                initDescriptionBlock(select);
1059                var input = $('#contacts-submit').find('input[name="contacts[' + select.data('type') + ']"]');
1060                input.val(select.val());
1061                errorWrapper.hide();
1062            }).fail(function () {
1063                errorWrapper.html(getTranslation('__Something_goes_wrong'));
1064                errorWrapper.show();
1065            });
1066            break;
1067    }
1068    initDescriptionBlock(select);
1069    var input = $('#contacts-submit').find('input[name="contacts[' + select.data('type') + ']"]');
1070    input.val(select.val());
1071}
1072
1073function initSelect2(selectedObject) {
1074    $('select.select-custom').select2('destroy');
1075    $('select.select-custom:not(select-custom-with-search)').select2({
1076        minimumResultsForSearch: Infinity,
1077        width: 'resolve'
1078    });
1079    $('select.select-custom-with-search').select2({
1080        minimumResultsForSearch: 1
1081    });
1082    if (selectedObject !== undefined) {
1083        selectedObject.select2('open');
1084    }
1085}
1086
1087function initDescriptionBlock(select) {
1088    var descriptionContainer = $('#description-container');
1089    var dataList = [select];
1090    dataList = dataList.concat($('select.select-custom').toArray());
1091    $.each(dataList, function (key, value) {
1092        var select = $(value);
1093        var targetSelect = select;
1094        do {
1095            targetSelect = $('select[data-type="' + targetSelect.val() + '"]');
1096        } while ($('select[data-type="' + targetSelect.val() + '"]').length > 0);
1097        if (targetSelect.length > 0) {
1098            select.siblings('div.domain-contact-details').html(
1099                targetSelect.siblings('div.domain-contact-details').html()
1100            );
1101        } else {
1102            var element = descriptionContainer.find('div[data-name="' + select.val() + '"]');
1103            select.siblings('div.domain-contact-details').html(element.clone());
1104        }
1105    });
1106}

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.