|
|
| 第1行: |
第1行: |
| // 移动端公告滚动效果 | | /* 网站公告的 CSS - 移动端和桌面端通用 */ |
| // 兼容 MobileFrontend 和桌面端
| |
|
| |
|
| (function() {
| | #siteNoticeScroll { |
| 'use strict'; | | width: 100% !important; |
| | | height: 25px !important; |
| // 初始化公告滚动 | | line-height: 25px !important; |
| function initSiteNoticeScroll() {
| | overflow: hidden !important; |
| var self = $('#siteNoticeScroll');
| | text-align: center !important; |
| if (!self.length || !self[0]) return;
| | margin-bottom: 0.25em !important; |
|
| | position: relative !important; |
| var ul = self.find('ul:first');
| | display: block !important; |
| if (!ul.length) return;
| | } |
|
| | |
| var lis = ul.find('li');
| | #siteNoticeScroll ul { |
|
| | height: 25px !important; |
| // 检查并修复被分割的 li 元素
| | line-height: 25px !important; |
| // 如果第一个 li 包含"我们目前有"但不包含"次编辑",说明被分割了
| | margin: 0 !important; |
| if (lis.length > 0) {
| | padding: 0 !important; |
| var firstLi = lis.eq(0);
| | list-style: none !important; |
| var firstText = firstLi.text().trim();
| | -webkit-transition: transform 0.73s ease-in-out !important; |
|
| | -moz-transition: transform 0.73s ease-in-out !important; |
| // 检查第一个 li 是否被分割(包含"我们目前有"但不包含"次编辑")
| | -o-transition: transform 0.73s ease-in-out !important; |
| if (firstText.indexOf('我们目前有') !== -1 && firstText.indexOf('次编辑') === -1) {
| | transition: transform 0.73s ease-in-out !important; |
| // 查找下一个包含"次编辑"的 li
| | display: block !important; |
| for (var i = 1; i < lis.length; i++) {
| | white-space: nowrap !important; |
| var nextLi = lis.eq(i);
| | position: relative !important; |
| var nextText = nextLi.text().trim();
| | will-change: transform !important; |
|
| | -webkit-backface-visibility: hidden !important; |
| // 如果下一个 li 包含"次编辑"但不包含"我们目前有",说明是分割的部分
| | backface-visibility: hidden !important; |
| if (nextText.indexOf('次编辑') !== -1 && nextText.indexOf('我们目前有') === -1) {
| | overflow: visible !important; |
| // 合并内容
| | } |
| var combinedHtml = firstLi.html() + ' ' + nextLi.html();
| | |
| firstLi.html(combinedHtml);
| | #siteNoticeScroll li { |
| nextLi.remove(); // 删除被合并的 li
| | height: 25px !important; |
| break;
| | line-height: 25px !important; |
| }
| | list-style: none !important; |
| }
| | float: left !important; |
| }
| | width: 100% !important; |
| }
| | display: inline-block !important; |
|
| | box-sizing: border-box !important; |
| // 重新获取修复后的 li 列表
| | padding: 0 !important; |
| lis = ul.find('li');
| | margin: 0 !important; |
| if (lis.length <= 1) return; // 如果只有一个或没有项目,不需要滚动
| | vertical-align: top !important; |
|
| | flex-shrink: 0 !important; |
| // 获取容器宽度(使用多种方法确保获取到)
| | white-space: nowrap !important; |
| var containerWidth = self.width() || self[0].offsetWidth || self[0].clientWidth;
| | overflow: visible !important; |
| if (containerWidth === 0) {
| | text-overflow: clip !important; |
| // 如果宽度为0,可能是DOM还未完全加载,延迟重试
| | text-align: center !important; |
| setTimeout(initSiteNoticeScroll, 100);
| | word-break: keep-all !important; |
| return;
| | word-wrap: normal !important; |
| }
| | max-width: 100% !important; |
|
| | position: relative !important; |
| // 设置 ul 宽度和初始 transform(使用 translate3d 启用 GPU 加速)
| | } |
| var totalWidth = containerWidth * lis.length;
| | |
| ul.css({
| | #siteNoticeScroll li * { |
| 'width': totalWidth + 'px',
| | text-align: center !important; |
| 'height': '25px',
| | white-space: nowrap !important; |
| 'margin': '0',
| | display: inline !important; |
| 'padding': '0',
| | } |
| 'list-style': 'none',
| | |
| 'display': 'block',
| | /* 确保 strong 标签不会导致换行 */ |
| 'position': 'relative',
| | #siteNoticeScroll li strong { |
| 'white-space': 'nowrap',
| | white-space: nowrap !important; |
| '-webkit-transform': 'translate3d(0, 0, 0)',
| | display: inline !important; |
| '-moz-transform': 'translate3d(0, 0, 0)',
| | } |
| '-ms-transform': 'translateX(0px)',
| | |
| '-o-transform': 'translate3d(0, 0, 0)',
| | /* 移动端优化 */ |
| 'transform': 'translate3d(0, 0, 0)',
| | @media screen and (max-width: 720px) { |
| '-webkit-transition': 'transform 0.73s ease-in-out',
| | #siteNoticeScroll { |
| '-moz-transition': 'transform 0.73s ease-in-out',
| | height: auto; |
| '-o-transition': 'transform 0.73s ease-in-out',
| | min-height: 25px; |
| 'transition': 'transform 0.73s ease-in-out',
| |
| 'will-change': 'transform'
| |
| }).attr({
| |
| 'data-left': 0,
| |
| 'data-length': lis.length
| |
| });
| |
|
| |
| // 设置每个 li 的宽度和样式(防止换行,确保居中)
| |
| lis.each(function() {
| |
| var $li = $(this);
| |
| // 先设置宽度,确保不换行,内容居中
| |
| $li.css({
| |
| 'width': containerWidth + 'px',
| |
| 'height': '25px',
| |
| 'line-height': '25px',
| |
| 'list-style': 'none',
| |
| 'float': 'left',
| |
| 'display': 'inline-block',
| |
| 'box-sizing': 'border-box',
| |
| 'padding': '0',
| |
| 'margin': '0',
| |
| 'vertical-align': 'top',
| |
| 'flex-shrink': '0',
| |
| 'white-space': 'nowrap',
| |
| 'overflow': 'visible',
| |
| 'text-overflow': 'clip',
| |
| 'text-align': 'center',
| |
| 'word-break': 'keep-all',
| |
| 'word-wrap': 'normal',
| |
| 'max-width': containerWidth + 'px',
| |
| 'position': 'relative'
| |
| });
| |
|
| |
| // 确保所有子元素(包括 strong、a、font 等)都不会换行
| |
| $li.find('*').css({
| |
| 'white-space': 'nowrap',
| |
| 'display': 'inline',
| |
| 'text-align': 'center'
| |
| });
| |
|
| |
| // 特别处理 strong 标签
| |
| $li.find('strong').css({
| |
| 'white-space': 'nowrap',
| |
| 'display': 'inline'
| |
| });
| |
| });
| |
|
| |
| // 强制重绘
| |
| ul[0].offsetHeight;
| |
|
| |
| // 清除之前的定时器(如果存在)
| |
| var oldInterval = self.data('scrollInterval');
| |
| if (oldInterval) {
| |
| clearInterval(oldInterval);
| |
| }
| |
|
| |
| // 开始滚动
| |
| var scrollInterval = window.setInterval(function() {
| |
| var dataset = ul[0].dataset;
| |
| if (!dataset) return;
| |
|
| |
| var currentLeft = parseInt(dataset.left) || 0;
| |
| var totalLength = parseInt(dataset.length) || lis.length;
| |
| var newLeft = currentLeft + 1;
| |
|
| |
| // 如果到达最后一个,重置到第一个(索引0)
| |
| if (newLeft >= totalLength) {
| |
| newLeft = 0;
| |
| }
| |
|
| |
| var translateX = -(newLeft * containerWidth);
| |
|
| |
| // 重置时先移除 transition,立即跳转,然后恢复
| |
| if (newLeft === 0) {
| |
| // 先移除 transition,立即跳转
| |
| ul.css({
| |
| '-webkit-transition': 'none',
| |
| '-moz-transition': 'none',
| |
| '-o-transition': 'none',
| |
| 'transition': 'none',
| |
| '-webkit-transform': 'translate3d(0, 0, 0)',
| |
| '-moz-transform': 'translate3d(0, 0, 0)',
| |
| '-ms-transform': 'translateX(0px)',
| |
| '-o-transform': 'translate3d(0, 0, 0)',
| |
| 'transform': 'translate3d(0, 0, 0)'
| |
| });
| |
| // 强制重绘
| |
| ul[0].offsetHeight;
| |
| // 恢复 transition
| |
| setTimeout(function() {
| |
| ul.css({
| |
| '-webkit-transition': 'transform 0.73s ease-in-out',
| |
| '-moz-transition': 'transform 0.73s ease-in-out',
| |
| '-o-transition': 'transform 0.73s ease-in-out',
| |
| 'transition': 'transform 0.73s ease-in-out'
| |
| });
| |
| }, 50);
| |
| } else {
| |
| // 正常滚动(使用 translate3d 启用 GPU 加速)
| |
| ul.css({
| |
| '-webkit-transition': 'transform 0.73s ease-in-out',
| |
| '-moz-transition': 'transform 0.73s ease-in-out',
| |
| '-o-transition': 'transform 0.73s ease-in-out',
| |
| 'transition': 'transform 0.73s ease-in-out',
| |
| '-webkit-transform': 'translate3d(' + translateX + 'px, 0, 0)',
| |
| '-moz-transform': 'translate3d(' + translateX + 'px, 0, 0)',
| |
| '-ms-transform': 'translateX(' + translateX + 'px)',
| |
| '-o-transform': 'translate3d(' + translateX + 'px, 0, 0)',
| |
| 'transform': 'translate3d(' + translateX + 'px, 0, 0)'
| |
| });
| |
| }
| |
|
| |
| dataset.left = newLeft;
| |
| }, 5000);
| |
|
| |
| // 窗口大小改变时重新计算(使用命名空间避免重复绑定)
| |
| $(window).off('resize.siteNoticeScroll').on('resize.siteNoticeScroll', function() {
| |
| containerWidth = self.width() || self[0].offsetWidth || self[0].clientWidth;
| |
| if (containerWidth === 0) return;
| |
|
| |
| var totalWidth = containerWidth * lis.length;
| |
| ul.css('width', totalWidth + 'px');
| |
| lis.each(function() {
| |
| $(this).css({
| |
| 'width': containerWidth + 'px',
| |
| 'white-space': 'nowrap',
| |
| 'overflow': 'hidden',
| |
| 'text-overflow': 'ellipsis',
| |
| 'text-align': 'center'
| |
| });
| |
| });
| |
|
| |
| var currentLeft = parseInt(ul[0].dataset.left) || 0;
| |
| if (currentLeft < 0) currentLeft = 0;
| |
| var translateX = -(currentLeft * containerWidth);
| |
| ul.css({
| |
| '-webkit-transition': 'transform 0.37s ease-in-out',
| |
| '-moz-transition': 'transform 0.37s ease-in-out',
| |
| '-o-transition': 'transform 0.37s ease-in-out',
| |
| 'transition': 'transform 0.37s ease-in-out',
| |
| '-webkit-transform': 'translate3d(' + translateX + 'px, 0, 0)',
| |
| '-moz-transform': 'translate3d(' + translateX + 'px, 0, 0)',
| |
| '-ms-transform': 'translateX(' + translateX + 'px)',
| |
| '-o-transform': 'translate3d(' + translateX + 'px, 0, 0)',
| |
| 'transform': 'translate3d(' + translateX + 'px, 0, 0)'
| |
| });
| |
| });
| |
|
| |
| // 保存 interval ID,以便后续清理
| |
| self.data('scrollInterval', scrollInterval);
| |
| } | | } |
| | | |
| // 初始化用户提示 | | #siteNoticeScroll ul { |
| function initUserPrompt() {
| | height: auto; |
| var siteNoticeScroll = $('#siteNoticeScroll');
| | min-height: 25px; |
| if (siteNoticeScroll.length === 0) {
| |
| return false;
| |
| }
| |
|
| |
| var ul = siteNoticeScroll.find('ul:first'); | |
| if (ul.length === 0) {
| |
| return false;
| |
| }
| |
|
| |
| var currentUser = null;
| |
| try {
| |
| if (typeof mw !== 'undefined' && mw.config && mw.config.get) {
| |
| currentUser = mw.config.get('wgUserName');
| |
| }
| |
| } catch (e) { | |
| // 忽略错误
| |
| }
| |
|
| |
| var promptElement = $('#userPrompt');
| |
|
| |
| // 如果页面没有 userPrompt 元素,创建一个
| |
| if (promptElement.length === 0) {
| |
| promptElement = $('<li id="userPrompt"></li>');
| |
| ul.append(promptElement);
| |
| }
| |
|
| |
| // 设置内容
| |
| if (currentUser && currentUser !== null && currentUser !== '') {
| |
| // 已登录用户
| |
| promptElement.html('<strong>欢迎回来,' + currentUser + '!感谢您对炼石百科的贡献!</strong>');
| |
| } else {
| |
| // 未登录用户
| |
| promptElement.html('<strong>欢迎加入炼石百科<a href="/wiki/Special:用户登录"><font color="#3862AE">注册一个账号</font></a>,一起参与编写吧!</strong>');
| |
| }
| |
|
| |
| return true;
| |
| } | | } |
| | | |
| // 防止重复初始化 | | #siteNoticeScroll li { |
| var initialized = false;
| | height: auto; |
|
| | min-height: 25px; |
| // 等待 DOM 和 MediaWiki 加载完成
| | line-height: 1.5; |
| function init() {
| | padding: 2px 10px; |
| if (initialized) {
| |
| return; // 防止重复初始化
| |
| }
| |
| initialized = true;
| |
|
| |
| // 先初始化用户提示(必须在滚动初始化之前)
| |
| var promptAdded = initUserPrompt();
| |
|
| |
| // 延迟初始化滚动效果,确保 DOM 完全更新和样式应用
| |
| setTimeout(function() {
| |
| // 再次确保所有 li 都有正确的样式(防止换行)
| |
| var siteNoticeScroll = $('#siteNoticeScroll');
| |
| if (siteNoticeScroll.length) {
| |
| var ul = siteNoticeScroll.find('ul:first');
| |
| if (ul.length) {
| |
| var lis = ul.find('li');
| |
| var containerWidth = siteNoticeScroll.width() || siteNoticeScroll[0].offsetWidth || siteNoticeScroll[0].clientWidth;
| |
| if (containerWidth > 0) {
| |
| lis.each(function() {
| |
| var $li = $(this);
| |
| $li.css({
| |
| 'white-space': 'nowrap',
| |
| 'overflow': 'hidden',
| |
| 'text-overflow': 'ellipsis',
| |
| 'text-align': 'center'
| |
| });
| |
| });
| |
| }
| |
| }
| |
| }
| |
| initSiteNoticeScroll();
| |
| }, promptAdded ? 200 : 100); | |
| } | | } |
|
| | } |
| // 多种初始化方式,确保在移动端和桌面端都能工作
| | |
| if (typeof $ !== 'undefined') {
| | /* 确保在移动端也能正常显示 */ |
| // jQuery 已加载
| | .mw-mf-viewport #siteNoticeScroll { |
| $(document).ready(function() {
| | width: 100%; |
| init();
| | overflow: hidden; |
| });
| | } |
|
| |
| // 如果已经在 ready 状态,延迟执行(避免重复)
| |
| if (document.readyState === 'complete' || document.readyState === 'interactive') {
| |
| setTimeout(function() {
| |
| if (!initialized) {
| |
| init();
| |
| }
| |
| }, 200);
| |
| }
| |
| } else { | |
| // 等待 jQuery 加载
| |
| if (document.readyState === 'loading') {
| |
| document.addEventListener('DOMContentLoaded', function() {
| |
| if (typeof $ !== 'undefined' && !initialized) {
| |
| setTimeout(init, 100);
| |
| }
| |
| });
| |
| } else {
| |
| // 如果 DOM 已加载,等待 jQuery
| |
| var checkJQuery = setInterval(function() {
| |
| if (typeof $ !== 'undefined' && !initialized) {
| |
| clearInterval(checkJQuery);
| |
| init();
| |
| }
| |
| }, 100);
| |
|
| |
| // 10秒后停止检查
| |
| setTimeout(function() {
| |
| clearInterval(checkJQuery);
| |
| }, 10000);
| |
| }
| |
| }
| |
|
| |
| // 使用 MediaWiki 的 hook(如果可用)
| |
| if (typeof mw !== 'undefined' && mw.hook) { | |
| mw.hook('mobile.init').add(function() {
| |
| if (!initialized) {
| |
| setTimeout(init, 200);
| |
| }
| |
| });
| |
| }
| |
| })();
| |