Wikipédia:Brouillons/interface ajax/js

//<syntaxhighlight lang="javascript" line>
/**
 * Scriptus
 *
 * La fonction Scriptus sert à rédiger sur wikipédia de manière naturelle, 
 * par simple doubleclic et confimation de sauvegarde. 
 * La définition de ce script se trouve ici : 
 * http://fr.wikipedia.org/wiki/Wikip%C3%A9dia:Brouillons/interface_ajax
 *
 * Le code du script est librement inspiré du système de modification-inline 
 * de Olivier Lance
 * http://olance.developpez.com/articles/web/javascript/modification-inline/
 *
 * Auteurs : ivo talvet (fr:user:Tavernier) , JoKerozen (fr:user:JoKerozen)
 * Date de dernière révision : 15 octobre 2007
 * copié-collé depuis 
 * http://fr.wikipedia.org/w/index.php?title=MediaWiki:JSScripts/Scriptus&oldid=21566322
 *
 * oldid tokens via action=edit
 * http://fr.wikipedia.org/w/index.php?title=Wikip%C3%A9dia:Brouillons/interface_ajax/js&oldid=21985960
 * oldid clic section
 * http://fr.wikipedia.org/w/index.php?title=Wikip%C3%A9dia:Brouillons/interface_ajax/js&oldid=23786371
 * oldid bouton test -> sous5
 * http://fr.wikipedia.org/w/index.php?title=Wikip%C3%A9dia:Brouillons/interface_ajax/js&oldid=24260671
 *
 * @todo : pouvoir modifier plusieurs paragraphes avant d'envoyer le concaténat au serveur
 * @todo : convertir les fonctions en méthodes et regrouper en une seule classe ?
 */

/**
 * Fait quelques tests préliminaires puis
 * place des eventListeners là où on veut que le script réagisse
 */
function Scriptus() {
    if (!wgIsArticle) return; 
    if (wgNamespaceNumber & 1) return; //si impair (discussion), retour
    if (/^Wikipédia:(Le_Bistro|Bulletin_des_administrateurs|Questions_techniques)/.test(wgPageName)
        || document.getElementById('transformeEnPageDeDiscussion')
       ) return; 

    $('#mw-content-text')
        .children('p')
        .addClass('scParagraphe')
        .dblclick(function () {
            findBlocScriptus(this);
        });
}

/**
 * Une fois un évènement capturé, effectue la requête de 
 * wikitexte à la bdd en fonction du numéro de section
 */
function findBlocScriptus(clicSur) {
    if (document.getElementsByTagName('textarea').length) return;

    var paragraphes = $('.scParagraphe');

    for (var index=0; index<paragraphes.length; index++) {
        if (paragraphes[index] == clicSur) break;
    }

    var xhrRawSource = wpajaxScriptus.http({ url: wgServer + wgScriptPath
                               +'/index.php?title='
                               + encodeURIComponent(mw.config.get('wgPageName'))
                               + '&action=raw&maxage=0',
                           async: false,
                           });

    var rawSource = xhrRawSource.responseText;

    var blocsTous = new Array();
    var flagIter = 0;
    var paragraphes = new Array();
    var flagIterParagraphe = 0;
    var ruptures = ['\n\n', '\n=', '\n*', '\n#', '\n;', '\n:', '{{', '<'];

    for (var iter=0; iter <= rawSource.length ; iter++) {
        if (iter == 0) continue; // eventuel arg error
        if (rawSource.toString().charCodeAt(iter) == 10) { // 10 = "\n"
            if (rawSource.toString().charCodeAt(iter-1) == 10) { // deux "\n" successifs
                paragraphes.push(rawSource.slice(flagIterParagraphe, iter)); 
                flagIterParagraphe = iter;

                blocsTous.push(rawSource.slice(flagIter, iter));
                flagIter = iter;
            }
        }
        if (rawSource.toString().charCodeAt(iter) == 61) { // 61 = "="
            if (rawSource.toString().charCodeAt(iter-1) == 10) { // un "=" précédé d'un "\n"
                blocsTous.push(rawSource.slice(flagIter, iter));
                flagIter = iter;
            }
        }
        if (iter == rawSource.length) {
            paragraphes.push(rawSource.slice(flagIterParagraphe, iter)); // on "vide" le raw
        }
    }

    var raw = paragraphes[index];

//    console.log(index, ":", raw);

    afficheBlocScriptus(raw, index, rawSource);
}

/**
 * Affiche un textarea avec le wikitexte et une interface
 */
function afficheBlocScriptus(raw, index, fullraw) {
    var bloc = $('.scParagraphe')[index];

    var interface = document.createElement("div");
    interface.id = "scInterface";

    $(interface).insertAfter(bloc);

    var journal = document.createElement("div");
    journal.textContent = "journal";

    interface.appendChild(journal);

    var form = document.createElement("form");
    form.className = 'ajaxedit';
    form.name = 'ajaxEditForm';
    form.method = 'get';
    form.action = "javascript:postScriptus();"; 

    var wpTextbox1 = raw;

    var textarea = document.createElement("textarea");
    textarea.className = "ajaxTextarea";
    var lines = wpTextbox1.split(/\n/).length;
    var nbchars = wpTextbox1.length;

    textarea.appendChild(document.createTextNode(raw));
    form.appendChild(textarea);

    var summary = document.createElement("input");
    summary.type = "Text";
    summary.name = "wpSummary";
    summary.id = "wpSummary"
    summary.value="Veuillez résumer vos modifications"
    form.appendChild(summary);

    var save = document.createElement("input");
    save.type = "button";
    save.value = "Envoyer"
    form.appendChild(save);

    var preview = document.createElement("input");
    preview.type = "button";
    preview.value = "Prévisualisation"
    form.appendChild(preview);

    var annuler = document.createElement("input");
    annuler.type = "button";
    annuler.value = "Annuler"
    form.appendChild(annuler);

    var tester = document.createElement("input");
    tester.type = "button";
    tester.value = "Tester"
    form.appendChild(tester);

    interface.appendChild(form);

    var largeur = form.offsetWidth;
    var colones = largeur*10/75;
    var nblines = nbchars/colones+lines;
    textarea.rows = nblines;

    save.addEventListener("click", function(){postScriptus(index, fullraw)}, false);
    annuler.addEventListener("click", function(){interface.parentNode.removeChild(interface)}, false);
    preview.addEventListener("click", previsualisationScriptus, false);
    tester.addEventListener("click", testScriptus, false);
}

/**
 * Fonction liée au bouton "tester" de l'interface
 */
function testScriptus() {
    return true;
}

/**
 * Envoye le wikitexte modifié au serveur
 */
function postScriptus(index, fullraw) {

    var rawTable = new Array();
    var flagIter = 0;

    for (var iter=0; iter <= fullraw.length ; iter++) {
        if (fullraw.toString().charCodeAt(iter) == 10) {
            if (iter == 0) continue; // eventuel arg error
            if (fullraw.toString().charCodeAt(iter-1) == 10) {// 2 lf successifs
                rawTable.push(fullraw.slice(flagIter, iter)); 
                // ^ on ajoute le contenu raw du paragraphe dans le tableau "paragraphes"
                flagIter = iter;
            }
        }
        if ((iter == fullraw.length) && (iter != flagIter)) {
            rawTable.push(fullraw.slice(flagIter, iter)); // on "vide" le raw
        }
    }

    var locWikitext = document.getElementsByTagName('textarea')[0].value;

    rawTable[index] = locWikitext;

    var iter = 0;
    var wpTextbox1 = "";
    while (rawTable[iter]) {
        wpTextbox1 += encodeURIComponent(rawTable[iter]);
        iter++;
    }

    var wpSummary = encodeURIComponent(document.getElementById('wpSummary').value);
    if (wpSummary == encodeURI("Veuillez résumer vos modifications")) wpSummary = ""; 

    console.log("fullraw : ", fullraw);
    console.log("rawTable : ", rawTable);
    console.log("wpTextBox1 : ", wpTextbox1);

    //var wpEdittime = document.getElementById('hiddenEdittime').value;
    //var wpEditToken = document.getElementById('hiddenEditToken').value;
    //var wpStarttime = document.getElementById('hiddenStarttime').value;


    var xhrApi = wpajaxScriptus.http({ url: mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php?action=query&prop=info&titles=' 
                                            + wgPageName 
                                            + '&intoken=edit&format=xml'
                                     , async:false });
    var parser = new DOMParser();
    var doc = parser.parseFromString(xhrApi.responseText, 'text/xml');

    var edittime = doc.getElementsByTagName('page')[0].getAttribute('touched');
    var ed1 = edittime.split('-')[0]+edittime.split('-')[1]+edittime.split('-')[2];
    var ed2 = ed1.split('T')[0]+ed1.split('T')[1];
    var ed3 = ed2.split(':')[0]+ed2.split(':')[1]+ed2.split(':')[2];
    var edfin = ed3.split('Z')[0]

    var date = new Date(); //ca doit être fait au tout début, pas lorsqu'on appuye sur le bouton de sauvegarde.

    var wpEdittime = edfin;
    var wpEditToken = encodeURIComponent(doc.getElementsByTagName('page')[0].getAttribute('edittoken'));
    var wpStarttime = getTimeStampScriptus(date);

    if (document.getElementById('ca-unwatch')) {
      var suivi = '&wpWatchthis=1';
    } else {
      var suivi = '';
    }

    var headers = new Array();
    headers['Content-Type'] = 'application/x-www-form-urlencoded';

    document.HttpWPedit = wpajaxScriptus.http({ url: mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?title=' 
                                 + encodeURIComponent(mw.config.get('wgPageName')) 
                                 + '&action=submit',
                          method: "POST", 
                          headers: headers,
                          async: false,
                          data: 'wpSave=Sauvegarder&wpTextbox1=' + wpTextbox1 
                                + '&wpStarttime=' + wpStarttime 
                                + '&wpEdittime=' + wpEdittime
                                + '&wpEditToken=' + wpEditToken 
                                + suivi
                                + '&wpSummary=' + wpSummary + encodeURIComponent(' (mpa)')}); 
    apresModifScriptus();
}


function previsualisationScriptus(wpEdittime, wpEditToken, wpStarttime) {

    if (document.getElementById('wikiPreview')) {
        var oldpreview = document.getElementById('wikiPreview').parentNode.removeChild(document.getElementById('wikiPreview'));
    }

    var wpTextbox1 = encodeURIComponent(document.getElementsByTagName('textarea')[0].value);
    var wpSummary = encodeURIComponent(document.getElementById('wpSummary').value);
    if (wpSummary == encodeURI("Veuillez résumer vos modifications")) wpSummary = ""; 

    // recuperation des champ hidden

    //var wpEdittime = document.getElementById('hiddenEdittime').value;
    //var wpEditToken = document.getElementById('hiddenEditToken').value;
    //var wpStarttime = document.getElementById('hiddenStarttime').value;

    if (document.getElementById('ca-unwatch')) {
      var suivi = '&wpWatchthis=1';
    } else {
      var suivi = '';
    }

    document.HttpWPpreview = wpajaxScriptus.http({ url: mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?title=' 
                                 + encodeURIComponent(mw.config.get('wgPageName')) 
                                 + '&action=submit',
                          method: "POST", 
                          async: false,
                          data: 'wpSave=1&wpTextbox1=' + wpTextbox1 
                                + '&wpStarttime=' + wpStarttime 
                                + '&wpEdittime=' + wpEdittime
                                + '&wpEditToken=' + wpEditToken 
                                + '&wpPreview=Prévisualisation'
                                + suivi
                                + '&wpSummary=' + wpSummary + encodeURIComponent(' (mpa)')});

    var parser = new DOMParser();

    var previewRetour = parser.parseFromString(document.HttpWPpreview.responseText, 'application/xhtml+xml');
    var previewHtml = previewRetour.getElementById('wikiPreview');
    var previewDiv = document.createElement("div");
    previewDiv = previewHtml;

    var titre = previewDiv.getElementsByTagName('h2')[0];

    var Aretirer = previewDiv.getElementsByTagName('div')[0];
    previewDiv.removeChild(Aretirer);

    previewDiv.style.border = "2px solid #FF8080";
    previewDiv.style.backgroundColor = "#FCFFE5";
    titre.style.color = "#FF8080";

    var form = $('.ajaxedit').first();
    $(previewDiv).insertAfter(form.parent());

    var fermeturePreview = document.createElement("span");
    fermeturePreview.style.fontSize = "xx-small";
    fermeturePreview.style.fontWeight = "normal";
    fermeturePreview.style.cssFloat = "none";
    fermeturePreview = titre.appendChild(fermeturePreview);
    fermeturePreview.innerHTML = '<a href="javascript:var temporaire = document.getElementById(\'wikiPreview\').parentNode.removeChild(document.getElementById(\'wikiPreview\'));" title="Fermer la prévisualisation">fermer</a>'; //virer le innerHTML

}


function apresModifScriptus() {

    var parser = new DOMParser();

    var doc = parser.parseFromString(document.HttpWPedit.responseText, 'application/xhtml+xml');

    document.importNode(doc.getElementsByTagName('html')[0],true);
    var actuel = document.getElementsByTagName('html')[0];
    var parentActuel = actuel.parentNode;
    parentActuel.removeChild(actuel);
    document.appendChild(doc.getElementsByTagName('html')[0]);

    //on relance les scripts sur le dom
    runOnloadHook();

}


var wpajaxScriptus = { // depuis http://fr.wikipedia.org/wiki/Utilisateur:EDUCA33E/LiveRC.js
  http: function(bundle) {
    // mandatory: bundle.url
    // optional:  bundle.async
    // optional:  bundle.method
    // optional:  bundle.headers
    // optional:  bundle.data
    // optional:  bundle.onSuccess (xmlhttprequest, bundle)
    // optional:  bundle.onFailure (xmlhttprequest, bundle)
    // optional:  bundle.otherStuff OK too, passed to onSuccess and onFailure
    var xmlhttp;
        try {xmlhttp = new XMLHttpRequest();} catch (e) {xmlhttp = false}
 
    if (xmlhttp) {
      xmlhttp.onreadystatechange = function() {
        if (xmlhttp.readyState == 4) {
          wpajaxScriptus.httpComplete(xmlhttp,bundle);
        }
      }
      xmlhttp.open(bundle.method ? bundle.method : "GET",bundle.url,bundle.async == false ? false : true);
      if (bundle.headers) {
        for (var field in bundle.headers)
          xmlhttp.setRequestHeader(field,bundle.headers[field]);
      }
      xmlhttp.send(bundle.data ? bundle.data : null); 
    }

    return xmlhttp;
  },
 
  httpComplete: function(xmlhttp,bundle) {

    if (xmlhttp.status == 200 || xmlhttp.status == 302) {
      if (bundle.onSuccess) {
        bundle.onSuccess(xmlhttp,bundle);
      } else if (bundle.onFailure) {
      bundle.onFailure(xmlhttp,bundle);
      } else {
      // A activer en debug mode ?
      if (xmlhttp.statusText != "OK") alert(xmlhttp.statusText);
      }
    }
  }
};

//depuis advancedcontribs de Maloq
function toNString(num, length)
{
	num = num + ""
 
	while(num.length < length)
		num = "0" + num
 
	return num
}

//renvoi le timeStamp depuis l'object date. A corriger avec le décalage horaire
function getTimeStampScriptus(date)
{
    return date.getFullYear() + 
        toNString(date.getMonth() + 1, 2) + 
        toNString(date.getDate(), 2) + 
        toNString(date.getHours() + (date.getTimezoneOffset() / 60), 2) + 
        toNString(date.getMinutes(), 2) + 
        toNString(date.getSeconds(), 2)
}

$(Scriptus);

//</syntaxhighlight>