JSF2 + AJAX: сохранить положение полосы прокрутки, обычный мохарра - PullRequest
1 голос
/ 08 марта 2012

У меня есть более сложное веб-приложение в JSF2 (+ EJB3.1 + JPA2 на glassfish 3.1), которое использует только стандартные (mojarra) JSF-компоненты и широко использует вложенные композиты и вызовы ajax.

Я хочу, чтобы все мои полосы прокрутки сохраняли и восстанавливали свое положение всякий раз, когда происходит ajax-вызов.

Я пробовал разные подходы, но ни один не кажется мне действительно хорошим, поэтому мне нужны некоторые подсказки, в какую сторону идти:

1) JavaScript:

Добавьте JavaScript, который считывает все позиции полосы прокрутки, либо когда происходит прокрутка (element.onScroll должен быть установлен javascript, потому что этот атрибут недоступен в XHTML4), либо когда ajax-request происходит (jsf.ajax.addOnEvent (savePositions)).Сохраняйте позиции полос прокрутки либо в скрытых полях ввода, либо в cookie.Восстановите их при возникновении ajax-ответа (jsf.ajax.addOnEvent (restorePositions)).

Противоположности, если файлы cookie не используются:

-Позиция прокрутки должна сохраняться в скрытом поле ввода передпроисходит ajax-запрос, поэтому здесь необходимо использовать атрибут element.onScroll.Не очень хорошо, потому что он сохраняет позиции много-много раз, хотя одного раза перед каждым ajax-запросом будет достаточно.

-Все скрытые поля ввода должны быть переданы в вызове ajax.Поскольку JSF-сайт использует несколько форм, кажется, нет способа автоматически добавить их во все ajax-вызовы.Вместо этого каждому элементу нужны скрытые поля ввода, добавленные в атрибут execute.

- Для каждого элемента с возможностью прокрутки необходимо одно скрытое поле ввода.

Против, если используются файлы cookie:

- ну, куки должны быть включены для веб-сайта.

Против общего:

-JavaScript-код должен либо знать, либо перебирать все элементы, имеющие полосы прокрутки.

-JavaScript-код должен быть выполнен снова, если компонент повторно визуализируется и ему нужен набор атрибутов onScroll.

2) JavaScript + Composite:

Поэтому я подумал о написании составного scrollStateSave,который указывает на JSF-идентификатор элемента, который имеет полосы прокрутки.Композит содержит скрытое поле ввода (или cookie) и javascript и обрабатывает все, поэтому мне просто нужно добавить один «экземпляр» композита на элемент, который имеет полосы прокрутки.Javascript использует замыкания для работы с несколькими элементами на одном сайте.

Contra:

-Javascript внутри композита не выполняется при повторном рендеринге после ajax-вызова.Для этого есть обходные пути, но мне они кажутся некрасивыми.

3) У Myfaces есть опция AUTO_SCROLL:

Как это работает точно?Работает ли он для non-myfaces-jsf-components?

4) Tomahawk предлагает по адресу: autoScroll-поведения:

Использование томагавк-замен для стандартных-mojarra-jsf2-компонентов будетдля меня нормально.Но документация по t: autoscroll говорит об атрибуте «событие», тогда как для реализации необходим атрибут «значение».Что я должен добавить в этот атрибут, чтобы t: autoScrolll работал?

1 Ответ

3 голосов
/ 09 марта 2012

ОК, я закончил решение 2, и оно работает довольно хорошо. Чтобы помочь другим разработчикам и получить подсказки, какие части моего решения могут быть лучше, я опубликую код.

Составной /WebContent/resources/components/scrollbarStateSaver.xhtml:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:composite="http://java.sun.com/jsf/composite">

<h:body>

<composite:interface>
    <composite:attribute name="for"/>
</composite:interface>

<composite:implementation>
    <h:outputScript name="scrollbars.js" library="js"/>
    <script type="text/javascript">
        saveScrollbarPos("#{cc.attrs.for}");
    </script>
</composite:implementation>
</h:body>
</html>

Javascript /WebContent/resources/js/scrollbar.js:

function saveScrollbarPos(id) {
var scrollbarid = id;

function savePos() {
    var scrollbar = document.getElementById(scrollbarid);
    document.cookie = scrollbarid+".scrolltop="+scrollbar.scrollTop+"; path=/";
}

function readCookie(name) {
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');
    for(var i=0;i < ca.length;i++) {
        var c = ca[i];
        while (c.charAt(0)==' ') c = c.substring(1,c.length);
        if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
    }
    return null;
}

function restorePos() {
    var scrollbar = document.getElementById(scrollbarid);
    scrollbar.scrollTop = readCookie(scrollbarid+".scrolltop");
}

function onStatusChange(data) {
    var status = data.status;
    if (status == "begin") {
        savePos();
    }
    else {
        restorePos();
    }
};

var scrollbar = document.getElementById(scrollbarid);
if (scrollbar != null) {
    jsf.ajax.addOnEvent(onStatusChange);
    jsf.ajax.addOnError(onStatusChange);
}
};

Маленький пример xhtml:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:c="http://java.sun.com/jsf/composite/components">

<h:head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Title</title>
</h:head>

<h:body>
    <h:form id="form">
        <div id="panel" style="overflow:auto;">
            long content with ajax-calls in it
        </div>
        <c:scrollbarStateSaver for="panel"/>

        <h:panelGroup id="panel" style="overflow:auto;">
            long content with ajax-calls in it
        </h:panelGroup>
        <c:scrollbarStateSaver for="form:panel"/>
    </h:form>
</h:body>
</html>

Конечно, составной может быть улучшен для вычисления jsf-идентификатора через # {cc.parent} и # {cc.clientId}, тогда атрибут for составного объекта может обрабатывать jsf-идентификаторы, если составной вставляется на том же уровне, что и h: panelGroup.

Скорее всего, JavaScript также можно решить лучше, но на самом деле это был мой первый javascript.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...