MediaWiki:Gadget-PrintOptions.js:修订间差异
外观
小无编辑摘要 |
小无编辑摘要 |
||
| (未显示同一用户的12个中间版本) | |||
| 第1行: | 第1行: | ||
( | /** | ||
* 打印选项是一个由 Derk-Jan Hartman / User:TheDJ 编写的小工具 | |||
* 更多信息参见 [[User:TheDJ/Print_options]] | |||
* | |||
* 采用 MIT 和/或 CC-by-SA 4.0 许可协议 | |||
* | |||
* 版权所有 (c) 2010-2017 Derk-Jan Hartman / User:TheDJ | |||
* | |||
* 特此免费授予任何获得本软件及相关文档文件(以下简称“软件”)副本的人,不受限制地处理本软件, | |||
* 包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或出售本软件的副本, | |||
* 并允许向其提供本软件的人这样做,但须符合以下条件: | |||
* | |||
* 上述版权声明和本许可声明应包含在本软件的所有副本或主要部分中。 | |||
* | |||
* 本软件按“原样”提供,不提供任何形式的明示或暗示担保, | |||
* 包括但不限于对适销性、特定用途适用性和非侵权性的担保。 | |||
* 在任何情况下,作者或版权持有人均不对因使用本软件而产生的任何索赔、损害或其他责任承担责任, | |||
* 无论是在合同诉讼、侵权诉讼还是其他诉讼中。 | |||
*/ | |||
( function () { | |||
'use strict'; | |||
var windowManager; // 窗口管理器实例 | |||
var printDialog; // 打印对话框实例 | |||
var printOptions = { | |||
/** | |||
* 安装打印选项功能 | |||
* - 找到页面上的打印链接 | |||
* - 重写打印链接的点击事件 | |||
* - 预加载必要的 OOUI 组件 | |||
*/ | |||
install: function () { | |||
var $printLink = $( '#t-print a' ); | |||
if ( $printLink.length === 0 ) { | |||
return; | |||
} | |||
$printLink | |||
.text( '打印页面' ) | |||
.off( 'click' ) | |||
.get( 0 ).addEventListener( 'click', function ( e ) { | |||
// 加载 OOUI 核心组件、窗口组件和控件组件 | |||
mw.loader.using( [ 'oojs-ui-core', 'oojs-ui-widgets', 'oojs-ui-windows' ] ).done( printOptions.createWindow ); | |||
e.stopPropagation(); | |||
e.preventDefault(); | |||
}, true ); // 使用捕获阶段,以优先于其他点击处理程序 | |||
// 延迟预加载 OOUI 组件 | |||
mw.loader.load( [ 'oojs-ui-core', 'oojs-ui-widgets', 'oojs-ui-windows' ] ); | |||
}, | |||
/** | |||
* 创建打印选项对话框 | |||
* - 定义对话框类 | |||
* - 设置对话框标题和操作按钮 | |||
* - 添加选项复选框 | |||
* - 初始化窗口管理器并打开对话框 | |||
*/ | |||
createWindow: function () { | |||
// 定义打印对话框类 | |||
function PrintDialog( config ) { | |||
PrintDialog.super.call( this, config ); | |||
} | |||
// 继承 OO.ui.ProcessDialog | |||
OO.inheritClass( PrintDialog, OO.ui.ProcessDialog ); | |||
// 对话框静态配置 | |||
PrintDialog.static.name = 'printdialog'; | |||
PrintDialog.static.title = '打印此页面'; | |||
PrintDialog.static.actions = [ | |||
{ action: 'print', label: '打印', flags: 'primary' }, // 打印按钮(主要操作) | |||
{ label: '取消', flags: 'safe' } // 取消按钮(安全操作) | |||
]; | |||
/** | |||
* 初始化对话框内容 | |||
* - 创建面板和字段集 | |||
* - 根据 questions 数组创建复选框 | |||
* - 将字段集添加到对话框中 | |||
*/ | |||
PrintDialog.prototype.initialize = function () { | |||
var checkbox, fieldset = []; | |||
PrintDialog.super.prototype.initialize.apply( this, arguments ); | |||
// 创建面板布局 | |||
this.panel = new OO.ui.PanelLayout( { padded: true, expanded: false } ); | |||
// 创建字段集布局 | |||
this.content = new OO.ui.FieldsetLayout(); | |||
// 遍历问题数组,创建复选框 | |||
for ( var i = 0; i < printOptions.questions.length; i++ ) { | |||
if ( printOptions.questions[ i ].type === 'checkbox' ) { | |||
checkbox = new OO.ui.CheckboxInputWidget( { | |||
selected: printOptions.questions[ i ].checked // 设置默认选中状态 | |||
} ); | |||
// 保存复选框实例到问题对象中 | |||
printOptions.questions[ i ].widget = checkbox; | |||
// 创建字段布局并添加到字段集 | |||
fieldset.push( new OO.ui.FieldLayout( checkbox, { label: printOptions.questions[ i ].label, align: 'inline' } ) ); | |||
} | |||
} | |||
// 将字段集添加到内容布局 | |||
this.content.addItems( fieldset ); | |||
// 将内容添加到面板,面板添加到对话框主体 | |||
this.panel.$element.append( this.content.$element ); | |||
this.$body.append( this.panel.$element ); | |||
}; | |||
/** | |||
* 处理对话框操作 | |||
* @param {string} action - 操作名称 | |||
* @returns {OO.ui.Process} 处理过程 | |||
*/ | |||
PrintDialog.prototype.getActionProcess = function ( action ) { | |||
var dialog = this; | |||
if ( action === 'print' ) { | |||
return new OO.ui.Process( function () { | |||
// 获取复选框的值 | |||
var question; | |||
for ( var i = 0; i < printOptions.questions.length; i++ ) { | |||
question = printOptions.questions[ i ]; | |||
if ( question.type === 'checkbox' && question.widget ) { | |||
printOptions[ question.returnvalue ] = question.widget.isSelected(); | |||
} | |||
} | |||
// 关闭对话框后执行打印操作 | |||
dialog.close( { action: action } ).done( function () { | |||
printOptions.changePrintCSS(); // 修改打印样式 | |||
printOptions.otherEnhancements(); // 其他增强处理 | |||
window.print(); // 触发浏览器打印 | |||
window.location = window.location; // 刷新页面恢复原始状态 | |||
} ); | |||
} ); | |||
} | |||
// 调用父类方法处理其他操作 | |||
return PrintDialog.super.prototype.getActionProcess.call( this, action ); | |||
}; | |||
// 初始化窗口管理器(如果未创建) | |||
if ( !windowManager ) { | |||
windowManager = new OO.ui.WindowManager(); | |||
$( 'body' ).append( windowManager.$element ); | |||
} | |||
// 创建打印对话框(如果未创建) | |||
if ( !printDialog ) { | |||
printDialog = new PrintDialog( { | |||
size: 'medium' // 设置对话框大小为中等 | |||
} ); | |||
windowManager.addWindows( [ printDialog ] ); // 将对话框添加到窗口管理器 | |||
} | |||
windowManager.openWindow( printDialog ); // 打开对话框 | |||
}, | |||
/** | |||
* 修改打印样式表 | |||
* - 禁用仅打印样式表 | |||
* - 为屏幕样式表添加打印介质 | |||
* - 删除仅打印的样式规则 | |||
* - 为屏幕样式规则添加打印介质 | |||
* - 根据选项添加自定义打印样式 | |||
*/ | |||
changePrintCSS: function () { | |||
/* 此处我们: | |||
- 禁用仅用于打印的样式表 | |||
- 使屏幕样式表也适用于打印介质 | |||
- 删除仅用于打印的样式规则 | |||
- 使屏幕样式规则也适用于打印介质 | |||
*/ | |||
var printStyle = ''; | |||
if ( this.enhanced === false ) { | |||
var i, j, k, | |||
rule, | |||
hasPrint, // 是否包含打印介质 | |||
hasScreen, // 是否包含屏幕介质 | |||
rules, // 样式规则集合 | |||
stylesheet, // 当前样式表 | |||
stylesheets = document.styleSheets; // 所有样式表 | |||
for ( i = 0; i < stylesheets.length; i++ ) { | |||
stylesheet = stylesheets[ i ]; | |||
if ( !stylesheet.media ) { | |||
continue; | |||
} | |||
// 处理样式表的介质类型 | |||
if ( stylesheet.media.mediaText && stylesheet.media.mediaText.indexOf( 'print' ) !== -1 ) { | |||
// 如果是仅打印样式表,禁用它 | |||
if ( stylesheet.media.mediaText.indexOf( 'screen' ) === -1 ) { | |||
stylesheet.disabled = true; | |||
} | |||
} else if ( stylesheet.media.mediaText && stylesheet.media.mediaText.indexOf( 'screen' ) !== -1 ) { | |||
// 如果是仅屏幕样式表,添加打印介质 | |||
if ( stylesheet.media.mediaText.indexOf( 'print' ) === -1 ) { | |||
try { | |||
stylesheet.media.appendMedium( 'print' ); | |||
} catch ( e ) { | |||
stylesheet.media.mediaText += ',print'; | |||
} | |||
} | |||
} | |||
/* 现在处理单个样式规则 */ | |||
try { | |||
rules = stylesheet.cssRules || stylesheet.rules; | |||
} catch ( e ) { | |||
/* 跨域问题 */ | |||
mw.log.warn( '由于跨域限制,无法修正样式表' ); | |||
continue; | |||
} | |||
// 兼容不同浏览器的删除规则方法 | |||
stylesheet.compatdelete = stylesheet.deleteRule || stylesheet.removeRule; | |||
for ( j = 0; rules && j < rules.length; j++ ) { | |||
rule = rules[ j ]; | |||
hasPrint = false; | |||
hasScreen = false; | |||
// 检查媒体规则 | |||
if ( rule.type === CSSRule.MEDIA_RULE && rule.media ) { | |||
for ( k = 0; k < rule.media.length; k++ ) { | |||
if ( rule.media[ k ] === 'print' ) { | |||
hasPrint = true; | |||
} else if ( rule.media[ k ] === 'screen' ) { | |||
hasScreen = true; | |||
} | |||
} | |||
} else { | |||
continue; | |||
} | |||
// 删除仅打印的规则 | |||
if ( hasPrint && !hasScreen ) { | |||
stylesheet.compatdelete( j ); | |||
j--; // 索引回退,因为删除了一个规则 | |||
} else if ( hasScreen && !hasPrint ) { | |||
// 为仅屏幕规则添加打印介质 | |||
try { | |||
rule.media.appendMedium( 'print' ); | |||
} catch ( e ) { | |||
rule.media.mediaText += ',print'; | |||
} | |||
} | |||
} | |||
} | |||
} | |||
/* 根据选项添加自定义打印样式 */ | |||
// 隐藏图片 | |||
if ( this.noimages ) { | |||
printStyle += 'img, .thumb {display:none;}\n'; | |||
} | |||
// 隐藏引用标记和引用列表 | |||
if ( this.norefs ) { | |||
printStyle += '.mw-heading:has(#References), ol.references, .reference {display:none;}\n'; | |||
} | |||
// 隐藏目录 | |||
if ( this.notoc ) { | |||
printStyle += '#toc, .toc {display:none;}\n'; | |||
} | |||
// 移除背景 | |||
if ( this.nobackground ) { | |||
printStyle += '* {background:none !important;}\n'; | |||
} | |||
// 强制文本为黑色 | |||
if ( this.blacktext ) { | |||
printStyle += '* {color:black !important;}\n'; | |||
} | |||
// 添加自定义样式到页面 | |||
if ( printStyle ) { | |||
$( 'head' ).append( '<style type="text/css" media="print">' + printStyle + '</style>' ); | |||
} | |||
}, | |||
/** | |||
* 其他增强处理 | |||
* - 将 "retrieved from" 链接转换为可读文本 | |||
*/ | |||
otherEnhancements: function () { | |||
var link = $( 'div.printfooter a' ); | |||
link.text( decodeURI( link.text() ) ); | |||
}, | |||
/** | |||
* 打印选项问题配置 | |||
* 每个对象包含: | |||
* - label: 复选框标签 | |||
* - type: 输入类型(checkbox) | |||
* - checked: 默认选中状态 | |||
* - returnvalue: 存储结果的属性名 | |||
*/ | |||
questions: [ | |||
{ | |||
label: '隐藏界面元素', | |||
type: 'checkbox', | |||
checked: true, | |||
returnvalue: 'enhanced' | |||
}, | |||
{ | |||
label: '隐藏图片', | |||
type: 'checkbox', | |||
checked: false, | |||
returnvalue: 'noimages' | |||
}, | |||
{ | |||
label: '隐藏引用', | |||
type: 'checkbox', | |||
checked: false, | |||
returnvalue: 'norefs' | |||
}, | |||
{ | |||
label: '隐藏目录', | |||
type: 'checkbox', | |||
checked: false, | |||
returnvalue: 'notoc' | |||
}, | |||
{ | |||
label: '移除背景(您的浏览器可能会覆盖此设置)', | |||
type: 'checkbox', | |||
checked: false, | |||
returnvalue: 'nobackground' | |||
}, | |||
{ | |||
label: '强制所有文本为黑色', | |||
type: 'checkbox', | |||
checked: true, | |||
returnvalue: 'blacktext' | |||
} | |||
] | |||
}; | |||
// 仅在主命名空间(ns >= 0)加载 | |||
if ( mw.config.get( 'wgNamespaceNumber' ) >= 0 ) { | |||
$( function () { | |||
// 这可能在 MW 安装点击处理程序之前执行 | |||
// 因此,将自己重新添加到 document.ready 队列的末尾 | |||
// 使用异步超时来实现 | |||
setTimeout( function () { | |||
$( printOptions.install ); | |||
} ); | |||
} ); | |||
} | |||
}() ); | |||
}()); | |||
2025年11月23日 (日) 19:40的最新版本
/**
* 打印选项是一个由 Derk-Jan Hartman / User:TheDJ 编写的小工具
* 更多信息参见 [[User:TheDJ/Print_options]]
*
* 采用 MIT 和/或 CC-by-SA 4.0 许可协议
*
* 版权所有 (c) 2010-2017 Derk-Jan Hartman / User:TheDJ
*
* 特此免费授予任何获得本软件及相关文档文件(以下简称“软件”)副本的人,不受限制地处理本软件,
* 包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或出售本软件的副本,
* 并允许向其提供本软件的人这样做,但须符合以下条件:
*
* 上述版权声明和本许可声明应包含在本软件的所有副本或主要部分中。
*
* 本软件按“原样”提供,不提供任何形式的明示或暗示担保,
* 包括但不限于对适销性、特定用途适用性和非侵权性的担保。
* 在任何情况下,作者或版权持有人均不对因使用本软件而产生的任何索赔、损害或其他责任承担责任,
* 无论是在合同诉讼、侵权诉讼还是其他诉讼中。
*/
( function () {
'use strict';
var windowManager; // 窗口管理器实例
var printDialog; // 打印对话框实例
var printOptions = {
/**
* 安装打印选项功能
* - 找到页面上的打印链接
* - 重写打印链接的点击事件
* - 预加载必要的 OOUI 组件
*/
install: function () {
var $printLink = $( '#t-print a' );
if ( $printLink.length === 0 ) {
return;
}
$printLink
.text( '打印页面' )
.off( 'click' )
.get( 0 ).addEventListener( 'click', function ( e ) {
// 加载 OOUI 核心组件、窗口组件和控件组件
mw.loader.using( [ 'oojs-ui-core', 'oojs-ui-widgets', 'oojs-ui-windows' ] ).done( printOptions.createWindow );
e.stopPropagation();
e.preventDefault();
}, true ); // 使用捕获阶段,以优先于其他点击处理程序
// 延迟预加载 OOUI 组件
mw.loader.load( [ 'oojs-ui-core', 'oojs-ui-widgets', 'oojs-ui-windows' ] );
},
/**
* 创建打印选项对话框
* - 定义对话框类
* - 设置对话框标题和操作按钮
* - 添加选项复选框
* - 初始化窗口管理器并打开对话框
*/
createWindow: function () {
// 定义打印对话框类
function PrintDialog( config ) {
PrintDialog.super.call( this, config );
}
// 继承 OO.ui.ProcessDialog
OO.inheritClass( PrintDialog, OO.ui.ProcessDialog );
// 对话框静态配置
PrintDialog.static.name = 'printdialog';
PrintDialog.static.title = '打印此页面';
PrintDialog.static.actions = [
{ action: 'print', label: '打印', flags: 'primary' }, // 打印按钮(主要操作)
{ label: '取消', flags: 'safe' } // 取消按钮(安全操作)
];
/**
* 初始化对话框内容
* - 创建面板和字段集
* - 根据 questions 数组创建复选框
* - 将字段集添加到对话框中
*/
PrintDialog.prototype.initialize = function () {
var checkbox, fieldset = [];
PrintDialog.super.prototype.initialize.apply( this, arguments );
// 创建面板布局
this.panel = new OO.ui.PanelLayout( { padded: true, expanded: false } );
// 创建字段集布局
this.content = new OO.ui.FieldsetLayout();
// 遍历问题数组,创建复选框
for ( var i = 0; i < printOptions.questions.length; i++ ) {
if ( printOptions.questions[ i ].type === 'checkbox' ) {
checkbox = new OO.ui.CheckboxInputWidget( {
selected: printOptions.questions[ i ].checked // 设置默认选中状态
} );
// 保存复选框实例到问题对象中
printOptions.questions[ i ].widget = checkbox;
// 创建字段布局并添加到字段集
fieldset.push( new OO.ui.FieldLayout( checkbox, { label: printOptions.questions[ i ].label, align: 'inline' } ) );
}
}
// 将字段集添加到内容布局
this.content.addItems( fieldset );
// 将内容添加到面板,面板添加到对话框主体
this.panel.$element.append( this.content.$element );
this.$body.append( this.panel.$element );
};
/**
* 处理对话框操作
* @param {string} action - 操作名称
* @returns {OO.ui.Process} 处理过程
*/
PrintDialog.prototype.getActionProcess = function ( action ) {
var dialog = this;
if ( action === 'print' ) {
return new OO.ui.Process( function () {
// 获取复选框的值
var question;
for ( var i = 0; i < printOptions.questions.length; i++ ) {
question = printOptions.questions[ i ];
if ( question.type === 'checkbox' && question.widget ) {
printOptions[ question.returnvalue ] = question.widget.isSelected();
}
}
// 关闭对话框后执行打印操作
dialog.close( { action: action } ).done( function () {
printOptions.changePrintCSS(); // 修改打印样式
printOptions.otherEnhancements(); // 其他增强处理
window.print(); // 触发浏览器打印
window.location = window.location; // 刷新页面恢复原始状态
} );
} );
}
// 调用父类方法处理其他操作
return PrintDialog.super.prototype.getActionProcess.call( this, action );
};
// 初始化窗口管理器(如果未创建)
if ( !windowManager ) {
windowManager = new OO.ui.WindowManager();
$( 'body' ).append( windowManager.$element );
}
// 创建打印对话框(如果未创建)
if ( !printDialog ) {
printDialog = new PrintDialog( {
size: 'medium' // 设置对话框大小为中等
} );
windowManager.addWindows( [ printDialog ] ); // 将对话框添加到窗口管理器
}
windowManager.openWindow( printDialog ); // 打开对话框
},
/**
* 修改打印样式表
* - 禁用仅打印样式表
* - 为屏幕样式表添加打印介质
* - 删除仅打印的样式规则
* - 为屏幕样式规则添加打印介质
* - 根据选项添加自定义打印样式
*/
changePrintCSS: function () {
/* 此处我们:
- 禁用仅用于打印的样式表
- 使屏幕样式表也适用于打印介质
- 删除仅用于打印的样式规则
- 使屏幕样式规则也适用于打印介质
*/
var printStyle = '';
if ( this.enhanced === false ) {
var i, j, k,
rule,
hasPrint, // 是否包含打印介质
hasScreen, // 是否包含屏幕介质
rules, // 样式规则集合
stylesheet, // 当前样式表
stylesheets = document.styleSheets; // 所有样式表
for ( i = 0; i < stylesheets.length; i++ ) {
stylesheet = stylesheets[ i ];
if ( !stylesheet.media ) {
continue;
}
// 处理样式表的介质类型
if ( stylesheet.media.mediaText && stylesheet.media.mediaText.indexOf( 'print' ) !== -1 ) {
// 如果是仅打印样式表,禁用它
if ( stylesheet.media.mediaText.indexOf( 'screen' ) === -1 ) {
stylesheet.disabled = true;
}
} else if ( stylesheet.media.mediaText && stylesheet.media.mediaText.indexOf( 'screen' ) !== -1 ) {
// 如果是仅屏幕样式表,添加打印介质
if ( stylesheet.media.mediaText.indexOf( 'print' ) === -1 ) {
try {
stylesheet.media.appendMedium( 'print' );
} catch ( e ) {
stylesheet.media.mediaText += ',print';
}
}
}
/* 现在处理单个样式规则 */
try {
rules = stylesheet.cssRules || stylesheet.rules;
} catch ( e ) {
/* 跨域问题 */
mw.log.warn( '由于跨域限制,无法修正样式表' );
continue;
}
// 兼容不同浏览器的删除规则方法
stylesheet.compatdelete = stylesheet.deleteRule || stylesheet.removeRule;
for ( j = 0; rules && j < rules.length; j++ ) {
rule = rules[ j ];
hasPrint = false;
hasScreen = false;
// 检查媒体规则
if ( rule.type === CSSRule.MEDIA_RULE && rule.media ) {
for ( k = 0; k < rule.media.length; k++ ) {
if ( rule.media[ k ] === 'print' ) {
hasPrint = true;
} else if ( rule.media[ k ] === 'screen' ) {
hasScreen = true;
}
}
} else {
continue;
}
// 删除仅打印的规则
if ( hasPrint && !hasScreen ) {
stylesheet.compatdelete( j );
j--; // 索引回退,因为删除了一个规则
} else if ( hasScreen && !hasPrint ) {
// 为仅屏幕规则添加打印介质
try {
rule.media.appendMedium( 'print' );
} catch ( e ) {
rule.media.mediaText += ',print';
}
}
}
}
}
/* 根据选项添加自定义打印样式 */
// 隐藏图片
if ( this.noimages ) {
printStyle += 'img, .thumb {display:none;}\n';
}
// 隐藏引用标记和引用列表
if ( this.norefs ) {
printStyle += '.mw-heading:has(#References), ol.references, .reference {display:none;}\n';
}
// 隐藏目录
if ( this.notoc ) {
printStyle += '#toc, .toc {display:none;}\n';
}
// 移除背景
if ( this.nobackground ) {
printStyle += '* {background:none !important;}\n';
}
// 强制文本为黑色
if ( this.blacktext ) {
printStyle += '* {color:black !important;}\n';
}
// 添加自定义样式到页面
if ( printStyle ) {
$( 'head' ).append( '<style type="text/css" media="print">' + printStyle + '</style>' );
}
},
/**
* 其他增强处理
* - 将 "retrieved from" 链接转换为可读文本
*/
otherEnhancements: function () {
var link = $( 'div.printfooter a' );
link.text( decodeURI( link.text() ) );
},
/**
* 打印选项问题配置
* 每个对象包含:
* - label: 复选框标签
* - type: 输入类型(checkbox)
* - checked: 默认选中状态
* - returnvalue: 存储结果的属性名
*/
questions: [
{
label: '隐藏界面元素',
type: 'checkbox',
checked: true,
returnvalue: 'enhanced'
},
{
label: '隐藏图片',
type: 'checkbox',
checked: false,
returnvalue: 'noimages'
},
{
label: '隐藏引用',
type: 'checkbox',
checked: false,
returnvalue: 'norefs'
},
{
label: '隐藏目录',
type: 'checkbox',
checked: false,
returnvalue: 'notoc'
},
{
label: '移除背景(您的浏览器可能会覆盖此设置)',
type: 'checkbox',
checked: false,
returnvalue: 'nobackground'
},
{
label: '强制所有文本为黑色',
type: 'checkbox',
checked: true,
returnvalue: 'blacktext'
}
]
};
// 仅在主命名空间(ns >= 0)加载
if ( mw.config.get( 'wgNamespaceNumber' ) >= 0 ) {
$( function () {
// 这可能在 MW 安装点击处理程序之前执行
// 因此,将自己重新添加到 document.ready 队列的末尾
// 使用异步超时来实现
setTimeout( function () {
$( printOptions.install );
} );
} );
}
}() );