跳转到内容

MediaWiki:Gadget-PrintOptions.js:修订间差异

勤求古训,博采众方
无编辑摘要
标签已被回退
无编辑摘要
 
(未显示同一用户的4个中间版本)
第1行: 第1行:
/*! PrintDialog v3.0 - 支持多语言&快捷键 */
/**
(function (mw, $) {
* 打印选项是一个由 Derk-Jan Hartman / User:TheDJ 编写的小工具
    'use strict';
* 更多信息参见 [[User:TheDJ/Print_options]]
   
*
    // 🌐 本地化文本库
* 采用 MIT 和/或 CC-by-SA 4.0 许可协议
    var i18n = {
*
        'title': mw.message('printdialog-title').plain() || '打印选项',
* 版权所有 (c) 2010-2017 Derk-Jan Hartman / User:TheDJ
        'print-btn': mw.message('printdialog-print-btn').plain() || '打印',
*
        'cancel-btn': mw.message('printdialog-cancel-btn').plain() || '取消',
* 特此免费授予任何获得本软件及相关文档文件(以下简称“软件”)副本的人,不受限制地处理本软件,
        'loading': mw.message('printdialog-loading').plain() || '准备打印中...',
* 包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或出售本软件的副本,
        'print-error': mw.message('printdialog-error').plain() || '打印失败:$1',
* 并允许向其提供本软件的人这样做,但须符合以下条件:
        'no-print-support': mw.message('printdialog-no-support').plain() || '您的浏览器不支持直接打印',
*
        // 选项文本
* 上述版权声明和本许可声明应包含在本软件的所有副本或主要部分中。
        'options': {
*
            'hideImages': mw.message('printdialog-opt-hide-images').plain() || '隐藏图片',
* 本软件按“原样”提供,不提供任何形式的明示或暗示担保,
            'hideRefs': mw.message('printdialog-opt-hide-refs').plain() || '隐藏参考文献'
* 包括但不限于对适销性、特定用途适用性和非侵权性的担保。
            // 可继续扩展其他选项...
* 在任何情况下,作者或版权持有人均不对因使用本软件而产生的任何索赔、损害或其他责任承担责任,
        },
* 无论是在合同诉讼、侵权诉讼还是其他诉讼中。
        'help': {
*/
            'hideImages': mw.message('printdialog-help-hide-images').plain() || '不打印页面中的图片和缩略图'
        }
    };


    var PrintDialog = {
( function () {
        // ⚙️ 配置项
'use strict';
        config: {
var windowManager; // 窗口管理器实例
            debug: false,
var printDialog; // 打印对话框实例
            dependencies: ['oojs-ui-core', 'oojs-ui-widgets', 'oojs-ui-windows'],
 
            hotkeys: {
var printOptions = {
                print: 'ctrl+enter', // 打印快捷键
/**
                cancel: 'esc'        // 取消快捷键
* 安装打印选项功能
            }
* - 找到页面上的打印链接
        },
* - 重写打印链接的点击事件
       
* - 预加载必要的 OOUI 组件
        // 🚀 初始化
*/
        init: function () {
install: function () {
            if (!this.shouldInit()) return;
var $printLink = $( '#t-print a' );
           
if ( $printLink.length === 0 ) {
            // 绑定打印按钮
return;
            $('#t-print a').first()
}
                .text(mw.message('printdialog-link-text').plain() || '可打印版本')
$printLink
                .off('click.print')
.text( '打印页面' )
                .on('click.print', this.onPrintClick.bind(this));
.off( 'click' )
           
.get( 0 ).addEventListener( 'click', function ( e ) {
            // 预加载资源
// 加载 OOUI 核心组件、窗口组件和控件组件
            if (!this.isDepsLoaded()) {
mw.loader.using( [ 'oojs-ui-core', 'oojs-ui-widgets', 'oojs-ui-windows' ] ).done( printOptions.createWindow );
                mw.loader.load(this.config.dependencies);
e.stopPropagation();
            }
e.preventDefault();
           
}, true ); // 使用捕获阶段,以优先于其他点击处理程序
            // 注册全局快捷键(需确保唯一性)
 
            this.registerHotkeys();
// 延迟预加载 OOUI 组件
        },
mw.loader.load( [ 'oojs-ui-core', 'oojs-ui-widgets', 'oojs-ui-windows' ] );
       
},
        // 🔥 快捷键支持
 
        registerHotkeys: function () {
/**
            $(document).off('keydown.printdialog')
* 创建打印选项对话框
                .on('keydown.printdialog', function (e) {
* - 定义对话框类
                    if (!PrintDialog.dialog || !PrintDialog.windowManager) return;
* - 设置对话框标题和操作按钮
                   
* - 添加选项复选框
                    // ESC - 取消
* - 初始化窗口管理器并打开对话框
                    if (e.key === 'Escape') {
*/
                        PrintDialog.dialog.executeAction('cancel');
createWindow: function () {
                        e.preventDefault();
// 定义打印对话框类
                    }
function PrintDialog( config ) {
                   
PrintDialog.super.call( this, config );
                    // Ctrl+Enter - 打印
}
                    if (e.ctrlKey && e.key === 'Enter') {
// 继承 OO.ui.ProcessDialog
                        PrintDialog.dialog.executeAction('print');
OO.inheritClass( PrintDialog, OO.ui.ProcessDialog );
                        e.preventDefault();
 
                    }
// 对话框静态配置
                });
PrintDialog.static.name = 'printdialog';
        },
PrintDialog.static.title = '打印此页面';
       
PrintDialog.static.actions = [
        // 🏗️ 创建对话框
{ action: 'print', label: '打印', flags: 'primary' }, // 打印按钮(主要操作)
        createDialog: function () {
{ label: '取消', flags: 'safe' } // 取消按钮(安全操作)
            if (this.dialog) {
];
                this.windowManager.openWindow(this.dialog);
 
                return;
/**
            }
* 初始化对话框内容
           
* - 创建面板和字段集
            // 对话框构造函数
* - 根据 questions 数组创建复选框
            function Dialog(config) {
* - 将字段集添加到对话框中
                Dialog.super.call(this, config);
*/
            }
PrintDialog.prototype.initialize = function () {
            OO.inheritClass(Dialog, OO.ui.ProcessDialog);
var checkbox, fieldset = [];
           
PrintDialog.super.prototype.initialize.apply( this, arguments );
            // 静态配置(使用本地化文本)
// 创建面板布局
            Dialog.static.name = 'printDialog';
this.panel = new OO.ui.PanelLayout( { padded: true, expanded: false } );
            Dialog.static.title = i18n.title;
// 创建字段集布局
            Dialog.static.actions = [
this.content = new OO.ui.FieldsetLayout();
                {  
 
                    action: 'print',
// 遍历问题数组,创建复选框
                    label: i18n['print-btn'],
for ( var i = 0; i < printOptions.questions.length; i++ ) {
                    flags: ['primary', 'progressive'],
if ( printOptions.questions[ i ].type === 'checkbox' ) {
                    icon: 'printer'
checkbox = new OO.ui.CheckboxInputWidget( {
                },
selected: printOptions.questions[ i ].checked // 设置默认选中状态
                {  
} );
                    action: 'cancel',
// 保存复选框实例到问题对象中
                    label: i18n['cancel-btn'],  
printOptions.questions[ i ].widget = checkbox;
                    flags: 'safe',
// 创建字段布局并添加到字段集
                    icon: 'close'
fieldset.push( new OO.ui.FieldLayout( checkbox, { label: printOptions.questions[ i ].label, align: 'inline' } ) );
                }
}
            ];
}
           
// 将字段集添加到内容布局
            // 初始化内容
this.content.addItems( fieldset );
            Dialog.prototype.initialize = function () {
 
                Dialog.super.prototype.initialize.apply(this, arguments);
// 将内容添加到面板,面板添加到对话框主体
                this.buildForm();
this.panel.$element.append( this.content.$element );
            };
this.$body.append( this.panel.$element );
           
};
            // 构建表单(本地化选项)
 
            Dialog.prototype.buildForm = function () {
/**
                var panel = new OO.ui.PanelLayout({ padded: true });
* 处理对话框操作
                var fieldset = new OO.ui.FieldsetLayout();
* @param {string} action - 操作名称
               
* @returns {OO.ui.Process} 处理过程
                PrintDialog.options.forEach(function (opt) {
*/
                    if (opt.type === 'checkbox') {
PrintDialog.prototype.getActionProcess = function ( action ) {
                        var widget = new OO.ui.CheckboxInputWidget({
var dialog = this;
                            selected: !!opt.default
if ( action === 'print' ) {
                        });
return new OO.ui.Process( function () {
                       
// 获取复选框的值
                        fieldset.addItems([
var question;
                            new OO.ui.FieldLayout(widget, {
for ( var i = 0; i < printOptions.questions.length; i++ ) {
                                label: i18n.options[opt.id] || opt.id,
question = printOptions.questions[ i ];
                                align: 'inline',
if ( question.type === 'checkbox' && question.widget ) {
                                help: i18n.help[opt.id] ?
printOptions[ question.returnvalue ] = question.widget.isSelected();
                                    new OO.ui.LabelWidget({ label: i18n.help[opt.id] }) : null
}
                            })
}
                        ]);
// 关闭对话框后执行打印操作
                       
dialog.close( { action: action } ).done( function () {
                        opt.widget = widget; // 保存引用
printOptions.changePrintCSS(); // 修改打印样式
                    }
printOptions.otherEnhancements(); // 其他增强处理
                });
window.print(); // 触发浏览器打印
               
window.location = window.location; // 刷新页面恢复原始状态
                panel.$element.append(fieldset.$element);
} );
                this.$body.append(panel.$element);
} );
            };
}
           
// 调用父类方法处理其他操作
            // 处理动作(含快捷键支持)
return PrintDialog.super.prototype.getActionProcess.call( this, action );
            Dialog.prototype.getActionProcess = function (action) {
};
                if (action === 'print') {
 
                    return new OO.ui.Process(function () {
// 初始化窗口管理器(如果未创建)
                        return this.executePrintAction();
if ( !windowManager ) {
                    }.bind(this));
windowManager = new OO.ui.WindowManager();
                }
$( 'body' ).append( windowManager.$element );
                return Dialog.super.prototype.getActionProcess.call(this, action);
}
            };
// 创建打印对话框(如果未创建)
           
if ( !printDialog ) {
            // 执行打印(拆分为独立方法)
printDialog = new PrintDialog( {
            Dialog.prototype.executePrintAction = function () {
size: 'medium' // 设置对话框大小为中等
                // 保存设置
} );
                PrintDialog.options.forEach(function (opt) {
 
                    PrintDialog.settings[opt.id] = opt.widget.isSelected();
windowManager.addWindows( [ printDialog ] ); // 将对话框添加到窗口管理器
                });
}
               
windowManager.openWindow( printDialog ); // 打开对话框
                // 关闭窗口并处理打印
},
                return this.close({ action: 'print' })
 
                    .then(PrintDialog.applyPrintStyles)
/**
                    .then(function () {
* 修改打印样式表
                        if (typeof window.print === 'function') {
* - 禁用仅打印样式表
                            window.print();
* - 为屏幕样式表添加打印介质
                        } else {
* - 删除仅打印的样式规则
                            mw.notify(i18n['no-print-support'], { type: 'warning' });
* - 为屏幕样式规则添加打印介质
                        }
* - 根据选项添加自定义打印样式
                    })
*/
                    .catch(function (err) {
changePrintCSS: function () {
                        mw.notify(i18n['print-error'].replace('$1', err.message), { type: 'error' });
/* 此处我们:
                    });
- 禁用仅用于打印的样式表
            };
- 使屏幕样式表也适用于打印介质
           
- 删除仅用于打印的样式规则
            // 初始化窗口管理器
- 使屏幕样式规则也适用于打印介质
            if (!this.windowManager) {
*/
                this.windowManager = new OO.ui.WindowManager();
var printStyle = '';
                $('body').append(this.windowManager.$element);
if ( this.enhanced === false ) {
            }
var i, j, k,
           
rule,
            // 创建对话框实例
hasPrint, // 是否包含打印介质
            this.dialog = new Dialog({ size: 'medium' });
hasScreen, // 是否包含屏幕介质
            this.windowManager.addWindows([this.dialog]);
rules, // 样式规则集合
            this.windowManager.openWindow(this.dialog);
stylesheet, // 当前样式表
        },
stylesheets = document.styleSheets; // 所有样式表
       
 
        // 🎨 应用打印样式
for ( i = 0; i < stylesheets.length; i++ ) {
        applyPrintStyles: function () {
stylesheet = stylesheets[ i ];
            var style = [];
if ( !stylesheet.media ) {
           
continue;
            if (PrintDialog.settings.hideImages) {
}
                style.push('img, .thumb { display:none !important; }');
// 处理样式表的介质类型
            }
if ( stylesheet.media.mediaText && stylesheet.media.mediaText.indexOf( 'print' ) !== -1 ) {
           
// 如果是仅打印样式表,禁用它
            // 清理旧样式并添加新样式
if ( stylesheet.media.mediaText.indexOf( 'screen' ) === -1 ) {
            $('style.print-styles').remove();
stylesheet.disabled = true;
            if (style.length) {
}
                $('<style>')
} else if ( stylesheet.media.mediaText && stylesheet.media.mediaText.indexOf( 'screen' ) !== -1 ) {
                    .addClass('print-styles')
// 如果是仅屏幕样式表,添加打印介质
                    .attr('media', 'print')
if ( stylesheet.media.mediaText.indexOf( 'print' ) === -1 ) {
                    .text(style.join('\n'))
try {
                    .appendTo('head');
stylesheet.media.appendMedium( 'print' );
            }
} catch ( e ) {
           
stylesheet.media.mediaText += ',print';
            return Promise.resolve();
}
        },
}
       
}
        // ✅ 工具方法
 
        shouldInit: function () {
/* 现在处理单个样式规则 */
            return mw.config.get('wgNamespaceNumber') >= 0;
try {
        },
rules = stylesheet.cssRules || stylesheet.rules;
       
} catch ( e ) {
        isDepsLoaded: function () {
/* 跨域问题 */
            return this.config.dependencies.every(function (dep) {
mw.log.warn( '由于跨域限制,无法修正样式表' );
                return mw.loader.getState(dep) === 'ready';
continue;
            });
}
        },
// 兼容不同浏览器的删除规则方法
       
stylesheet.compatdelete = stylesheet.deleteRule || stylesheet.removeRule;
        // 🖨️ 主入口处理
for ( j = 0; rules && j < rules.length; j++ ) {
        onPrintClick: function (e) {
rule = rules[ j ];
            e.preventDefault();
hasPrint = false;
           
hasScreen = false;
            var notification = mw.notify(
// 检查媒体规则
                new OO.ui.ProgressBarWidget({ progress: false }).$element,
if ( rule.type === CSSRule.MEDIA_RULE && rule.media ) {
                {  
for ( k = 0; k < rule.media.length; k++ ) {
                    title: i18n.loading,
if ( rule.media[ k ] === 'print' ) {
                    autoHide: false
hasPrint = true;
                }
} else if ( rule.media[ k ] === 'screen' ) {
            );
hasScreen = true;
           
}
            mw.loader.using(this.config.dependencies)
}
                .then(this.createDialog.bind(this))
} else {
                .catch(function (err) {
continue;
                    mw.notify(i18n['print-error'].replace('$1', err.message), { type: 'error' });
}
                })
// 删除仅打印的规则
                .always(function () {
if ( hasPrint && !hasScreen ) {
                    notification.close();
stylesheet.compatdelete( j );
                });
j--; // 索引回退,因为删除了一个规则
        },
} else if ( hasScreen && !hasPrint ) {
       
// 为仅屏幕规则添加打印介质
        // ⚙️ 可配置选项
try {
        options: [
rule.media.appendMedium( 'print' );
            {
} catch ( e ) {
                id: 'hideImages',
rule.media.mediaText += ',print';
                type: 'checkbox',
}
                default: false
}
            },
}
            {
}
                id: 'hideRefs',
}
                type: 'checkbox',
/* 根据选项添加自定义打印样式 */
                default: false
// 隐藏图片
            }
if ( this.noimages ) {
        ],
printStyle += 'img, .thumb {display:none;}\n';
       
}
        // 🗃️ 状态存储
// 隐藏引用标记和引用列表
        settings: {},
if ( this.norefs ) {
       
printStyle += '.mw-heading:has(#References), ol.references, .reference {display:none;}\n';
        // ♻️ 清理方法
}
        destroy: function () {
// 隐藏目录
            $(document).off('keydown.printdialog');
if ( this.notoc ) {
            if (this.windowManager) {
printStyle += '#toc, .toc {display:none;}\n';
                this.windowManager.destroy();
}
                this.windowManager = null;
// 移除背景
            }
if ( this.nobackground ) {
            this.dialog = null;
printStyle += '* {background:none !important;}\n';
        }
}
    };
// 强制文本为黑色
   
if ( this.blacktext ) {
    // 📅 延迟初始化
printStyle += '* {color:black !important;}\n';
    mw.hook('wikipage.content').add(function () {
}
        setTimeout(PrintDialog.init.bind(PrintDialog), 300);
 
    });
// 添加自定义样式到页面
   
if ( printStyle ) {
    // 🖇️ 暴露到全局(可选)
$( 'head' ).append( '<style type="text/css" media="print">' + printStyle + '</style>' );
    window.PrintDialog = PrintDialog;
}
})(mediaWiki, jQuery);
},
 
/**
* 其他增强处理
* - 将 "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 );
			} );
		} );
	}
}() );