Wikipedia:Technik/Baustellen/projectNotice/Implementierungsvorschlag PerfektesChaos

Der nachstehende Code wurde aus vorhandenen Bröseln zusammengekittet; er wurde noch niemals gestartet, enthält möglicherweise noch Detailfehler, gibt aber einen Eindruck, wie ich mir das so vorstelle.

Features

Bearbeiten

Er arbeitet mit dem Nachfolger der watchlist-message und unterstützt auch automatisch die Abspeicherung des bisherigen site-notice-Klicks auf dem Server. Wie bisher wird nur mittels JS etwas angezeigt.

Nicht angemeldete Benutzer

Bearbeiten

Nicht angemeldete Benutzer würden die Nachrichten auch sehen können; haben aber keine Beo, jedoch BD und auch die Hauptseite.

  • Verbergen geht; abspeichern der Kenntnisnahme mangels Account aber nicht.
  • Ersatzweise wird im localStorage des Browsers gespeichert.
  • Das Feature MediaWiki:Anonnotice wird sinngemäß unterstützt: Wird eine Nachrichten-Zeichenkette in eckige (Array-)Klammern gesetzt, dann sehen das nur angemeldete; wird dem als Array-Element ein true angehängt, sehen das nur die nicht angemeldeten Benutzer.

MediaWiki:Gadget-projectNotice.js

Bearbeiten
/* gadget-projectNotice 2013-11-20 PerfektesChaos@de.wikipedia */
/*jshint curly:true, forin:false, latedef:true, laxbreak:true,
         strict:true, trailing:true, undef:true, white:false           */
/*global window:false                                                  */
( function ( mw ) {
   "use strict";
   // Nächste unbenutzte ID: 43
   var launch,
       o = false,
       siteNotice = mw.config.get( "wgSiteNoticeId" );
// Bei Nichtgebrauch den folgenden Block einfach löschen:
o = { "42": "<div class='hintergrundfarbe8' style='border: 1px solid #bbb padding: 3px'>"
            + "Beteiligt Euch an der Wahl zur Wiki-Weltregierung."
            + " Mehr unter [[WP:Wiki-Weltregierung]].</div>"
    };

   // Ab hier bitte nur nach Diskussion ändern.
   if ( siteNotice  ||  ( o  &&  typeof o === "object" ) ) {
      if ( siteNotice ) {
         launch = true;
      } else {
         launch = false;
         switch ( mw.config.get( "wgNamespaceNumber" ) ) {
            case -1 :
               switch ( mw.config.get( "wgCanonicalSpecialPageName" ) ) {
                  case "Watchlist" :
                  case "Notifications" :
                     launch = true;
                     break;
               }   // switch wgCanonicalSpecialPageName
               break;
            case 2 :
            case 3 :
               launch = ( mw.config.get( "wgTitle" )
                          ===
                          mw.config.get( "wgUserName" ) );
               break;
            case 4 :
               launch = ( mw.config.get( "wgTitle" ) === "Hauptseite" );
               // Autorenportal, Über Uns usw.?
               break;
         }   // switch wgNamespaceNumber
      }
      if ( launch ) {
         mw.libs.projectNotice = { broadcast: o,
                                   siteNotice: siteNotice };
         mw.loader.load( "//de.wikipedia.org/w/index.php?title="
                         + "MediaWiki:Gadget-projectNotice/core.js"
                         + "&action=raw&ctype=text/javascript"
                         + "&maxage=604800&*",
                         "" );
      }
   }
}( window.mediaWiki ) );

+ /editnotice mit Kopiervorlage und Link zu mehr Infos.

MediaWiki:Gadget-projectNotice/core.js

Bearbeiten
/* gadget-projectNotice/core 2013-11-26 PerfektesChaos@de.wikipedia */
/*jshint curly:true, forin:false, latedef:true, laxbreak:true,
         strict:true, trailing:true, undef:true, white:false           */
/*global window:false                                                  */
( function ( mw, $ ) {
   "use strict";
   var NOTICE,
       MaxRememberIDs = 5,
       Self           = "projectNotice",
       Separator      = "~",
       StorageID      = "userjs-gadget-" + Self;
   mw.libs[ Self ] = mw.libs[ Self ]  ||  { };
   NOTICE = mw.libs[ Self ];
   NOTICE.vsn = "2013-11-26";



   function fire() {
      // Initialize processing
      // Uses:
      //    >  .broadcast
      //    >  StorageID
      //    >  Separator
      //     < .lazy
      //     < .received
      //    mw.user.options.get()
      //    (furnish)
      var i, s, seen, v;
      NOTICE.lazy = mw.user.isAnon();
      if ( NOTICE.siteNotice ) {
         NOTICE.siteNotice = "SiteNotice_" + NOTICE.siteNotice;
      }
      if ( NOTICE.lazy ) {
         if ( window.localStorage ) {
            seen = window.localStorage.getItem( StorageID );
         }
      } else {
         seen = mw.user.options.get( StorageID );
      }
      if ( seen ) {
         NOTICE.received = seen.split( Separator );
         for ( i = 0;  i < NOTICE.received.length;  i++ ) {
            s = NOTICE.received[ i ];
            if ( NOTICE.broadcast[ s ] ) {
               delete NOTICE.broadcast[ s ];
            }
         }   // for i
      }
      for ( s in NOTICE.broadcast ) {
         v = NOTICE.broadcast[ s ];
         if ( typeof v  ===  "object" ) {
            if ( v[ 1 ] == NOTICE.lazy ) {   // mixed types
               NOTICE.broadcast[ s ] = v[ 0 ];
            } else {
               delete NOTICE.broadcast[ s ];
            }
         }
      }   // for s in .broadcast
      if ( ! $.isEmpty( NOTICE.broadcast ) ) {
         $( furnish );
      }
   }   // fire()



   function flip( $assign, assigned ) {
      // Equip clickable with click function
      // Precondition:
      //    $assign   -- jQuery clickable
      //    assigned  -- ID of notice
      $assign.click( function () {  flush( assigned );  } );
   }   // flip()



   function flush( assigned ) {
      // Dismiss button / link has been clicked
      // Precondition:
      //    assigned  -- ID of notice
      // Uses:
      //    >  .board
      //    >  .received
      //    >  MaxRememberIDs
      //    >  Separator
      //    >  mw.Api
      //     < .store
      //    (forward)
      var got, k, request,
          $item = NOTICE.board[ assigned ];
      if ( $item ) {
         $item.hide();
      }
      got = NOTICE.received  ||  [ ];
      got.push( assigned );
      k = got.length - MaxRememberIDs;
      if ( k > 0 ) {
         got = got.slice( k );
      }
      NOTICE.store = got.join( Separator );
      if ( NOTICE.lazy ) {
         if ( window.localStorage ) {
            window.localStorage.setItem( StorageID, NOTICE.store );
         }
      } else {
         request = new mw.Api();
         request.get( { "action": "tokens",
                        "type":   "options" } )
                .done( forward );
      }
   }   // flush()



   function foreign( access, assigned ) {
      // Equip siteNotice extension message or others with server memory
      // Precondition:
      //    siteNotice active
      //    document ready
      //    access    -- selector
      //    assigned  -- ~ wgSiteNoticeId etc.
      var i,
          $elt = $( access );
      if ( $elt.length ) {
         for ( i = 0;  i < NOTICE.received.length;  i++ ) {
            if ( NOTICE.received[ i ] === assigned ) {
               $elt.hide();
               $elt = false;
               break;   // for i
            }
         }   // for i
         if ( $elt ) {
            flip( $elt.find( "a" ), assigned );
         }
      }
   }   // foreign()



   function forward( arrived ) {
      // Store IDs of all dismissed messages
      // Precondition:
      //    arrived  -- JSON result of ajax query for optionstoken
      // Uses:
      //    >  mw.Api
      //    >  .store
      var pars, request, token;
      if ( typeof arrived   ===  "object" ) {
         token = arrived.tokens;
         if ( token ) {
            pars = { "action":      "options",
                     "token":       token.optionstoken,
                     "optionname":  StorageID,
                     "optionvalue": NOTICE.store
                   };
            request = new mw.Api();
            request.post( pars );
         }
      }
   }   // forward()



   function furnish() {
      // Equip page with notices
      // Precondition:
      //    document ready
      // Uses:
      //    >  Self
      //    >  .broadcast
      //    >  mw.util.$content
      //     < .board
      var s, store, v, $btn, $item,
          ltr = true,
          pars = [ mw.config.get( "wgUserName" ) ],
          sign = "gadget-" + Self,
          $button = $(  mw.html.element( "button",
                                         { type: "button" } ) ),
          $label = $(  mw.html.element( "span",
                                        { style: "color:#FF0000;"
                                                 + "font-weight:bolder;"
                                        } ) ),
          $wrap = $(  mw.html.element( "div",
                                        { id:    sign,
                                          class: "watchlist-message"
                                        } ) );
      $label.text( "X" );
      $button.css( "float",  ( ltr ? "right" : "left" ) );
      $button.append( $label );
      NOTICE.board = { };
      for ( s in NOTICE.broadcast ) {
         v = NOTICE.broadcast[ s ];
         if ( typeof v === "string" ) {
            store = sign + "-" + s;
            mw.messages.set( store, v );
            $item = $( mw.message( store, pars ).parse() );
            $btn  = $button.clone();
            flip( $btn, s );
            $item.append( $btn );
            $wrap.append( $item );
            NOTICE.board[ s ] = $item;
         }
      }   // for s in .broadcast
      $( "#siteNotice" ).prepend( $wrap );
      // Alternativ  mw.util.$content.prepend( $wrap )  falls nicht immer
      if ( NOTICE.siteNotice ) {
         foreign( ".mw-dismissable-notice-close", NOTICE.siteNotice );
      }
   }   // furnish()



   if ( typeof NOTICE.broadcast === "object" ) {
      mw.loader.using( [ "user.options",
                         "mediawiki.api",
                         "mediawiki.jqueryMsg",
                         "mediawiki.user",
                         "mediawiki.util" ],
                       fire );
   }
}( window.mediaWiki, window.jQuery ) );


  • Auf üppige Ausstattung der Elemente mit class= und id= wurde verzichtet. Benutzer sollen die Nachrichten nicht umdekorieren, sondern lesen und wegklicken.
  • Auf Failure-Apparat beim Abspeichern wurde ebenfalls verzichtet. Wenn die API mal streikt, erscheint die Meldung halt auf einer anderen Seite nochmal. Wenn es einen systematischen Fehler gibt, weiß sich das Debugging-Personal zu helfen.
  • $1 in der Nachricht ist übrigens der Benutzername.

Anwendungsobjekt

Bearbeiten
  • mw.libs.projectNotice ist kaum zu vermeiden, um die aktuellen Werte nach /core.js zu übermitteln.
    • sessionStorage wäre eine Alternative; aber nicht bei älteren Browsern und teils aus Datenschutzgründen deaktiviert.
    • Schadet ja auch nichts.
  • Die Funktionen sind zurzeit privat; könnten aber bei Bedarf als API public gestellt werden, etwa die Speicherung der ID.
  • Die Daten stehen zurzeit offen; auch zum schnelleren Debuggen.