نکته: پس از انتشار ممکن است برای دیدن تغییرات نیاز باشد که حافظهٔ نهانی مرورگر خود را پاک کنید.

  • فایرفاکس / سافاری: کلید Shift را نگه دارید و روی دکمهٔ Reload کلیک کنید، یا کلید‌های Ctrl-F5 یا Ctrl-R را با هم فشار دهید (در رایانه‌های اپل مکینتاش کلید‌های ⌘-R)
  • گوگل کروم: کلیدهای Ctrl+Shift+R را با هم فشار دهید (در رایانه‌های اپل مکینتاش کلید‌های ⌘-Shift-R)
  • اینترنت اکسپلورر/ Edge: کلید Ctrl را نگه‌دارید و روی دکمهٔ Refresh کلیک کنید، یا کلید‌های Ctrl-F5 را با هم فشار دهید
  • اپرا: Ctrl-F5 را بفشارید.
/*

Permet de fournir des suggestions de page pour un champ de saisie

Documentation : [[Projet:JavaScript/Notices/Suggest]]

{{Catégorisation JS|Suggest}}

*/

// ************************************ VARIABLES GLOBALES ***********************
var Suggest_Params = new Array();

///////////////////////////////// Variables personnalisables

Suggest_Params["ZIndex"] = 5;                                            // Propriété "z-index" de départ
Suggest_Params["TitleCaseSensitive"] = false;                            // Première lettre du titre sensible à la casse
Suggest_Params["ImgSrc"] = new Array(                                    // Icônes :
   "//upload.wikimedia.org/wikipedia/commons/d/d1/Icon_no.png",     // « n'existe pas »
   "//upload.wikimedia.org/wikipedia/commons/a/a7/Icon_yes.png"     // « existe »
 );
Suggest_Params["ImgTitle"] = new Array(                                  // Pop-up :
   "La page « $1 » n'existe pas",                                        // « n'existe pas »
   "La page « $1 » existe"                                               // « existe »
 );

///////////////////////////////// Variables non personnalisables

Suggest_Params["Input"] = new Array();                                   // Matrice des <input> (champ de saisie)
Suggest_Params["Suggest"] = new Array();                                 // Matrice des <select> (liste de suggestions)
Suggest_Params["ExistInput"] = new Array();                              // Matrice des <input> (page existe ou pas)
Suggest_Params["ExistImg"] = new Array();                                // Matrice des <img> (page existe ou pas)
Suggest_Params["IsRunning"] = new Array();                               // Matrice de l'état de la requête de suggestions
Suggest_Params["NSFilter"] = new Array();                                // Matrice de l'option de filtrage par espace de noms
Suggest_Params["StripNS"] = new Array();                                 // Matrice de l'option d'affichage de l'espace de noms
Suggest_Params["SuggestLimit"] = new Array();                            // Matrice de la limite des suggestions
Suggest_Params["SuggestSelectLimit"] = new Array();                      // Matrice de la taille de la liste de suggestions
Suggest_Params["ListDown"] = new Array();                                // Matrice de l'affichage de la liste de suggestions
Suggest_Params["AddExist"] = new Array();                                // Matrice de l'affichage de l'icône
Suggest_Params["Prefix"] = new Array();                                  // Matrice des préfixes de filtrage
Suggest_Params["Suffix"] = new Array();                                  // Matrice des suffixes de filtrage
Suggest_Params["RedirectFilter"] = new Array();                          // Matrice des filtrages de redirection
Suggest_Params["Index"] = 1;                                             // Index de départ (id)

// Valeurs par défaut
Suggest_Params["NSFilter"][0] = false;
Suggest_Params["StripNS"][0] = false;
Suggest_Params["SuggestLimit"][0] = 10;
Suggest_Params["SuggestSelectLimit"][0] = 5;
Suggest_Params["ListDown"][0] = false;
Suggest_Params["AddExist"][0] = false;
Suggest_Params["Prefix"][0] = false;
Suggest_Params["Suffix"][0] = false;
Suggest_Params["RedirectFilter"][0] = "all";


// ************************************ CRÉATION SUGGESTION D'ESPACE DE NOMS ***********************

function Suggest_AddNamespaceSuggestion(ID, CLASS){
     if(typeof(mw.config.get('wgFormattedNamespaces'))=="undefined") return;
     var AllNS = new Array();
     var Options = new Array();
     for(var NS in mw.config.get('wgFormattedNamespaces')){
          if(NS<0) continue;
          AllNS.push(NS);
          var Value = (mw.config.get('wgFormattedNamespaces')[NS]==="" ? "(Main)" : mw.config.get('wgFormattedNamespaces')[NS]);
          var Option = document.createElement('option');
          Option.value = NS;
          Option.appendChild(document.createTextNode(Value));
          Options.push(Option);
     }
     var AllOption = document.createElement('option');
     AllOption.value = AllNS.join("|");
     AllOption.appendChild(document.createTextNode("*"));
     Options.unshift(AllOption);
     var Select = document.createElement('select');
     if(ID) Select.id = ID;
     if(ID) Select.name = ID;
     if(CLASS) Select.className = CLASS;
     for(var a=0,l=Options.length;a<l;a++){
          Select.appendChild(Options[a]);
     }
     return Select;
}

// ************************************ CRÉATION SUGGESTION DE PAGE ***********************

function Suggest_AddPageSuggestion(Args){
     if(!Args) return;
     var InputNode = Args["InputNode"];
     if(!InputNode) return;
     var GlobalIndex = Suggest_Params["Index"]++;
     var NSFilter = (Args["NSFilter"] ? Args["NSFilter"] : Suggest_Params["NSFilter"][0] );
     var StripNS = (Args["StripNS"] ? Args["StripNS"] : Suggest_Params["StripNS"][0] );
     var SuggestLimit = (Args["SuggestLimit"] ? Args["SuggestLimit"] : Suggest_Params["SuggestLimit"][0] );
     var SuggestListSize = (Args["SuggestListSize"] ? Args["SuggestListSize"] : Suggest_Params["SuggestSelectLimit"][0] );
     var AddExist = (Args["AddExist"] ? Args["AddExist"] : Suggest_Params["AddExist"][0] );
     var ListDown = (Args["ListDown"] ? Args["ListDown"] : Suggest_Params["ListDown"][0]);
     var Prefix = (Args["Prefix"] ? Args["Prefix"] : Suggest_Params["Prefix"][0]);
     var Suffix = (Args["Suffix"] ? Args["Suffix"] : Suggest_Params["Suffix"][0]);
     var RedirectFilter = (Args["RedirectFilter"] ? Args["RedirectFilter"] : Suggest_Params["RedirectFilter"][0]);
     Suggest_UpDateLabel(InputNode, "InputWithSuggestion_"+GlobalIndex);
     InputNode.id = "InputWithSuggestion_"+GlobalIndex;
     var ExistInputNode = document.createElement("input");
     ExistInputNode.type = "hidden";
     ExistInputNode.id = "ThisPageExist_"+GlobalIndex;
     ExistInputNode.value = "0";
     InputNode.parentNode.insertBefore(ExistInputNode, InputNode.nextSibling);
     if(AddExist===true){
          var ExistImgNode = document.createElement("img");
          ExistImgNode.id = "ThisPageExistIMG_"+GlobalIndex;
          ExistImgNode.width = 20;
          ExistImgNode.height = 20;
          ExistImgNode.src = Suggest_Params["ImgSrc"][0];
          ExistImgNode.className = "SuggestionExist";
          InputNode.parentNode.insertBefore(ExistImgNode, InputNode.nextSibling);
     }
     var SelectNode = document.createElement('select');
     SelectNode.id = "SuggestionForInput_"+GlobalIndex
     SelectNode.style.display = "none";
     SelectNode.className = "SuggestionList";
     InputNode.parentNode.insertBefore(SelectNode, InputNode.nextSibling);
     Suggest_Params["Input"][GlobalIndex] = InputNode;
     Suggest_Params["Suggest"][GlobalIndex] = SelectNode;
          Suggest_Params["ExistInput"][GlobalIndex] = ExistInputNode;
     if(AddExist===true){
          Suggest_Params["ExistImg"][GlobalIndex] = ExistImgNode;
     }
     Suggest_Params["NSFilter"][GlobalIndex] = NSFilter;
     if(!NSFilter) StripNS = false;
     if(Prefix){
          if(NSFilter){
               var ThisNamespaceName = mw.config.get('wgFormattedNamespaces')[NSFilter];
               var Match = new RegExp("^"+ThisNamespaceName+":", "ig");
               if(Prefix.match(Match)!=null){
                    Prefix = Prefix.substring((ThisNamespaceName=="" ? "" : ThisNamespaceName+":").length, Prefix.length);
               }
               StripNS = true;
          }
     }
     Suggest_Params["StripNS"][GlobalIndex] = StripNS;
     Suggest_Params["Prefix"][GlobalIndex] = Prefix;
     Suggest_Params["Suffix"][GlobalIndex] = Suffix;
     Suggest_Params["SuggestLimit"][GlobalIndex] = SuggestLimit;
     Suggest_Params["SuggestSelectLimit"][GlobalIndex] = SuggestListSize;
     Suggest_Params["ListDown"][GlobalIndex] = ListDown;
     Suggest_Params["AddExist"][GlobalIndex] = AddExist;
     Suggest_Params["RedirectFilter"][GlobalIndex] = RedirectFilter;
     Suggest_Params["IsRunning"][GlobalIndex] = false;
     InputNode.onkeyup = function(){
          var ThisIndex = Suggest_GetSuggestionIndex(this);
          Suggest_GetSuggestions(ThisIndex);
     }
     return GlobalIndex;
}

// ************************************ MISE A JOUR DU LABEL ***********************

function Suggest_UpDateLabel(InputNode, NewID){
     var OldId = InputNode.id;
     if(!OldId) return;   
     var Labels = document.getElementsByTagName('label');
     for(var a=0,l=Labels.length;a<l;a++){
          var For = Labels[a].getAttribute("for");
          if(For){
               if(For == OldId){
                    Labels[a].setAttribute("for", NewID);
                    return;
               }
          }
     }
}

// ************************************ LANCEMENT REQUÊTE SUGGESTIONS ***********************

function Suggest_GetSuggestions(Index){
     var IsRunning = Suggest_Params["IsRunning"][Index];
     if(IsRunning===true) return;

     var NamespaceFilter = Suggest_Params["NSFilter"][Index];
     var StripNamespace = Suggest_Params["StripNS"][Index];
     var Limit = Suggest_Params["SuggestLimit"][Index];
     var Select = Suggest_Params["Suggest"][Index];
     var Input = Suggest_Params["Input"][Index];
     var Prefix = Suggest_Params["Prefix"][Index];
     var Suffix = Suggest_Params["Suffix"][Index];
     var RedirectFilter = Suggest_Params["RedirectFilter"][Index];
     var Page = Input.value;
     if(Page===""){
          Select.style.display = "none";
          return;
     }
     var ValueNamespace = (NamespaceFilter ? NamespaceFilter : Suggest_GetNamespaceInfoFormPage((Prefix+Page),"NamespaceNumber"));
     var ValuePageName = Suggest_GetNamespaceInfoFormPage(Page, "PageName");
     if(StripNamespace && NamespaceFilter && !Prefix){
          var ThisNamespaceName = mw.config.get('wgFormattedNamespaces')[NamespaceFilter];
          var Match = new RegExp("^"+ThisNamespaceName+":", "ig");
          if(Page.match(Match)!=null){
               Page = ValuePageName;
          }
          Input.value = Suggest_ucFirst(Page);
     }else if(Prefix && NamespaceFilter){
          Match = new RegExp("^"+Prefix, "ig");
          if(Page.match(Match)!=null){
               Page = Page.substring(Prefix.length, Page.length);
          }
          Input.value = Page;
          Page = Prefix+Page;
     }else if(Prefix && !NamespaceFilter){
          Page = Suggest_GetNamespaceInfoFormPage((Prefix+Page), "PageName");
     }else if(!Prefix && !NamespaceFilter){
          ValueNamespace = Suggest_GetNamespaceInfoFormPage(Page,"NamespaceNumber");
          Page = Suggest_GetNamespaceInfoFormPage(Page, "PageName");
     }
     Suggest_Params["IsRunning"][Index] = true;
     var APILimit = ( ((mw.config.get('wgUserGroups').indexOf("sysop")!=-1)||(mw.config.get('wgUserGroups').indexOf("bot")!=-1)) ? 4999 : 499 );
     if(Limit>APILimit) Limit = APILimit;
     var URL =  "/api.php?format=xml&action=query&list=allpages"
              + "&apnamespace=" + ValueNamespace
              + "&apprefix=" + Page.replace(/&/g, "%26")
              + "&apfilterredir=" + RedirectFilter
              + "&aplimit=" + Limit;
 
     var SuggestRequest = new sajax_init_object() ;
     SuggestRequest.open('GET', mw.config.get('wgServer') + mw.config.get('wgScriptPath') + URL, true);
     SuggestRequest.onreadystatechange = function () {
          if (SuggestRequest.readyState != 4) return;
          var xml = SuggestRequest.responseXML ;
          if ( xml == null ) return ;
          var titles = new Array () ;
          var pages = xml.getElementsByTagName("p") ;
          for(var i=0;i<pages.length;i++){
               var s = pages[i].getAttribute("title");
               if(Suffix){
                    var Reg = new RegExp(Suffix+"$", "g")
                    if(s.match(Reg)==null) continue;
               }
               if(StripNamespace){
                    var ThisNamespaceName = mw.config.get('wgFormattedNamespaces')[NamespaceFilter];
                    var Match = new RegExp("^"+ThisNamespaceName+":", "ig");
                    if(s.match(Match)!=null){
                         s = Suggest_GetNamespaceInfoFormPage(s, "PageName");
                    }
               }
               if(Prefix){
                    s = s.substring(s.indexOf(Prefix)+Prefix.length, s.length);
               }
               if(titles.indexOf(s)==-1) titles.push(s);
          }
          Suggest_Params["IsRunning"][Index] = false;
          Suggest_ShowSuggestions(titles, Index);
     };
     SuggestRequest.send(null);
}

// ************************************ AFFICHAGE SUGGESTIONS ***********************

function Suggest_ShowSuggestions(titles, Index){
     var Select = Suggest_Params["Suggest"][Index];
     var Input = Suggest_Params["Input"][Index];
     var ExistInputNode = Suggest_Params["ExistInput"][Index];
     var ExistImgNode = Suggest_Params["ExistImg"][Index];
     var ListDown = Suggest_Params["ListDown"][Index];
     var NamespaceFilter = Suggest_Params["NSFilter"][Index];
     var Prefix = Suggest_Params["Prefix"][Index];
     var TheNamespace = "";
     if(NamespaceFilter!==false){
          TheNamespace = mw.config.get('wgFormattedNamespaces')[NamespaceFilter];
          TheNamespace = (TheNamespace ==="" ? "" : TheNamespace+":");
     }
     if(Prefix){
          TheNamespace += Prefix;
     }
     var CurrentValue = Input.value;
     if(ExistInputNode) ExistInputNode.value = "0";
     if(ExistImgNode){
          ExistImgNode.src = Suggest_Params["ImgSrc"][0];
          ExistImgNode.title = Suggest_Params["ImgTitle"][0].split("$1").join(TheNamespace+CurrentValue);
          ExistImgNode.alt = Suggest_Params["ImgTitle"][0].split("$1").join(TheNamespace+CurrentValue);
     }
     if(titles.length==0){
          Select.style.display = "none" ;
          Input.title = ""; 
          return;
     }
     Select.style.display = "inline" ;
     if(ExistInputNode) ExistInputNode.value = "1";
     if(ExistImgNode){
          ExistImgNode.src = Suggest_Params["ImgSrc"][1];
          ExistImgNode.title = Suggest_Params["ImgTitle"][1].split("$1").join(TheNamespace+CurrentValue);
          ExistImgNode.alt = Suggest_Params["ImgTitle"][1].split("$1").join(TheNamespace+CurrentValue);
     }
     if(titles[0]===Input.value){
          Select.style.display = "none" ;
          Input.title = ""; 
          return;
     }
     var TailleListe = Suggest_Params["SuggestSelectLimit"][Index];
     if (titles.length < TailleListe ) TailleListe = titles.length;
     Select.size = TailleListe ;
     Select.style.align = "right" ;
     Select.style.zIndex = Suggest_Params["ZIndex"]++ ;
     Select.style.position = "relative" ;
     Select.style.width = Input.offsetWidth + "px" ;
     Select.style.height = (TailleListe * 20) + "px" ;
     while(Select.firstChild) Select.removeChild(Select.firstChild);
     for ( var i = 0 ; i < titles.length ; i++ ) {
          var opt = document.createElement("option");
          var ot = document.createTextNode(titles[i]);
          opt.appendChild(ot) ;
          opt.value = titles[i];
          Select.appendChild(opt) ;
     }
     Select.onkeyup = Suggest_ReplaceSuggestionsKeyPress;
     Select.onclick = Suggest_ReplaceSuggestions;
     if(ListDown){
          Select.style.top = parseInt(Input.offsetHeight) + "px";
          Select.style.marginBottom = "-" + ((TailleListe * 20) + parseInt(Input.offsetHeight)) + "px" ;
     }else{
          Select.style.marginTop = "-" + (TailleListe * 20) + "px" ;
     }
     Select.style.marginRight = "-" + Input.offsetWidth + "px" ;
     var suggestion = titles[0] ;
     if(suggestion.match(new RegExp("^"+CurrentValue))==null){
          Suggest_GetSuggestions(Index);
          return;
     }
     var StripNamespace = Suggest_Params["StripNS"][Index];
     var CurrentValueLength = CurrentValue.length;
     if(StripNamespace){
          var NamespaceName = Suggest_GetNamespaceInfoFormPage(CurrentValue,"NamespaceName");
          NamespaceName = ( NamespaceName==="" ? "" : NamespaceName+":");
          if(NamespaceName==TheNamespace){
               CurrentValueLength = Suggest_GetNamespaceInfoFormPage(CurrentValue,"PageName").length + TheNamespace.length;
          }
     }else if(NamespaceFilter!==false && !Prefix){
          var NamespaceName = Suggest_GetNamespaceInfoFormPage(CurrentValue,"NamespaceName");
          NamespaceName = ( NamespaceName==="" ? "" : NamespaceName+":");
          if(NamespaceName==TheNamespace){
               CurrentValueLength = Suggest_GetNamespaceInfoFormPage(CurrentValue,"PageName").length + TheNamespace.length;
          }else{
               CurrentValueLength = CurrentValueLength  + TheNamespace.length;
          }
     }
     //alert("CurrentValueLength : "+CurrentValueLength+"\nsuggestion.length : "+suggestion.length);
     Input.value = suggestion;
     Input.title = TheNamespace + suggestion;
     if (Input.createTextRange) {
          var ra = Input.createTextRange();
          ra.moveStart("character", CurrentValueLength);
          ra.moveEnd("character", suggestion.length);
          ra.select();
     } else if( Input.setSelectionRange ) {
          Input.setSelectionRange( CurrentValueLength, suggestion.length );
     } else {
          Input.selectionStart = CurrentValueLength;
          Input.selectionEnd = suggestion.length ;
     }
     if(ExistImgNode){
          CurrentValue = Input.value;
          ExistImgNode.src = Suggest_Params["ImgSrc"][1];
          ExistImgNode.title = Suggest_Params["ImgTitle"][1].split("$1").join(TheNamespace+CurrentValue);
          ExistImgNode.alt = Suggest_Params["ImgTitle"][1].split("$1").join(TheNamespace+CurrentValue);
     }
}

// ************************************ SÉLECTION D'UNE SUGGESTION (CLAVIER) ***********************

function Suggest_ReplaceSuggestionsKeyPress(e){
     if (!e) var e = window.event;
     if (e.keyCode != 13) return;
     Suggest_ReplaceSuggestions();
}

// ************************************ APPLICATION D'UNE SUGGESTION ***********************

function Suggest_ReplaceSuggestions(){
     var Index = Suggest_GetSuggestionIndex(this);
     var Select = Suggest_Params["Suggest"][Index];
     var Input = Suggest_Params["Input"][Index];
     if(!Input|| !Select) return;
     var NamespaceFilter = Suggest_Params["NSFilter"][Index];
     var Prefix = Suggest_Params["Prefix"][Index];
     var TheNamespace = "";
     if(NamespaceFilter){
          TheNamespace = mw.config.get('wgFormattedNamespaces')[NamespaceFilter];
          TheNamespace = (TheNamespace ==="" ? "" : TheNamespace+":");
     }
     if(Prefix){
          TheNamespace += Prefix;
     }
     Select.style.zIndex = Suggest_Params["ZIndex"]++ ;
     var Options = Select.getElementsByTagName('option');
     for(var a=0;a<Options.length;a++){
          if(Options[a].selected){
            Input.value = Options[a].value;
            Input.title = TheNamespace+Options[a].value;
            Input.focus();
            Suggest_GetSuggestions(Index);
            return;
        }
    }
}

// ************************************ RÉCUPÉRATION N° D'INDEX ***********************

function Suggest_GetSuggestionIndex( Element ){
    return parseInt(Element.id.replace(/[^0-9]/g, ""));
}

// ************************************ RÉCUPÉRATION INFORMATIONS NAMESPACE ***********************

function Suggest_GetNamespaceInfoFormPage(Page, ToReturn){
     if(!ToReturn) ToReturn = false;
     var NamespaceNumber = 0;
     var NamespaceName = "";
     var PageName = Page;
     var Found = false;
     for(var NS in mw.config.get('wgFormattedNamespaces')){
          if(Found) continue;
          var ThisNamespaceName = mw.config.get('wgFormattedNamespaces')[NS];
          if(ThisNamespaceName==="") continue;
          var NamespaceNameRegExp = new RegExp("^"+ThisNamespaceName+":", "ig");
          var Matches = Page.match(NamespaceNameRegExp);
          if(Matches!=null && Matches.length == 1){
               NamespaceNumber = parseInt(NS);
               NamespaceName = ThisNamespaceName;
               PageName = Page.replace(NamespaceNameRegExp, "");
               Found = true;
          }
     }

     if(ToReturn==="NamespaceName") return NamespaceName;
     if(ToReturn==="PageName") return PageName;
     return NamespaceNumber;
}

// ************************************ PREMIÈRE LETTRE EN MAJUSCULE ***********************
 
function Suggest_ucFirst(Text) {
    if(Suggest_Params["TitleCaseSensitive"]) return Text;
    return Text.substr(0,1).toUpperCase() + Text.substr(1,Text.length);
}