MediaWiki:Gadget-CustomSidebar.js

Da Wikipedia, l'ençiclopedia libara.

Ocio: Daspò ver salvà, podaria esare neçesario snetare ła cache dal propio navegadore web par vedare i canbiamenti.

  • Firefox / Safari: tegner strucà el boton de łe letare grande Shift e schiciare sora Ricarga, o se nò struca Ctrl-F5 o Ctrl-R (⌘-R so Mac)
  • Google Chrome: strucare Ctrl-Shift-R (⌘-Shift-R so on Mac)
  • Internet Explorer / Edge: tegner strucà el boton Ctrl e schiciare so Ajorna, o sinò Ctrl-F5
  • Opera: Va in tel Menu → Inpostasion (Opera → Prefarense so on Mac) e pò in Privacy & sicuresa → Sneta dati del navegadore → Imajini e file in te ła cache.
/*
* DA [[:fr:MediaWiki:Gadget-CustomSidebar.js]]
* CustomSidebar
*
* ...
*
* {{Projet:JavaScript/Script|CustomSidebar}}
*/
/* <nowiki> */

/* globals mw, OO, $ */

mw.loader.using( [ 'mediawiki.util', 'oojs-ui.styles.icons-interactions', 'oojs-ui-widgets' ], function () {
    'use strict';

    // Site-related parameters
    const PREFID = 'userjs-customsidebar',
          PORTLETID = 'p-cs';
    
    const MAGIC_WORDS = {
        day: 'dì',
        week: 'stimana',
        month: 'mexe',
        monthname: 'nome del mexe',
        year: 'ano',
        page: 'voxe',
        title: 'tìtuło',
        diff: 'diff',
        user: 'utensa'
    };
    
    const MONTH_NAMES = [
    	'xenaro',
    	'febraro',
    	'marso',
    	'april',
    	'majo',
    	'xugno',
    	'lujo',
    	'agosto',
    	'setenbre',
    	'otobre',
    	'novenbre',
    	'disenbre'
    ];
    
    const deltaDayRegex = new RegExp( '{ *' + MAGIC_WORDS.day + '([\+\-][0-9]+) *}' ),
		deltaWeekRegex = new RegExp( '{ *' + MAGIC_WORDS.week + '([\+\-][0-9]+) *}' ),
		deltaMonthRegex = new RegExp( '{ *(?:' + MAGIC_WORDS.month + '|' + MAGIC_WORDS.monthname + ')([\+\-][0-9]+) *}' ),
		deltaYearRegex = new RegExp( '{ *' + MAGIC_WORDS.year + '([\+\-][0-9]+) *}' ),
		dayRegex = new RegExp( '{ *' + MAGIC_WORDS.day + '([\+\-][0-9]+)* *}', 'g' ),
		weekRegex = new RegExp( '{ *' + MAGIC_WORDS.week + '([\+\-][0-9]+)* *}', 'g' ),
		monthRegex = new RegExp( '{ *' + MAGIC_WORDS.month + '([\+\-][0-9]+)* *}', 'g' ),
		monthnameRegex = new RegExp( '{ *' + MAGIC_WORDS.monthname + '([\+\-][0-9]+)* *}', 'g' ),
		yearRegex = new RegExp( '{ *' + MAGIC_WORDS.year + '([\+\-][0-9]+)* *}', 'g' ),
		pageRegex = new RegExp( '{ *' + MAGIC_WORDS.page + ' *}', 'g' ),
		titleRegex = new RegExp( '{ *' + MAGIC_WORDS.title + ' *}', 'g' ),
		diffRegex = new RegExp( '{ *' + MAGIC_WORDS.diff + ' *}', 'g' ),
		userRegex = new RegExp( '{ *' + MAGIC_WORDS.user + ' *}', 'g' );

    // global vars
    var $links,
        links = [];

    var isBootstrapped = false;
	var instanceWindowManager;
	var instanceSidebarEditor;


    /**
     * I18N Messages
     */
    const messages = {
        'fr': {
            'cside-portlet-label': 'I me lighi',
            'cside-edit-title': 'Xontar o cavar lighi',
            'cside-edit-label': 'Canbiar i lighi',
            'sidebareditor-title': 'Costumar el menù laterałe',
            'sidebareditor-nolinkmessage': 'Nisun ligo cuà.<br>Xònteło doparando el boton cuà xo!',
            'sidebareditor-action-save': 'Salvar',
            'sidebareditor-action-cancel': 'Descançełar',
            'sidebareditor-action-add': 'Xontar',
            'sidebareditor-action-delete': 'Cavar',
            'sidebareditor-notif-success': 'La costumasion del menù laterałe ła xe sta salvada.',
            'cside-linkfield-label': 'Testo inte el menù',
            'cside-linkfield-target': 'Nome voxe o linganbo foresto',
            'cside-linkfield-target-help': 'Sto canpo el połe cntegner on ligo interior o foresto. Le parołe màxeghe łe consente de canbiar denamegamente determenai vałori : {$1}, {$2}, {$3}, {$4}, {$5}, {$6}, {$7}, {$8} et {$9}. Le prime parołe màxeghe łe połe èsar conpagnar on nùmaro par canbiarghe el perìodo; par exénpio {$1-2} par l/ altro ieri o {$4+1} par el mexe che vegnarà.',
        }
    };
    mw.messages.set( messages.fr );
    var lang = mw.config.get( 'wgUserLanguage' );
    if ( lang !== 'vec' && lang in messages ) {
        mw.messages.set( messages[ lang ] );
    }


    /**
     * ...
     */
    function fetchLinks() {
        var fetchedLinks,
            raw = mw.user.options.get( PREFID );

        // If there is nothing stored, default to an empty array
        if ( raw === null ) {
            return [];
        }

        fetchedLinks = JSON.parse( raw );
        if ( ! Array.isArray( fetchedLinks ) ) {
            return [];
        }

        return fetchedLinks;
    }

    function createPortlet() {
        var portlet = $( '<div class="portal" role="navigation" id="' + PORTLETID + '" aria-labelledby="' + PORTLETID + '-label">' ),
            title = $( '<h3 id="' + PORTLETID + '-label">' ).text( mw.msg( 'cside-portlet-label' ) ).appendTo( portlet ),
            wrapper = $( '<div class="body">' ).appendTo( portlet ),
            editButton = new OO.ui.ButtonWidget( {
                framed: false,
                icon: 'settings',
                label: mw.msg( 'cside-edit-label' ),
                invisibleLabel: true,
                title: mw.msg( 'cside-edit-title' ),
                classes: [ 'cs-editbutton' ]
            } );
        editButton.$element.prependTo( portlet );
        $links = $( '<ul>' ).prependTo( wrapper );

        // Manage events
        editButton.on( 'click', function() {
            mw.loader.using( [ 'oojs-ui', 'mediawiki.notification' ], function() {
                bootstrapOnce();
                instanceSidebarEditor.open();
            } );

        } );
        
        // Add the new portlet to the DOM
        $( '#p-tb' ).after( portlet );
    }

	// Returns the ISO week of the date.
	function getWeek( d ) {
		var date = new Date(d.getTime());
		date.setHours(0, 0, 0, 0);
		// Thursday in current week decides the year.
		date.setDate(date.getDate() + 3 - (date.getDay() + 6) % 7);
		// January 4 is always in week 1.
		var week1 = new Date(date.getFullYear(), 0, 4);
		// Adjust to Thursday in week 1 and count number of weeks from date to week1.
		return 1 + Math.round(((date.getTime() - week1.getTime()) / 86400000 - 3 + (week1.getDay() + 6) % 7) / 7);
	}
	
	function daysInYear( year ) {
		if ( year % 4 === 0 ) { // Should be fixed if we approch year 2100
			return 366;
		}
		return 365;
	}

	function daysInMonth( month, year ) {
	    return new Date( year, month + 1, 0 ).getDate();
	}

    function fillPortlet( links ) {
        var i, j, target, today, deltaDay, deltaWeek, deltaMonth, deltaYear, coef, offset;

        // Empty the portlet in case of a second run
        $links.empty();

        // Fill the portlet with all the given links
        for ( i = 0; i < links.length; i++ ) {
            target = links[ i ][ 0 ];
            today = new Date();

            // Change the date if asked to
            deltaDay = parseInt( ( deltaDayRegex.exec( target ) || [0,0])[1]);
            deltaWeek = parseInt( ( deltaWeekRegex.exec( target ) || [0,0])[1]);
            deltaMonth = parseInt( ( deltaMonthRegex.exec( target ) || [0,0])[1]);
            deltaYear = parseInt( ( deltaYearRegex.exec( target ) || [0,0])[1]);
            if ( mw.config.get( 'debug' ) === true ) {
				console.log( '===', links[ i ][ 1 ] );
				console.log( 'deltaDay', deltaDay );
				console.log( 'deltaWeek', deltaWeek );
				console.log( 'deltaMonth', deltaMonth );
				console.log( 'deltaYear', deltaYear );
            }
            
            today.setTime( today.getTime() + ( ( deltaDay + ( deltaWeek * 7 ) ) * 24 * 3600 * 1000 ) );
            coef = deltaMonth < 0 ? -1 : 1;
            offset = deltaMonth < 0 ? -1 : 0;
            for ( j = Math.abs( deltaMonth ); j > 0; j--) {
            	today.setTime( today.getTime() + ( coef * daysInMonth( today.getMonth() + offset, today.getYear() ) * 24 * 3600 * 1000 ) );
            }
            coef = deltaYear < 0 ? -1 : 1;
            offset = deltaYear < 0 ? -1 : 0;
            for ( j = Math.abs( deltaYear ); j > 0; j--) {
            	today.setTime( today.getTime() + ( coef * daysInYear( today.getYear() + offset ) * 24 * 3600 * 1000 ) );
            }
            
            // Render magic words
            target = target.replace( dayRegex, today.getDate() );
            target = target.replace( weekRegex, getWeek( today ) );
            target = target.replace( monthRegex, ( today.getMonth() + 1 ) );
            target = target.replace( monthnameRegex, MONTH_NAMES[ today.getMonth() ] );
            target = target.replace( yearRegex, today.getFullYear() );
            target = target.replace( pageRegex, mw.config.get( 'wgPageName' ) );
            target = target.replace( titleRegex, mw.config.get( 'wgTitle' ) );
            target = target.replace( diffRegex, mw.config.get( 'wgRevisionId' ) );
            target = target.replace( userRegex, mw.config.get( 'wgRelevantUserName' ) || '' );
            
            // Convert internal links to URL
            if ( ! ( target.lastIndexOf( 'https://', 0) === 0 || target.lastIndexOf( 'http://', 0) === 0 ) ) {
                target = mw.util.getUrl( target );
            }
            
            mw.util.addPortletLink( PORTLETID, target, links[ i ][ 1 ] );
        }
    }


    /**
     * Main function
     */
    $( function ( $ ) {
        links = fetchLinks();
        createPortlet();
        fillPortlet( links );
    } );


    // Instanciate SidebarEditor and add it to MediaWiki's UI.
    function bootstrapOnce() {
        if (isBootstrapped) {
            return;
        }

        isBootstrapped = true;

        /**
		 * Main class of the configuration windows SidebarEditor,
		 * which is displayed as a ProcessDialog
		 *
		 * @class
		 * @extends OO.ui.ProcessDialog
		 *
		 * @constructor
		 */
        var SidebarEditor = function () {
            // Initialize config
            var config = { size: 'large' };

            // Parent constructor
            SidebarEditor.parent.call( this, config );

            // Properties
            this.api = new mw.Api( { timeout: 7000 } );

            // Graphical properties
            this.linkFields = [];
            this.$noLinkMessage = $( '<p class="cs-nolinkmessage">' ).html( mw.msg( 'sidebareditor-nolinkmessage' ) );
            this.content = new OO.ui.PanelLayout( { padded: true, expanded: false } );
            this.layout = new OO.ui.Widget( { content: [] } );
            this.$body;
        };

        /* Setup */
        OO.inheritClass( SidebarEditor, OO.ui.ProcessDialog );

        /* Static Properties */
        SidebarEditor.static.name = 'sidebareditor';
        SidebarEditor.static.title = mw.msg( 'sidebareditor-title' );
        SidebarEditor.static.actions = [
            { action: 'save', label: mw.msg( 'sidebareditor-action-save' ), flags: [ 'primary', 'progressive' ] },
            { action: 'cancel', label: mw.msg( 'sidebareditor-action-cancel' ), flags: [ 'safe', 'back' ] },
            { action: 'add', label: mw.msg( 'sidebareditor-action-add' ), flags: 'other' }
        ];

        /* ProcessDialog-related Methods */

        /**
		 * Build the interface displayed inside the ProcessDialog box.
		 */
        SidebarEditor.prototype.initialize = function () {
            var i = 0;
            SidebarEditor.parent.prototype.initialize.apply( this, arguments );
            
            for ( i = 0; i < links.length; i++ ) {
                this.addField( links[ i ][ 0 ], links[ i ][ 1 ] );
            }

            this.content.$element.append( this.$noLinkMessage );
            this.content.$element.append( this.layout.$element );
            this.$body.append( this.content.$element );

            this.setSize( this.size );
            this.updateSize();
        };

        /**
		 * Get a process for taking action.
		 *
		 * This method is called within the ProcessDialog when the user clicks
		 * on an action button (the one defined in SidebarEditor.static.actions).
		 * @param {string} action Name of the action button clicked.
		 * @return {OO.ui.Process} Action process.
		 */
        SidebarEditor.prototype.getActionProcess = function ( action ) {
            var process = new OO.ui.Process();

            if ( action === 'cancel' || action === '' ) { // empty string when closing with Escape key
                process.next( this.closeDialog, this );
            }
            else if ( action === 'add' ) {
                process.next( this.addField, this );
            }
            else if ( action === 'save' ) {
                process.next( this.save, this )
                    .next( this.success, this )
                    .next( this.closeDialog, this );
            }

            return process;
        };

        /**
		 * Close the window.
		 *
		 * @return {jQuery.Promise} Promise resolved when window is closed
		 */
        SidebarEditor.prototype.closeDialog = function () {
            var dialog = this;

            var lifecycle = dialog.close();

            return lifecycle.closed;
        };

        /**
		 * Get the height of the window body.
		 * Used by the ProcessDialog to set an accurate height to the dialog.
		 *
		 * @return {number} Height in px the dialog should be.
		 */
        SidebarEditor.prototype.getBodyHeight = function () {
            return 400; //this.content.$element.outerHeight( true );
        };

        /* Process step methods */
        SidebarEditor.prototype.addField = function ( target, label ) {
            var i = this.linkFields.push( new LinkField( target, label ) );
            this.linkFields[ i - 1 ].on( 'delete', this.removeField.bind( this, this.linkFields[ i - 1 ] ) );
            this.layout.$element.append( this.linkFields[ i - 1 ].$element );
            this.$noLinkMessage.hide();
        };

        SidebarEditor.prototype.removeField = function ( field ) {
            var i = this.linkFields.indexOf( field );
            
            this.linkFields[ i ].$element.detach();
            this.linkFields.splice( i, 1 );
            
            if ( this.linkFields.length === 0 ) {
                this.$noLinkMessage.show();
            }
        };

        SidebarEditor.prototype.save = function () {
            var i;
            this.newLinks = [];

            for ( i = 0; i < this.linkFields.length; i++ ) {
                this.newLinks.push( this.linkFields[ i ].getValue() );
            }

            return this.api.saveOption( PREFID, JSON.stringify( this.newLinks ) );
        };

        SidebarEditor.prototype.success = function () {
            // Reload the sidebar with the new links
            fillPortlet( this.newLinks );
            links = this.newLinks;

            // Notify the user that it's a success!
            mw.notification.notify( mw.msg( 'sidebareditor-notif-success' ), { autoHide: true } );
        };
        

        /**
		 * ...
		 *
		 * @class
		 * @extends OO.ui.Widget
		 *
		 * @constructor
		 */
        var LinkField = function ( target, label, config ) {
            // Initialize config
            config = config || {};

            // Parent constructor
            LinkField.parent.call( this, config );

            // Properties
            this.api = new mw.Api( { timeout: 15000 } );

            // Graphical properties
            this.targetTextInput = new OO.ui.TextInputWidget( {
                value: target,
                
            } );
            this.labelTextInput = new OO.ui.TextInputWidget( {
                value: label,
            } );
            this.deleteButton = new OO.ui.ButtonWidget( {
                icon: 'trash',
                framed: false,
                label: mw.msg( 'sidebareditor-action-delete' ),
                invisibleLabel: true,
                title: mw.msg( 'sidebareditor-action-delete' ),
                flags: [ 'destructive' ]
            } );
            
            // Layouts
            var line1 = new OO.ui.ActionFieldLayout( this.labelTextInput, this.deleteButton, {
                align: 'left',
                label: mw.msg( 'cside-linkfield-label' )
            } );
            var line2 = new OO.ui.FieldLayout( this.targetTextInput, {
                align: 'left',
                label: mw.msg( 'cside-linkfield-target' ),
                help: mw.msg( 'cside-linkfield-target-help', MAGIC_WORDS.day, MAGIC_WORDS.week, MAGIC_WORDS.month, MAGIC_WORDS.monthname, MAGIC_WORDS.year, MAGIC_WORDS.page, MAGIC_WORDS.title, MAGIC_WORDS.diff, MAGIC_WORDS.user )
            } );
            
            // Events
            this.deleteButton.on( 'click', this.emit.bind( this, 'delete' ) );
            
            // Add all those widgets to the layout
            this.$element.append( line1.$element )
                .append( line2.$element );
            this.$element.addClass( 'cs-linkfield' );
        };

        /* Setup */
        OO.inheritClass( LinkField, OO.ui.Widget );

        LinkField.prototype.getValue = function () {
            return [ this.targetTextInput.getValue(), this.labelTextInput.getValue() ];
        };


        instanceWindowManager = new OO.ui.WindowManager();
        $( 'body' ).append( instanceWindowManager.$element );

        instanceSidebarEditor = new SidebarEditor();
        instanceWindowManager.addWindows( [ instanceSidebarEditor ] );
    }

} );

/* </nowiki> */
Traesto fora da Wikipèdia - L'ençiclopedia łìbara e cołaboradiva in łéngua Vèneta "https://vec.wikipedia.org/w/index.php?title=MediaWiki:Gadget-CustomSidebar.js&oldid=849231"