Подождите, пока страница загрузится при переходе обратно в jquery mobile

У меня есть одностраничное веб-приложение, созданное с помощью jQuery Mobile. После того, как пользователь выполнит определенное действие, я хочу программно вернуть его на страницу меню, что включает в себя возвращение в историю и последующее выполнение некоторых действий с элементами страницы меню.

Просто делать

window.history.go(-1); //or $.mobile.back();
doSomethingWith(menuPageElement);

не работает, потому что действие возврата является асинхронным, т.е. мне нужен способ ожидания загрузки страницы перед вызовом doSomethingWith().

В итоге я использовал window.setTimeout(), но мне интересно, нет ли более простого способа (другого шаблона?) Сделать это в jQM. Еще один вариант — слушать события загрузки страницы, но я считаю его хуже с точки зрения организации кода.

(РЕДАКТИРОВАТЬ: оказывается, что собственные промисы js не поддерживаются в Mobile Safari, их нужно будет заменить сторонней библиотекой)

//promisify window.history.go()
function go(steps, targetElement) {
    return new Promise(function(resolve, reject) {
        window.history.go(steps);
        waitUntilElementVisible(targetElement);

        //wait until element is visible on page (i.e. page has loaded)
        //resolve on success, reject on timeout
        function waitUntilElementVisible(element, timeSpentWaiting) {
            var nextCheckIn = 200;
            var waitingTimeout = 1000;

            timeSpentWaiting = typeof timeSpentWaiting !== 'undefined' ? timeSpentWaiting : 0;

            if ($(element).is(":visible")) {
                resolve();
            } else if (timeSpentWaiting >= waitingTimeout) {
                reject();
            } else { //wait for nextCheckIn ms
                timeSpentWaiting += nextCheckIn;
                window.setTimeout(function() {
                    waitUntilElementVisible(element, timeSpentWaiting);
                }, nextCheckIn);
            }
        }
    });
}

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

go(-2, menuPageElement).then(function() { 
    doSomethingWith(menuPageElement);
}, function() {
    handleError();
});

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


person margold    schedule 18.08.2014    source источник


Ответы (1)


Обновлять

Чтобы определить, был ли пользователь направлен со страницы X, вы можете передать настраиваемый параметр в функцию изменения контейнера страницы. В pagecontainerchange извлеките этот параметр и в соответствии с ним привяжите pagecontainershow один раз только к doSomething().

$(document).on("pagecreate", "#fooPage", function () {
    $("#bar").on("click", function () {
        /* determine whether the user was directed */
        $(document).one("pagecontainerbeforechange", function (e, data) {
            if ($.type(data.toPage) == "string" && $.type(data.options) == "object" && data.options.stuff == "redirect") {
                /* true? bind pagecontainershow one time */
                $(document).one("pagecontainershow", function (e, ui) {
                    /* do something */
                    $(".ui-content", ui.toPage).append("<p>redirected</p>");
                });
            }
        });
        /* redirect user programmatically */
        $.mobile.pageContainer.pagecontainer("change", "#menuPage", {
            stuff: "redirect"
        });
    });
});

Демо


Вам нужно полагаться на события pageContainer, вы можете выбрать любое из этих событий, pagecontainershow, pagecontainerbeforeshow, pagecontainerhide и pagecontainerbeforehide.

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

Вторые два события генерируются во время скрытия предыдущей страницы, но перед первыми двумя событиями.

Все события несут объект ui с двумя разными свойствами ui.prevPage и ui.toPage. Используйте эти свойства, чтобы определить, когда запускать код.

Обратите внимание, что приведенный ниже код работает только с jQM 1.4.3.

$(document).on("pagecontainershow", function (e, ui) {
   var previous = $(ui.prevPage),
       next = $(ui.toPage);

   if (previous[0].id == "pageX" && next[0].id == "menuPage") {
       /* do something */
   }
});
person Omar    schedule 18.08.2014
comment
Как я писал в вопросе, я думаю, что использование событий сделает код более нечитаемым, + вам также нужно будет различать приведенный выше вариант использования и вариант использования, когда пользователь переходит от pageX к menuPage. - person margold; 18.08.2014
comment
@marrgold эти события постоянно генерируются в pagecontainer, независимо от того, перемещаетесь ли вы программно или вручную. - person Omar; 18.08.2014
comment
да, следовательно, необходимо различать два случая, поскольку в случае, когда пользователь перешел туда вручную, вы не хотите doSomething() - person margold; 19.08.2014
comment
@marrgold вы можете передать параметр в функцию изменения страницы, чтобы определить, был ли пользователь направлен системой slow/21174455#21174455" title="хранение переменной в локальном хранилище происходит слишком медленно">stackoverflow.com/questions/21139572/ - person Omar; 19.08.2014