Javascript-форум (https://javascript.ru/forum/)
-   jQuery (https://javascript.ru/forum/jquery/)
-   -   Как заставить сработать условие, после добавление класса (https://javascript.ru/forum/jquery/78832-kak-zastavit-srabotat-uslovie-posle-dobavlenie-klassa.html)

Luther 11.11.2019 01:14

Как заставить сработать условие, после добавление класса
 
Доброго времени суток. Проблема следующая: есть блок, изначально его позиция скрыта от визуального контакта right: -300, при клике, к блоку подключается class "mobile-menu--active", после чего его позиция должна равняться right: 0, но этого не происходит. Как исправить это, условие вроде написано правильно, но мне кажется оно срабатывает один раз и дальше не проверяется, как отследить добавление нового класса и проиграть условие повторно? Не судите строго, я только учусь:)
(function($) {
    
    $.fn.mobileMenu = function(options) {

        //Defaults to extend options
        var settings = {
            side: 'right',
            width: 300,
            animationSpeed: 600
        };

        //Extend those options
        var options = $.extend(settings, options);

        return this.each(function () {

            var mob = $(this),
                mobMenu = $('.mobile-menu');

            mob.on('click touchend', function () {

                if(mobMenu.is('.mobile-menu--active')) {
                    mobMenu.removeClass('mobile-menu--active');
                    $('.hamburger--active').removeClass('hamburger--active');
                } else {
                    mobMenu.addClass('mobile-menu--active');
                    mob.addClass('hamburger--active');
                }
                return false;
            });


/////// ANIMATION
            var rightSide = 'mobile-menu--right-side',
                leftSide = 'mobile-menu--left-side',
                topSide = 'mobile-menu--top-side';

            if(options.side == "right") {
                mobMenu
                    .addClass(rightSide)
                    .css({"right": - options.width, "z-index" : 3});
                if (mobMenu.is('mobile-menu--active')) {
                    mobMenu
                        .animate({"right": 0}, options.animationSpeed);
                }
            }
        }); //each call
    }; //mobileMenu plugin

})(jQuery);

рони 11.11.2019 03:33

Luther,
строки 29 - 30 перенести в начало строки 47, если не поможет, делайте макет.

[html run]
... минимальный код страницы с вашей проблемой
[/html]

О том, как вставить в сообщение исполняемый javascript и html-код, а также о дополнительных возможностях форматирования - читайте http://javascript.ru/formatting.

Luther 11.11.2019 13:04

Перенес как вы сказали, не помогло, прикрепляю код, надеюсь все правильно сделал.

<!DOCTYPE html>
<html lang="ru">
<html>
    <head>
    <meta http-equiv="x-ua-compatible" content="IE=edge">
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
.hamburger {width: 20px;height: 20px;background-color: red}
.hamburger--active {background-color: green}

.mobile-menu {position: fixed;width: 100%;max-width: 300px;height: 100%; top: 0}
</style>
</head>
<body>
<div class="hamburger">
</div>
<div class="mobile-menu">
<h1>Заголовок блока</h1>
<p>Далеко-далеко за словесными горами в стране, гласных и согласных живут рыбные тексты. Проектах знаках переулка курсивных снова журчит жизни все приставка безопасную!</p>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script>
(function($) {
    
    $.fn.mobileMenu = function(options) {

        //Defaults to extend options
        var settings = {
            side: 'right',
            width: 300,
            animationSpeed: 600
        };

        //Extend those options
        var options = $.extend(settings, options);

        return this.each(function () {

            var mob = $(this),
                mobMenu = $('.mobile-menu');

            mob.on('click touchend', function () {

                if(mobMenu.is('.mobile-menu--active')) {
                    mobMenu.removeClass('mobile-menu--active');
                    $('.hamburger--active').removeClass('hamburger--active');
                } else {
                    mobMenu.addClass('mobile-menu--active');
                    mob.addClass('hamburger--active');
                }
                return false;
            });


/////// ANIMATION
            var rightSide = 'mobile-menu--right-side',
                leftSide = 'mobile-menu--left-side',
                topSide = 'mobile-menu--top-side';

            if(options.side == "right") {
                mobMenu
                    .addClass(rightSide)
                    .css({"right": - options.width, "z-index" : 3});
                if (mobMenu.is('mobile-menu--active')) {
                    mobMenu
                        .animate({"right": 0}, options.animationSpeed);
                }
            }
        }); //each call
    }; //mobileMenu plugin

})(jQuery);

$('.hamburger').mobileMenu({
    });
</script>
</body>
</html>

laimas 11.11.2019 14:24

Luther, у вас же не css анимация, а изменение класса, это асинхронное событие. Тогда сразу по смене класса и выполняйте анимацию:

(function($) {
    
    $.fn.mobileMenu = function(options) {

        var settings = {
            side: 'right',
            width: 300,
            animationSpeed: 600
        };

        //Extend those options
        var options = $.extend(settings, options);

        return this.each(function () {

            var mob = $(this),
                mobMenu = $('.mobile-menu');

            mob.on('click touchend', function () {

                mobMenu.toggleClass('mobile-menu--active');
                mob.toggleClass('hamburger--active');
                mobMenu.animate({right: -options.width + mob.is('.hamburger--active') * options.width}, options.animationSpeed);
                
            });
        });
    };
})(jQuery);

$('.hamburger').mobileMenu();

Luther 11.11.2019 15:27

Цитата:

Сообщение от laimas (Сообщение 515358)
Luther, у вас же не css анимация, а изменение класса, это асинхронное событие. Тогда сразу по смене класса и выполняйте анимацию:

(function($) {
    
    $.fn.mobileMenu = function(options) {

        var settings = {
            side: 'right',
            width: 300,
            animationSpeed: 600
        };

        //Extend those options
        var options = $.extend(settings, options);

        return this.each(function () {

            var mob = $(this),
                mobMenu = $('.mobile-menu');

            mob.on('click touchend', function () {

                mobMenu.toggleClass('mobile-menu--active');
                mob.toggleClass('hamburger--active');
                mobMenu.animate({right: -options.width + mob.is('.hamburger--active') * options.width}, options.animationSpeed);
                
            });
        });
    };
})(jQuery);

$('.hamburger').mobileMenu();


Оказывается это было проще, чем то что я варганил, спасибо большое за помощь, все работает

laimas 11.11.2019 15:46

Цитата:

Сообщение от Luther
все работает

Странно как-то у вас это работает (определяется). В CSS задается макс ширина, и в опциях можно передать ширину и надо полагать позицию (side: 'right'). Если так, то ведь придется менять и CSS. Если параметры меню можно определять опциями, значит в CSS нужно задать только основные, то есть до инициализации, все остальное в плагине. К тому же странно плагин определять не основному, то есть меню, а кнопке. По идее блоку нужно определять, а кнопку можно переопределять также через опции, при этом блок скрывается изначально, чтобы "не моргал" при загрузке страницы.

<!DOCTYPE html>
<html lang="ru">
<html>
    <head>
    <meta http-equiv="x-ua-compatible" content="IE=edge">
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
.hamburger-button {width: 20px;height: 20px;background-color: red}
.hamburger--active {background-color: green}

.hamburger {
    position: fixed;
    top: 20px;
    height: 100%;
    display: none; 
}
</style>
</head>
<body>
<div class="hamburger-button">
</div>
<div class="hamburger">
<h1>Заголовок блока</h1>
<p>Далеко-далеко за словесными горами в стране, гласных и согласных живут рыбные тексты. Проектах знаках переулка курсивных снова журчит жизни все приставка безопасную!</p>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script>
(function($) {
    
    $.fn.mobileMenu = function(options) {

        var settings = {
            side: 'right',
            width: 300,
            animationSpeed: 600,
            button: $('div.hamburger-button') 
        };

        var options = $.extend(settings, options), mobMenu = $(this);
        
        mobMenu.css({maxWidth: options.width, [options.side]: -options.width}).show(); //так определить в литеральном объекте свойство через переменную можно в ES6
        
        return this.each(function () {

            options.button.on('click touchend', function () {
                options.button.toggleClass('hamburger--active');
                 //и только так определить в литеральном объекте свойство через переменную можно для старичков
                var opt = {};
                opt[options.side] = -options.width + options.button.is('.hamburger--active') * options.width; 
                mobMenu.animate(opt, options.animationSpeed);
                
            });
        });

    };
})(jQuery);

$('div.hamburger').mobileMenu({side: 'left', width: 600});
</script>
</body>
</html>

рони 11.11.2019 15:57

:) потом будет вопрос как закрыть по клику вне меню.

laimas 11.11.2019 15:58

рони, :D

Luther 12.11.2019 00:51

Цитата:

Сообщение от laimas (Сообщение 515371)
Странно как-то у вас это работает (определяется). В CSS задается макс ширина, и в опциях можно передать ширину и надо полагать позицию (side: 'right'). Если так, то ведь придется менять и CSS. Если параметры меню можно определять опциями, значит в CSS нужно задать только основные, то есть до инициализации, все остальное в плагине. К тому же странно плагин определять не основному, то есть меню, а кнопке. По идее блоку нужно определять, а кнопку можно переопределять также через опции, при этом блок скрывается изначально, чтобы "не моргал" при загрузке страницы.

<!DOCTYPE html>
<html lang="ru">
<html>
    <head>
    <meta http-equiv="x-ua-compatible" content="IE=edge">
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
.hamburger-button {width: 20px;height: 20px;background-color: red}
.hamburger--active {background-color: green}

.hamburger {
    position: fixed;
    top: 20px;
    height: 100%;
    display: none; 
}
</style>
</head>
<body>
<div class="hamburger-button">
</div>
<div class="hamburger">
<h1>Заголовок блока</h1>
<p>Далеко-далеко за словесными горами в стране, гласных и согласных живут рыбные тексты. Проектах знаках переулка курсивных снова журчит жизни все приставка безопасную!</p>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script>
(function($) {
    
    $.fn.mobileMenu = function(options) {

        var settings = {
            side: 'right',
            width: 300,
            animationSpeed: 600,
            button: $('div.hamburger-button') 
        };

        var options = $.extend(settings, options), mobMenu = $(this);
        
        mobMenu.css({maxWidth: options.width, [options.side]: -options.width}).show(); //так определить в литеральном объекте свойство через переменную можно в ES6
        
        return this.each(function () {

            options.button.on('click touchend', function () {
                options.button.toggleClass('hamburger--active');
                 //и только так определить в литеральном объекте свойство через переменную можно для старичков
                var opt = {};
                opt[options.side] = -options.width + options.button.is('.hamburger--active') * options.width; 
                mobMenu.animate(opt, options.animationSpeed);
                
            });
        });

    };
})(jQuery);

$('div.hamburger').mobileMenu({side: 'left', width: 600});
</script>
</body>
</html>


Только щас увидел и чет не очень понятно, но я сделал следующем образом, если интересно:


<!DOCTYPE html>
<html lang="ru">
<html>
    <head>
    <meta http-equiv="x-ua-compatible" content="IE=edge">
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
.hamburger {width: 20px;height: 20px;background-color: red}
.hamburger--active {background-color: green}
.mobile-menu {position: fixed;height: 100%;top: 0;background-color: yellow}
.overlay {
    left: 0;
    width: 100%;
    background-color: rgba(0,0,0,.4);
    position: fixed;
    top: 0;
    height: 100%;
}

</style>
</head>
<body>
<div class="hamburger">
</div>
<div class="mobile-menu">
   <h1>Заголовок</h1>
   <p>  Далеко-далеко за словесными горами в стране, гласных и согласных живут рыбные тексты. Запятой lorem текста, первую ему ее, над родного. Если, алфавит ручеек коварный там города образ великий маленькая текстов вопроса он.</p>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script>
(function($) {
    
    $.fn.mobileMenu = function(options) {

        //Defaults to extend options
        var settings = {
            side: 'left',
            butClass: 'hamburger',
            butClassActive: 'hamburger--active',
            width: 300, // if puted (side: 'top'), there must be 100
            zIndex: 99,
            exit: true,
            overlay: true,
            animationSpeed: 400,
            // afterChange: function(){}
        };

        //Extend those options
        var options = $.extend(settings, options);

        return this.each(function () {
            var mob = $(this),
                btn = $('.' + options.butClass),
                mobMenu = $('.mobile-menu'),
                mobMenuActive = 'mobile-menu--active';

            var rightSide = 'mobile-menu--right-side',
                leftSide = 'mobile-menu--left-side',
                topSide = 'mobile-menu--top-side';


            if (options.side == 'right') {
                mobMenu.addClass(rightSide).css({right: -options.width, width: options.width, 'z-index': options.zIndex});
            }
            if (options.side == 'left') {
                mobMenu.addClass(leftSide).css({left: -options.width, width: options.width, 'z-index': options.zIndex});
            }
            if (options.side == 'top') {
                mobMenu.addClass(topSide).css({top: -options.width+'%', width: options.width+'%', 'z-index': options.zIndex});
            }

            function moveMenu() {
                if (options.side == 'right') {
                    $('.' + rightSide).animate({right: -options.width + mob.hasClass(options.butClassActive) * options.width}, options.animationSpeed);
                }
                if (options.side == 'left') {
                    $('.' + leftSide).animate({left: -options.width + mob.hasClass(options.butClassActive) * options.width}, options.animationSpeed);
                }
                if (options.side == 'top') {
                    $('.' + topSide).animate({top: -options.width + mob.hasClass(options.butClassActive) * options.width+'%'}, options.animationSpeed);
                }
            }

            if (options.overlay) {
                if (options.overlay == "false") { return false; }
                var directionalOverlayHTML = '<div class="overlay"></div>';
                mobMenu.before(directionalOverlayHTML);

                var bgOverlay = $('div.overlay');
                bgOverlay.hide().css({'z-index': options.zIndex - 1});
            }


            mob.on('click touchend', function () {
                mobMenu.stop().toggleClass(mobMenuActive);
                btn.stop().toggleClass(options.butClassActive);
                if (options.overlay) {
                    if(options.overlay == "false") { return false; }

                    if (mobMenu.hasClass(mobMenuActive)) {
                        if (btn.hasClass(options.butClassActive)) {
                            bgOverlay.fadeIn(options.animationSpeed);
                            bgOverlay.on('click touchend', function () {
                                mobMenu.stop().removeClass(mobMenuActive);
                                btn.stop().removeClass(options.butClassActive);
                                bgOverlay.fadeOut(options.animationSpeed);
                                moveMenu();
                            });
                        }
                    }
                }
                moveMenu();
            });

            if (options.exit) {

                if(options.exit == "false") { return false; }

                var directionalExitHTML = '<div class="mobile-menu-inner"><span class="mobile-menu__exit">exit</span></div>';

                mobMenu.append(directionalExitHTML);

                var exitBtn = mobMenu.children('div.mobile-menu-inner').children('span.mobile-menu__exit');

                exitBtn.on('click touchend', function () {
                    mobMenu.stop().removeClass(mobMenuActive);
                    btn.stop().removeClass(options.butClassActive);
                    moveMenu();
                    if (options.overlay) {
                        if(options.overlay == "false") { return false; }
                        bgOverlay.fadeOut(options.animationSpeed);
                    }
                });
            }

            $(document).keyup(function(esc) {
                if (esc.keyCode === 27) {
                    if (mobMenu.hasClass(mobMenuActive)) {
                        if (btn.hasClass(options.butClassActive)) {
                            mobMenu.stop().removeClass(mobMenuActive);
                            btn.stop().removeClass(options.butClassActive);
                            moveMenu();
                            if (options.overlay) {
                                if(options.overlay == "false") { return false; }
                                bgOverlay.fadeOut(options.animationSpeed);
                            }
                        }
                    }
                }
            });
        }); //each call
    }; //mobileMenu plugin

})(jQuery);

$('.hamburger').mobileMenu();
</script>
</body>
</html>
[/quote]

Да, я думаю код в некоторых местах некорректный, ну как получается, сейчас пытаюсь настроить анимацию так чтоб она не прыгала, при многократном нажатии, добавил .stop(), но работает не очень привлекательно, как можно сделать, чтоб анимация проигрывалась до конца, а не постоянно обрабатывалась? + еще надо , чтобы на .hamburger вешался класс .hamburger--active только после того как анимация проигралась, ну т.е. Зеленой, кнопка должна стать, только когда меню окончательно выдвинулось

laimas 12.11.2019 01:10

Зачем 'z-index': options.zIndex все время определять, а не единожды? Выполните для позиции лево/верх, и сразу будет виден баг. И почему вы упорно определяете кнопку управления как целевой объект для плагина вместо самого меню?

И лишнего много.


Часовой пояс GMT +3, время: 04:27.