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
BearbeitenEr 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
BearbeitenNicht 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=
undid=
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
Bearbeitenmw.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.