Jump to content

User:TheDJ/printdialog.js

From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
/*global jQuery, mediaWiki */
(function( $, mw ) {
	'use strict';
	var windowManager;
	var printDialog;

	var printOptions = {
		install: function () {
			$( '#t-print a' )
				.click( function ( e ) {
					mw.loader.using( ['oojs-ui-core', 'oojs-ui-widgets', 'oojs-ui-windows'] ).done( printOptions.createWindow );
					e.preventDefault();
				} )
				.text( 'Print page' );
			// 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.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() {
							/* The browser's animation and the .done are not synchronized,
							 * so they race eachother. delay with a further 300ms to avoid
							 * the dialog still being in view while printing */
							setTimeout(function() {
								printOptions.changePrintCSS();
								printOptions.otherEnhancements();
								window.print();
								window.location = window.location;
							}, 300);
						});
					} );
				}
				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 ) {
		$( printOptions.install );
	}
} ) ( jQuery, mediaWiki );