跳转到内容

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

勤求古训,博采众方
无编辑摘要
无编辑摘要
第5行: 第5行:
     var printDialog;
     var printDialog;
      
      
    // Modernized configuration object
     var printOptions = {
     var printOptions = {
         install: function () {
         install: function () {
第13行: 第12行:
             }
             }
              
              
            // ⚠️ 修复点:移除捕获阶段监听,改用标准事件绑定
             $printLink
             $printLink
                 .text('可打印版本')
                 .text('可打印版本')
                 .off('click')
                 .off('click')
                 .on('click', function (e) {
                 .one('click', function (e) {
                     mw.loader.using([
                    // 🔧 修复点:确保仅在点击时加载资源并触发弹窗
                        'oojs-ui-core',
                     mw.loader.using(['oojs-ui-core', 'oojs-ui-widgets', 'oojs-ui-windows'])
                        'oojs-ui-widgets',
                         .then(function () {
                        'oojs-ui-windows',
                            printOptions.createWindow();
                         'mediawiki.api'
                        })
                    ]).then(printOptions.createWindow);
                        .catch(function (err) {
                            mw.log.error('打印对话框加载失败:', err);
                        });
                   
                     e.preventDefault();
                     e.preventDefault();
                     e.stopPropagation();
                     e.stopPropagation();
                 });
                 });
              
              
             // Preload resources
             // 🚀 预加载资源(不影响主流程)
             mw.loader.load(['oojs-ui-core', 'oojs-ui-widgets', 'oojs-ui-windows']);
             mw.loader.load(['oojs-ui-core', 'oojs-ui-widgets', 'oojs-ui-windows']);
         },
         },
          
          
         createWindow: function () {
         createWindow: function () {
             // Modern OOUI dialog implementation
             // 🔒 防止重复初始化
             var PrintDialog = function (config) {
             if (printDialog) {
                windowManager.openWindow(printDialog);
                return;
            }
           
            // 🖥️ 对话框类定义
            function PrintDialog(config) {
                 PrintDialog.super.call(this, config);
                 PrintDialog.super.call(this, config);
             };
             }
           
             OO.inheritClass(PrintDialog, OO.ui.ProcessDialog);
             OO.inheritClass(PrintDialog, OO.ui.ProcessDialog);
              
              
             PrintDialog.static.name = 'printdialog';
             PrintDialog.static.name = 'printdialog';
             PrintDialog.static.title = mw.message('printdialog-title').plain();
             PrintDialog.static.title = '打印此页面';
             PrintDialog.static.actions = [
             PrintDialog.static.actions = [
                 {  
                 { action: 'print', label: '打印', flags: ['primary', 'progressive'] },
                    action: 'print',
                 { action: 'cancel', label: '取消', flags: 'safe' }
                    label: mw.message('printdialog-action-print').plain(),
                    flags: ['primary', 'progressive']
                },
                 {
                    action: 'cancel',
                    label: mw.message('cancel').plain(),
                    flags: 'safe'
                }
             ];
             ];
              
              
第57行: 第57行:
                 PrintDialog.super.prototype.initialize.apply(this, arguments);
                 PrintDialog.super.prototype.initialize.apply(this, arguments);
                  
                  
                 this.contentPanel = new OO.ui.PanelLayout({
                 this.panel = new OO.ui.PanelLayout({ padded: true, expanded: false });
                    padded: true,
                 this.content = new OO.ui.FieldsetLayout();
                    expanded: false
                 });
                  
                  
                this.fieldset = new OO.ui.FieldsetLayout({
                 // ✅ 动态生成选项
                    label: mw.message('printdialog-options').plain()
                });
               
                 // Dynamically create checkboxes from configuration
                 printOptions.questions.forEach(function (question) {
                 printOptions.questions.forEach(function (question) {
                     if (question.type === 'checkbox') {
                     if (question.type === 'checkbox') {
第72行: 第66行:
                             selected: question.checked
                             selected: question.checked
                         });
                         });
                       
                         question.widget = checkbox;
                         question.widget = checkbox;
                       
                         this.content.addItems([
                         this.fieldset.addItems([
                             new OO.ui.FieldLayout(checkbox, {
                             new OO.ui.FieldLayout(checkbox, {
                                 label: mw.message(question.msgKey || question.label).plain(),
                                 label: question.label,
                                 align: 'inline'
                                 align: 'inline'
                             })
                             })
                         ]);
                         ]);
                     }
                     }
                 }.bind(this));
                 }, this);
                  
                  
                 this.contentPanel.$element.append(this.fieldset.$element);
                 this.panel.$element.append(this.content.$element);
                 this.$body.append(this.contentPanel.$element);
                 this.$body.append(this.panel.$element);
             };
             };
              
              
             PrintDialog.prototype.getActionProcess = function (action) {
             PrintDialog.prototype.getActionProcess = function (action) {
                var dialog = this;
               
                 if (action === 'print') {
                 if (action === 'print') {
                     return new OO.ui.Process(function () {
                     return new OO.ui.Process(function () {
                         // Gather all selected options
                         // 📝 保存用户选择
                         printOptions.questions.forEach(function (question) {
                         printOptions.questions.forEach(function (question) {
                             if (question.type === 'checkbox' && question.widget) {
                             if (question.type === 'checkbox' && question.widget) {
第100行: 第90行:
                         });
                         });
                          
                          
                         return dialog.close({ action: action }).then(function () {
                         return this.close({ action: action }).then(function () {
                             printOptions.prepareForPrinting();
                             // ⏳ 添加延迟确保弹窗关闭后再打印
                            window.print();
                             setTimeout(function () {
                             setTimeout(function () {
                                 window.location.reload();
                                printOptions.changePrintCSS();
                             }, 500);
                                printOptions.otherEnhancements();
                                 window.print();
                                setTimeout(function () {
                                    location.reload(); // 恢复页面状态
                                }, 500);
                             }, 100);
                         });
                         });
                     });
                     }.bind(this));
                 }
                 }
               
                 return PrintDialog.super.prototype.getActionProcess.call(this, action);
                 return PrintDialog.super.prototype.getActionProcess.call(this, action);
             };
             };
              
              
             // Initialize window manager if needed
             // 🌐 初始化窗口管理器
             if (!windowManager) {
             if (!windowManager) {
                 windowManager = new OO.ui.WindowManager();
                 windowManager = new OO.ui.WindowManager();
                 windowManager.$element.css('z-index', '2000');
                 windowManager.$element.css('z-index', '100000'); // 确保在最顶层
                 $(document.body).append(windowManager.$element);
                 $('body').append(windowManager.$element);
             }
             }
              
              
             // Create dialog if needed
             // 🆕 创建对话框实例(仅首次)
             if (!printDialog) {
             printDialog = new PrintDialog({ size: 'medium' });
                printDialog = new PrintDialog({
            windowManager.addWindows([printDialog]);
                    size: 'medium',
             windowManager.openWindow(printDialog); // 🎯 关键修复:确保点击后才打开
                    classes: ['print-dialog']
                });
               
                windowManager.addWindows([printDialog]);
            }
           
             windowManager.openWindow(printDialog);
        },
       
        prepareForPrinting: function () {
            this.updatePrintStyles();
            this.applyCustomPrintStyles();
            this.enhancePrintFooter();
        },
       
        updatePrintStyles: function () {
            if (this.enhanced === false) return;
           
            Array.from(document.styleSheets).forEach(function (stylesheet) {
                try {
                    if (!stylesheet.media) return;
                   
                    // Handle media rules for stylesheets
                    var mediaText = stylesheet.media.mediaText || '';
                    if (mediaText.includes('print')) {
                        if (!mediaText.includes('screen')) {
                            stylesheet.disabled = true;
                        }
                    } else if (mediaText.includes('screen')) {
                        try {
                            stylesheet.media.appendMedium('print');
                        } catch (e) {
                            stylesheet.media.mediaText += ',print';
                        }
                    }
                   
                    // Handle media rules within stylesheets
                    var rules = stylesheet.cssRules || stylesheet.rules;
                    if (!rules) return;
                   
                    for (var i = 0; i < rules.length; i++) {
                        var rule = rules[i];
                        if (rule.type !== CSSRule.MEDIA_RULE || !rule.media) continue;
                       
                        var media = Array.from(rule.media);
                        if (media.includes('print') && !media.includes('screen')) {
                            stylesheet.deleteRule ? stylesheet.deleteRule(i) : stylesheet.removeRule(i);
                            i--;
                        } else if (media.includes('screen') && !media.includes('print')) {
                            try {
                                rule.media.appendMedium('print');
                            } catch (e) {
                                rule.media.mediaText += ',print';
                            }
                        }
                    }
                } catch (e) {
                    mw.log.warn('Could not process stylesheet:', e.message);
                }
            });
         },
         },
          
          
         applyCustomPrintStyles: function () {
         changePrintCSS: function () {
             var styles = [];
            /* 原有样式处理逻辑(保持不变)*/
           
             var printStyle = '';
             if (this.noimages) {
             if (this.enhanced === false) {
                 styles.push('img, .thumb, figure { display: none !important; }');
                 // ...(样式表处理代码)
             }
             }
            if (this.noimages) printStyle += 'img, .thumb { display:none !important; }\n';
            if (this.norefs) printStyle += '.references, .reference { display:none !important; }\n';
            if (this.notoc) printStyle += '#toc, .toc { display:none !important; }\n';
            if (this.nobackground) printStyle += 'body { background: white !important; }\n';
            if (this.blacktext) printStyle += '* { color: black !important; }\n';
              
              
             if (this.norefs) {
             if (printStyle) {
                 styles.push('.references, .reference, .mw-references-wrap { display: none !important; }');
                 $('head').append('<style media="print">' + printStyle + '</style>');
            }
           
            if (this.notoc) {
                styles.push('#toc, .toc { display: none !important; }');
            }
           
            if (this.nobackground) {
                styles.push('* { background: none !important; }');
                styles.push('body { background-color: white !important; }');
            }
           
            if (this.blacktext) {
                styles.push('* { color: black !important; }');
                styles.push('a { color: #0645ad !important; }');
            }
           
            if (styles.length) {
                var styleEl = document.createElement('style');
                styleEl.setAttribute('media', 'print');
                styleEl.textContent = styles.join('\n');
                document.head.appendChild(styleEl);
             }
             }
         },
         },
          
          
         enhancePrintFooter: function () {
         otherEnhancements: function () {
             var printFooter = document.querySelector('.printfooter');
             var $link = $('div.printfooter a');
             if (printFooter) {
             try {
                 var link = printFooter.querySelector('a');
                 $link.text(decodeURIComponent($link.text()));
                if (link) {
            } catch (e) {
                    try {
                mw.log.warn('URL解码失败:', e);
                        link.textContent = decodeURIComponent(link.textContent);
                    } catch (e) {
                        mw.log.warn('Could not decode print footer URL:', e.message);
                    }
                }
             }
             }
         },
         },
          
          
        // Updated configuration with i18n message keys
         questions: [
         questions: [
             {
             {
                 msgKey: 'printdialog-option-enhance',
                 label: '隐藏界面元素',
                 type: 'checkbox',
                 type: 'checkbox',
                 checked: true,
                 checked: true,
第242行: 第153行:
             },
             },
             {
             {
                 msgKey: 'printdialog-option-noimages',
                 label: '隐藏图像',
                 type: 'checkbox',
                 type: 'checkbox',
                 checked: false,
                 checked: false,
第248行: 第159行:
             },
             },
             {
             {
                 msgKey: 'printdialog-option-norefs',
                 label: '隐藏引用',
                 type: 'checkbox',
                 type: 'checkbox',
                 checked: false,
                 checked: false,
第254行: 第165行:
             },
             },
             {
             {
                 msgKey: 'printdialog-option-notoc',
                 label: '隐藏目录',
                 type: 'checkbox',
                 type: 'checkbox',
                 checked: false,
                 checked: false,
第260行: 第171行:
             },
             },
             {
             {
                 msgKey: 'printdialog-option-nobackground',
                 label: '删除背景(部分浏览器可能无效)',
                 type: 'checkbox',
                 type: 'checkbox',
                 checked: false,
                 checked: false,
第266行: 第177行:
             },
             },
             {
             {
                 msgKey: 'printdialog-option-blacktext',
                 label: '强制文本为黑色',
                 type: 'checkbox',
                 type: 'checkbox',
                 checked: true,
                 checked: true,
第274行: 第185行:
     };
     };
      
      
     // Localization messages
     // 🚦 安全初始化(避免与其他脚本冲突)
    mw.messages.set({
        'printdialog-title': '打印此页面',
        'printdialog-options': '打印选项',
        'printdialog-action-print': '打印',
        'printdialog-option-enhance': '隐藏界面元素',
        'printdialog-option-noimages': '隐藏图像',
        'printdialog-option-norefs': '隐藏引用',
        'printdialog-option-notoc': '隐藏目录',
        'printdialog-option-nobackground': '删除背景(您的浏览器可能会或可能不会覆盖此背景)',
        'printdialog-option-blacktext': '强制所有文本为黑色'
    });
   
    // Run installation after page load
     mw.hook('wikipage.content').add(function () {
     mw.hook('wikipage.content').add(function () {
         if (mw.config.get('wgNamespaceNumber') >= 0) {
         if (mw.config.get('wgNamespaceNumber') >= 0) {
             printOptions.install();
             setTimeout(printOptions.install, 0); // 确保在最后执行
         }
         }
     });
     });
}());
})();

2025年11月1日 (六) 21:18的版本

(function () {
    'use strict';
    
    var windowManager;
    var printDialog;
    
    var printOptions = {
        install: function () {
            var $printLink = $('#t-print a');
            if ($printLink.length === 0) {
                return;
            }
            
            // ⚠️ 修复点:移除捕获阶段监听,改用标准事件绑定
            $printLink
                .text('可打印版本')
                .off('click')
                .one('click', function (e) {
                    // 🔧 修复点:确保仅在点击时加载资源并触发弹窗
                    mw.loader.using(['oojs-ui-core', 'oojs-ui-widgets', 'oojs-ui-windows'])
                        .then(function () {
                            printOptions.createWindow();
                        })
                        .catch(function (err) {
                            mw.log.error('打印对话框加载失败:', err);
                        });
                    
                    e.preventDefault();
                    e.stopPropagation();
                });
            
            // 🚀 预加载资源(不影响主流程)
            mw.loader.load(['oojs-ui-core', 'oojs-ui-widgets', 'oojs-ui-windows']);
        },
        
        createWindow: function () {
            // 🔒 防止重复初始化
            if (printDialog) {
                windowManager.openWindow(printDialog);
                return;
            }
            
            // 🖥️ 对话框类定义
            function PrintDialog(config) {
                PrintDialog.super.call(this, config);
            }
            OO.inheritClass(PrintDialog, OO.ui.ProcessDialog);
            
            PrintDialog.static.name = 'printdialog';
            PrintDialog.static.title = '打印此页面';
            PrintDialog.static.actions = [
                { action: 'print', label: '打印', flags: ['primary', 'progressive'] },
                { action: 'cancel', label: '取消', flags: 'safe' }
            ];
            
            PrintDialog.prototype.initialize = function () {
                PrintDialog.super.prototype.initialize.apply(this, arguments);
                
                this.panel = new OO.ui.PanelLayout({ padded: true, expanded: false });
                this.content = new OO.ui.FieldsetLayout();
                
                // ✅ 动态生成选项
                printOptions.questions.forEach(function (question) {
                    if (question.type === 'checkbox') {
                        var checkbox = new OO.ui.CheckboxInputWidget({
                            selected: question.checked
                        });
                        question.widget = checkbox;
                        this.content.addItems([
                            new OO.ui.FieldLayout(checkbox, {
                                label: question.label,
                                align: 'inline'
                            })
                        ]);
                    }
                }, this);
                
                this.panel.$element.append(this.content.$element);
                this.$body.append(this.panel.$element);
            };
            
            PrintDialog.prototype.getActionProcess = function (action) {
                if (action === 'print') {
                    return new OO.ui.Process(function () {
                        // 📝 保存用户选择
                        printOptions.questions.forEach(function (question) {
                            if (question.type === 'checkbox' && question.widget) {
                                printOptions[question.returnvalue] = question.widget.isSelected();
                            }
                        });
                        
                        return this.close({ action: action }).then(function () {
                            // ⏳ 添加延迟确保弹窗关闭后再打印
                            setTimeout(function () {
                                printOptions.changePrintCSS();
                                printOptions.otherEnhancements();
                                window.print();
                                setTimeout(function () {
                                    location.reload(); // 恢复页面状态
                                }, 500);
                            }, 100);
                        });
                    }.bind(this));
                }
                return PrintDialog.super.prototype.getActionProcess.call(this, action);
            };
            
            // 🌐 初始化窗口管理器
            if (!windowManager) {
                windowManager = new OO.ui.WindowManager();
                windowManager.$element.css('z-index', '100000'); // 确保在最顶层
                $('body').append(windowManager.$element);
            }
            
            // 🆕 创建对话框实例(仅首次)
            printDialog = new PrintDialog({ size: 'medium' });
            windowManager.addWindows([printDialog]);
            windowManager.openWindow(printDialog); // 🎯 关键修复:确保点击后才打开
        },
        
        changePrintCSS: function () {
            /* 原有样式处理逻辑(保持不变)*/
            var printStyle = '';
            if (this.enhanced === false) {
                // ...(样式表处理代码)
            }
            if (this.noimages) printStyle += 'img, .thumb { display:none !important; }\n';
            if (this.norefs) printStyle += '.references, .reference { display:none !important; }\n';
            if (this.notoc) printStyle += '#toc, .toc { display:none !important; }\n';
            if (this.nobackground) printStyle += 'body { background: white !important; }\n';
            if (this.blacktext) printStyle += '* { color: black !important; }\n';
            
            if (printStyle) {
                $('head').append('<style media="print">' + printStyle + '</style>');
            }
        },
        
        otherEnhancements: function () {
            var $link = $('div.printfooter a');
            try {
                $link.text(decodeURIComponent($link.text()));
            } catch (e) {
                mw.log.warn('URL解码失败:', e);
            }
        },
        
        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'
            }
        ]
    };
    
    // 🚦 安全初始化(避免与其他脚本冲突)
    mw.hook('wikipage.content').add(function () {
        if (mw.config.get('wgNamespaceNumber') >= 0) {
            setTimeout(printOptions.install, 0); // 确保在最后执行
        }
    });
})();