Pengguna:Kurniasan/catimport.js

Catatan: Selepas menyiarkan perubahan, anda mungkin perlu memintas cache pelayar untuk melihatnya.

  • Firefox / Safari: Tahan Shift sambil mengklik Reload, atau tekan sama ada Ctrl-F5 atau Ctrl-R (⌘-R pada Mac)
  • Google Chrome: Tekan Ctrl-Shift-R (⌘-Shift-R pada Mac)
  • Internet Explorer / Edge: Tahan Ctrl sambil mengklik Refresh, atau tekan Ctrl-F5
  • Opera: Tekan Ctrl-F5.
/*
 * Pengarang: Kurniasan
 * Kegunaan: Skrip untuk membantu mengimport kategori daripada Wikipedia bahasa lain.
 * Sila sertakan pepijat di [[Perbincangan pengguna:Kurniasan/catimport.js]]
 */

if (CatImporter !== undefined && CatImporter._installed) { CatImporter.uninstall(); }
var DialogBox = function(title, parent) { this._init(title, parent); };
 
DialogBox.prototype = {
    _init: function(title, parent) {
        this._title = title;
        this._parent = parent;
        this._gen();
        this._appendToParent();
        return this;
    },
    _gen: function() {
        this.$box = $('<div id="dialog-box">');
        this.$header = $('<div class="dialog-box-header">');
        this.$body = $('<div class="dialog-box-body">');
        this.$footer = $('<div class="dialog-box-footer">');
        this.$closeButton = $('<span id="dialog-box-close-button">');
        this.$header.append(this._title).append(this.$closeButton);
        this.$box.append(this.$header).append(this.$body).append(this.$footer);
    },
    _appendToParent: function() {
        $('#'+this._parent).append(this.$box);
        var $box = this.$box.css('display', 'none');
        this.$closeButton.click(function() {
            $box.fadeOut('slow');
            $('#ci-button-save').hide();
        });
    },
    addToBody: function(arg) {
        this.$body.append(arg);
        return this;
    },
    addButton: function(o) {
        if (o.visible === undefined)
            o.visible = true;
        if (o.id === undefined || o.label === undefined)
            throw new Error('id and label not provided.');
        this.$footer
            .append('<a id="'+o.id+'" class="button"'
                    + (!o.visible ? ' style="display:none"' : '')
                    + '><span>'+o.label+'</span></a>');
        if (o.action !== undefined) {
            $('#'+o.id).click(o.action);
        }
        return this;
    },
    show: function() {
        this.fixPosition();
        this.$box.css('opacity',1).css('height','').fadeIn('fast');
        return this;
    },
    fixPosition: function(animate, duration) {
        var newH = ($(window).height() - this.$box.height())/2;
        if (animate === true) {
            if (duration === undefined) {
                duration = 'fast';
            }
    	   this.$box.animate({'top':newH}, duration);
    	} else
    	   this.$box.css('top', newH);
    }
};
 
var CatImporter = {
	api: new mw.Api(),
    getURL : function() {
        if (CatImporter.lang === undefined) {
            throw new Error('CatImporter.lang is not defined');
        }
        return 'https://'+CatImporter.lang+'.wikipedia.org/w/api.php';
    },
    params : {action:'query', format:'json'},
    get : function(extraParams, cb) {
        var params = $.extend(CatImporter.params, extraParams);
        var src = CatImporter.getURL()+'?'+$.param(params);
        if (CatImporter.lang == mw.config.get('wgUserLanguage'))
            $.get(src, cb);
        else
            $('body').append('<script src="'+src+'"></script>');
    },
    addResult: function(o) {
        var title = o.title;
        var name = 'ci-cat-'+o.pageid;
        if (o.langlinks === undefined) {
            $('#ci-result-wrapper .notfound').append('<div>'
                    + '<span class="ci-chkbx-wrap">'
                    + '<input disabled="true" type="checkbox" name="'+name+'" /></span>'
                    + '<label for="'+name+'"><input title="Terjemah \''+title
                    + '\'" type="text" class="ci-notfound" placeholder="'
                    + title.replace(/^[^:]+\:/,'')+'" /></label></div>');
        } else {
            var label = o.langlinks[0]['*'];
            if (CatImporter.curPgCats === undefined || CatImporter.curPgCats.indexOf(label) == -1)
                $('#ci-result-wrapper .found').append('<div><span class="ci-chkbx-wrap">'
                        + '<input type="checkbox" name="'+name+'" value="'+label+'" /></span>'
                        + '<label for="'+name+'">'
                        + '<a href="/wiki/'+label.replace(' ','_')+'" title="'+title+'">'
                        + label.replace(/^[^:]+\:/,'') +'</a>'
                        + '<input title="Isih halaman dalam kategori dengan teks ini" '
                        + 'type="text" class="ci-cat-sorter" placeholder="Teks pengisih"/>'
                        + '</label></div>');
        }
        CatImporter.dialog.fixPosition(false);
    },
    getCategories : function(lang, title, callback) {
        if (callback === undefined) {
            callback = 'CatImporter.categoriesCB';
        }
        if (lang == mw.config.get('wgUserLanguage')) {
            CatImporter.api.get( {
                prop:'categories',
                titles:title,
                clshow:'!hidden',
                cllimit:500
             } ).done( function(d) {callback(d)} );
        } else {
            CatImporter.lang = lang;
            CatImporter.get( {
                titles:title,
                prop:'categories',
                clshow:'!hidden',
                cllimit:500,
                callback:callback
            } );
        }
    },
    categoriesCB : function(o) {
        for (var i in o.query.pages) {
            if (i == -1) {
                alert('Laman `' + o.query.pages[i].title + '` tidak ditemui.');
                $('#ci-button-save').hide();
                CatImporter.$throbber.css('display', 'none');
                CatImporter.dialog.$footer.css('display', 'block');
                return;
            }
            var titles = [];
            for (var j in o.query.pages[i].categories) {
                titles.push(o.query.pages[i].categories[j].title);
            }
            CatImporter.get( {
                titles: titles.join('|'),
                prop: 'langlinks',
                lllang: mw.config.get('wgUserLanguage'),
                callback: 'CatImporter.langlinksCB'
            } );
        }
    },
    _installed : false,
    _ciSuggestionsFetcher : function(d, y) {
        var elem = this;
        var $container = $($(this).data('suggestions-context').data.$container);
        $container.css('font-size', '13px');
        if ($container.find('.ci-translate-head').length === 0)
            $container.prepend('<div class="ci-translate-head">Terjemah <i><b>'
                    + $(elem).attr('placeholder')
                    + '</b></i></div>');
		$.map( mw.config.get('wgNamespaceIds'), function(v, k) {
			var r = new RegExp('^\('+k+'\)\\:', 'i');
			if (v === 14 && d.match(r) !== null) {
				d = d.replace(r, '');
				$(elem).val(d);
			}
		} );
        var cbNm = $(this).parent().attr('for');
        var disabled_old = $('input[name='+cbNm+']').attr('disabled');
        var disabled_new = d.trim() === '';
 
        if (disabled_old != disabled_new)
            $('input[name='+cbNm+']').attr('disabled', disabled_new);
 
        $('input[name='+cbNm+']').val('Kategori:'+d);
		var search = d.replace(/\|.*$/,'$1');
        CatImporter.api.get( {
            action: 'opensearch',
            format: 'json',
            search: search,
            namespace: 14,
            limit: 10,
            suggest: ''
        } ).done( function(a) {
            if (a.length >= 2)
                $(elem).suggestions('suggestions', a[1].map( function(c) {
                    return c.replace(/^[^:]+\:/, '');
                } ));
        } );
    },
    langlinksCB : function(o) {
        for (var i in o.query.pages)
            CatImporter.addResult(o.query.pages[i]);
        $('input.ci-notfound').suggestions('fetch', this._ciSuggestionsFetcher);
        $('input.ci-cat-sorter').keyup( function() {
            var cbName = $(this).parent().attr('for');
            var $cb = $('input[name='+cbName+']');
            var newVal = $cb.val().split('|')[0].trim();
            var sorter = this.value;
            if (sorter.match(/^\s+$/))
                sorter = ' ';
            else
                sorter = sorter.split('|', 1)[0].trimRight();
            if (sorter !== '')
                newVal += '|' + sorter;
            $cb.val(newVal);
        } );
        $('input.ci-notfound').focusout(function() {
            $('#ci-suggestions').remove();
        });
        $('#ci-throbber').css('display','none');
        $('#ci-result-wrapper').css('max-height', $(window).height() - 140);
        CatImporter.dialog.fixPosition();
        $('.dialog-box-footer').fadeIn('fast', function() {
            $(this).find('.button').show();
        });
    },
    savePage : function(c, s, t) {
        CatImporter.api.postWithToken( 'edit', {
            format: 'json',
            action: 'edit',
            title: mw.config.get( 'wgPageName' ),
            summary: s,
            text: c,
        } ).done( function( data ) {
            if ( data && data.edit && data.edit.result == 'Success' ) {
                window.location.reload(); // reload page if edit was successful
            } else if ( data && data.error ) {
                alert( 'Ralat: API memulangkan kod ralat "' + data.error.code + '": ' + data.error.info );
            } else {
                alert( 'Ralat: Hasil tidak diketahui daripada API.' );
            }
        } ).fail( function( xhr ) {
            alert( 'Ralat: Permintaan gagal.' );
        } );
    },
    apply : function(cats) {
        if (cats.length === 0) {
            alert('Ralat : Tiada kategori dipilih');
            return;
        }
        $('.dialog-box-footer .button').hide('slow');
        CatImporter.api.get( {
            action: 'query',
            format: 'json',
            titles: mw.config.get('wgPageName'),
            prop: 'info|revisions',
            intoken: 'edit',
            rvprop: 'content',
        } ).done( function(d) {
            pages = d.query.pages;
            var filterCB = function(k) { return ns[k].trim() !== ''; };
            var mapCB = function(k) { return ns[k]; };
            var mapCB2 = function(i) {  return '[[' + i.replace(/\|.*$/, '') + ']]'; };
            for (var id in pages) {
                t = pages[id].edittoken;
                c = '';
                if ((revs = pages[id].revisions)) c = revs[0]['*'];
                lcat1 = c.lastIndexOf('[[Kategori:');
                lcat2 = c.lastIndexOf('[[Category:');
                a = Math.max(lcat1, lcat2);
                b = c.indexOf(']]', a) + 2;
                if (a == -1) {
                    var ns = mw.config.get('wgFormattedNamespaces');
                    var nsPat = Object.keys(ns).filter(filterCB).map(mapCB).join('|');
                    a = c.search(new RegExp('\\[\\[(?!'+nsPat+')\\w+:[^\\]]+\\]\\]'));
                    b = c.lastIndexOf('\n', a);
                }
                if (a == -1) {
                    if (mw.config.get('wgNamespaceNumber') == 10) {
                        b = c.lastIndexOf('</noinclude>');
                        if (b == -1) {
                            b = c.length + '<noinclude>'.length;
                            c = c + '<noinclude></noinclude>';
                        }
                    } else {
                        c = c.trimRight() + '\n';
                        b = c.length + 1;
                    }
                }
                cA = c.slice(0, b);
                cB = c.slice(b);
                wCats = cats.map( mapCB2 );
                c = cA + '\n' + wCats.join('\n') + '\n\n' + cB.trimLeft();
                CatImporter.savePage(c, 'Menambah ' + wCats + ' ([[Pengguna:Kurniasan/CatImport|CatImport]])', t);
                return;
            }
        } );
    },
    _importAction : function() {
        $('.dialog-box-footer').hide();
        $('input.ci-notfound').map(function() {
            var ctx = $(this).data('suggestions-context');
            if (ctx)
                $(ctx.data.$container).remove();
        } );
        $('#ci-result-wrapper > div > div').remove();
    	CatImporter.$throbber.css('display','inline');
    	CatImporter.dialog.fixPosition();
    	CatImporter.getCategories($('input[name="ci-lang"]').val(),
    	       $('input[name="ci-title"]').val());
    },
    _saveAction: function() {
        var cats = [];
        var xcats = [];
        CatImporter.$resultWrapper.find('input[type="checkbox"]').map(function () {
            if (!this.checked) { return; }
            var $input = CatImporter.$resultWrapper.find('label[for=' + this.name + '] input.ci-notfound');
            var cat = 'Kategori:' + $input.val();
            if ($input.length === 0) { cat = $(this).val(); }
            if (CatImporter.curPgCats !== undefined && CatImporter.curPgCats.indexOf(cat.split('|')[0].trim()) !== -1) {
                xcats.push(cat.split('|')[0].trim());
            } else { cats.push(cat); }
        });
        if (xcats.length !== 0) {
            alert('Ralat: Kategori berikut telah sedia ada:\n- ' + xcats.join('\n- '));
            return;
        }
        CatImporter.apply(cats);
    },
    _createDialog : function() {
        this.$inputWrapper = $('<div>').addClass('ci-input-wrapper');
        this.$inputWrapper.append($('<input>').attr( {
            type: 'text',
            name: 'ci-lang',
            placeholder: 'Kod bahasa'
        } )).append($('<input>').attr( {
            type: 'text',
            name: 'ci-title',
            placeholder: 'Judul'
        } ));
        this.$throbber = $('<img>').attr( {
            id: 'ci-throbber',
            style: 'display:none',
            src: '//upload.wikimedia.org/wikipedia/commons/b/b6/Loading_2_transparent.gif'
        } );
        this.$resultWrapper = $('<div>').attr('id', 'ci-result-wrapper');
        this.$resultWrapper.append('<div class="found" />')
                .append('<div class="notfound" />')
                .append(this.$throbber);
        this.dialog = new DialogBox('Import kategori', 'bodyContent')
                .addToBody(this.$inputWrapper)
                .addButton( {
                    id: 'ci-button-get',
                    label: 'Dapatkan',
                    action: this._importAction
                } )
                .addButton( {
                    id: 'ci-button-save',
                    label: 'Simpan',
                    visible: false,
                    action: this._saveAction
                } );
        this.$inputWrapper.after(this.$resultWrapper);
    },
    install : function() {
        var ci = CatImporter;
    	ci.lang = mw.config.get('wgUserLanguage');
    	ci.get( {
            titles: mw.config.get('wgPageName'),
            prop: 'langlinks|categories',
            lllimit: 500,
            cllimit: 500,
            clshow: '!hidden',
            format: 'json'
        }, function(o) {
            ci.curPgLangLinks = {};
            var pages = o.query.pages;
        	for (pgId in pages) {
                if (pages[pgId].categories)
                    ci.curPgCats = pages[pgId].categories.map( function(cat) {
                        return cat.title;
                    } );
        		lls = o.query.pages[pgId].langlinks;
        		for (i in lls) {
        			ll = lls[i];
        			ci.curPgLangLinks[ll.lang] = ll['*'];
        		}
        		break;
        	}
 
        	$(window).resize(function(e) {
        	    $('#ci-result-wrapper').css('max-height', $(window).height() - 140);
            	ci.dialog.fixPosition();
            });
 
            CatImporter._createDialog();
 
            $('input[name="ci-lang"]').keyup(function(e) {
            	if (Object.keys(ci.curPgLangLinks).indexOf(this.value) >= 0) {
            		$('input[name="ci-title"]').val(ci.curPgLangLinks[this.value]);
            	}
            });
 
            var $ciLink = $('<a>').attr( {
                href: "#dialog-box",
                class: "ci-import-link",
            } ).append('Import');
 
            if ($('#mw-normal-catlinks').length == 0) {
                $('#catlinks').removeClass('catlinks-allhidden');
                $('#catlinks').append('<div id="mw-normal-catlinks" class="mw-normal-catlinks">');
            }
 
            if (!pages[pgId].categories)
                $ciLink.css('float', 'none').append(' kategori');
 
            $('#mw-normal-catlinks').append($ciLink);
 
            $('.ci-import-link').click( function(e) {
				e.preventDefault();
                $('#ci-result-wrapper > div > div').remove();
                $('.ci-input-wrapper input').val('');
                ci.dialog.show();
                ci.dialog.fixPosition();
                $('input[name=ci-lang]').focus();
            } );
        } );
        CatImporter._installed = true;
    },
    uninstall : function() {
        $('.ci-import-link').remove();
        $('#dialog-box').remove();
        DialogBox = null;
        CatImporter = null;
    }
}
 
if (String.prototype.trimRight === undefined)
	String.prototype.trimRight = function() {
		return this.replace(/\s+$/g, '');
	};
if (String.prototype.trimLeft === undefined)
	String.prototype.trimLeft = function() {
		return this.replace(/^\s+/g, '');
	};
if (mw.config.get('wgAction') === 'view' && mw.config.get('wgIsArticle') && mw.config.get('wgPageContentModel') == 'wikitext' && mw.config.get('wgTitle') != mw.config.get('wgMainPageTitle')) {
    window.CatImporter = CatImporter;
    $(CatImporter.install);
}