Прерываются запросы при использовании PJAX

Вопросы по вёрстке и JavaScript
Ответить
Apron63
Сообщения: 13
Зарегистрирован: 2015.02.26, 06:25

Прерываются запросы при использовании PJAX

Сообщение Apron63 »

Доброго времени суток!
Возможно вопрос имеет больше отношения к Yii чем к JS но поместил его сюда.
Итак, я беру "коробочные" формы регистрации и авторизации, дорабатываю немного под свои нужды (в качестве логина используется e-mail). Теперь я хочу сделать модальное окно. Добавил соответствующий код модали, а в формы "обернул" в PJAX. И все бы хорошо, но вот что заметил - при первом вызове, например, окна авторизации все замечательно - нажали кнопу входа, сформировался запрос к контроллеру. Но если зайти в форму авторизации, ввести неверные данные (e-mail или пароль, т.е. валидатор этих данных работает на сервере), потом закрыть форму и открыть ее вновь - формируется уже 2 запроса к серверу - один со статусом Aborted, второй нормальный. Мало того, если повторить действия, то оборванных запросов станет три! То есть где то есть некий глобальный "счетчик", который обнуляется с перезагрузкой страницы.
Сразу отмечу, тему гуглил, но нарыл лишь про настройки таймаута. Поигрался, не помогло.
Почему вопрос важен - из окна авторизации у меня есть переход на окно с запросом смены пароля (так же как "в коробке"). Вот в этом окне "счетчик" уже "начинает отсчет", на сервер идет минимум два запроса, и сервер успевает их обработать оба, а результате приходит два письма со ссылкой на смену пароля.
Вопрос скорее по JS, так как вероятно есть "хитрые настройки".
Apron63
Сообщения: 13
Зарегистрирован: 2015.02.26, 06:25

Re: Прерываются запросы при использовании PJAX

Сообщение Apron63 »

Код: Выделить всё

<?php

use yii\helpers\Html;
use yii\bootstrap\ActiveForm;
use yii\captcha\Captcha;
use yii\widgets\Pjax;

Pjax::begin(['enablePushState' => false]);

$form = ActiveForm::begin([
    'enableClientValidation'=>'true',
    'options' => ['data-pjax' => 0,],
    'layout' => 'horizontal',
    'fieldConfig' => [
        'template' => "{label}\n{beginWrapper}\n{input}\n{hint}\n{error}\n{endWrapper}",
        'horizontalCssClasses' => [
            'label' => 'col-sm-3',
            'offset' => 'col-sm-offset-4',
            'wrapper' => 'col-sm-8',
            'error' => '',
            'hint' => '',
        ],
    ],
]);

echo $form->field($model, 'email')->input('email');
echo $form->field($model, 'password')->passwordInput();
echo $form->field($model, 'rememberMe')->checkbox();
?>

<div style="color:#999;margin:1em 0">
    <?= Html::button('Восстановить пароль', ['class' => 'btn btn-link', 
                                             'id' => 'buttonResetPassword', 
                                             'data-pjax'=> 1]) ?>
</div>

<?php if($model->captchaNeeded):?>
    <script> $("#my-modal").modal("hide"); status = "LoginCapcha"; </script>
<?php endif;?>

<?php
echo Html::beginTag('div', ['class' => 'form-row buttons']);
echo Html::submitButton('Войти', ['class' => 'btn btn-primary', 
                                  'name' => 'next', 
                                  'value' => 'next', 
                                  'data-pjax'=> 1]);
echo Html::endTag('div');
?>


<div style="color:#999;margin:1em 0">
    Еще не зарегистрировались? <?= Html::button('Зарегистрироваться', ['class' => 'btn btn-link', 
                                                                       'id' => 'buttonSignup', 
                                                                       'data-pjax'=> 1]);?>
</div>

<?php ActiveForm::end();?>

<script>

$("#buttonSignup").click(function(e){
    e.preventDefault();
    e.stopPropagation();
    $("#my-modal").modal("hide");
    status = "Signup";
    return false;
});

$("#buttonResetPassword").click(function(e){
    e.preventDefault();
    e.stopPropagation();
    $("#my-modal").modal("hide");
    status = "resetPassword";
    return false;
});

</script>

<?php $this->registerJs('$(document).on("pjax:timeout", function(event) {event.preventDefault()});');?>
<?php Pjax::end(); ?>
Это код формы

Код: Выделить всё

$("#my-modal").on("hidden.bs.modal",function(e){
    e.preventDefault();
    e.stopPropagation();
    $("#my-modal.modal-body").html("");
    switch (status){
    case "Signup":
        $("#my-header").empty().append("Регистрация");
        $("#my-modal").find("#modal-content")
        .load("site/registration", function( response, status, xhr ) {
            if ( status == "error" ) {
                $("#myError").html(xhr.status + " " + xhr.statusText);
            }
            $("#my-modal").modal("show");
        });
        break;
    case "Login":
        $("#my-header").empty().append("Вход в личный кабинет");
        $("#my-modal").find("#modal-content")
            .load("site/login", function( response, status, xhr ) {
             if ( status == "error" ) {
                 $("#myError").html(xhr.status + " " + xhr.statusText);
             }
             $("#my-modal").modal("show");
        });
        break;
    case "LoginCapcha":
        $("#my-header").empty().append("Вход в личный кабинет");
        $("#my-modal").find("#modal-content")
            .load("site/login1", function( response, status, xhr ) {
             if ( status == "error" ) {
                 $("#myError").html(xhr.status + " " + xhr.statusText);
             }
             $("#my-modal").modal("show");
        });
        break;
    case "ChangePass":
        $("#my-header").empty().append("Замена временного пароля");
        $("#my-modal").find("#modal-content")
            .load("site/login2", function( response, status, xhr ) {
             if ( status == "error" ) {
                 $("#myError").html(xhr.status + " " + xhr.statusText);
             }
             $("#my-modal").modal("show");
        });
        break;
    case "resetPassword":
        $("#my-header").empty().append("Восстановление пароля");
        $("#my-modal").find("#modal-content")
            .load("site/request-password-reset", function( response, status, xhr ) {
             if ( status == "error" ) {
                 $("#myError").html(xhr.status + " " + xhr.statusText);
             }
             $("#my-modal").modal("show");
        });
        break;
    }             
    status = "";
    return false;
}); 
Это JS код для управления модальным окном
Onotole
Сообщения: 1808
Зарегистрирован: 2012.12.24, 12:49

Re: Прерываются запросы при использовании PJAX

Сообщение Onotole »

Javascript вынесите из пиджака. И для джаваскрипта используйте $this->registerJs()
Apron63
Сообщения: 13
Зарегистрирован: 2015.02.26, 06:25

Re: Прерываются запросы при использовании PJAX

Сообщение Apron63 »

Выполнил, но, к сожалению, не помогло. Самой полезной информацией по этому поводу считаю вот это: https://github.com/defunkt/jquery-pjax/issues/46. Вычитал, что могут быть проблемы, если объявлены собственные обработчики событий. Действительно, у меня установлен обработчик события

Код: Выделить всё

$("#my-modal").on("hidden.bs.modal",function(e){ 
действительно ли из-за него получается такое поведение и если да, как можно переписать код?
Почему я воспользовался этим событием? из за того что окно анимировано, чтобы сначала обновлять контент в закрытом окне, а потом оно всплывает уже "готовое к применению". Возможно, этот вариант можно заменить?
Onotole
Сообщения: 1808
Зарегистрирован: 2012.12.24, 12:49

Re: Прерываются запросы при использовании PJAX

Сообщение Onotole »

Покажите код с изменениями
Apron63
Сообщения: 13
Зарегистрирован: 2015.02.26, 06:25

Re: Прерываются запросы при использовании PJAX

Сообщение Apron63 »

в файл site/index.php добавил

Код: Выделить всё

<?php $this->registerJsFile(Url::to('@web') . '/js/login.js', ['depends' => [JqueryAsset::className()]]);?>
скрипты из вьюшки убрал
Apron63
Сообщения: 13
Зарегистрирован: 2015.02.26, 06:25

Re: Прерываются запросы при использовании PJAX

Сообщение Apron63 »

После ковыряния непосредственно в пиджаке отвечу сам же себе

Код: Выделить всё

Pjax::begin(['enablePushState' => false, 'clientOptions' => ['skipOuterContainers' => true]]); 
в последней версии 2.0.6 добавлена опция skipOuterContainers
именно она управляет вложенными контейнерами.
Пока что полет нормальный :D
Спасибо Onotole за помощь!
Ответить