Files
layui/src/modules/flow.js
morning-star d96ad79960 feat(i18n): 国际化支持 (#2698)
* wip(i18n): laydate 国际化

* wip(i18n): colorpicker 国际化

* wip(i18n): laypage 国际化

* fix

* update code

* wip(i18n): 修改国际化消息对象结构

* wip(i18n): update

* wip(i18n): code 国际化

* wip(i18n): dropdown 国际化

* wip(i18n): flow 国际化

* wip(i18n): form 国际化

* wip(i18n): layer 国际化

* wip(i18n): table 国际化

* wip(i18n): transfer 国际化

* wip(i18n): tree 国际化

* wip(i18n): treeTable 控制台提示统一为英文

* wip(i18n): upload 国际化

* wip(i18n): util 国际化

* wip(i18n): update code

* wip(i18n): update code

* wip(i18n): fix

* wip(i18n): 优化 $t 代码细节

* wip(i18n): 修复 laydate lang

* wip(i18n): 改进 upload i18n key

* wip(i18n): 修复打包后 laydate 和 layer 异常

* wip(i18n): 移除国际化消息中的 `lay` 命名空间

* refactor(i18n): 改进国际化支持

* wip(i18n): 修复 table text.none 切换 locale 无效问题

* style(laydate): 优化逗号格式

* chore(laydate): 优化部分提示

* chore(i18n): 优化演示中部分国际化消息

* refactor: 剔除 laydate 单独版的判断逻辑

为接下来全面支持国际化做铺垫

* wip(i18n): 为 laydate 重新添加完整国际化的支持

* i18n(laydate): 优化 lang() 方法中的逻辑

* chore(util): 删除未使用的代码

* chore(i18n): 优化注释

* docs(i18n): 新增国际化文档(beta)

note: 由于时间关系,本次提交仅为初版,该文档尚未完成

* wip(docs): 完善 i18n 文档

* fix(i18n): 修复 laypage 变量定义前使用

* wip(i18n): 转义翻译结果

* fix(i18n): 修复 table 排序 key 无效

* wip(i18n): 优化获取对象中指定路径值的性能

* wip(i18n): 删除 $t 可变长参数重载

* chore(i18n): 删除不必要的注释

* refactor(i18n): laydate 国际化方案迁移至 i18n.$t (#2745)

* wip(i18n): 改进 laydate i18nMsg key

* update code

* wip(i18n): 改进 laydate 面板中的日期格式处理

* wip(i18n): 改进 util.toDateString meridiem

遵循 CLDR day periods 标准

* update code

* wip(docs): 优化 i18n 文档示例

* docs(i18n): 优化正式文档

* docs(i18n): 优化部分文案

* docs(i18n): 优化示例

---------

Co-authored-by: 贤心 <3277200+sentsim@users.noreply.github.com>
2025-09-08 10:31:02 +08:00

206 lines
6.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* flow 流加载组件
*/
layui.define(['i18n', 'jquery'], function(exports) {
"use strict";
var $ = layui.$;
var i18n = layui.i18n;
var Flow = function(options) {};
var ELEM_MORE = 'layui-flow-more';
var ELEM_LOAD = '<i class="layui-anim layui-anim-rotate layui-anim-loop layui-icon ">&#xe63e;</i>';
// 主方法
Flow.prototype.load = function(options) {
var that = this, page = 0, lock, isOver, lazyimg, timer;
options = options || {};
var elem = $(options.elem); if(!elem[0]) return;
var scrollElem = $(options.scrollElem || document); // 滚动条所在元素
var threshold = 'mb' in options ? options.mb : 50; // 临界距离
var isAuto = 'isAuto' in options ? options.isAuto : true; // 否自动滚动加载
var moreText = options.moreText || i18n.$t('flow.loadMore'); // 手动加载时,加载更多按钮文案
var end = options.end || i18n.$t('flow.noMore'); // “末页”显示文案
var direction = options.direction || 'bottom';
var isTop = direction === 'top';
// 重复执行时清理旧的事件绑定
that._cleanup(elem, scrollElem);
//滚动条所在元素是否为document
var notDocument = options.scrollElem && options.scrollElem !== document;
//加载更多
var ELEM_TEXT = '<cite>' + moreText + '</cite>'
,more = $('<div class="layui-flow-more"><a href="javascript:;">'+ ELEM_TEXT +'</a></div>');
if(!elem.find('.layui-flow-more')[0]){
elem[isTop ? 'prepend' : 'append'](more);
}
//加载下一个元素
var next = function(html, over){
var scrollHeightStart = notDocument ? scrollElem.prop('scrollHeight') : document.documentElement.scrollHeight;
var scrollTopStart = scrollElem.scrollTop();
html = $(html);
more[isTop ? 'after' : 'before'](html);
over = over == 0 ? true : null;
over ? more.html(end) : more.find('a').html(ELEM_TEXT);
isOver = over;
lock = null;
lazyimg && lazyimg();
if(isTop){
var scrollHeightEnd = notDocument ? scrollElem.prop('scrollHeight') : document.documentElement.scrollHeight;
if(page === 1){
// 首次渲染后滑动到底部
scrollElem.scrollTop(scrollHeightEnd);
}else if(page > 1){
var nextElementHeight = scrollHeightEnd - scrollHeightStart;
scrollElem.scrollTop(scrollTopStart + nextElementHeight);
}
}
};
//触发请求
var done = function(){
lock = true;
more.find('a').html(ELEM_LOAD);
typeof options.done === 'function' && options.done(++page, next);
};
done();
//不自动滚动加载
more.find('a').on('click.flow', function(){
var othis = $(this);
if(isOver) return;
lock || done();
});
//如果允许图片懒加载
if(options.isLazyimg){
lazyimg = that.lazyimg({
elem: options.elem + ' img'
,scrollElem: options.scrollElem
,direction: options.direction
});
}
if(!isAuto) return that;
scrollElem.on('scroll.flow', function(){
var othis = $(this), top = othis.scrollTop();
if(timer) clearTimeout(timer);
if(isOver || !elem.width()) return; //如果已经结束,或者元素处于隐藏状态,则不执行滚动加载
timer = setTimeout(function(){
//计算滚动所在容器的可视高度
var height = notDocument ? othis.height() : $(window).height();
//计算滚动所在容器的实际高度
var scrollHeight = notDocument
? othis.prop('scrollHeight')
: document.documentElement.scrollHeight;
//临界点
if(!isTop ? scrollHeight - top - height <= threshold : top <= threshold){
lock || done();
}
}, 100);
});
return that;
};
//图片懒加载
Flow.prototype.lazyimg = function(options){
var that = this, index = 0, haveScroll;
options = options || {};
var scrollElem = $(options.scrollElem || document); //滚动条所在元素
var elem = options.elem || 'img';
var direction = options.direction || 'bottom';
var isTop = direction === 'top';
//滚动条所在元素是否为document
var notDocument = options.scrollElem && options.scrollElem !== document;
//显示图片
var show = function(item, height){
var start = scrollElem.scrollTop(), end = start + height;
var elemTop = notDocument ? function(){
return item.offset().top - scrollElem.offset().top + start;
}() : item.offset().top;
/* 始终只加载在当前屏范围内的图片 */
if((isTop ? elemTop + item.height() : elemTop) >= start && elemTop <= end){
if(item.attr('lay-src')){
var src = item.attr('lay-src');
layui.img(src, function(){
var next = that.lazyimg.elem.eq(index);
item.attr('src', src).removeAttr('lay-src');
/* 当前图片加载就绪后,检测下一个图片是否在当前屏 */
next[0] && render(next);
index++;
}, function(){
var next = that.lazyimg.elem.eq(index);
item.removeAttr('lay-src');
});
}
}
}, render = function(othis, scroll){
//计算滚动所在容器的可视高度
var height = notDocument ? (scroll||scrollElem).height() : $(window).height();
var start = scrollElem.scrollTop(), end = start + height;
that.lazyimg.elem = $(elem);
if(othis){
show(othis, height);
} else {
//计算未加载过的图片
for(var i = 0; i < that.lazyimg.elem.length; i++){
var item = that.lazyimg.elem.eq(i), elemTop = notDocument ? function(){
return item.offset().top - scrollElem.offset().top + start;
}() : item.offset().top;
show(item, height);
index = i;
//如果图片的top坐标超出了当前屏则终止后续图片的遍历
if(elemTop > end) break;
}
}
};
render();
if(!haveScroll){
var timer;
scrollElem.on('scroll.lazyimg' , function(){
var othis = $(this);
if(timer) clearTimeout(timer)
timer = setTimeout(function(){
render(null, othis);
}, 50);
});
haveScroll = true;
}
return render;
};
// 重复执行时清理旧的事件绑定,私有方法
Flow.prototype._cleanup = function(elem, scrollElem){
scrollElem.off('scroll.flow').off('scroll.lazyimg');
elem.find('.layui-flow-more').find('a').off('click.flow');
}
//暴露接口
exports('flow', new Flow());
});