Utilisateur:Deep silence/MenuPopup.js
Apparence
Note : après avoir enregistré la page, vous devrez forcer le rechargement complet du cache de votre navigateur pour voir les changements.
Mozilla / Firefox / Konqueror / Safari : maintenez la touche Majuscule (Shift) en cliquant sur le bouton Actualiser (Reload) ou pressez Maj-Ctrl-R (Cmd-R sur Apple Mac) ;
Firefox (sur GNU/Linux) / Chrome / Internet Explorer / Opera : maintenez la touche Ctrl en cliquant sur le bouton Actualiser ou pressez Ctrl-F5./**
* MenuPopUp (MPU)
*
* Display a menu in a popup. This menu can be customized and contains any link or javascript code the user needs.
* Affiche un menu dans un popup. Ce menu peut être configuré pour contenir tous les liens ou code javascript que l'utilisateur souhaite.
*
* Add the following line in the monobook to activate the popups :
* Ajouter la ligne suivante au monobook pour activer les popups :
* importScript( "Utilisateur:Deep silence/MenuPopup.js" );
*
* The following parameters can be cutomized :
* Les paramètres qui suivent peuvent être modifiés par l'utilistateur :
* var MPU_key = 'a'; // name of the keybord key used to open the menu (Obligatoire/Mandatory)
* var MPU_modifier = 'Alt'; // name of the 'modifier' used to open the menu conjointly with the MPU_key (Optionnel/Optional, or 'Alt', 'Ctrl', 'Shift')
* var PMU_menu_definition = 'xxxxx' // content of the menu : see documentation bellow (Optionnel/Optional, uses default definition file is not defined)
* var PMU_menu_style = 'xxxxx' // style of the menu (Optionnel/Optional, uses default CSS file is not defined)
* var PMU_menu_refresh = true // set this parameter to true forces the cache refresh of the menu definition. It is usefull when updating a menu definition, but should be discarded once its definition is fixed. (Optionnel/Optional, uses 'false' by default)
*
* Auteurs : [[:fr:User:Deep silence]]
* License: GFDL
* Date de dernière révision : 27/04/2009
*
* MENU DEFINITION
* xxx:(title) //title in xxx menu (if 'xxxx' is not given, it is assumed for the main menu)
* xxx:------ //separator in xxx menu
* xxx:linklabel=linklabel // link
* xxx:menulabel->submenu // submenu
*
* submenu:(title) // title of submenu 'submenu'
* etc...
*
* KEYWORDS :
* %%USERNAME%% Name of the user
* %%_USERNAME_%% Name of the user with '_' as space
* %%PAGENAME%% Name of the current page
* %%_USERNAME_%% Name of the current page with '_' as space
* %%JJMMAAAA%% Date
* %%INSERT%%param1%%param2%%param3%% Insertion code : will insert 'param1' before the selected text, 'param2' after the selected text, will insert 'param3' at the caret place
* These three parameters are optional
*
*/
/*
*
* Fonctions et variables communes
*
*/
// DATES DU JOUR A DIFFERENTS FORMATS
var MPU_Mois = new Array('janvier','février','mars','avril','mai','juin','juillet','août','septembre','octobre','novembre','décembre');
var MPU_today = new Date();
var MPU_jjmmaa = MPU_today.getDate() + '_' + MPU_Mois[MPU_today.getMonth()] + '_' + (MPU_today.getYear() + 1900);
// NOM DE LA PAGE ACTUELLE (sans namespace)
if (typeof mw.config.get('wgPageName') == "undefined"){
MPU_pageName = "unknown"; // pour debugage en dehors de wikipedia
} else {
MPU_pageName = mw.config.get('wgPageName').replace(/_/g, ' ');
MPU_pageName_ = mw.config.get('wgPageName');
}
// NOM DU USER
if (typeof mw.config.get('wgUserName') == "undefined"){
MPU_userName = "user unknown"; // pour debugage en dehors de wikipedia
} else {
MPU_userName = mw.config.get('wgUserName');
MPU_userName_ = mw.config.get('wgUserName').replace(/ /g, '_') ;
}
/*
* FONCTION DE GESTION DES TOUCHES ENFONCEES
* retourne "Shift", "Ctrl", "Alt", séparés par "+",
* selon les touches enfoncées lors d'un clic de souris.
* (doit être appelée avec l'evenement du clic souris)
*/
function MPU_getAdditionalKey(event) {
event = (event ? event: window.event );
var ctrlPressed=event.ctrlKey;
var altPressed=event.altKey;
var shiftPressed=event.shiftKey;
var listResult = new Array;
if (shiftPressed) {
listResult.push("Shift");
}
if (altPressed) {
listResult.push("Alt");
}
if (ctrlPressed) {
listResult.push("Ctrl");
}
var result = "";
for (var i=0;i<listResult.length;i++){
if (i != 0){
result +="+";
}
result += listResult[i];
}
return result;
}
/*
* GESTION DE LA SOURIS
*/
document.onmousemove = MPU_getMouseXY;
var MPU_mousePositionX = 0
var MPU_mousePositionY = 0
// Main function to retrieve mouse x-y pos.s
function MPU_getMouseXY(event) {
event = (event ? event : window.event );
// rattrapage du scroll quand position des divs = 'fixed'
MPU_mousePositionX = (event.x ? event.x : event.clientX) + document.body.scrollLeft;
MPU_mousePositionY = (event.y ? event.y : event.clientY) + document.body.scrollTop;
return true
}
// for DOM parent
function MPU_addDOMElt(parentElt, tag, params){
var att;
var mn;
// TEXTNODE
if (typeof params == "undefined"){
mn = document.createTextNode(tag);
// DOM NODE
} else {
mn = document.createElement( tag );
for (var e=0; e<params.length; e++){
att = document.createAttribute(params[e][0]);
att.nodeValue = params[e][1];
mn.setAttributeNode(att);
}
}
parentElt.appendChild(mn);
return mn;
}
// for MPU object parent
function MPU_addContent(menuParent, tag, params){
var par = null;
if (menuParent == null || typeof menuParent == "undefined"){ // main menu
par = document.getElementsByTagName('body')[0];
} else { //sub menu
par = document.getElementById(menuParent.nom);
}
return MPU_addDOMElt(par, tag, params);
}
/*
*
* MENU POPUP PROTOTYPES
*
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ELEMENT : définit un élément de menu (parent racine)
function MPU_menuElement() {
this.menuParent = null; // default value, overiden for sub menus
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// MENU : contient une liste d options,
// qui peuvent être des liens, des fonctions
// javascript, ou des sous-menus
MPU_menuPopUp.prototype = new MPU_menuElement() ;
function MPU_menuPopUp(){
this.parent = MPU_menuElement;
this.parent();
this.contenu = new Array;
// nom du menu principal par defaut
this.nom = "menu_maincontext";
this.subMenuList = new Array; // liste des sous menus
}
// fonction d'ajout d'un élément au menu
MPU_menuPopUp.prototype.addElement = function( element ) {
// save any sub menu
if (element.sousMenu != null){
this.subMenuList.push( element.sousMenu );
element.sousMenu.menuParent = this;
}
// save the new element and link it back
this.contenu.push(element);
element.menuParent = this;
}
// fonction d'initialisation du menu
MPU_menuPopUp.prototype.initialiser = function( ) {
MPU_addContent(this.menuParent, 'div', [["id", this.nom], ["class", 'MPU_menu']]);
// initialise les lignes du menu
for(var a=0;a<this.contenu.length;a++){
this.contenu[a].initialiser();
}
// crée un lien de la balise vers l'objet menu
document.getElementById( this.nom ).menuObject = this;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// LIEN: définit un élément de menu de type lien
MPU_menuLien.prototype = new MPU_menuElement() ;
function MPU_menuLien(lib, addr){
this.parent = MPU_menuElement;
this.parent();
this.libelle = lib;
this.address = addr;
}
MPU_menuLien.prototype.initialiser = function() {
var elt = MPU_addContent(this.menuParent, 'div', [["class", 'MPU_lien'], ["onMouseOver", "MPU_closeSubMenus(null, '"+ this.menuParent.nom + "');"]]);
elt = MPU_addDOMElt(elt, 'a', [["href", this.address]]);
elt = MPU_addDOMElt(elt, this.libelle);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// LIGNE TITRE: définit un élément de menu de type titre
MPU_menuTitre.prototype = new MPU_menuElement() ;
function MPU_menuTitre(lib){
this.parent = MPU_menuElement;
this.parent();
this.libelle = lib;
}
MPU_menuTitre.prototype.initialiser = function() {
var elt = MPU_addContent(this.menuParent, 'div', [["class", 'MPU_title']]);
elt = MPU_addDOMElt(elt, 'b', []);
elt = MPU_addDOMElt(elt, this.libelle);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// SEPARATEUR: définit un élément de menu de ligne de séparation
MPU_menuSeparateur.prototype = new MPU_menuElement() ;
function MPU_menuSeparateur(){
this.parent = MPU_menuElement;
this.parent();
}
MPU_menuSeparateur.prototype.initialiser = function() {
MPU_addContent(this.menuParent, 'hr', []);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// SOUS MENU: définit un élément de menu de type lien vers un sous menu
MPU_sousMenuLien.prototype = new MPU_menuLien() ;
function MPU_sousMenuLien(lib, sousMenu){
this.parent = MPU_menuLien;
this.parent( lib , "#" );
this.sousMenu = sousMenu;
// renomage puisque devient sous-menu
this.sousMenu.nom = "menu_" + lib.replace(/ /,"");
}
MPU_sousMenuLien.prototype.initialiser = function() {
this.sousMenu.initialiser();
var elt = MPU_addContent(this.menuParent, 'div', [["class", 'MPU_menuLien'], ["onMouseOver", "MPU_closeSubMenus(null, '"+ this.menuParent.nom + "');MPU_openSubMenu( '"+this.sousMenu.nom+"')"]]);
MPU_addDOMElt(elt, this.libelle);
elt = MPU_addDOMElt(elt, 'div', [["class", 'MPU_menuLienFleche']] );
elt = MPU_addDOMElt(elt, 'b', [] );
MPU_addDOMElt(elt, '\u0020\u00BB' );
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
*
* MENU POPUP ESSENTIAL FUNCTIONS
*
*/
// fonction appelée pour ouvrir un menu
function MPU_openMainMenu( event ){
var key = (event ? event.which: window.event.keyCode );
if ( (String.fromCharCode(key)==MPU_key && (MPU_modifier=='' || MPU_getAdditionalKey((event ? event: window.event ))==MPU_modifier) && document.getElementById) ){
var menu = document.getElementById( "menu_maincontext" );
// vérifie si le menu dépasse de l'écran
var okDroite = (parseInt(MPU_mousePositionX) + parseInt(menu.offsetWidth) + 3) < window.innerWidth;
var okBas = (parseInt(MPU_mousePositionY) + parseInt(menu.offsetHeight) + 3) < window.innerHeight;
if (okBas){
menu.style.top = MPU_mousePositionY + 'px';
} else {
menu.style.top = (parseInt(MPU_mousePositionY) - 5 - parseInt(menu.offsetHeight)) + 'px';
}
if (okDroite){
menu.style.left = MPU_mousePositionX + 'px';
} else {
menu.style.left = (parseInt(MPU_mousePositionX) - 5 - parseInt(menu.offsetWidth)) + 'px';
}
menu.style.visibility = "visible";
}
}
// fonction appelée pour ouvrir un sous menu
// le nom indique quel sousmenu afficher
function MPU_openSubMenu( nom ){
if ( nom!=null && document.getElementById ){
var menu = document.getElementById( nom );
var menuParent = document.getElementById( menu.menuObject.menuParent.nom );
// vérifie si le menu dépasse de l'écran
var okDroite = (parseInt( menuParent.offsetLeft ) + parseInt( menuParent.offsetWidth ) + parseInt(menu.offsetWidth) ) < window.innerWidth;
var okBas = (parseInt( menuParent.offsetTop) + parseInt( menuParent.offsetHeight ) + parseInt(menu.offsetHeight) ) < window.innerHeight;
if (okDroite){
menu.style.left = parseInt( menuParent.offsetLeft ) + parseInt( menuParent.offsetWidth ) + 2 + 'px';
} else {
menu.style.left = parseInt( menuParent.offsetLeft ) - parseInt( menu.offsetWidth ) - 3 + 'px';
}
menu.style.visibility = "visible";
}
}
// fonction appelée pour fermer un menu ou un sous menu
// le nom en paramètre est null pour le menu ppal
function MPU_closeMenu(e, nom){
if (document.getElementById){
MPU_closeSubMenus(e, nom); // closes its submenus
if (nom == null){
nom = "menu_maincontext";
}
var menu = document.getElementById( nom );
menu.style.visibility = "hidden";
}
}
// fonction appelée pour fermer les sous menus d'un menu
// le nom en paramètre est null pour le menu ppal
function MPU_closeSubMenus(e, nom){
if (document.getElementById){
if (nom == null){
nom = "menu_maincontext";
}
var menu = document.getElementById( nom );
// ferme tous les sous menus
for (var i=0;i<menu.menuObject.subMenuList.length;i++){
MPU_closeMenu(e, menu.menuObject.subMenuList[i].nom);
}
}
}
// internal function used to get the user's menu definition file
function MPU_loadMenu_GetDefinitionFile()
{
var xmlhttp = false;
/* IE */
/*@cc_on
@if (@_jscript_version >= 5)
try
{
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e)
{
try
{
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (E)
{
xmlhttp = false;
}
}
@else
xmlhttp = false;
@end @*/
//try again with normal browsers
if (!xmlhttp && typeof XMLHttpRequest != 'undefined')
{
try
{
xmlhttp = new XMLHttpRequest();
}
catch (e)
{
xmlhttp = false;
}
}
if (xmlhttp)
{
/* on définit ce qui doit se passer quand la page répondra */
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState == 4) // 4 : état "complete"
{
if (xmlhttp.status == 200) // 200 : code HTTP pour OK
{
MPU_loadMenu_ParseDefinition(xmlhttp.responseText);
}
}
}
}
return xmlhttp;
}
// internal function used to get the parts of the user's menu
function MPU_loadMenu_GetMenu(name, create){
if (create == null){ // by default, creates the submenu if it does not exist
create = true;
}
var currentMenu;
if (name == ""){ // adds title to the main menu
currentMenu = MPU_menuPrincipal;
} else {
currentMenu = menusMap.Get(name);
if (create && typeof currentMenu == "undefined"){
currentMenu = new MPU_menuPopUp( );
menusMap.Set(name, currentMenu);
}
}
return currentMenu;
}
// function used to replace keywords (see MPU_PARSER_MENU_KEYWORDS)
// by their corresponding values
function MPU_loadMenu_ReplaceKeywords(str){
str = str.replace (/%%USERNAME%%/, MPU_userName);
str = str.replace (/%%_USERNAME_%%/, MPU_userName_);
str = str.replace (/%%PAGENAME%%/, MPU_pageName);
str = str.replace (/%%_PAGENAME_%%/, MPU_pageName_);
str = str.replace (/%%JJMMAAAA%%/, MPU_jjmmaa);
if (/%%INSERT%%([^%]*)%%([^%]*)%%([^%]*)%%/.exec(str)){
var p1 = RegExp.$1.replace(/'/g, "\\'");
var p2 = RegExp.$2.replace(/'/g, "\\'");
var p3 = RegExp.$3.replace(/'/g, "\\'");
str = str.replace (/%%INSERT%%([^%]*)%%([^%]*)%%([^%]*)%%/, "javascript:insertTags('"+p1+"','"+p2+"','"+p3+"');");
}
return str;
}
// function used to parse and create the user's menu definition file
function MPU_loadMenu_ParseDefinition(def) {
var MPU_PARSER_MENU_NOWIKI = /^\s*(<\s*pre\s*>)?\s*<\s*\/?\s*nowiki\s*>\s*(<\s*\/\s*pre\s*>)?\s*$/;
var MPU_PARSER_MENU_TITLE = /^\s*([^:]*)\s*:\s*\((.+)\)\s*$/;
var MPU_PARSER_MENU_SEPARATOR = /^\s*([^:]*)\s*:\s*-{2,}\s*$/;
var MPU_PARSER_MENU_LINK = /^\s*([^:]*)\s*:\s*([^=]+)\s*=\s*(.+)\s*$/;
var MPU_PARSER_MENU_SUB = /^\s*([^:]*)\s*:\s*([^()]+)\s*->\s*([^\s]+)\s*$/;
var defs = def.split("\n");
var l=defs.length;
var line;
var currentMenu;
var errorFound = false;
MPU_menuPrincipal = new MPU_menuPopUp();
menusMap = {
Set : function(key, menu) {this[key] = menu;},
Get : function(key) {return this[key];}
}
for (var i=0; i<l; i++){
line = defs[i];
if (! /^ *$/.test(line)){
if (MPU_PARSER_MENU_NOWIKI.exec( line )){
// skipped
} else if (MPU_PARSER_MENU_TITLE.exec( line )){
currentMenu = MPU_loadMenu_GetMenu(RegExp.$1);
currentMenu.addElement( new MPU_menuTitre( MPU_loadMenu_ReplaceKeywords(RegExp.$2) ) );
} else if (MPU_PARSER_MENU_SEPARATOR.exec( line )){
currentMenu = MPU_loadMenu_GetMenu(RegExp.$1);
currentMenu.addElement( new MPU_menuSeparateur( ) );
} else if (MPU_PARSER_MENU_LINK.exec( line )){
currentMenu = MPU_loadMenu_GetMenu(RegExp.$1);
currentMenu.addElement( new MPU_menuLien( MPU_loadMenu_ReplaceKeywords(RegExp.$2), MPU_loadMenu_ReplaceKeywords(RegExp.$3) ));
} else if (MPU_PARSER_MENU_SUB.exec( line )){
currentMenu = MPU_loadMenu_GetMenu(RegExp.$1);
currentMenu.addElement( new MPU_sousMenuLien( RegExp.$2, MPU_loadMenu_GetMenu(RegExp.$3) ) );
} else {// shows unparsed lines at the bottom of the menu
errorFound = true;
currentMenu = MPU_loadMenu_GetMenu("unknown");
currentMenu.addElement( new MPU_menuTitre( line) );
}
}
}
if (errorFound) { // shows unparsed lines at the bottom of the menu
MPU_menuPrincipal.addElement( new MPU_sousMenuLien( "ERRORS" , MPU_loadMenu_GetMenu("unknown") ) );
}
// toujours à faire en dernier
MPU_menuPrincipal.initialiser();
}
/////////////////////////////////////////////////////////////////////////////////////////////
// INITIALISATIONS
// 1. evenements
// 2. Loads CSS
// 3. menu
/////////////////////////////////////////////////////////////////////////////////////////////
function MPU_INIT($){
var url;
// 1. Loads CSS
if (typeof PMU_menu_style == "undefined"){
url = "Utilisateur:Deep_silence/MenuPopup.css";
} else {
url = "Utilisateur:" + MPU_userName_ +"/"+ PMU_menu_style;
}
var MPU_fileref=document.createElement("link");
MPU_fileref.setAttribute("rel", "stylesheet");
MPU_fileref.setAttribute("type", "text/css");
MPU_fileref.setAttribute("href", "/w/index.php?title="+ url +"&action=raw&ctype=text/css");
document.getElementsByTagName("head")[0].appendChild( MPU_fileref );
// 2. Loads menu
if (typeof PMU_menu_definition == "undefined"){
url = "Utilisateur:Deep silence/MenuDefinitionDéfaut";
} else {
url = "Utilisateur:" + MPU_userName_ +"/"+ PMU_menu_definition;
}
var xmlhttp = MPU_loadMenu_GetDefinitionFile();
if (typeof PMU_menu_refresh != "undefined" && PMU_menu_refresh){
url += "&maxage=0&smaxage=0";
} else {
url += "&maxage=1800&smaxage=1800";
}
xmlhttp.open("GET", "/w/index.php?title="+ url +"&action=raw&ctype=text/css" ,true);
xmlhttp.send(null);
// 3. initialise les évenements
document.onkeypress = MPU_openMainMenu;
document.onclick = MPU_closeMenu;
}
$(MPU_INIT);