Pengguna:Iwan Novirion/TemplateDataEditor.js

Revisi sejak 2 Desember 2021 09.35 oleh Ladsgroup (bicara | kontrib) (Membalikkan revisi 19479887 oleh Ladsgroup (bicara))
(beda) ← Revisi sebelumnya | Revisi terkini (beda) | Revisi selanjutnya → (beda)

Catatan: Setelah menyimpan, Anda harus memintas tembolok (cache) peramban Anda untuk melihat perubahannya. Google Chrome, Firefox, Microsoft Edge dan Safari: Tahan tombol Shift dan klik Muat ulang (Reload) di tombol bilah alat. Untuk detail dan instruksi tentang peramban lain, lihat halaman menghapus singgahan (Inggris).

/*
 * Gadget pour éditer les balises 'templatedata' de l’extension « TemplateData » de MediaWiki
 * sans avoir à manipuler le JSON.
 * 
 * Un lien est ajouté dans la « Boîte à outils » lors de l’édition d’un modèle.
 * Il ouvre une fenêtre de modification permettant toutes les modifications autorisées.
 * 
 * Auteur : Ltrlg
 * Dernière mise à jour : 7 juillet 2013
 * 
 * {{catégorisation JS|TemplateDataEditor}}
 * 
 * <nowiki>
 */
 
function TemplateDataEditor($) {
 
    var
        $body, $cont, $button,
        uniq = 0,
        cssSep = {
            marginLeft: '1em'
        },
        $desc = $('<textarea>').css({margin: 0, boxSizing: 'border-box', height: '6em'}),
        $params = $('<ul>'),
        $sets = $('<ul>'),
        tagRegExp = /<templatedata[^>]*>([^]*)<\/templatedata>|<templatedata(?:)[^>]*\/>/;
 
    ////////// READ CURRENT DATA //////////
 
    function removeThisLi() {
        $(this).closest('li').remove();
        return false;
    }
 
    function $paramType(type, label, currentType) {
        return $('<option>')
            .val(type)
            .attr('title', type)
            .text(label)
            .prop('selected', currentType == type);
    }
 
    function paramFromJson(name, jsonParam) {
        uniq++;
        return $('<li>')
            .append($('<a>')
                .attr({
                    href: '#',
                    title: 'Retirer ce paramètre'
                })
                .click(removeThisLi)
                .css({
                    float: 'right',
                    marginRight: '0.5em'
                })
                .append($('<img>')
                    .attr({
                        src: '//upload.wikimedia.org/wikipedia/commons/thumb/1/13/VisualEditor_-_Icon_-_Clear.svg/24px-VisualEditor_-_Icon_-_Clear.svg.png',
                        alt: 'Retirer ce paramètre'
                    })
                )
            )
            .append($('<label>')
                .attr('for', 'tde-paramName-'+uniq)
                .text( 'Nom réel\xA0: ' )
            )
            .append($('<input>')
                .addClass('tde-paramName')
                .attr('type', 'text')
                .attr('id', 'tde-paramName-'+uniq)
                .val( name )
            )
            .append($('<input>')
                .css(cssSep)
                .addClass('tde-paramRequired')
                .attr('type', 'checkbox')
                .attr('id', 'tde-paramRequired-'+uniq)
                .prop('checked', !! jsonParam.required )
            )
            .append($('<label>')
                .attr('for', 'tde-paramRequired-'+uniq)
                .text('Obligatoire')
            )
            .append('<br>')
            .append($('<label>')
                .attr('for', 'tde-paramLabel-'+uniq)
                .text( 'Nom affiché\xA0: ' )
            )
            .append($('<input>')
                .addClass('tde-paramLabel')
                .attr('type', 'text')
                .attr('id', 'tde-paramLabel-'+uniq)
                .val( jsonParam.label || '' )
            )
            .append('<br>')
            .append($('<label>')
                .attr('for', 'tde-paramType-'+uniq)
                .text( 'Type\xA0: ' )
            )
            .append($('<select>')
                .addClass('tde-paramType')
                .attr('type', 'text')
                .attr('id', 'tde-paramType-'+uniq)
                .append($paramType('unknown', 'Inconnu', jsonParam.type))
                .append($paramType('number', 'Nombre', jsonParam.type))
                .append($paramType('string', 'Texte', jsonParam.type))
                .append($paramType('string/wiki-user-name', 'Nom d’utilisateur', jsonParam.type))
                .append($paramType('string/wiki-page-name', 'Titre de page', jsonParam.type))
            )
            .append($('<label>')
                .css(cssSep)
                .attr('for', 'tde-paramDefault-'+uniq)
                .text( 'Valeur par défaut\xA0: ' )
            )
            .append($('<input>')
                .addClass('tde-paramDefault')
                .attr('type', 'text')
                .attr('id', 'tde-paramDefault-'+uniq)
                .val( jsonParam['default'] || '' )
            )
            .append($('<label>')
                .css(cssSep)
                .attr('for', 'tde-paramInherits-'+uniq)
                .text( 'Hérite de\xA0: ' )
            )
            .append($('<input>')
                .addClass('tde-paramInherits')
                .attr('type', 'text')
                .attr('id', 'tde-paramInherits-'+uniq)
                .val( jsonParam.inherits || '' )
            )
            .append('<br>')
            .append($('<input>')
                .addClass('tde-paramDeprecated')
                .attr('type', 'checkbox')
                .attr('id', 'tde-paramDeprecated-'+uniq)
                .prop('checked', (typeof jsonParam.deprecated == 'string' ) || !! jsonParam.deprecated )
            )
            .append($('<label>')
                .attr('for', 'tde-paramDeprecated-'+uniq)
                .text('Obsolète')
            )
            .append(document.createTextNode(' ('))
            .append($('<label>')
                .attr('for', 'tde-paramDeprecatedTooltip-'+uniq)
                .text( 'précision\xA0: ' )
            )
            .append($('<input>')
                .addClass('tde-paramDeprecatedTooltip')
                .attr('type', 'text')
                .attr('size', 50)
                .attr('id', 'tde-paramDeprecatedTooltip-'+uniq)
                .val(  (typeof jsonParam.deprecated == 'string' ) ? jsonParam.deprecated : '')
            )
            .append(document.createTextNode(')'))
            .append('<br>')
            .append($('<label>')
                .attr('for', 'tde-paramAliases-'+uniq)
                .text( 'Autre noms (séparés par des tubes « | »)\xA0: ' )
            )
            .append($('<input>')
                .addClass('tde-paramAliases')
                .css({
                    display: 'block',
                    width: '100%',
                    boxSizing: 'border-box',
                })
                .attr('type', 'text')
                .attr('id', 'tde-paramAliases-'+uniq)
                .val( ( jsonParam.aliases || [] ).join(' | ') )
            )
            .append($('<label>')
                .attr('for', 'tde-paramDescription-'+uniq)
                .text( 'Description\xA0: ' )
            )
            .append($('<textarea>')
                .css({
                    margin: 0,
                    boxSizing: 'border-box',
                    height: '4em'
                })
                .attr('id', 'tde-paramDescription-'+uniq)
                .addClass('tde-paramDescription')
                .text( jsonParam.description || '' )
            );
    }
 
    function initParamsFromJson(jsonParams) {
        for(var i in jsonParams) {
            $params.append( paramFromJson(i, jsonParams[i]) );
        }
    }
 
    function setFromJson(jsonSet) {
        uniq++;
        return $('<li>')
            .append($('<a>')
                .attr({
                    href: '#',
                    title: 'Retirer cet ensemble'
                })
                .click(removeThisLi)
                .css({
                    float: 'right',
                    marginRight: '0.5em'
                })
                .append($('<img>')
                    .attr({
                        src: '//upload.wikimedia.org/wikipedia/commons/thumb/1/13/VisualEditor_-_Icon_-_Clear.svg/24px-VisualEditor_-_Icon_-_Clear.svg.png',
                        alt: 'Retirer cet ensemble'
                    })
                )
            )
            .append($('<label>')
                .attr('for', 'tde-setLabel-'+uniq)
                .text( 'Nom\xA0: ' )
            )
            .append($('<input>')
                .addClass('tde-setLabel')
                .attr('type', 'text')
                .attr('id', 'tde-setLabel-'+uniq)
                .val( jsonSet.label || '' )
            )
            .append($('<label>')
                .css(cssSep)
                .attr('for', 'tde-setParams-'+uniq)
                .text( 'Paramètres (séparés par des tubes « | »)\xA0: ' )
            )
            .append($('<input>')
                .addClass('tde-setParams')
                .css({
                    display: 'block',
                    width: '100%',
                    boxSizing: 'border-box',
                })
                .attr('type', 'text')
                .attr('id', 'tde-setParams-'+uniq)
                .val( ( jsonSet.params || [] ).join(' | ') )
            )
    }
 
    function initSetFromJson(jsonSets) {
        for(var i=0; i<jsonSets.length; i++) {
            $sets.append( setFromJson(jsonSets[i]) );
        }
    }
 
    function dataExists() {
        return tagRegExp.test( $('#wpTextbox1').val() );
    }
 
    function getData() {
        var
            dataString = tagRegExp.exec( $('#wpTextbox1').val() )[1],
            data;
        try {
            data = JSON.parse(dataString);
        } catch(e) {
            data = {};
        }
        if( $.type(data.description) != 'string' ) data.description = '';
        if( $.type(data.params) != 'object' ) data.params = {};
        if( $.type(data.sets) != 'array' ) data.sets = [];
        return data;
    }
 
    ////////// READ INPUT //////////
 
    function trim(str) {
        return str.replace(/^\s*(\S.*\S|\S)\s*$/, '$1');
    }
 
    function trimArray(Arr) {
        var i = 0;
        for(; i<Arr.length; i++) {
            Arr[i] = trim(Arr[i]);
        }
        return Arr;
    }
 
    function selectValue($select) {
        var res;
        $select.children('option').each(function(){
            if( $(this).prop('selected') ) {
                res = $(this).val();
            }
        });
        return res;
    }
 
    function formatString(str) {
        return '"' + str
            .replace(/\n/g, '\\n')
            .replace(/"/g, '\\"') + '"';
    }
 
    function formatParamList(Arr) {
        var
            i=0,
            res = '[',
            first = true;
        for(; i<Arr.length; i++) {
            if(first) {
                first = false;
            } else {
                res += ', ';
            }
            res += formatString( Arr[i] );
        }
        return res + ']';
    }
 
    function readInputParams() {
        var
            params = '{',
            paramsUsed = [],
            firstParam = true;
 
        function nextParam() {
            if(firstParam) {
                firstParam = false;
            } else {
                params += ',';
            }
        }
 
        function addParam() {
            var
                $li = $(this),
                name = $li.find('.tde-paramName').val(),
                firstProperty = true,
                type;
 
            function nextProperty() {
                if(firstProperty) {
                    firstProperty = false;
                } else {
                    params += ',';
                }
                params += '\n\t\t\t';
            }
 
            if( paramsUsed.indexOf(name) != -1  ) {
                console.log(params[name]);
                console.log(Object.keys(params));
                throw new Error('Paramètre «\xA0' + name + '\xA0» défini deux fois');
            }
            
            paramsUsed.push(name);
 
            nextParam();
            params += '\n\t\t' + formatString(name) + ': {';
 
            if( $li.find('.tde-paramLabel').val() != '' ) {
                nextProperty();
                params += '"label": ' + formatString( $li.find('.tde-paramLabel').val() );
            }
 
            type = selectValue($li.find('.tde-paramType'));
            if( type != 'unknown' ) {
                nextProperty();
                params += '"type": ' + formatString( type );
            } 
 
            if( $li.find('.tde-paramDefault').val() != '' ) {
                nextProperty();
                params += '"default": ' + formatString( $li.find('.tde-paramDefault').val() );
            }
 
            if( $li.find('.tde-paramInherits').val() != '' ) {
                nextProperty();
                params += '"inherits": ' + formatString( $li.find('.tde-paramInherits').val() );
            }
 
            if( $li.find('.tde-paramRequired').prop('checked') ) {
                nextProperty();
                params += '"required": true'
            }
 
            if( $li.find('.tde-paramDeprecated').prop('checked') ) {
                nextProperty();
                params += '"deprecated": '
                if( $li.find('.tde-paramDeprecatedTooltip').val() != '' ) {
                    params += formatString( $li.find('.tde-paramDeprecatedTooltip').val() );
                } else {
                    params += 'true';
                }
            }
 
            if( $li.find('.tde-paramDescription').val() != '' ) {
                nextProperty();
                params += '"description": ' + formatString( $li.find('.tde-paramDescription').val() );
            }
 
            if( $li.find('.tde-paramAliases').val() != '' ) {
                nextProperty();
                params += '"aliases":' + formatParamList( trimArray( $li.find('.tde-paramAliases').val().split('|') ) );
            }
 
            params += '\n\t\t}';
        }
 
        $params.children().each(addParam);
 
        return params + '\n\t}';
    }
 
    function readInputSets() {
        var
            sets = '[';
 
        function addParam(i) {
            var
                $li = $(this),
                first = true;
 
            if(i != 0) {
                sets += ','
            }
 
            sets += '\n\t\t{';
 
            if( $li.find('.tde-setLabel').val() != '' ) {
                sets += '\n\t\t\t"label": ' + formatString( $li.find('.tde-setLabel').val() );
                first = false;
            }
 
            if( $li.find('.tde-setParams').val() != '' ) {
                if(!first) {
                    sets += ',';
                }
                sets += '\n\t\t\t"params": ' + formatParamList( trimArray( $li.find('.tde-setParams').val().split('|') ) );
            }
 
            sets += '\n\t\t}';
        }
 
        $sets.children().each(addParam);
 
        return sets + '\n\t]';
    }
 
    function apply() {
        try {
            var
                params = readInputParams(),
                sets = readInputSets(),
                json = '{',
                i;
 
            if( $desc.val() != '' ) {
                json += '\n\t"description": ' + formatString( $desc.val() ) + ',';
            }
 
            json += '\n\t"params": ' + params;
 
            if( ! /^\[\s*\]$/.test(sets) ) {
                json += ',\n\t"sets": ' + sets;
            }
 
            json += '\n}';
 
            $('#wpTextbox1').val( $('#wpTextbox1').val().replace(tagRegExp, '<templatedata>\n' + json + '\n</templatedata>') );
            close();
        } catch(e) {
        	alert('Une erreur est survenue\xA0:\n' + e.message);
        }
    }
 
    ////////// DIALOG //////////
 
    function addNewParam() {
        $params.append(paramFromJson('', {}));
        return false;
    }
 
    function addNewSet() {
        $sets.append(setFromJson({}));
        return false;
    }
 
    function close() {
        $cont.fadeOut('slow', function(){
            $params.children().remove();
            $sets.children().remove();
        });
    }
 
    function open() {
        var data;
        $cont.fadeIn('slow');
        if( dataExists() ) {
            data = getData();
            $body
                .html($('<h3>')
                    .text('Description')
                )
                .append($('<div>')
                    .attr('id', 'tde-desc-cont')
                    .append($desc.text(data.description || ''))
                )
                .append($('<h3>')
                    .text('Paramètres')
                )
                .append($params)
                .append($('<p>')
                    .css({
                        textAlign: 'right',
                        paddingRight: '1em'
                    })
                    .append($('<a>')
                        .attr({
                            href: '#',
                            title: 'Ajouter un paramètre'
                        })
                        .click(addNewParam)
                        .append($('<img>')
                            .attr({
                                src: '//upload.wikimedia.org/wikipedia/commons/thumb/8/8b/VisualEditor_-_Icon_-_Add-item.svg/24px-VisualEditor_-_Icon_-_Add-item.svg.png',
                                alt: 'Ajouter un paramètre'
                            })
                        )
                    )
                )
                .append($('<h3>')
                    .text('Ensembles')
                )
                .append($sets)
                .append($('<p>')
                    .css({
                        textAlign: 'right',
                        paddingRight: '1em'
                    })
                    .append($('<a>')
                        .attr({
                            href: '#',
                            title: 'Ajouter un ensemble'
                        })
                        .click(addNewSet)
                        .append($('<img>')
                            .attr({
                                src: '//upload.wikimedia.org/wikipedia/commons/thumb/8/8b/VisualEditor_-_Icon_-_Add-item.svg/24px-VisualEditor_-_Icon_-_Add-item.svg.png',
                                alt: 'Ajouter un ensemble'
                            })
                        )
                    )
                );
            initParamsFromJson(data.params);
            initSetFromJson(data.sets);
        } else {
            $body.html($('<p>')
                .css('color', 'red')
                .text('Aucune donnée n’a été trouvée. Veuillez ajouter une balise <templatedata /> pour pouvoir l’éditer')
            )
        }
    }
 
    ////////// BUILDING //////////
 
    function buildHTML() {
        $body = $('<div>')
            .attr('id', 'tde-body');
 
        $button = $('<input>')
            .attr('id', 'tde-apply')
            .attr('type', 'button')
            .val('Appliquer')
            .click(apply);
 
        $cont = $('<div>')
            .attr('id', 'tde-cont')
            .append($('<div>').attr('id', 'tde-mask'))
            .append($('<div>')
                .attr('id', 'tde-dialog')
                .append($('<h2>')
                    .text('Modifier les données du modèle (')
                    .append($('<a>').attr('href', '//fr.wiki-indonesia.club/wiki/Projet:Modèle/TemplateData').text('documentation'))
                    .append(document.createTextNode(')'))
                )
                .append($('<a>')
                    .attr({
                        id: 'tde-close',
                        href: '#',
                        title: 'Fermer'
                    })
                    .click(function(){
                        close();
                        return false;
                    })
                    .append($('<img>')
                        .attr({
                            alt: 'Fermer',
                            src: '//upload.wikimedia.org/wikipedia/commons/thumb/8/8d/VisualEditor_-_Icon_-_Close.svg/24px-VisualEditor_-_Icon_-_Close.svg.png'
                        })
                    )
                )
                .append($body)
                .append($button)
            )
            .hide();
 
        $(document.body).append($cont);
    }
 
    function addPortletLink() {
        $(
            mw.util.addPortletLink('p-tb', '#', 'TemplateData', 'ted-toolbox', 'Modifier les données du modèle')
        ).click(function(){
            open();
            return false;
        })
    }
 
    ////////// START //////////
 
    buildHTML();
    addPortletLink();
 
}
 
if( mw.config.get('wgNamespaceNumber') == 10 && mw.config.get('wgAction') == 'edit' ) {
    importStylesheet('Utilisateur:Ltrlg/styles/TemplateDataEditor.css')
    $(document).ready(TemplateDataEditor);
}
 
/*
 * </nowiki>
 */