PageSourceSearch

https://worldofwarplanes.com/static/1.22.0/portal/js/wgsdk.forms.js

js worldofwarplanes.com collected 2026-09-24 21:54:31 UTC 56,679 bytes, 1,576 lines download raw bytes

1wgsdk.showFormFieldError = (function($) {
2    var obj = function(form_id) {
3        $('input[type=password], input[type=text]', form_id).each(function(){
4            var fieldset = $(this).parents('fieldset');
5            if ($('.b-error-text', fieldset).length > 0){
6                fieldset.removeClass('accept').addClass('decline');
7                $('.b-decline', fieldset).css({'display': 'none'});
8            }
9        })
10    };
11    return obj;
12})($)
13
14
15wgsdk.InputLengthValidator = (function($){
16    var obj = function (inputSelector, params) {
17        params = params || {};
18        var minValue = params.min;
19        var maxValue = params.max;
20        var required = params.required;
21        var requiredErrorMsg = params.requiredErrorMsg || translate('FORMS_VALIDATION_EMPTY_FIELD_ERROR');
22        var minLengthErrorMsg = params.minLengthErrorMsg || translate('FORMS_VALIDATION_MIN_LENGTH_ERROR');
23        var maxLengthErrorMsg = params.maxLengthErrorMsg || translate('FORMS_VALIDATION_MAX_LENGTH_ERROR');
24
25        minValue = minValue !== undefined ? minValue : -1;
26        maxValue = maxValue !== undefined ? maxValue : $(inputSelector).attr('maxlength');
27
28        return function(value) {
29            var length = value.length;
30            var empty = length == 0;
31
32            if (required && empty) {
33                return {'status': 'error',
34                        'error': requiredErrorMsg};
35            }
36
37            if (!empty && length < minValue)
38                return {'status': 'error',
39                        'error': minLengthErrorMsg};
40
41            if (maxValue && maxValue > 0) {
42                if (length > maxValue)
43                    return {'status': 'error',
44                            'error': maxLengthErrorMsg};
45            }
46
47            return {'status': 'ok'};
48        };
49    }
50    return obj;
51})($)
52
53
54wgsdk.InputWatcher = (function($) {
55
56    var obj = function($selector, preprocessor, onChange, postprocessor, events) {
57        var instance = this,
58            defaultEvents = 'input.iw propertychange.iw change.iw forceCheck.iw';
59
60        if (typeof(events) !== 'string' || events.length === 0) {
61            events = defaultEvents;
62        }
63        
64        this.oldValue = '';
65        this.$selector = $selector;
66
67        // public interfaces
68        this.getValue = function() {
69            return this.$selector.val();
70        };
71        this.setValue = function(value, apply) {
72            if (typeof postprocessor === 'function') {
73                value = postprocessor(value, apply, this.oldValue);
74            }
75            this.$selector.val(value);
76            if (apply) {
77                instance.oldValue = value;
78            }
79        };
80        this.restoreValue = function() {
81            this.setValue(instance.oldValue, false);
82        };
83        this.destroy = function() {
84            this.$selector.off('.iw');
85        };
86        this.processChange = function(e) {
87            var value = instance.getValue(), v;
88
89            if (preprocessor) {
90                v = preprocessor(value);
91                if (v != value) {
92                    instance.setValue(v, false);
93                    value = instance.getValue();
94                }
95            }
96            if (value != instance.oldValue || e.type === 'forceCheck') {
97                if (onChange) {
98                    onChange(value, instance.oldValue);
99                }
100                instance.oldValue = value;
101            }
102        };
103        this.stopWatch = function() {
104            this.$selector.off(events);
105        };
106        this.startWatch = function() {
107            this.$selector.on(events, this.processChange);
108        };
109
110        this.startWatch();
111    }
112
113    return obj;
114})($);
115
116
117wgsdk.removeError = (function($){
118    var obj = function(selector){
119        var fieldset = $(selector).parents('fieldset');
120        $('.b-error', fieldset).remove();
121        $('.b-decline, .b-accept, .b-verification', fieldset).removeAttr('style');
122    };
123    return obj
124})($)
125
126wgsdk.AjaxFetcher = (function($){
127
128    var obj = function (defAjaxSettings, requestStarted, requestFinished, delay){
129        var instance = this;
130        var curAjax;
131        var curAjaxTimer;
132
133        function onError(XMLHttpRequest, textStatus, errorThrown){
134            requestFinished(null);
135            instance.cleanRequest();
136        }
137        function onSuccess(data, textStatus, XMLHttpRequest){
138            requestFinished(data);
139            instance.cleanRequest();
140        }
141
142        this.sendRequest = function(data, instant){
143            instance.cancelRequest();
144
145            var settings = {    'dataType': 'json',
146                                'success': onSuccess,
147                                'error': onError};
148
149            $.extend(true, settings, defAjaxSettings, {'data': data});
150
151            function sendIt(){
152                if(requestStarted)
153                    requestStarted(settings);
154
155                curAjax = $.ajax(settings);
156            }
157            if( !instant && delay && (delay > 0))
158                curAjaxTimer = window.setTimeout(sendIt, delay);
159            else
160                sendIt();
161        };
162
163        this.cancelRequest = function(){
164            if(curAjax || curAjaxTimer)
165                onError();  //   cleanRequest is called from it
166        };
167        this.cleanRequest = function(){
168            if(curAjaxTimer){
169                window.clearTimeout(curAjaxTimer);
170                curAjaxTimer = null;
171            }
172
173            if(curAjax){
174                curAjax.abort();
175                curAjax = null;
176            }
177        };
178    }
179    return obj;
180
181})($)
182
183wgsdk.NoAjaxFetcher = (function ($){
184    var obj = function(getDataCallback, requestStarted, requestFinished){
185        this.sendRequest = function(data, instant){
186            requestFinished(getDataCallback(data));
187        };
188
189        this.cancelRequest = function(){
190            requestFinished(null);
191        };
192    }
193    return obj
194})($)
195
196
197
198
199wgsdk.forms = (function($){
200    var obj = {
201
202        auth: function(params) {
203            var RELOGIN_FORM_URL = window.RELOGIN_FORM_URL ? window.RELOGIN_FORM_URL : "should be defined like global workspace";
204            var submit_params = {
205                success: function() {
206                    // here we have guaranties from the server, that there will be no 600 error
207                    // (since relogin has successed), so we can close dialog
208                    params.success();
209                    $('#js-relogin-form-wrapper').dialog('close');
210                },
211                iframeProxy: true
212            };
213            var ext_params = { source: RELOGIN_FORM_URL,
214                            OnReady: function(dialog) {
215                                $('.js-cancel-button', dialog).click(function(){
216                                    if(params.OnCancel) {
217                                        params.OnCancel();
218                                    }
219                                });
220                            } };
221
222            wgsdk.forms.submit_from_popup(false, '#js-relogin-form', '#js-relogin-form-wrapper', submit_params, ext_params);
223        },
224
225        auth_dialog: function() {
226            var LOGIN_FORM_URL = window.LOGIN_FORM_URL ? window.LOGIN_FORM_URL : 'should be defined in global namespace';
227            var submit_params = {
228                success: function(data) {
229                    if (data && data.redirect_to) {
230                        location.href = data.redirect_to;
231                    }
232                    else {
233                        setTimeout(function() {
234                            location.reload();
235                        }, 100);
236                    }
237                },
238                error: function(data) {
239                    if(data.enable_captcha){
240                        window.wotCaptcha.Enable();
241                        $('.fieldset_captcha').show();
242                    }
243                    wgsdk.waiting('close');
244                },
245                iframeProxy: true
246            };
247            var ext_params = {
248                source: LOGIN_FORM_URL,
249                stayOpened: true,
250                OnSubmitCallback: function() {
251                    wgsdk.waiting('open');
252                }
253            };
254
255            wgsdk.forms.submit_from_popup(false, '#js-auth-popup-form', '#js-auth-popup-dialog', submit_params, ext_params);
256        },
257
258        post: function(params) {
259
260            wgsdk.waiting('open');
261
262            $.ajax({
263                type: 'post',
264                data: params.data || {},
265                url:  params.url,
266                dataType: 'json',
267                success: function(data, status, request) {
268                    if (!data) {
269                        wgsdk.error(translate('FORMS_UNKNOWN_ERROR'));
270                        return;
271                    }
272
273                    if (data.error_code == 600) {
274                        wgsdk.forms.auth({ success: function() {wgsdk.forms.post(params); } });
275                        return;
276                    }
277
278                    if (data.status == 'redirect') {
279                        if (data.redirect_url) {
280                            location.href = data.redirect_url;
281                        }
282                        return;
283                    }
284
285                    if (data.error) {
286                        wgsdk.error(data.error);
287                        return;
288                    }
289
290                    if (params.success_replace) {
291                        $(params.success_replace.hide, selector).hide();
292                        $(params.success_replace.show, selector).show();
293                    }
294                    if (params.success_add_text) {
295                        wgsdk.forms.add_text_to_element(params.success_add_text.selector, params.success_add_text.params);
296                    }
297
298                    if (params.success) params.success(data, status, request);
299                },
300                error:  params.error || function(request, text, errorThrown) {
301                    if (wgsdk.dev != null) {
302                        wgsdk.dev.ajax_default_error_handler(request, text, errorThrown);
303                    } else {
304                        wgsdk.error(translate('FORMS_UNKNOWN_ERROR'));
305                        return;
306                    }
307                },
308                complete: function() {
309                    wgsdk.waiting('close');
310                    if (params.complete) params.complete();
311                    wotUpdateDateTimeFields();
312                }
313            });
314        },
315
316        hide_errors: function (form_selector) {
317            $(form_selector).removeClass('b-error-on-form');
318            $('.b-message-error-text', form_selector).empty();
319
320            $('.b-error-on-form-field', form_selector).removeClass('b-error-on-form-field');
321            $('.b-error-text', form_selector).empty();
322        },
323
324        clear_inputs: function(form_selector) {
325            $('input[type="password"]', form_selector).val('');
326            $('input[type="text"]', form_selector).val('');
327        },
328
329        get_next_iframe_number: function(){
330            if (!wgsdk.forms.__iframe_number) {
331                wgsdk.forms.__iframe_number = 0;
332            }
333            return ++wgsdk.forms.__iframe_number;
334        },
335
336        submit: function(selector, params) {
337            params = params || {};
338            params.after_error = 'after_error' in params ? params.after_error : 'focus';
339            var form = $(selector);
340
341            var MAX_PROCESSING_TIME = 10;
342            if (window.PENDING_OPERATION_JAVASCRIPT_TIMEOUT) {
343                MAX_PROCESSING_TIME = window.PENDING_OPERATION_JAVASCRIPT_TIMEOUT;
344            }
345
346            var processingStartTime = undefined;
347
348            var onFormErrorHandler = params.onFormError || wgsdk.forms.submit_onFormError;
349            var onFormError = function(error_message) {
350                onFormErrorHandler(form, error_message);
351            };
352
353            var onFieldErrorHandler = params.onFieldError || wgsdk.forms.submit_onFieldError;
354            var onFieldError = function(element_id, error_message) {
355                onFieldErrorHandler(element_id, form, error_message);
356            };
357
358            function set_focus(wrapper){
359                window.setTimeout(function(e){
360                    wgsdk.set_focus(wrapper);
361                }, 1000);
362            }
363
364            var processing = false;
365
366            var OnSuccess = function(data, status, request) {
367                processing = false;
368
369                wgsdk.forms.hide_errors(form);
370                if (!data) {
371                    wgsdk.error(translate('FORMS_UNKNOWN_ERROR'));
372                    return;
373                }
374
375                if (data.status === 'ok') {
376                    if (params.success) params.success(data, status, request);
377
378                    if (params.success_replace) {
379                        $(params.success_replace.hide, selector).hide();
380                        $(params.success_replace.show, selector).show();
381                    }
382
383                    if (params.success_add_text) {
384                        if (params.success_add_text.params.from_server) {
385                            params.success_add_text.params.text = data.log_message;
386                        }
387
388                        wgsdk.forms.add_text_to_element(params.success_add_text.selector,
389                                                    params.success_add_text.params);
390                    }
391
392                    if (data.success_url) location.href=data.success_url;
393                    if (params.success_url) location.href=params.success_url;
394
395                    return;
396                }
397
398                if (data.status === 'warning') {
399                    if (params.warning) params.warning(data, status, request);
400                    return;
401                }
402
403                if (data.status === 'processing') {
404
405                    var date = new Date();
406                    if (processingStartTime === undefined) {
407                        processingStartTime = date.getTime();
408                    }
409
410                    if (date.getTime() - processingStartTime < MAX_PROCESSING_TIME * 1000) {
411
412                        processing = true;
413
414                        setTimeout(function() {
415                            $.ajax({
416                                type: 'get',
417                                url:  data.status_url,
418                                dataType: 'json',
419                                success: OnSuccess,
420                                error: OnError,
421                                complete: OnComplete,
422                                cache: false
423                            });
424                        }, 1000);
425
426                        return;
427                    }
428
429                    if ('onTimeout' in params) {
430                        params.onTimeout(form);
431                    }
432
433                    if ('stop_url' in data && data['stop_url']) {
434                        // stop processing
435                        $.ajax({ type: 'post',
436                                    url:  data.stop_url,
437                                    dataType: 'json'
438                                    });
439                    }
440
441                    // form error data
442                    data.status = 'error';
443                    data.error = translate('FORMS_TIMEOUT');
444                }
445
446                if (data.status === 'redirect') {
447                    if (data.redirect_url) {
448                        location.href = data.redirect_url;
449                    }
450                    return;
451                }
452
453                if (data.status == 'error')
454                {
455                    if (data.error_type == 'admin_error'){
456                        alert(data.errors['__all__']);
457                    }
458
459                    if (window.wotCaptcha) {
460                        wotCaptcha.Reload();
461                    }
462
463                    if (data.error_code == 600) {
464                        wgsdk.forms.auth({ success: function() {form.submit();},
465                                        OnCancel: function() {
466                                            onFormError(translate('FORMS_AUTH_NOT_CONFIRMED'));
467                                        }
468                                    });
469                        return;
470                    }
471
472                    if (data.error_code == 413) {
473                        data.error = translate('FORMS_ERROR_413');
474                        if (data.data.size_limit) {
475                            var limit = data.data.size_limit;
476                            var size = '' + limit + ' b';
477                            if (limit > 1024) {
478                                limit = limit / 1024;
479                                size = limit.toFixed(2) + ' Kb';
480                            }
481                            if (limit > 1024) {
482                                limit = limit / 1024;
483                                size = limit.toFixed(2) + ' Mb';
484                            }
485                            data.error = translate('FORMS_ERROR_413_WITH_LIMIT').replace('%(size)i', size);
486                        }
487                    }
488
489                    if (data.errors && data.errors.__all__ && data.errors.__all__.length > 0)
490                        onFormError(data.errors.__all__[0]);
491                    if (data.error && data.error.length > 0)
492                        onFormError(data.error);
493
494                    if (data.errors)
495                        for (var field in data.errors)
496                            if (field != '__all__' && data.errors[field] && data.errors[field].length > 0) {
497                                var prefix = data.form_prefix? data.form_prefix + "-" : "";
498                                onFieldError('id_'+prefix+field, data.errors[field][0]);
499                            }
500                }
501                else
502                {
503                    onFormError(translate('FORMS_UNKNOWN_ERROR'));
504                }
505
506                if (params.error_replace) {
507                    $(params.error_replace.hide, selector).hide();
508                    $(params.error_replace.show, selector).show();
509                }
510
511                if (params.success_add_text && params.success_add_text.params.from_server) {
512                    wgsdk.forms.add_text_to_element(params.success_add_text.selector,
513                                                {clear: true});
514                }
515
516                if (params.error) params.error(data);
517
518                if (params.after_error == 'focus') set_focus(form);
519
520            };
521
522            var OnError = function(request, text, errorThrown) {
523                wgsdk.forms.hide_errors(form);
524                onFormError(translate('FORMS_SERVER_UNAVAILABLE'));
525
526                if (window.wotCaptcha) {
527                    wotCaptcha.Reload();
528                }
529
530                if (params.error) params.error();
531
532                if (window.ajax_default_error_handler != null){
533                    window.ajax_default_error_handler(request, text, errorThrown);
534                }
535
536                if (params.after_error == 'focus') set_focus(form);
537            };
538
539            var OnComplete = function() {
540                if (!processing) {
541                    wgsdk.waiting('close');
542                    wotUpdateDateTimeFields();
543                }
544            };
545
546            wgsdk.waiting('open');
547
548            var target = form.attr('target');
549            if (target) {
550                var iframe_number = wgsdk.forms.get_next_iframe_number();
551                var iframe_id = target+'-'+iframe_number;
552                var iframe = $('<iframe id="'+iframe_id+'" name="'+iframe_id+'" style="display:none;"></iframe>');
553                iframe.appendTo($('body'));
554
555                form.attr('target', iframe_id);
556
557                if (params.action) {
558                    form.attr('action', params.action);
559                }
560
561                function ProcessIframeAnswer(dataString, params) {
562                    params = params || {};
563
564                    var data = undefined;
565                    var status = 'success';
566                    var request = {
567                        status: 200,
568                        statusText: 'iframe fake status'
569                    };
570                    try {
571                        var text = dataString;
572                        if (!text) return;
573                        data = JSON.parse(text);
574                    }
575                    catch(err) {
576                        status = 'error';
577                        request.status = 404;
578                        OnError(request, status, translate('FORMS_WRONG_SERVER_ANSWER'));
579                        OnComplete();
580                    }
581                    if (data) {
582                        OnSuccess(data, status, request);
583                        OnComplete();
584                    }
585
586                    if (params.OnComplete) params.OnComplete();
587
588                    iframe.remove();
589                }
590
591                if (params.iframeProxy) {
592                    var IFRAME_PROXY = window.IFRAME_PROXY ? window.IFRAME_PROXY : "should be defined in global workspace";
593                    var proxy = new Porthole.WindowProxy(IFRAME_PROXY, iframe_id);
594                    Porthole.proxies[proxy.proxyIFrameName] = proxy;
595
596                    var EventListener = undefined;
597
598                    EventListener = function(messageEvent) {
599                        ProcessIframeAnswer(messageEvent.data,
600                                            {OnComplete: function(){
601                                                proxy.removeEventListener(EventListener);
602                                                delete Porthole.proxies[iframe_id];
603                                            } } );
604                    };
605                    proxy.addEventListener(EventListener);
606                }
607                else {
608
609                    iframe.load(function(e){
610                        var dataString = '';
611                        if($('#json_data', iframe.contents()).length){
612                            dataString = $('#json_data', iframe.contents()).text();
613                        }else{
614                            dataString = $('body', iframe.contents()).text();
615                        }
616                        ProcessIframeAnswer(dataString);
617                    });
618                }
619
620                return false;
621            }
622            else {
623                var ext_data = params.ext_data || [];
624
625                if (typeof ext_data === 'function') {
626                    ext_data = ext_data(selector, params);
627                }
628
629                var data = form.serializeArray();
630
631                $.ajax({ type: 'post',
632                        url:  params.action || form.attr('action'),
633                        data: data.concat(ext_data),
634                        dataType: 'json',
635                        success: OnSuccess,
636                        error: OnError,
637                        complete: OnComplete
638                    });
639                return true;
640            }
641        },
642
643        submit_onFormError: function(form, error_message) {
644            var block = $('.b-message-error', form);
645            if (!block.length) {
646                block = $('<div class="b-message-error b-message-error__none" />').prependTo(form);
647            }
648
649            var text = $('.b-message-error-text', block);
650            if (!text.length) {
651                text = $('<div class="b-message-error-text" />').prependTo(block);
652            }
653
654            text.html(error_message);
655            block.parents('form').addClass('b-error-on-form');
656        },
657
658        submit_onFieldError: function(element_id, form, error_message) {
659            var field = $('#' + element_id, form);
660            if (!field.length) {
661                wgsdk.forms.submit_onFormError(form, element_id + ': ' + error_message);
662                return;
663            }
664
665            //trying to find elements for display error message
666            var block = false;
667            var owner = field.parent();
668            for (var i = 0; i < 2; ++i) {
669                block = $('.b-error', owner);
670                if (block.length > 0) break;
671
672                owner = owner.parent();
673            }
674
675            if (!block.length) {
676                block = $('<div class="b-error" />');
677                var tinymce_object = field.parent().find('#'+element_id+'_parent');
678                // If error for WYSIWYG TinyMCE editor field - display error under editor field
679                if( tinymce_object.length){
680                    tinymce_object.after(block);
681                }else{
682                    field.after(block);
683                }
684            }
685
686            var arrow = $('.arrow', block);
687            if (!arrow.length) {
688                arrow = $('<div class="arrow png"><!-- --></div>').appendTo(block);
689            }
690
691            var text = $('.b-error-text', block);
692            if (!text.length) {
693                text = $('<div class="b-error-text" />').appendTo(block);
694            }
695
696            text.html(error_message);
697            block.parents('fieldset').addClass('b-error-on-form-field');
698        },
699
700        /*
701            selector,
702            params:
703                text,
704                clear, | boolean
705        */
706        add_text_to_element: function(selector, params) {
707            var element = $(selector);
708            if (params.clear && params.clear==true)  element.html('');
709            if (params.text) element.html((element.html() != "" ? element.html() + '<br />' : '') + params.text);
710        },
711
712
713        // initialized dialogs on all popup_selector-s
714        // wrap submit function - open modal popup with form to wich connected wgsdk.forms.submit
715        // add some wrappers to submit callbacks (success, error)
716        // get all parameters which are available in submit
717        // ext parameters:
718        // - OnOpenCallback = function (popup_selector, form_selector, submit_params, ext_params)
719        // - OnCloseCallback = function (popup_selector, form_selector, submit_params, ext_params)
720        // - source - selector or url of the popup
721        submit_from_popup: function(popup_selector, form_selector, dialog_id, submit_params, ext_params) {
722
723
724            var src = '';
725            if (ext_params.source) {
726                src = ext_params.source;
727            }
728
729            var OnClosed = function (e ,ui) {
730                var dialog = $(dialog_id);
731                var form = $(form_selector, dialog);
732                if (ext_params.OnCloseCallback) {
733                    ext_params.OnCloseCallback(popup_selector, form_selector, submit_params, ext_params);
734                }
735                form.unbind();
736            };
737
738
739            var OnReady = function(e, ui) {
740
741                var dialog = $(dialog_id);
742
743                var success = submit_params.success;
744
745                var OnSuccess = function(data, textStatus, XmlHttpRequest) {
746                    if (success) { success(data, textStatus, XmlHttpRequest); }
747
748                    if (!ext_params.stayOpened) {
749                        dialog.dialog('close');
750                    }
751                };
752
753                submit_params.success = OnSuccess;
754
755                var form = $(form_selector, dialog);
756
757                if (ext_params.OnOpenCallback) {
758                    ext_params.OnOpenCallback(popup_selector, form_selector, submit_params, ext_params);
759                }
760
761                wgsdk.forms.init_countables();
762
763                wgsdk.set_focus(dialog);
764
765                form.submit(function (e){
766                    if (ext_params.OnSubmitCallback)
767                        ext_params.OnSubmitCallback();
768
769                    if (wgsdk.forms.submit(form_selector, submit_params)) {
770                        e.preventDefault();
771                    }
772                });
773
774                dialog.dialog( "option", "position", 'center' );
775
776                if (ext_params.OnReady) {
777                    ext_params.OnReady(dialog);
778                }
779                if ($('.js-step').length) {
780                    var IE='\v'=='v';
781                    var stepWrap = $(this);
782                    if(IE) {
783                    setTimeout(function() {
784                        wgsdk.step(stepWrap);
785                    }, 100);
786                    } else {
787                        wgsdk.step($(this));
788                    }
789                }
790            };
791
792            var dialog_params = {
793                modal: true,
794                open: OnReady,
795                close: OnClosed,
796                type: ext_params.type || "get",
797                resizable: false
798            };
799            if(typeof(ext_params.autoOpen)) dialog_params.autoOpen = ext_params.autoOpen;
800
801            var ShowDialog = function(e){
802                //TODO: move to OnReady?
803                try {
804                    //since src can be an url instead of selector
805                    $(src).removeClass('js-hidden');
806                }
807                catch(err){}
808
809                if (src) {
810                    if (typeof ext_params.source === 'function') {
811                        dialog_params.url = src();
812                    }
813                    else {
814                        dialog_params.url = src;
815                    }
816                }
817
818                if (typeof ext_params.buttons !== 'undefined') {
819                    dialog_params.buttons = ext_params.buttons;
820                }
821
822                if (ext_params.data) {
823                    if (typeof ext_params.data === 'function') {
824                        dialog_params.ext_data = ext_params.data();
825                    }
826                    else {
827                        dialog_params.ext_data = ext_params.data;
828                    }
829                }
830
831                wgsdk.dialog(dialog_id, dialog_params);
832
833                if (e) e.preventDefault();
834            }
835
836            if (popup_selector) {
837                $(popup_selector).click(ShowDialog);
838            }
839            else {
840                ShowDialog();
841            }
842
843        },
844
845        init_countables: function() {
846
847            $(".js-countable-input").add(".js-countable-field input[type=text]").add(".js-countable-field textarea").each( function(idx, field) {
848                $(field).closest(".js-countable-field").removeClass('js-countable-field');
849                $(field).closest(".js-countable-input").removeClass('js-countable-input');
850
851                var fieldset = $(field).closest('fieldset');
852                if (fieldset.length != 1) { alert('js-countable: fieldset not found'); return; }
853
854                var max_value_el = $('.js-countable-max-value', fieldset);
855                if (max_value_el.length != 1) { alert('js-countable: max-value not specified'); return; }
856
857                var focusInColor = max_value_el.data('focusinColor'),
858                    focusOutColor = max_value_el.data('focusoutColor'),
859                    zeroNumColor = max_value_el.data('zeronumColor'),
860                    defaultColor = max_value_el.css('color'),
861                    isFocusColorsAvailable = (focusInColor !== undefined && focusOutColor !== undefined);
862
863                var addFocusInOutEvents = function (counter) {
864                    if (isFocusColorsAvailable) {
865                        var input = $('input', counter.closest('fieldset'));
866
867                        input.focusout(function() {
868                            if (counter.text() !== "0") {
869                                counter.css('color', focusOutColor);
870                            }
871                        });
872
873                        input.focusin(function() {
874                            if (counter.text() !== "0") {
875                                counter.css('color', focusInColor);
876                            }
877                        });
878                   }
879                };
880
881                var handleCounterColor = function (counter) {
882                    if (counter.text() === "0" && zeroNumColor !== undefined) {
883                        counter.css('color', zeroNumColor);
884                    } else {
885                        if (isFocusColorsAvailable) {
886                            if ($('input', counter.closest('fieldset')).is(":focus")) {
887                                counter.css('color', focusInColor);
888                            } else {
889                                counter.css('color', focusOutColor);
890                            }
891                        } else {
892                            counter.css('color', defaultColor);
893                        }
894                    }
895                }
896
897                var max_value = parseInt(max_value_el.text());
898                $(field).attr('maxlength', max_value);
899                max_value_el.text(wgsdk.thousands(max_value));
900                
901                var curr_number = $('.b-informer .number', fieldset);
902                if (curr_number.length != 1) { fieldset.append('<span class="number"></span>'); }
903
904                var onPress = function(e) {
905                    var isCharacterKeyPress = function(evt) {
906                        if (typeof evt.which == "undefined") {
907                            // This is IE, which only fires keypress events for printable keys
908                            return true;
909                        } else if (typeof evt.which == "number" && evt.which > 0) {
910                            // In other browsers except old versions of WebKit, evt.which is
911                            // only greater than zero if the keypress is a printable key.
912                            // We need to filter out backspace and ctrl/alt/meta key combinations
913                            return !evt.ctrlKey && !evt.metaKey && !evt.altKey && evt.which != 8;
914                        }
915                        return false;
916                    };
917                    var value = $(field).val();
918                    if (!isCharacterKeyPress(e)) {
919                        return true;
920                    }
921
922                    if (wgsdk.forms.calc_textarea_real_length(value) >= max_value) {
923                        /* Allow user to change selected part of text, even if input value length equals maximum length */
924                        if ('selectionStart' in this) { /* IE9+ */
925                            if (this.selectionStart !== this.selectionEnd) {
926                                return true;
927                            }
928                        } else if (document.selection.createRange) { /* IE7/8 */
929                            if (document.selection.createRange().text !== '') {
930                                return true;
931                            }
932                        }
933                        return false;
934                    }
935                    return true;
936                };
937                var onChange = function(e){
938                    var value = $(field).val();
939                    if (wgsdk.forms.calc_textarea_real_length(value) > max_value) {
940                        value = value.substring(0, max_value);
941                        $(field).val(value);
942                    }
943                    curr_number.text( wgsdk.thousands(max_value - wgsdk.forms.calc_textarea_real_length($(field).val()) ));
944                    handleCounterColor(curr_number);
945                };
946                $(field).change(onChange);
947                $(field).keyup(onChange);
948                $(field).keypress(onPress);
949                addFocusInOutEvents(max_value_el);
950                onChange();
951            })
952        },
953
954        calc_textarea_real_length: function(str) {
955            /* function find in passed string all newline symbols and redouble it when calculate the number of symbols.
956            * use when need to calc the length of string before sending to server.
957            * pass params: str - string,
958            * return: number - the patched length. */
959            return (typeof str === 'string' || str instanceof String) ? str.replace(/\r?\n/gm, "\r\n").length : 0;
960        }
961    }
962    return obj;
963})($)
964
965
966$.extend(wgsdk.forms,{
967    /* returned value from static/ajax validator shoud be in form:
968     * {'status': 'ok'|'error',
969     *  'error': 'Optional error description',
970     *  'text': 'Optional success text'}
971    */
972    validate_input: function(input_selector, options) {
973        var defaults = {
974            'preprocessor': null,
975            'postprocessor': null,
976            'validator': null,
977            'ajaxValidator': null,
978            'ajaxDelay': 0,
979            'ignoreAccept': false,
980            'onStateChange': null,
981            'events': null,
982            'initValue': undefined
983        };
984
985        options = $.extend({}, defaults, options);
986
987        var input = $(input_selector);
988        var fieldset = input.parents('fieldset:first');
989        var accept = $('.b-accept', fieldset);
990        var decline = $('.b-decline', fieldset);
991
992        var context = {
993            'input': input,
994            'fieldset': fieldset
995        };
996
997        var ON_BLUR_DELAY = 200;
998        var ON_SET_BLUR_CALLBACK_DELAY = 125;
999
1000        var onStateChange = options.onStateChange || function(){};
1001        var setState = function(states) {
1002            fieldset.addClass(states);
1003            onStateChange(context);
1004        };
1005        var clearState = function(states) {
1006            fieldset.removeClass(states || 'decline accept verification');
1007            onStateChange(context);
1008        };
1009        var hasAnyOfStates = function(states) {
1010            states = states.split(' ');
1011            for (var i in states) {
1012                var state = states[i];
1013                if (state && fieldset.hasClass(state))
1014                    return true;
1015            }
1016
1017            return false;
1018        };
1019
1020        function cleanResult(){
1021            clearState();
1022            accept.text('');
1023            decline.text('');
1024        }
1025        function isFailed(res){
1026            return (!res.status || (res.status=='error'));
1027        }
1028        function processResult(res){
1029            function set_text(el, text){
1030                if(text)
1031                    el.html(text);
1032                else
1033                    el.html('&nbsp;');
1034            }
1035            cleanResult();
1036            if(isFailed(res)){
1037                setState('decline');
1038                set_text(decline, res.error);
1039                return false;
1040            }
1041
1042            if (!options.ignoreAccept) {
1043                setState('accept');
1044                set_text(accept, res.text);
1045            }
1046            return true;
1047        }
1048
1049        function inputEqualInitialValue(value) {
1050            if (options.initValue !== undefined) {
1051                return options.initValue === value;
1052            } else {
1053                return false;
1054            }
1055        }
1056
1057        function Validate(value, validateStatic, validateAjax, instant){
1058            var isInputEqualInitialValue = inputEqualInitialValue(value);
1059
1060            if(validateStatic && options.validator && !isInputEqualInitialValue){
1061                var res = options.validator(value);
1062
1063                // we'd like to cancel request before updating ui,
1064                // cause it can clean our changes through callback
1065                var failed = isFailed(res);
1066                if(failed)
1067                    fetcher.cancelRequest();
1068
1069                processResult(res);
1070
1071                if(failed)
1072                    return; // already failed. do not need ajax
1073            }
1074            if(validateAjax && options.ajaxValidator && !isInputEqualInitialValue){
1075                clearState('accept'); // not yet
1076                fetcher.sendRequest({'value': value}, instant);
1077            }
1078
1079            if (isInputEqualInitialValue) {
1080                cleanResult();
1081            }
1082        }
1083
1084        function onChange(value, old_value){
1085            if(value.length){
1086                Validate(value, true, true, false);
1087            } else{
1088                cleanResult();
1089                fetcher.cancelRequest();
1090            }
1091        }
1092        function onRequestStarted(settings){
1093            cleanResult();
1094            setState('verification');
1095        }
1096        function onRequestFinished(data){
1097            cleanResult();
1098            if(data)
1099                processResult(data);
1100        }
1101
1102        // wrap in setTimeout, since we sometimes move focus in form (see submit_from_popup) right before
1103        // this code is executed and it cause processing an unexpecred OnBlur event in IE
1104        setTimeout(function() {
1105            input.blur(function(event) {
1106                setTimeout(function() {
1107                    if (!hasAnyOfStates('accept decline verification')) {
1108                        var value = watcher.getValue();
1109
1110                        // AJAX validation is pointless for empty values
1111                        var validateAjax = value != '';
1112                        Validate(value, true, validateAjax, true);
1113                    }
1114                }, ON_BLUR_DELAY);
1115            });
1116        }, ON_SET_BLUR_CALLBACK_DELAY);
1117     
1118        var watcher = new wgsdk.InputWatcher(input, options.preprocessor, onChange, options.postprocessor, options.events);
1119        var fetcher = new wgsdk.AjaxFetcher(options.ajaxValidator, onRequestStarted, onRequestFinished, options.ajaxDelay);
1120        var submitHandler = function(event){
1121            if (!hasAnyOfStates('accept error decline verification'))
1122                Validate(watcher.getValue(), true, false, true);
1123
1124            if (hasAnyOfStates('error decline verification')) {
1125                event.preventDefault();
1126                event.stopImmediatePropagation();
1127            }
1128        };
1129        input.parents('form:first').submit(submitHandler);
1130        input.bind('remove', function(){
1131            $(this).parents('form:first').unbind('submit', submitHandler);
1132        });
1133    },
1134
1135    validate_input_size: function(inputSelector, params) {
1136        this.validate_input(inputSelector, {'validator': wgsdk.InputLengthValidator(inputSelector, params)});
1137    }
1138});
1139
1140wgsdk.forms.Forms  = (function(){
1141    var obj = {
1142        create: function(method, url, params, target) {
1143            var form = $('<form>')
1144                .attr('method', method)
1145                .attr('action', url);
1146
1147            if (target) {
1148                form.attr('target', target);
1149            }
1150
1151            $.each(params, function(key, value) {
1152                $('<input type="hidden">')
1153                    .attr('name', key)
1154                    .attr('value', value)
1155                    .appendTo(form);
1156            });
1157
1158            form.appendTo('body');
1159            return form;
1160        },
1161        send: function(method, url, params, target) {
1162            var form = wgsdk.forms.Forms.create(method, url, params, target);
1163            form.submit();
1164        },
1165        sendGet: function(url, params, target) {
1166            return wgsdk.forms.Forms.send('GET', url, params, target);
1167        },
1168        sendPost: function(url, params, target) {
1169            return wgsdk.forms.Forms.send('POST', url, params, target);
1170        }
1171    };
1172    return obj;
1173})($);
1174
1175
1176wgsdk.autocomplete = (function($, wgsdk) {
1177    'use strict';
1178
1179    var globalAutocompleteCounter = 0,
1180        KEY_BACKSPACE = 8,
1181        KEY_ENTER = 13,
1182        KEY_ESCAPE = 27,
1183        KEY_DOWN = 40,
1184        KEY_UP = 38,
1185        ON_BLUR_HIDE_TIMEOUT = 200,
1186        CONTAINER_SELECTOR = '.js-autocomplete-container';
1187        
1188    var module = function (inputSelector, url, options) {
1189
1190        var autocompleteContainerId = 'js-autocomplete-container-' + (++globalAutocompleteCounter),
1191            defaults = {
1192                'autosubmit': false,   /* Submit form on click/enter */
1193                'minlength': 0,
1194                'preprocessor': function(value, prefix) {
1195                    value = $.trim(value);
1196                    prefix = $.trim(prefix);
1197                    var matchedSubstrIndex = value.toLowerCase().indexOf(prefix.toLowerCase());
1198                    value = value.substr(0, matchedSubstrIndex) + '<span class="b-autocomplete_match">'+value.substr(matchedSubstrIndex, prefix.length)+'</span>'+value.substr(matchedSubstrIndex+prefix.length);
1199                    return value;
1200                },  
1201                'zindex': null,
1202                'customWrapper': null,
1203                'postprocessor': null,
1204                'dataprocessor': null,  /* AJAX params processor before send */
1205                'changeCallback': null,
1206                'responseDataPreprocessor': null,
1207                'customClass': ''
1208            },
1209            $input, $lines, $wrapper, $wrapperContainer, $template, watcher, fetcher, searchValue, $form;
1210            
1211        options = $.extend({}, defaults, options);
1212        
1213        function getItemContainer() {
1214            if (options.customWrapper === null) {
1215                return $wrapper;
1216            } else {
1217                return $wrapperContainer;
1218            }
1219        }
1220
1221        function updatePosition() {
1222            var inputOffset = $input.offset();
1223
1224            $wrapper
1225                .outerWidth($input.outerWidth())
1226                .css({
1227                    'top' : inputOffset.top + $input.outerHeight(), 
1228                    'left': inputOffset.left
1229                });
1230        }
1231
1232        function getSelected() {
1233            return $('.b-autocomplete_item__selected:first');
1234        }
1235
1236        function hasScroll() {
1237            var $container = getItemContainer(),
1238                scrollHeight = $container[$.fn.prop ? 'prop' : 'attr']('scrollHeight');
1239
1240            return $container.height() < scrollHeight;
1241        }
1242
1243        function setSelected($sel) {
1244            getSelected().removeClass('b-autocomplete_item__selected');
1245
1246            if ($sel && $sel.length > 0) {
1247                $sel.addClass('b-autocomplete_item__selected');
1248
1249                if (hasScroll()) {
1250                    var $container = getItemContainer(),
1251                        offset = $sel.offset().top - $container.offset().top,
1252                        scroll = $container.scrollTop(),
1253                        elementHeight = $container.height();
1254
1255                    if (offset < 0) {
1256                        $container.scrollTop(scroll + offset);
1257                    } else if (offset >= elementHeight) {
1258                        $container.scrollTop(scroll + offset - elementHeight + $sel.height());
1259                    }
1260                }
1261            }
1262        }
1263
1264        function updateInputWithSelected(applyFilter) {
1265            var $sel = getSelected();
1266            
1267            if ($sel.length) {
1268                watcher.setValue($sel.text(), applyFilter);
1269                if (typeof options.changeCallback === 'function') {
1270                    options.changeCallback();
1271                }
1272            }
1273        }
1274        
1275        function restoreInput() {
1276            watcher.restoreValue();
1277            if (typeof options.changeCallback === 'function') {
1278                options.changeCallback();
1279            }
1280        }
1281
1282        function isSuggestionVisible(){
1283            return $wrapper.css('display') !== 'none';
1284        }
1285
1286        function setVisibility(show) {
1287            if (show !== isSuggestionVisible()) {
1288                if (show && $lines && $lines.length) {
1289                    updatePosition();
1290                    $wrapper.show();
1291                } else {
1292                    $wrapper.hide();
1293                }
1294            }
1295        }
1296
1297        function applySelected() {
1298            fetcher.cancelRequest();
1299            updateInputWithSelected(true);
1300            setVisibility(false);
1301
1302            // value was set by .val() call, which doesn't trigger change event
1303            $input.change();
1304        }
1305
1306        function onRequestComplete(data) {
1307            var template, i, len, content, $newElement;
1308
1309            if (data && data.result) {
1310                // overwrite template with new value or add to DOM
1311                if (data.tmpl) {
1312                    template = $(data.tmpl).hide();
1313                    if ($template) {
1314                        $template.replaceWith(template);
1315                    } else {
1316                        $input.after(template);
1317                        $template = template;
1318                    }
1319                }
1320                if (!$template && !data.tmpl) {
1321                    $template = $('<div></div>');
1322                }
1323        
1324                $lines = undefined;
1325                getItemContainer().empty();
1326                
1327                if ($template) {
1328
1329                    $('.js-autocomplete').remove();
1330
1331                    if (typeof options.responseDataPreprocessor === 'function') {
1332                        data = options.responseDataPreprocessor(data);
1333                    }
1334
1335                    for (i = 0, len = data.result.length; i < len; ++i) {
1336                        content = data.result[i].text;
1337                        if (typeof options.preprocessor === 'function') {
1338                            content = options.preprocessor(content, searchValue, data.result[i]);
1339                        }
1340                        $newElement = $template.clone().addClass('js-autocomplete b-autocomplete_item').html(content).show();
1341                        
1342                        getItemContainer().append($newElement);
1343                        
1344                    }
1345                    $lines = $('.js-autocomplete');
1346                    setVisibility(data.result.length > 0 ? true : false);
1347                }
1348
1349                $lines
1350                    .on('click', function() {
1351
1352                        applySelected();
1353                        $input.focus();
1354                        if (options.autosubmit) {
1355                            $form = $input.closest('form');
1356                            $form.submit();
1357                        }
1358
1359                    })
1360                    .hover(
1361                        function(e) { setSelected($(this)); },
1362                        function(e) { setSelected(null); }
1363                    );
1364
1365            } else {
1366                setVisibility(false);
1367            }
1368        }
1369
1370        function preventAutocomplete() {
1371            fetcher.cancelRequest();
1372            setVisibility(false);
1373        }
1374
1375        function destroy() {
1376            preventAutocomplete();
1377            if ($input.length) {
1378                $wrapper.remove();
1379                $input.off('.autocomplete');
1380                $input.parents('form:first').off('.autocomplete');
1381            }
1382            if (watcher) {
1383                watcher.destroy();
1384            }
1385        }
1386        
1387        function onValueChange(value, oldValue) {
1388            var data = {'fl': value};
1389        
1390            if (value.length === 0 || value.length < options.minlength) {
1391                fetcher.cancelRequest();
1392                setVisibility(false);
1393                return;
1394            }
1395        
1396            searchValue = value;
1397        
1398            if (!$template) {
1399                data.tmpl = 1;
1400            }
1401        
1402            if (typeof options.dataprocessor === 'function') {
1403                data = options.dataprocessor(data);
1404            }
1405        
1406            fetcher.sendRequest(data, false);
1407        }
1408        
1409        
1410        $(document).ready(function() {
1411
1412            $input = $(inputSelector);
1413
1414            if ($input.length) {
1415                if (options.customWrapper === null) {
1416                    $wrapper = $('<div class="b-autocomplete"></div>');
1417                } else {
1418                    $wrapper = $(options.customWrapper);
1419                    $wrapperContainer = $wrapper.find(CONTAINER_SELECTOR);
1420                }
1421                
1422                if (options.zindex !== null) {
1423                    $wrapper.css('zIndex', options.zindex + globalAutocompleteCounter);
1424                }
1425
1426                $wrapper.addClass(options.customClass);
1427
1428                $wrapper
1429                    .attr('id', autocompleteContainerId)
1430                    .hide()
1431                    .appendTo('body');
1432                $wrapper.trigger('appended');
1433        
1434                $input.on('keydown.autocomplete', function(event) {
1435                    if (event.keyCode === KEY_BACKSPACE) {
1436                        setTimeout(function() { $input.trigger('input'); }, 1); // IE 9 doesn't trigger 'input' event on backspace
1437                    }
1438                
1439                    if (event.keyCode === KEY_ENTER) {
1440                        fetcher.cancelRequest();
1441                    }
1442                    
1443                    if (!options.autosubmit && isSuggestionVisible() && event.keyCode === KEY_ENTER) {
1444                        applySelected();
1445                        event.preventDefault();
1446                    }
1447                });
1448
1449                $input.on('keyup.autocomplete', function(event) {
1450                    var $selected;
1451
1452                    if (!isSuggestionVisible()) {
1453                        return;
1454                    }
1455                
1456                    // suggestions navigation.
1457                    if(event.keyCode === KEY_ESCAPE) {   
1458                        restoreInput();
1459                        setVisibility(false);
1460                    }
1461                
1462                    if ($lines && (event.keyCode === KEY_UP || event.keyCode === KEY_DOWN)) { 
1463                        // select next element
1464                        $selected = getSelected();
1465                        if ($selected.length) {
1466                            setSelected((event.keyCode === KEY_UP) ? $selected.prev() : $selected.next());
1467                        } else {
1468                            setSelected((event.keyCode === KEY_UP) ? $lines.last() : $lines.first());
1469                        }
1470
1471                        watcher.stopWatch(); /* IE 7/8 fires propertychange */
1472                        // if no selection. restore user's input
1473                        if (getSelected().length) {
1474                            updateInputWithSelected(false);
1475                        } else {
1476                            restoreInput();
1477                        }
1478                        watcher.startWatch();
1479                    }
1480                });
1481
1482                $input.parents('form:first').on('submit.autocomplete', function(event) {
1483                    if (isSuggestionVisible()) {
1484                        applySelected();
1485                    }
1486                });
1487                
1488                $input.on('blur.autocomplete', function(event) {
1489                    if (isSuggestionVisible()) {
1490                        setTimeout(function() {
1491                            setVisibility(false);
1492                        }, ON_BLUR_HIDE_TIMEOUT);   // give some time to process click on suggestion element
1493                    }
1494                });
1495
1496                watcher = new wgsdk.InputWatcher($input, null, onValueChange, options.postprocessor);
1497                if (typeof(url) === 'function') {
1498                    fetcher = new wgsdk.NoAjaxFetcher(url, null, onRequestComplete);
1499                } else {
1500                    fetcher = new wgsdk.AjaxFetcher({'url': url}, null, onRequestComplete, 600);
1501                }
1502                
1503            }
1504        
1505        });
1506
1507        // API
1508        return {
1509            'setVisibility': setVisibility,
1510            'preventAutocomplete': preventAutocomplete,
1511            'destroy': destroy
1512        };
1513    };
1514    
1515    return module;
1516
1517})(jQuery, wgsdk);
1518    
1519
1520wgsdk.clearer = (function($) {
1521    'use strict';
1522
1523    var module = function(inputSelector, clrSelector, options) {
1524        var $instance = $(clrSelector),
1525            $input = $(inputSelector),
1526            defaults = {
1527                clearCallback: undefined
1528            };
1529            
1530        options = $.extend({}, defaults, options);
1531
1532        if (!($input.length && $instance.length)) {
1533            return;
1534        }
1535
1536        function show() {
1537            $instance.css('display', 'block');
1538        }
1539
1540        function hide() {
1541            $instance.css('display', 'none');
1542        }
1543
1544        function update() {
1545            if ($input.val() !== '') {
1546                show();
1547            } else {
1548                hide();
1549            }
1550        }
1551
1552        $input.keyup(update);
1553
1554        $instance.click(function(e) {
1555            $instance.css('display', 'none');
1556            if (typeof options.clearCallback === 'function') {
1557                options.clearCallback(e);
1558            }
1559        });
1560
1561        // API
1562        return {
1563            'update': update,
1564            'hide': hide,
1565            'show': show
1566        };
1567    };
1568
1569    return module;
1570
1571})(jQuery);
1572
1573
1574$(document).ready( function() {
1575    wgsdk.forms.init_countables();
1576});

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.