MediaWiki:Gadget-PrintOptions.js

/**

* 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.

*/

( function () {

'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,

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';

}

}

}

/* 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-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( '' );

}

},

/* 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 );

} );

} );

}

}() );