MediaWiki:Gadget-ChangeCategorie.js

La bibliothèque libre.

Note : après avoir enregistré vos modifications, il se peut que vous deviez forcer le rechargement complet du cache de votre navigateur pour voir les changements.

  • Firefox / Safari : Maintenez la touche Maj (Shift) en cliquant sur le bouton Actualiser ou pressez Ctrl-F5 ou Ctrl-R (⌘-R sur un Mac) ;
  • Google Chrome : Appuyez sur Ctrl-Maj-R (⌘-Shift-R sur un Mac) ;
  • Internet Explorer : Maintenez la touche Ctrl en cliquant sur le bouton Actualiser ou pressez Ctrl-F5 ;
  • Opera : Allez dans Menu → Settings (Opera → Préférences sur un Mac) et ensuite à Confidentialité & sécurité → Effacer les données d'exploration → Images et fichiers en cache.
/*
 * Voir Aide:Gadget-Change catégorie
 */
change_category = {
    user_data : null,
    article_categories : [],
    all_articles_cats : [],

    do_sync_request : function (request, type, datas) {
        var http_request = sajax_init_object();
        url = mw.config.get('wgServer') + wgScriptPath + '/api.php?' + request;
        http_request.open(type, url, false);
        if (datas) {
            http_request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        }
        http_request.send(datas);
        return http_request;
    },
 
    get_sync : function (request) {
        return change_category.do_sync_request(request, "GET", null);
    },
 
    do_json_request : function (request) {
        http_request = change_category.get_sync(request + '&format=json');

        return JSON.parse(http_request.responseText);
    },

    // FIXME: use mw.Api() so we can remove do_json_request(), get_sync() and do_sync_request()
    read_page : function (pagename) {
        var request = 'action=query&prop=revisions&rvprop=timestamp|content&titles=' + pagename;
        var json = change_category.do_json_request(request);
 
        for (var page in json.query.pages) {
            if (Number(page) > 0)
                return json.query.pages[page].revisions[0]['*'];
        }
        return null;
    },

    write_page : function (pagename, text, comment) {
        var api = new mw.Api();

        return api.postWithEditToken( {
           action : 'edit',
           text : text,
           comment : comment,
           title : pagename,
           } );
    },

    // A simple hash.
    hash : function(str) {
        var init = arguments.length >= 2 ? arguments[1] : 0;
        for (var i in str) {
            init *= 65599;
            init += str.charCodeAt(i);
            init &= 0x7fffffff;
        }
        return init;
    },

    hash_list_str : function (list) {
        var init = arguments.length >= 2 ? arguments[1] : 0;
        for (var i in list) {
            init = change_category.hash(list[i], init);
        }
        return init;
    },

    to_hex : function (value) {
        var result = "";
        while (value) {
            result += "0123456789ABCDEF"[value % 16];
            value  = Math.round(value / 16);
        }
        return result;
    },

    cat_regex : '([Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy]|[Cc][Aa][Tt][Éé][Gg][Oo][Rr][Ii][Ee])',

    regex_from_title : function (title) {
          // FIXME: will catch most common case but not all.
          if (title.length >= 1) {
              var first_char = title[0];
              title = '[' + first_char.toLowerCase() + first_char.toUpperCase() + ']' + title.substr(1);
          } else {
              title = title.replace(/[ _]+/g, '[ _]+');
          }
          return new RegExp('\\[\\[[ _]*' + change_category.cat_regex + '[ _]*:[ _]*' + title + '[ _]*\\]\\][\n ]?', 'g');
    },

    _set_user_data : function (data) {
        if (typeof(data.nb_colonnes) == 'undefined' || !data.nb_colonnes)
            data.nb_colonnes = 1;
        if (typeof(data.prefix) == 'undefined')
            data.prefix = '';
        if (typeof(data.list) == 'undefined')
            data.list = [];
        if (typeof(data.implicit) == 'undefined')
            data.implicit = [];
        if (typeof(data.raccourci) == 'undefined')
            data.raccourci = '';
        change_category.user_data = data;

        $(document).ready(function() {
            if($.inArray(mw.config.get('wgNamespaceNumber'), [ 8 ]) == -1 && (mw.config.get('wgAction') === 'view')) {
            	mw.loader.using('mediawiki.util', function() {
                mw.util.addPortletLink(
                'p-cactions',
                null,
                'ChangeCat',
                'ca-change-cat',
                'Changer les catégories de la page'
               );
                $('li#ca-change-cat').click(function() {
                    change_category.open_dialog();
                });
            	});
            }
        });

        if (change_category.user_data.raccourci) {
            var isCtrl = false;
 
            document.onkeyup = function(e) { 
                if (e.which == 17) isCtrl = false;
            };
 
            document.onkeydown = function(e) {
                if (e.which == 17) {
                    isCtrl = true;
                    return;
                }
 
                if (isCtrl) {
                    switch (e.which) { 
                        case change_category.user_data.raccourci.charCodeAt(): 
                            change_category.open_dialog();
                            return false;
                    }
                }
            };
        return true;
        }
    },

    set_user_data : function (data) {
        modules = [ 'mediawiki.api', 'mediawiki.api.edit' ];

	$.when( mw.loader.using( modules ),
		$.ready
	).then( function() {
		change_category._set_user_data(data);
	} );
    },

    list_from_array : function (arr) {
        var html = '';
        for (var i in arr) {
            html += '<li>' + arr[i] + '</li>\n';
        }
        return html;
    },

    remove_prefix : function (cat_name) {
        if (change_category.user_data.prefix.length && cat_name.indexOf(change_category.user_data.prefix) === 0) {
            cat_name = '@' + cat_name.substr(change_category.user_data.prefix.length);
        }
        return cat_name;
    },

    setup : function () {
        if (!$('#dialog').length) {
            $('#content').append('<div id="dialog" class="change-cat-dialog" title="Changement de catégories"></div>');

            $('<style type="text/css"></style>')
                .html(".ui-selecting { background: silver; }\n.ui-selected { background: gray; }")
                .appendTo("head");

            $('#catlinks ul li a').each(function () {
                var cat_name = change_category.remove_prefix($(this).text());
                if ($.inArray(cat_name, change_category.user_data.implicit) == -1) {
                    change_category.article_categories.push(cat_name);
                }
                change_category.all_articles_cats.push(cat_name);
            });

            $('#dialog').html('<div id="ui-prefix" style="text-align:center;"></div><div style="text-align:center;display:block;float:left;width:30%;">Suppression&nbsp;:<ul style="text-align:left;" id="selectable_removable"></ul></div><div style="text-align:center;display:block;float:right;width:68%;">Ajout&nbsp;:<ul id="selectable_addable" style="text-align:left;"></ul></div>');

            $('#selectable_addable').css( { '-moz-column-count' : String(change_category.user_data.nb_colonnes),
                                            '-webkit-column-count' : String(change_category.user_data.nb_colonnes),
                                            '-column-count' : String(change_category.user_data.nb_colonnes)
                                          } );

            $('#selectable_removable').html(change_category.list_from_array(change_category.article_categories));
            $('#selectable_addable').html(change_category.list_from_array(change_category.user_data.list));

            $('#selectable_removable').selectable();
            $('#selectable_addable').selectable();

            if (change_category.user_data.prefix.length) {
                $('#ui-prefix').text('Préfixe@ : ' + change_category.user_data.prefix);
            }
        }
    },

    get_selected : function (id) {
        result = [];
        var selected = $(id + ' .ui-selected').each( function() {
            result.push($(this).text());
        });
        return result;
    },

    remove_category : function (wiki_text, cat_name) {
        var cat_regex = change_category.regex_from_title(cat_name);
        return wiki_text.replace(cat_regex, '');
    },

    get_category_placement : function (wiki_text) {
        // FIXME ?
        return wiki_text.length;
    },

    add_category : function (wiki_text, cat_name) {
        var pos = change_category.get_category_placement(wiki_text);
        var cat = '\n[[Catégorie:' + cat_name + ']]';
        return wiki_text.substr(0, pos) + cat + wiki_text.substr(pos);
    },

    real_cat_name : function (cat_name) {
        if (cat_name[0] == '@') {
            return change_category.user_data.prefix + cat_name.substr(1);
        } else {
            return cat_name;
        }
    },

    on_ok : function () {
        var cat_added = change_category.get_selected('#selectable_addable');

        for (var i in change_category.user_data.implicit) {
            var cat_name = change_category.user_data.implicit[i];
            cat_name = change_category.real_cat_name(cat_name);
            if ($.inArray(cat_name, change_category.all_articles_cats) == -1) {
                cat_added = cat_added.concat(cat_name);
            }
        }

        var cat_removed = change_category.get_selected('#selectable_removable');

        if (!cat_added.length && !cat_removed.length) {
            $("#dialog").dialog("close");
            return;
        }

        var pagename = mw.config.get("wgPageName");
        var wiki_text = change_category.read_page(pagename);

        /* remove the cat added too, to avoid duplicate */
        cat_removed = cat_removed.concat(cat_added);
        for (var i in cat_removed) {
            var cat_name = change_category.real_cat_name(cat_removed[i]);
            wiki_text = change_category.remove_category(wiki_text, cat_name);
        }

        for (var i in cat_added) {
            var cat_name = change_category.real_cat_name(cat_added[i]);
            wiki_text = change_category.add_category(wiki_text, cat_name);
        }

        var $promise = change_category.write_page(pagename, wiki_text, 'Catégorie(s) ([[Aide:Gadget-Change catégorie|Gadget-ChangeCategorie.js]])');

        /* needed because we save the dialog setting in the close event */
        $("#dialog").dialog("close");

        $.when($promise.done()).then( function() { window.location = window.location; } );
    },

    /* The config cookie name depend on the user data to allow different
     * config for different user data. The drawback is that each list change
     * loose the current configuration.
     */
    config_cookie_name : function () {
        var hash = change_category.hash_list_str(change_category.user_data.list);
        return 'change_cat_' + change_category.to_hex(hash);
    },

    save_config : function () {
	var value = { width : $( "#dialog" ).dialog( "option", "width" ),
		      height : $( "#dialog" ).dialog( "option", "height" ) };

	var serialized = JSON.stringify(value);
        var name = change_category.config_cookie_name();
        mw.cookie.set(name, serialized, { path : '/wiki/', expires : 180 } );
    },

    load_config : function (name) {
        var result = { width : 300, height : 480 };

        var name = change_category.config_cookie_name();
        var cookie_value = mw.cookie.get(name);

        if (cookie_value) {
	    var value = JSON.parse(cookie_value);
	    result = $.extend({}, result, value);
        }
	return result;
    },

    open_dialog : function () {
        change_category.setup();

        var buttons = [
            {
                text: "Ok",
                click: function() { change_category.on_ok(); }
            },
            {
                text: "Annuler",
                click: function() { $(this).dialog("close"); }
            }
        ];

        var defaults = change_category.load_config();
        $("#dialog").dialog({
            create: function(event, ui) {
                $(event.target).parent().css( { position : 'fixed' } );
            },
            close : function (event, ui) {
                change_category.save_config();
            },
/*
            resizeStop: function(event, ui) {
                alert('resizeStop');
                $(event.target).parent().css('position', 'fixed');
                $(dlg).dialog('option','position', 'right');
            },
*/
            buttons : buttons,
            position : 'right',
            height : defaults.height,
            width  : defaults.width,
            minHeight: 240,
            maxHeight : 640
            });

        /* FIXME: must be unbinded when closing the dialog or must be setup in setup() */
        $(window).resize(function() {
            $("#dialog").dialog('option','position', 'right');
        });
    },
};