Jump to content

User:TheDJ/printdialog.js

From Wikipedia, the free encyclopedia
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
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 );