( function ( mw, uw, $, OO ) { function LicensePreviewDialog( config ) { LicensePreviewDialog.parent.call( this, config ); } OO.inheritClass( LicensePreviewDialog, OO.ui.Dialog ); LicensePreviewDialog.static.name = 'licensePreviewDialog'; LicensePreviewDialog.prototype.initialize = function () { var dialog = this; LicensePreviewDialog.parent.prototype.initialize.call( this ); this.content = new OO.ui.PanelLayout( { padded: true, expanded: false } ); this.$body.append( this.content.$element ); this.$spinner = $.createSpinner( { size: 'large', type: 'block' } ) .css( { width: 200, padding: 20, 'float': 'none', margin: '0 auto' } ); $( 'body' ).on( 'click', function ( e ) { if ( !$.contains( dialog.$body.get( 0 ), e.target ) ) { dialog.close(); } } ); }; LicensePreviewDialog.prototype.addCloseButton = function () { var dialog = this, closeButton = new OO.ui.ButtonWidget( { label: OO.ui.msg( 'ooui-dialog-process-dismiss' ) } ); closeButton.on( 'click', function () { dialog.close(); } ); this.content.$element.append( closeButton.$element ); }; LicensePreviewDialog.prototype.getBodyHeight = function () { return this.content.$element.outerHeight( true ); }; LicensePreviewDialog.prototype.setLoading = function ( isLoading ) { if ( isLoading ) { this.content.$element.empty().append( this.$spinner ); this.addCloseButton(); } else { this.content.$element.empty(); } this.updateSize(); }; LicensePreviewDialog.prototype.setPreview = function ( html ) { this.content.$element.empty().append( html ); this.addCloseButton(); this.updateSize(); }; /** * Create a group of radio buttons for licenses. N.B. the licenses are named after the templates they invoke. * Note that this is very anti-MVC. The values are held only in the actual form elements themselves. * * @extends OO.ui.Widget * @param {Array|undefined} values License key name(s) to activate by default * @param {Object} config Configuration. Must have following properties: * @param {string} config.type Whether inclusive or exclusive license allowed ("and"|"or") * @param {string[]} config.licenses Template string names (matching keys in mw.UploadWizard.config.licenses) * @param {string[]} [config.licenseGroups] Groups of licenses, with more explanation * @param {string} [config.special] Indicates, don't put licenses here, instead use a special widget * @param {Number} count Number of the things we are licensing (it matters to some texts) * @param {mw.Api} api API object, used for wikitext previews */ mw.UploadWizardLicenseInput = function ( values, config, count, api ) { mw.UploadWizardLicenseInput.parent.call( this ); this.count = count; this.api = api; if ( config.type === undefined || ( config.licenses === undefined && config.licenseGroups === undefined ) ) { throw new Error( 'improper initialization' ); } this.$selector = this.$element; this.type = config.type === 'or' ? 'radio' : 'checkbox'; this.defaults = []; if ( config.defaults ) { this.defaults = config.defaults; } else if ( config.licenses && config.licenses[ 0 ] ) { this.defaults = [ config.licenses[ 0 ] ]; } mw.UploadWizardLicenseInput.prototype.count++; this.name = 'license' + mw.UploadWizardLicenseInput.prototype.count; // the jquery wrapped inputs (checkboxes or radio buttons) for this licenseInput. this.inputs = []; // create inputs and licenses from config if ( config.licenseGroups === undefined ) { this.createInputs( this.$selector, config ); } else { this.createGroupedInputs( this.$selector, config.licenseGroups ); } // set values of the whole license input if ( values ) { this.setValues( values ); } this.windowManager = new OO.ui.WindowManager(); $( 'body' ).append( this.windowManager.$element ); this.previewDialog = new LicensePreviewDialog(); this.windowManager.addWindows( [ this.previewDialog ] ); // [wikitext => list of templates used in wikitext] map, used in // getUsedTemplates to reduce amount of API calls this.templateCache = {}; }; OO.inheritClass( mw.UploadWizardLicenseInput, OO.ui.Widget ); $.extend( mw.UploadWizardLicenseInput.prototype, { count: 0, /** * Creates the license input interface in toggleable groups. * * @param {jQuery} $el Selector * @param {Object} configGroups License input configuration groups */ createGroupedInputs: function ( $el, configGroups ) { var input = this; $.each( configGroups, function ( i, group ) { var $body, $head, $licensesDiv, $group = $( '
' ).addClass( 'mwe-upwiz-deed-license-group' ); if ( group.head === undefined ) { // if there is no header, just append licenses to the group div. $body = $group; } else { // if there is a header, make a toggle-to-expand div and append inputs there. $head = $( '' ) .addClass( 'mwe-upwiz-deed-license-group-head mw-collapsible-toggle mw-collapsible-arrow' ) .msg( group.head, input.count ); $body = $( '
' ).addClass( 'mwe-upwiz-deed-license-group-body mw-collapsible-content' ); $group.append( $head, $body ).makeCollapsible( { collapsed: true } ); } if ( group.subhead !== undefined ) { $body.append( $( '
' ).addClass( 'mwe-upwiz-deed-license-group-subhead' ).msg( group.subhead, input.count ) ); } $licensesDiv = $( '
' ).addClass( 'mwe-upwiz-deed-license' ); input.createInputs( $licensesDiv, group ); $body.append( $licensesDiv ); input.$selector.append( $group ); } ); }, /** * append defined license inputs to element. * SIDE EFFECT: also records licenses and inputs in the object * * Abstracts out simple lists of licenses, more complex groups with layout * * @param {jQuery} $el Selector to which to add inputs * @param {Array} config License configuration, which must have a 'licenses' property, which is * an array of license names. It may also have: * * 'prependTemplates' or 'template', which alter the final wikitext value * * 'prependTemplates' will prepend Templates. If prependTemplates were [ 'pre', 'pended' ], * then [ 'fooLicense' ] -> "{{pre}}{{pended}}{{fooLicense}}" * * 'template' will filter Templates, as in "own work". If 'filterTemplate' was 'filter', * then [ 'fooLicense', 'barLicense' ] -> {{filter|fooLicense|barLicense}} */ createInputs: function ( $el, config ) { var input = this; if ( config.licenses === undefined || typeof config.licenses !== 'object' ) { throw new Error( 'improper license config' ); } $.each( config.licenses, function ( i, licenseName ) { var $customDiv, license, templates, $input, $label, customDefault; if ( mw.UploadWizard.config.licenses[ licenseName ] !== undefined ) { license = { name: licenseName, props: mw.UploadWizard.config.licenses[ licenseName ] }; templates = license.props.templates === undefined ? [ license.name ] : license.props.templates.slice( 0 ); $input = input.createInputElement( templates, config ); $label = input.createInputElementLabel( license, $input ); input.inputs.push( $input ); $el.append( $input, $label, $( '
' ) ); // TODO add popup help? $input.addClass( 'mwe-upwiz-copyright-info-radio' ); // this is so we can tell if a particular license ought to be set in setValues() $input.data( 'licenseName', licenseName ); if ( config.special === 'custom' ) { customDefault = mw.UploadWizard.config.licenses[ licenseName ].defaultText; $customDiv = input.createCustomWikiTextInterface( $input, customDefault ); $el.append( $customDiv ); $input.data( 'textarea', $customDiv.find( 'textarea' ) ); } } } ); }, /** * License templates are these abstract ideas like cc-by-sa. In general they map directly to a license template. * However, configuration for a particular option can add other templates or transform the templates, * such as wrapping templates in an outer "self" template for own-work * * @param {Array} templates Array of license template names * @param {Object} config License input configuration * @return {string} of wikitext */ createInputValueFromTemplateConfig: function ( templates, config ) { var wikiTexts; if ( config.prependTemplates !== undefined ) { $.each( config.prependTemplates, function ( i, template ) { templates.unshift( template ); } ); } if ( config.template !== undefined ) { templates.unshift( config.template ); templates = [ templates.join( '|' ) ]; } wikiTexts = $.map( templates, function ( t ) { return '{{' + t + '}}'; } ); return wikiTexts.join( '' ); }, /** * Return a radio button or checkbox with appropriate values, depending on config * * @param {Array} templates Array of template strings * @param {Object} config for this license input * @return {jQuery} wrapped input */ createInputElement: function ( templates, config ) { var input = this, attrs = { id: this.name + '_' + this.inputs.length, // unique id name: this.name, // name of input, shared among all checkboxes or radio buttons. type: this.type, // kind of input value: this.createInputValueFromTemplateConfig( templates, config ) }; return $( '' ).attr( attrs ).click( function () { input.emit( 'change' ); } ); }, /** * Get a label for the form element * * @param {Object} license License definition from global config. Will tell us the messages, and * maybe icons. * @param {jQuery} $input Wrapped input * @return {jQuery} wrapped label referring to that input, with appropriate HTML, decorations, etc. */ createInputElementLabel: function ( license, $input ) { var messageKey = license.props.msg === undefined ? '[missing msg for ' + license.name + ']' : license.props.msg, languageCode = mw.config.get( 'wgUserLanguage' ), // The URL is optional, but if the message includes it as $2, we surface the fact // that it's missing. licenseURL = license.props.url === undefined ? '#missing license URL' : license.props.url, licenseLink, $icons = $( '' ); if ( license.props.languageCodePrefix !== undefined ) { licenseURL += license.props.languageCodePrefix + languageCode; } licenseLink = $( '
' ).attr( { target: '_blank', href: licenseURL } ); if ( license.props.icons !== undefined ) { $.each( license.props.icons, function ( i, icon ) { $icons.append( $( '' ).addClass( 'mwe-upwiz-license-icon mwe-upwiz-' + icon + '-icon' ) ); } ); } return $( '