Javascript-форум (https://javascript.ru/forum/)
-   jQuery (https://javascript.ru/forum/jquery/)
-   -   Помогите использовать функцию onscroll (https://javascript.ru/forum/jquery/78978-pomogite-ispolzovat-funkciyu-onscroll.html)

ozoro 01.12.2019 09:03

Помогите использовать функцию onscroll
 
Есть кнопка открытия модального окна ближе к низу страницы.
При закрытии модального окна происходит скролл наверх страницы.

Необходимо чтобы при закрытии модального окна не скролило наверх страницы, а контент оставался в текущем положении.

Сделал вот так:
var scl = $(window).scrollTop();
var scrtop = "-"+scl+"px";

//открытие модального окна
$(document).on("shown.bs.modal", ".modal", function () {
// Когда модальное окно открыто, фиксируем элемент body
$("body").css("position","fixed").css("top", scrtop);
});

// закрытие модального окна
$(document).on("hidden.bs.modal", ".modal", function () {
// Когда модальное окно скрыто...
$("body").removeAttr("style").removeAttr("class");
$(window).scrollTop(scl);
});


НО работает только если прокрутить до кнопки вниз и обновить страницу.
Динамически определить скролл не хватает знаний.

Конечно есть функция, которая динамически определяет скрол, но как ее прикрутить к вышеуказанному коду или как-то сделать по другому, ума не приложу.

Вот эта функция:
$(window).on("scroll", function() {
$(window).scrollTop();
});



Заранее, благодарю!

laimas 01.12.2019 09:26

Вместо $("body").css("position","fixed").css("top", scrtop);

$("html").css("overflow","hidden");

и

$("html").css("overflow","auto");

соответственно. А фиксировать окно.

рони 01.12.2019 09:39

Цитата:

Сообщение от ozoro
При закрытии модального окна происходит скролл наверх страницы.

type="button" в кнопке закрыть есть?

ozoro 01.12.2019 09:46

laimas,

Сделал как сказал
//открытие модального окна
$(document).on("shown.bs.modal", ".modal", function () {
$("html").css("overflow","hidden");
});

// закрытие модального окна
$(document).on("hidden.bs.modal", ".modal", function () {
$("html").css("overflow","auto");
});


Но это не помогает, при открытии страница на месте, а при закрытии окна все равно скролится в самый верх.

laimas 01.12.2019 09:50

Кто скролится, окно? Если оно вызывается в любом месте страницы, то оно фиксируется либо к верхнему краю, либо по центру вертикали. А overflow hidden/auto, это запрет скролла документа, чтобы после закрытия окна была прежняя позиция.

ozoro 01.12.2019 09:50

Цитата:

Сообщение от рони (Сообщение 516577)
type="button" в кнопке закрыть есть?

Да, есть... но окно закрывается не только по кнопке, но и по клику за пределами окна.

laimas 01.12.2019 09:52

Да какая разница как оно закрывается, кнопкой, щелчком вне его, ESC ...

ozoro 01.12.2019 09:53

Цитата:

Сообщение от laimas (Сообщение 516580)
Кто скролится, окно? Если оно вызывается в любом месте страницы, то оно фиксируется либо к верхнему краю, либо по центру вертикали. А overflow hidden/auto, это запрет скролла документа, чтобы после закрытия окна была прежняя позиция.

В том то и дело, после закрытия окна не остается преждняя позиция, а страница скролится наверх, то есть как после ctrl+F5

ozoro 01.12.2019 10:21

Цитата:

Сообщение от laimas (Сообщение 516576)
Вместо $("body").css("position","fixed").css("top", scrtop);

$("html").css("overflow","hidden");

и

$("html").css("overflow","auto");

соответственно. А фиксировать окно.

так заработало, не знаю почему до этого не сработало;)

Подскажите еще, как сделать чтобы контент элементы не сдвигались вправо когда пропадает скролл?

laimas 01.12.2019 10:40

<html>
<head>
<meta charset="utf-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<style>
body {
    margin: 0;
}
.overlap {
    position: fixed;
    top: 0;
    width: 100%;
    height: 100%;
    background-color: #00000055;
    z-index: 100;
}
.modal {
    position: fixed;
    width: 400px;
    height: 200px;
    top: -200px;
    left: 50%;
    margin-left: -200px;
    background-color: #fff;
    border-radius: 0 0 10px 10px;
}
</style>
<script type="text/javascript">
$(function() {
    for(var i=1; i < 80; ++i) $('body').append('<p>'+i+'</p>');
    $('html').animate({
        scrollTop: 1000
    }, 500, function() {
        $("html").css("overflow","hidden");
        $('<div class="overlap"><div class="modal"><button>Close</button></div></div>')
            .appendTo('body')
            .find('.modal')
            .animate({top: 0}, 500)
            .find('button').click(function() {
                $(this).parent().animate({top: -200}, 500, function() {
                    $("html").css("overflow","auto");
                     $(this).parent().remove()
                })
            })
    });
});
</script>
</head>
<body>
</body>
</html>


На месте же документ остается? Overflow для html потому, что среди плагинов sticky есть один (какой именно теперь не помню), который отказывается работать после разрешения прокрутки если overflow определять для body.

Цитата:

Сообщение от ozoro
как сделать чтобы контент элементы не сдвигались вправо когда пропадает скролл?

Никак, это увеличивается размер клиентской области, за счет размера полосы прокрутки. Добавить телу отступ справа? Ну так будет пустая область.

ozoro 01.12.2019 10:44

laimas,
рони,

Цитата:

Сообщение от ozoro (Сообщение 516584)
так заработало, не знаю почему до этого не сработало;)

Подскажите еще, как сделать чтобы контент элементы не сдвигались вправо когда пропадает скролл?

Подскажите, как динамически вычислять сдвиг контента, чтобы добавить в html для компенсации места, занимаемого скроллом?
$("html").css("overflow","hidden").css("padding-right","17px");


Ведь не у всех браузеров полоса прокрутки = 17px, особенно у мобильных.

ozoro 01.12.2019 10:55

Цитата:

Сообщение от laimas (Сообщение 516585)
[HTML run]<html>
Никак, это увеличивается размер клиентской области, за счет размера полосы прокрутки. Добавить телу отступ справа? Ну так будет пустая область.

А здесь по какой причине не остается у тела отступ справа при открытии окна?
https://getbootstrap.ru/docs/v4-alpha/components/modal/

laimas 01.12.2019 10:56

Проще вернуться к восстановлению позиции без запрещения прокрутки, почему у вас не работает не понять, но все должно.

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<style>
body {
    margin: 0;
}
.overlap {
    position: fixed;
    top: 0;
    width: 100%;
    height: 100%;
    background-color: #00000055;
    z-index: 100;
}
.modal {
    position: fixed;
    width: 400px;
    height: 200px;
    top: -200px;
    left: 50%;
    margin-left: -200px;
    background-color: #fff;
    border-radius: 0 0 10px 10px;
}
</style>
<script type="text/javascript">
$(function() {
    for(var i=1; i < 80; ++i) $('body').append('<p>'+i+'</p>');
    $('html').animate({
        scrollTop: 500
    }, 500, function() {
        $('<div class="overlap"><div class="modal"><button>Close</button></div></div>')
            .appendTo('body')
            .find('.modal')
            .animate({top: 0}, 500, function() {
                $(this).data({top: $(window).scrollTop()}) //запомнить позицию прокрутки
            })
            .find('button').click(function() {
                $(this).parent().animate({top: -200}, 500, function() {
                     $(window).scrollTop($(this).data('top')) //восстановить позицию прокрутки  
                    $(this).parent().remove()
                })
            })
    });
});
</script>
</head>
<body>
</body>
</html>

laimas 01.12.2019 10:57

Цитата:

Сообщение от ozoro
А здесь по какой причине не остается у тела отступ справа при открытии окна?

По той, что есть полоса прокрутки.

ozoro 01.12.2019 11:12

Цитата:

Сообщение от laimas (Сообщение 516588)
Проще вернуться к восстановлению позиции без запрещения прокрутки, почему у вас не работает не понять, но все должно.

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<style>
body {
    margin: 0;
}
.overlap {
    position: fixed;
    top: 0;
    width: 100%;
    height: 100%;
    background-color: #00000055;
    z-index: 100;
}
.modal {
    position: fixed;
    width: 400px;
    height: 200px;
    top: -200px;
    left: 50%;
    margin-left: -200px;
    background-color: #fff;
    border-radius: 0 0 10px 10px;
}
</style>
<script type="text/javascript">
$(function() {
    for(var i=1; i < 80; ++i) $('body').append('<p>'+i+'</p>');
    $('html').animate({
        scrollTop: 500
    }, 500, function() {
        $('<div class="overlap"><div class="modal"><button>Close</button></div></div>')
            .appendTo('body')
            .find('.modal')
            .animate({top: 0}, 500, function() {
                $(this).data({top: $(window).scrollTop()}) //запомнить позицию прокрутки
            })
            .find('button').click(function() {
                $(this).parent().animate({top: -200}, 500, function() {
                     $(window).scrollTop($(this).data('top')) //восстановить позицию прокрутки  
                    $(this).parent().remove()
                })
            })
    });
});
</script>
</head>
<body>
</body>
</html>

Как это применить в моем случае?

Цитата:

Сообщение от laimas (Сообщение 516589)
По той, что есть полоса прокрутки.

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

laimas 01.12.2019 11:29

Цитата:

Сообщение от ozoro
При открытии маленьких окон полоса прокрутки скрывается, но контент не сдвигается и пустого места не образуется.

Уверены? Откройте страницу в отладчике и смотрите body. При появлении окна скрывается прокрутка и добавляется отступ справа. Не видно пустого места потому, что на этой странице справа ничего нет, а была бы к примеру шапка страницы, было бы заметно, хотя конечно, если ее позиционировать иначе, перекрывая тело документа....

laimas 01.12.2019 11:30

Цитата:

Сообщение от ozoro
Как это применить в моем случае?

Это тоже самое, что вы и делали, которое почему то у вас не работает, а вот почему, сказать не могу.

ozoro 01.12.2019 12:00

Цитата:

Сообщение от laimas (Сообщение 516596)
Это тоже самое, что вы и делали, которое почему то у вас не работает, а вот почему, сказать не могу.

А как оно будет работать, если таким образом нельзя это определить, на сколько px вниз проскроллена страница. Только если проскролить вниз и нажать F5, тогда определяет.

Проверь сам:
var scl = $(window).scrollTop();
console.log(scl);


при самом скроле значение не меняются

Поэтому и просил функцию помочь применить...

laimas 01.12.2019 12:10

Цитата:

Сообщение от ozoro
при самом скроле значение не меняются

В примере:

$(this).data({top: $(window).scrollTop()}) запоминает позицию прокрутки на момент открытия модалки и сохраняет ее в самой модалке. Что пользователю охота, смотреть содержимое модалки или скролить страницу, это модалке боком.

После закрытия окна, это (window).scrollTop($(this).data('top')) получает сохраненную позицию и прокручивает страницу к ней.

А вам чего хочется - раскрыть модалку, крутить скролл, запоминая его, чтобы потом получить последнюю позицию? А смысл, она и так будет на ней. И вообще в чем тогда смысл окна модального?

ozoro 01.12.2019 13:07

Цитата:

Сообщение от laimas (Сообщение 516601)
В примере:

$(this).data({top: $(window).scrollTop()}) запоминает позицию прокрутки на момент открытия модалки и сохраняет ее в самой модалке. Что пользователю охота, смотреть содержимое модалки или скролить страницу, это модалке боком.

После закрытия окна, это (window).scrollTop($(this).data('top')) получает сохраненную позицию и прокручивает страницу к ней.

А вам чего хочется - раскрыть модалку, крутить скролл, запоминая его, чтобы потом получить последнюю позицию? А смысл, она и так будет на ней. И вообще в чем тогда смысл окна модального?


Что-то не работает.


Я заморочился из-за того, что у меня при открытии модального окна не удалялась полоса прокрутки, контент прокручивался. Решил сделать чтобы не прокручивался контент страницы, а блокировался в текущем положении, при этом чтобы не смещалось тело вправо.

Нашел способ с помощью fixed. Но при этом при открытии модального окна страница стала прокручиваться в top: 0.
Поэтому, решил определять значение скролла - на сколько страница прокручена вниз и добавлять его отрицательное значение в top:.

Например, на 1200px вниз, то добавлять top:-1200px.
var scl = $(window).scrollTop();//определяем значение скрола, например, определилось 1200
var scrtop = "-"+scl+"px";//добавляем - и px, получается -1200px

//функция определения открытия модального окна
$(document).on("shown.bs.modal", ".modal", function () {
$("body").css("position","fixed").css("top", scrtop);// фиксируем body и делаем top:-1200px
});


//функция определения закрытия модального окна
$(document).on("hidden.bs.modal", ".modal", function () {
$("body").removeAttr("style").removeAttr("class"); //удаляем атрибуты style и class  
$(window).scrollTop(scl);//остаемся на той позиции, которая была при открытии окна, то есть .scrollTop(1200) 
});


Но это работает только если проскролить вниз, после нажать F5 - обновить страницу. Тогда при закрытии модального окна позиция тела остается как при открытии окна.

Вот эта функция определяет сразу при скроле значение
$(window).on("scroll", function() {
$(window).scrollTop();
});


Если бы как-то значение (результат выполнения) этой функции можно бы использовать за ее пределами, об этом я и просил по большому счету. То есть чтобы использовать результат выполнения функции в функциях открытия и закрытия модального окна.

laimas 01.12.2019 14:48

Цитата:

Сообщение от ozoro
Вот эта функция определяет сразу при скроле значение

При вызове окна это имеет значение? Вам же нужно запомнить позицию прокрутки на момент вызова окна, а после закрытия его восстановить:

Open: получить текущую позицию $(window).scrollTop(), запомнить ее (это удобно делать в .data() объекта, которым и манипулируете) и только затем $("body").css("position","fixed"). Это .css("top", scrtop) зачем?

Close: $("body").removeAttr("style") - сбросили стили, затем восстановили позицию $(window).scrollTop(объект_хранящий_ позицию.data('имя')). И не обязательно .removeAttr("style"), можно и $("body").css("position","static");

ozoro 01.12.2019 15:24

Цитата:

Сообщение от laimas (Сообщение 516605)
Это .css("top", scrtop) зачем?

Это для того, чтобы после открытия окна страница не скролилась наверх.

Если не трудно, исправь мой код, по твоему варианту, а то не пойму что куда нужно вставить.

laimas 01.12.2019 15:30

Цитата:

Сообщение от ozoro
Это для того, чтобы после открытия окна страница не скролилась наверх.

Выбросить, это ни к чему.

var scl = $(window).scrollTop();
var scrtop = "-"+scl+"px";


//открытие модального окна
$(document).on("shown.bs.modal", ".modal", function () {
    // Когда модальное окно открыто, фиксируем элемент body
    $(this).data({top: $(window).scrollTop()});
    $("body").css("position", "fixed");
});
 
// закрытие модального окна
$(document).on("hidden.bs.modal", ".modal", function () {
    // Когда модальное окно скрыто...
    $("body").css("position", "static");
    $(window).scrollTop($(this).data('top'));
});

ozoro 01.12.2019 15:47

laimas,
Так работает, но при открытии окна страница вначале скролится наверх, а при закрытии окна возвращается в то место где кнопка вызова (то есть откуда вызывалось окно, например, страница прокручена на 1200px вниз, там кнопка вызова, нажимаем и страница прокручивается вверх в шапку сайта, а при закрытии возвращается опять на 1200px вниз).

Поэтому как-то надо еще и .css("top", scrtop) прикрутить, чтобы позиция не менялась.

ozoro 01.12.2019 15:55

Вот так заработало как надо:
//открытие модального окна
$(document).on("shown.bs.modal", ".modal", function () {
    // Когда модальное окно открыто, фиксируем элемент body
    $(this).data({top: $(window).scrollTop()});
	var scl = "-"+$(window).scrollTop()+"px";
    $("body").css("position", "fixed").css("top", scl);
});
 
// закрытие модального окна
$(document).on("hidden.bs.modal", ".modal", function () {
    // Когда модальное окно скрыто...
    $("body").css("position", "static");
    $(window).scrollTop($(this).data('top'));
});


Огромная благодарность за помощь!

laimas 01.12.2019 15:57

Цитата:

Сообщение от ozoro
но при открытии окна страница вначале скролится наверх

Значит ей добавляется что-то каким-то сценарием. Открывайте отладчик и следите за тегом body. Если это добавление некоторого класса, то при открытии:

$("body").removeClass('name').css("position", "fixed");

Если при этом $(window).scrollTop() запоминает позицию уже с этой прокруткой, то попробуйте удалять этот класс в событии show.bs.modal

laimas 01.12.2019 15:59

Цитата:

Сообщение от ozoro
var scl = "-"+$(window).scrollTop()+"px";

Это все глупости, подогнать под ответ называется. Выясните причину и блокируйте ее.

ozoro 01.12.2019 16:06

В body добавляется класс modal-open и больше ничего.
Правила этого класса
.modal-open {
    overflow: hidden;    
}

Это ведь не может влиять на то, что при открытии скролится вверх?

laimas 01.12.2019 16:11

Цитата:

Сообщение от ozoro
Это ведь не может влиять на то, что при открытии скролится вверх?

Нет. Но если возникает прокрутка, то либо это работа сценария какого либо, либо css, и класс может добавляться тегу html. В общем нужно анализировать/выяснять. А событий два: show - возникает на момент показа, shown - когда полностью показано. Выяснив причину, можно устранять ее еще до полного показа окна.

PS. А собственно да, вы же пытаетесь оставить при fixed ту позицию, которая была на момент прокрутки? Все верно, запомнить ее, и на это же значение с отрицательным знаком вверх. Это я запутал. )

ozoro 01.12.2019 16:22

Буду икать причину...

Еще раз благодарю за помощь.

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


Я тебе оставлял отзыв, но после уже многим оставил... это что, глюк (баг) какой-то?

ozoro 01.12.2019 16:24

Цитата:

Сообщение от laimas (Сообщение 516618)
PS. А собственно да, вы же пытаетесь оставить при fixed ту позицию, которая была на момент прокрутки? Все верно, запомнить ее, и на это же значение с отрицательным знаком вверх. Это я запутал. )

Все, понял, значит я в правильном направлении мыслил:write: :dance:

laimas 01.12.2019 16:42

Цитата:

Сообщение от ozoro
это что, глюк (баг) какой-то?

Не знаю, но я не страдаю.

Что касаемо причины, то все верно, это я "на несколько фронтов в сети", и сам уже не помню о чем речь в каком посте, и тебя запутал. Fixed, нужно указать позицию, по умолчанию 0, поэтому и прокрутка. Ты же хочешь при открытии окна остаться на той же позиции, так что все верно $(window).scrollTop() - это запомнить, а -$(window).scrollTop(), это сместить до позиции. То есть вот так записать:

$(document).on("shown.bs.modal", ".modal", function () {
    // Когда модальное окно открыто, фиксируем элемент body
    var top = $(window).scrollTop();
    $(this).data({top: top});
    $("body").css({position: "fixed", top: -top});
});

ozoro 03.12.2019 02:25

Цитата:

Сообщение от laimas (Сообщение 516621)
Что касаемо причины, то все верно, это я "на несколько фронтов в сети", и сам уже не помню о чем речь в каком посте

Бывает:)

Еще раз благодарю! Сделал по последнему твоему варианту.


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