MediaWiki:Gadget-PrintOptions.js

Jump to navigation Jump to search

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.
/**
 * Print options is a Gadget writen by Derk-Jan Hartman / User:TheDJ
 * For more information see [[User:TheDJ/Print_options]]
 * 
 * Licensed MIT and/or CC-by-SA 4.0
Copyright (c) 2010-2017 Derk-Jan Hartman / User:TheDJ

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

 */
/*global jQuery, mediaWiki */
(function( $, mw ) {
	'use strict';
	var windowManager;
	var printDialog;

	var printOptions = {
		install: function () {
			var $printLink = $( '#t-print a' );
			if ( $printLink.length === 0 ) {
				return;
			}
			$printLink
				.text( 'Print page' )
				.off( 'click' )
				.get( 0 ).addEventListener( 'click', function ( e ) {
					mw.loader.using( ['oojs-ui-core', 'oojs-ui-widgets', 'oojs-ui-windows'] ).done( printOptions.createWindow );
					e.stopPropagation();
					e.preventDefault();
				}, true ); // Use capturing phase, to beat the other click handler
			
			// Late pre-loading
			mw.loader.load( ['oojs-ui-core', 'oojs-ui-widgets', 'oojs-ui-windows'] );
		},

		createWindow: function () {
			function PrintDialog ( config ) {
				PrintDialog.super.call( this, config );
			}
			OO.inheritClass( PrintDialog, OO.ui.ProcessDialog );
			
			PrintDialog.static.name = 'printdialog';
			PrintDialog.static.title = 'Print this page';
			PrintDialog.static.actions = [
				{action: 'print', label: 'Print', flags: 'primary'},
				{label: 'Cancel', flags: 'safe' }
			];
			
			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 );   
			};
			
			PrintDialog.prototype.getActionProcess = function ( action ) {
				var dialog = this;
				if ( action === 'print' ) {
					return new OO.ui.Process( function () {
						// Get values of checkboxes
						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 () {
			/* Here we:
				 - disable stylesheets that are print specific
				 - make screen specific stylesheets also enabled for print medium
				 - remove print specific stylerules
				 - make screen specific stylerules also enabled for print medium
			*/
			var printStyle = '';
			if( this.enhanced === false ) {
 				var i, j, k,
 					rule,
				 	hasPrint,
				 	hasScreen,
				 	rules,
					stylesheet,
					disabled,
				 	stylesheets = document.styleSheets;

				for( i = 0; i < stylesheets.length; i++ ) {
					stylesheet = stylesheets[i];
					disabled = false;
					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';
							}
						}
					}

					/* now test individual stylesheet rules */
					try {
						rules = stylesheet.cssRules || stylesheet.rules;
					} catch( e ) {
						/* Cross domain issue. */
						mw.log.warn( 'Not possible to correct stylesheet due to cross origin restrictions.' );
						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';
							}
						}
					}
				}
			}
			/* Add css to hide images */
			if( this.noimages ) {
				printStyle += 'img, .thumb {display:none;}\n';
			}
			/* Add css to hide references markers and the references lists */
			if( this.norefs ) {
				printStyle += '.mw-headline[id="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>' );
			}
		},

		/* Rewrite the "retrieved from" url to be readable */
		otherEnhancements: function () {
			var link = $( 'div.printfooter a' );
			link.text( decodeURI( link.text() ) );
		},

		questions: [
			{
				label: "Hide interface elements",
				type: "checkbox",
				checked: true,
				returnvalue: 'enhanced'
			},
			{
				label: 'Hide images',
				type: 'checkbox',
				checked: false,
				returnvalue: 'noimages'
			},
			{
				label: 'Hide references',
				type: 'checkbox',
				checked: false,
				returnvalue: 'norefs'
			},
			{
				label: 'Hide Table of Contents',
				type: 'checkbox',
				checked: false,
				returnvalue: 'notoc'
			},
			{
				label: 'Remove backgrounds (Your browser might or might not override this)',
				type: 'checkbox',
				checked: false,
				returnvalue: 'nobackground'
			},
			{
				label: 'Force all text to black',
				type: 'checkbox',
				checked: true,
				returnvalue: 'blacktext'
			}
		]
	};

	if ( mw.config.get( 'wgNamespaceNumber' ) >= 0 ) {
		$( function() {
			// This can be before the click handler by MW is installed. Instead,
			// re-add ourselves to the back of the document.ready list
			// use async timeoute to do this
			setTimeout( function() {
				$( printOptions.install );
			}, 0);
		} );
	}
} ) ( jQuery, mediaWiki );