001/**
002 * Copyright (c) 2015-2022, Michael Yang 杨福海 (fuhai999@gmail.com).
003 * <p>
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 * <p>
008 * http://www.apache.org/licenses/LICENSE-2.0
009 * <p>
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package io.jboot.web.directive.base;
017
018import com.jfinal.plugin.activerecord.Page;
019import com.jfinal.template.Env;
020import com.jfinal.template.io.Writer;
021import com.jfinal.template.stat.Scope;
022import io.jboot.utils.StrUtil;
023
024import java.util.ArrayList;
025import java.util.List;
026
027
028public abstract class PaginateDirectiveBase extends JbootDirectiveBase {
029
030    private static final String PREVIOUS_CLASS_KEY = "previousClass";
031    private static final String NEXT_CLASS_KEY = "nextClass";
032    private static final String ACTIVE_CLASS_KEY = "activeClass";
033    private static final String DISABLED_CLASS_KEY = "disabledClass";
034    private static final String ONLY_SHOW_PREVIOUS_AND_NEXT_KEY = "onlyShowPreviousAndNext";
035
036    private static final String PREVIOUS_TEXT_KEY = "previousText";
037    private static final String NEXT_TEXT_KEY = "nextText";
038    private static final String PAGE_ITEMS_NAME_KEY = "pageItemsName";
039    private static final String PAGE_DATA_KEY = "pageData";
040    private static final String SIBLINGS_ITEM_COUNT_KEY = "siblingsItemCount";
041    private static final String START_ITEM_COUNT_KEY = "startItemCount";
042    private static final String END_ITEM_COUNT_KEY = "endItemCount";
043
044
045    private static final String DEFAULT_PREVIOUS_CLASS = "previous";
046    private static final String DEFAULT_NEXT_CLASS = "next";
047    private static final String DEFAULT_ACTIVE_CLASS = "active";
048    private static final String DEFAULT_DISABLED_CLASS = "disabled";
049
050    private static final String DEFAULT_PREVIOUS_TEXT = "上一页";
051    private static final String DEFAULT_NEXT_TEXT = "下一页";
052    private static final String DEFAULT_PAGE_ITEMS_NAME = "pages";
053    private static final String DEFAULT_PAGE_DATA_KEY = "pageData";
054
055    private static final String JAVASCRIPT_TEXT = "javascript:;";
056    private static final String ELLIPSIS_TEXT = "...";
057
058    private static final int SIBLINGS_ITEM_COUNT = 2;
059    private static final int START_ITEM_COUNT = 1;
060    private static final int END_ITEM_COUNT = 1;
061
062
063    @Override
064    public void onRender(Env env, Scope scope, Writer writer) {
065
066        String previousClass = getPara(PREVIOUS_CLASS_KEY, scope, DEFAULT_PREVIOUS_CLASS);
067        String nextClass = getPara(NEXT_CLASS_KEY, scope, DEFAULT_NEXT_CLASS);
068        String activeClass = getPara(ACTIVE_CLASS_KEY, scope, DEFAULT_ACTIVE_CLASS);
069        String disabledClass = getPara(DISABLED_CLASS_KEY, scope, DEFAULT_DISABLED_CLASS);
070        boolean onlyShowPreviousAndNext = getParaToBool(ONLY_SHOW_PREVIOUS_AND_NEXT_KEY, scope, false);
071
072        String previousText = getPara(PREVIOUS_TEXT_KEY, scope, DEFAULT_PREVIOUS_TEXT);
073        String nextText = getPara(NEXT_TEXT_KEY, scope, DEFAULT_NEXT_TEXT);
074        String pageItemsName = getPara(PAGE_ITEMS_NAME_KEY, scope, DEFAULT_PAGE_ITEMS_NAME);
075
076        String pageDataKey = getPara(PAGE_DATA_KEY, scope, DEFAULT_PAGE_DATA_KEY);
077
078        int siblingsItemCount = getParaToInt(SIBLINGS_ITEM_COUNT_KEY, scope, SIBLINGS_ITEM_COUNT);
079        if (siblingsItemCount < 1) {
080            siblingsItemCount = SIBLINGS_ITEM_COUNT;
081        }
082
083
084        int startItemCount = getParaToInt(START_ITEM_COUNT_KEY, scope, START_ITEM_COUNT);
085        if (startItemCount < 1) {
086            startItemCount = START_ITEM_COUNT;
087        }
088
089
090        int endItemCount = getParaToInt(END_ITEM_COUNT_KEY, scope, END_ITEM_COUNT);
091        if (endItemCount < 1) {
092            endItemCount = END_ITEM_COUNT;
093        }
094
095
096        Page<?> page = getPage(env, scope, writer);
097
098        int currentPageNumber = page == null ? 1 : page.getPageNumber();
099        int totalPage = page == null ? 0 : page.getTotalPage();
100
101        if (totalPage == 0) {
102            return;
103        }
104
105        if (currentPageNumber > totalPage) {
106            currentPageNumber = totalPage;
107        }
108
109        int startPage = currentPageNumber - siblingsItemCount;
110        if (startPage < 1) {
111            startPage = 1;
112        }
113
114        int endPage = currentPageNumber + siblingsItemCount;
115        if (endPage > totalPage) {
116            endPage = totalPage;
117        }
118
119        List<PaginateItem> pages = new ArrayList<PaginateItem>();
120        if (currentPageNumber == 1) {
121            pages.add(new PaginateDirectiveBase.PaginateItem(previousClass + StrUtil.SPACE + disabledClass, JAVASCRIPT_TEXT, previousText));
122        } else {
123            pages.add(new PaginateDirectiveBase.PaginateItem(previousClass, getUrl(currentPageNumber - 1, env, scope, writer), previousText));
124        }
125
126        if (!onlyShowPreviousAndNext) {
127
128            //开始页码
129            for (int i = 1; i <= startItemCount; i++) {
130                if (i < currentPageNumber - siblingsItemCount) {
131                    pages.add(new PaginateDirectiveBase.PaginateItem(StrUtil.EMPTY, getUrl(i, env, scope, writer), i));
132                }
133            }
134
135            //省略号
136            if (currentPageNumber > startItemCount + siblingsItemCount + 1) {
137                pages.add(new PaginateDirectiveBase.PaginateItem(disabledClass, JAVASCRIPT_TEXT, ELLIPSIS_TEXT));
138            }
139
140
141            //中间页码
142            for (int i = startPage; i <= endPage; i++) {
143                if (currentPageNumber == i) {
144                    pages.add(new PaginateDirectiveBase.PaginateItem(activeClass, JAVASCRIPT_TEXT, i));
145                } else {
146                    pages.add(new PaginateDirectiveBase.PaginateItem(StrUtil.EMPTY, getUrl(i, env, scope, writer), i));
147                }
148            }
149
150
151            //省略号
152            if (currentPageNumber < totalPage - siblingsItemCount - endItemCount) {
153                pages.add(new PaginateDirectiveBase.PaginateItem(disabledClass, JAVASCRIPT_TEXT, ELLIPSIS_TEXT));
154            }
155
156            //后边页码
157            for (int i = (endItemCount - 1); i >= 0; i--) {
158                if (i < totalPage - (currentPageNumber + siblingsItemCount)) {
159                    pages.add(new PaginateDirectiveBase.PaginateItem(StrUtil.EMPTY, getUrl(totalPage - i, env, scope, writer), totalPage - i));
160                }
161
162            }
163        }
164
165
166        if (currentPageNumber == totalPage) {
167            pages.add(new PaginateDirectiveBase.PaginateItem(nextClass + StrUtil.SPACE + disabledClass, JAVASCRIPT_TEXT, nextText));
168        } else {
169            pages.add(new PaginateDirectiveBase.PaginateItem(nextClass, getUrl(currentPageNumber + 1, env, scope, writer), nextText));
170        }
171
172        scope.setLocal(pageItemsName, pages);
173        scope.setLocal(pageDataKey, page);
174
175        renderBody(env, scope, writer);
176    }
177
178
179    protected abstract String getUrl(int pageNumber, Env env, Scope scope, Writer writer);
180
181    protected abstract Page<?> getPage(Env env, Scope scope, Writer writer);
182
183
184    @Override
185    public boolean hasEnd() {
186        return true;
187    }
188
189
190    public static class PaginateItem {
191        private String style;
192        private String url;
193        private String text;
194
195        public PaginateItem(String style, String url, Object text) {
196            this.style = style;
197            this.url = url;
198            this.text = String.valueOf(text);
199        }
200
201        public String getStyle() {
202            return style;
203        }
204
205        public void setStyle(String style) {
206            this.style = style;
207        }
208
209        public String getUrl() {
210            return url;
211        }
212
213        public void setUrl(String url) {
214            this.url = url;
215        }
216
217        public String getText() {
218            return text;
219        }
220
221        public void setText(String text) {
222            this.text = text;
223        }
224    }
225}