User:Liangent/Scripts/RDT.js

维基百科,自由的百科全书

注意:保存之后,你必须清除浏览器缓存才能看到做出的更改。Google ChromeFirefoxMicrosoft EdgeSafari:按住⇧ Shift键并单击工具栏的“刷新”按钮。参阅Help:绕过浏览器缓存以获取更多帮助。

mw.loader.using( [
    'jquery', 'jquery.ui'
], function() {
    (function($) { $(function() {
        if ($('#rdtui_wrapper').length == 0) return;
        $('#rdtui_wrapper').text('正在初始化,请稍候……');
        var rdt_config = {
            data_page: 'Wikipedia:铁路系统标示/图标列表/机读格式',
            help_page: 'Wikipedia:铁路系统标示/编辑器/帮助',
            html_unusedvalue: '_unused',
            icon_size: 24, // icon size in template: 20px, cannot provide high enough cells for textboxes
            max_layers: 6,
            max_icons_in_row: 10,
            max_undo: -1,
            fake_title: '铁路系统标示'
        };
        var data_prefix = [];
        var data_base = [];
        var data_reverse = {};
        var map = [];
        var maprow_blank = { icons: [], text1: '', text2: '', text3: '', text4: '', backgroundColor: '', textWidth: '' };
        var icon_blank = { layers: [], link: '' };
        var maprow_default = $.extend(true, {}, maprow_blank), icon_default = $.extend(true, {}, icon_blank);
        var getcode_icon = function(icon, pos) {
            var text = '';
            $.each(icon.layers, function(index) {
                text += '|';
                switch (index) {
                case 0:
                    text += pos;
                    break;
                case 1:
                    text += 'O' + pos;
                    break;
                default:
                    text += 'O' + pos + index;
                }
                text += '=' + this;
            });
            if (icon.link.length != 0) {
                text += '|L' + pos + '=' + icon.link;
            }
            return text;
        };
        var getcode_row = function(row) {
            var text = '{\{BS';
            if (row.icons.length > 1) {
                text += row.icons.length;
            }
            $.each(row.icons, function(index) {
                text += getcode_icon(this, index + 1);
            });
            var textvarindex = row.icons.length;
            if (textvarindex == 0) {
                textvarindex = 1;
            }
            if (row.text1.length != 0) {
                text += '|' + (textvarindex + 1) + '=' + row.text1;
            }
            if (row.text2.length != 0) {
                text += '|' + (textvarindex + 2) + '=' + row.text2;
            }
            if (row.text3.length != 0) {
                text += '|' + (textvarindex + 3) + '=' + row.text3;
            }
            if (row.text4.length != 0) {
                text += '|' + (textvarindex + 4) + '=' + row.text4;
            }
            if (row.backgroundColor.length != 0) {
                text += '|bg=' + row.backgroundColor;
            }
            if (row.textWidth.length != 0) {
                text += '|tw=' + row.textWidth;
            }
            text += '}}';
            return text;
        };
        var getcode = function() {
            return $.map(map, function(row) {
                return getcode_row(row);
            }).join($.browser.msie ? '\r\n' : '\n');
        };
        var geticondesc = function(prefix, base) {
            var iconname = prefix + (base === undefined ? '' : base);
            var rev = data_reverse[iconname];
            return rev === undefined ? iconname : rev;
        };
        var geticonname_cur = function() {
            if ($('#rdtui_iconselect_own').val().length != 0) {
                return $('#rdtui_iconselect_own').val();
            } else if ($('#rdtui_iconselect_prefix').val() != rdt_config.html_unusedvalue &&
                $('#rdtui_iconselect_base').val() != rdt_config.html_unusedvalue) {
                return $('#rdtui_iconselect_prefix').val() + $('#rdtui_iconselect_base').val();
            } else {
                return null;
            }
        };
        var geticon_url = function(prefix, base) {
            // thumb.php cannot handle file redirects. we just hope that the user's browser supports svg
            return '//zh.wikipedia.org/wiki/Special:FilePath/' +
                encodeURIComponent('BSicon_' + prefix + (base === undefined ? '' : base) + '.svg');
        };
        var geticon_img = function(prefix, base) {
            return $('<img />').attr({
                'src': geticon_url(prefix, base),
                'width': rdt_config.icon_size,
                'height': rdt_config.icon_size
            });
        };
        var drawicon = function(icon) {
            var div = $('<div />').css('position', 'relative').attr(
                'title', (icon.link.length != 0 ? '链接到:' + icon.link + ',' : '') +
                    icon.layers.length + '层' +
                    (icon.layers.length > 0 ? ':(从下到上)' +
                        $.map(icon.layers, function(iconname) {
                            return geticondesc(iconname) + '(' + iconname + ')'
                        }).join('、') : '')
            );
            // we must add something for background? (placeholder) // transparent?
            geticon_img('').css('z-index', -1).appendTo(div);
            $.each(icon.layers, function(index) {
                geticon_img(this).css({
                    'position': 'absolute',
                    'left': 0,
                    'top': 0,
                    'z-index': index
                }).appendTo(div);
            });
            return div;
        };
        var drawicon_row = function(icons) {
            var table = $('<table />').css({
                'margin': '0 auto',
                'border-collapse': 'collapse',
                'cursor': 'pointer',
                'background': 'transparent'
            });
            var tr = $('<tr />').appendTo(table);
            $.each(icons, function() {
                var icon = this;
                $('<td />').append(drawicon(this)).click(function(event) {
                    if (event.altKey || event.ctrlKey) {
                        if (event.shiftKey) {
                            var newicon = $.extend(true, {}, icon);
                            var td = this;
                            var dialog = $('<div title="图标编辑" />');
                            dialog.html('<div id="rdtui_icon_preview" style="float: right;" />' +
                                '<p>链接到:<input type="text" id="rdtui_icon_link" />' +
                                '</p><ul id="rdtui_icon_layers"></ul>'
                            );
                            var updpreview = function() {
                                $('#rdtui_icon_preview').empty().append(drawicon(newicon));
                            };
                            $('#rdtui_icon_link').val(newicon.link).change(function() {
                                newicon.link = $(this).val();
                                updpreview();
                            });
                            var drawlayers = function() {
                                // avoid using a table -- possible tbody element problems...
                                var ul = $('#rdtui_icon_layers').empty().css({
                                    'white-space': 'nowrap',
                                    'cursor': 'move', // we are not resizing, so not ns-resize
                                    'margin-left': 0,
                                    'list-style': 'none'
                                });
                                var li_idprefix = 'rdtui_icon_layer_';
                                $.each(newicon.layers, function(index) {
                                    var li = $('<li />');
                                    var iconname = this.toString();
                                    li.append($('<a href="#" />').text('×').click(function() {
                                        newicon.layers.splice(index, 1);
                                        drawlayers(); // or bad index numbers
                                        updpreview();
                                    })).append(' ');
                                    li.append(geticon_img(this)).append(' ');
                                    li.append(geticondesc(this)).append(' ');
                                    li.append(iconname);
                                    li.attr('id', li_idprefix + iconname);
                                    li.appendTo(ul);
                                });
                                ul.sortable({
                                    update: function(event, ui) {
                                        newicon.layers = $.map(ul.sortable('toArray'), function(i) {
                                            return i.slice(li_idprefix.length);
                                        });
                                        drawlayers(); // or bad index numbers
                                        updpreview();
                                    },
                                    forcePlaceholderSize: true,
                                    forceHelperSize: true
                                });
                            };
                            drawlayers();
                            dialog.dialog({
                                buttons: {
                                    '确定': function() {
                                        icon.layers = newicon.layers;
                                        icon.link = newicon.link;
                                        $(td).empty().append(drawicon(icon));
                                        $(this).dialog('close');
                                    },
                                    '取消': function() {
                                        $(this).dialog('close');
                                    }
                                },
                                close: function() {
                                    $(this).remove();
                                },
                                modal: true,
                                width: 'auto',
                                height: 'auto'
                            });
                            updpreview();
                            return;
                        } else {
                            icon.link = '';
                            icon.layers = [];
                        }
                    } else {
                        var iconname = geticonname_cur();
                        if (iconname == null) return;
                        if (event.shiftKey) {
                            icon.layers = [iconname];
                        } else {
                            if (icon.layers.length >= rdt_config.max_layers) {
                                alert('层数超过限制(这个限制取决于此wiki系统的模板)');
                                return;
                            }
                            icon.layers.push(iconname);
                        }
                    }
                    $(this).empty().append(drawicon(icon));
                }).css({'padding': 0, 'border': '1px solid gray'}).appendTo(tr);
            });
            return table;
        };
        var drawmap = function() {
            $('#rdtui_map').html('<table><tr><th>控制</th><th>图标</th>' +
                '<th>文字1</th><th>文字2</th><th>文字3</th><th>文字4</th>' +
                '<th>背景</th><th>文字宽度</th></tr></table>'
            ).css({
                'white-space': 'nowrap',
                'font-size': '100%'
            });
            $('#rdtui_map > table').css('border-collapse', 'collapse');
            var genrow = function(index) {
                var row = this;
                var tr = $('<tr />');
                $('<td />').append($('<a href="#" />').text('+R').click(function(event) {
                    event.preventDefault();
                    map.splice(index, 0, $.extend(true, {}, maprow_default));
                    // can we avoid this to improve performance?
                    drawmap(); // must redraw. or index numbers (like above) may become a mess
                })).append(' ').append($('<a href="#" />').text('-R').click(function(event) {
                    event.preventDefault();
                    map.splice(index, 1);
                    // can we avoid this to improve performance?
                    drawmap(); // must redraw. or index numbers (like above) may become a mess
                })).append(' ').append($('<a href="#" />').text('I+').click(function(event) {
                    event.preventDefault();
                    if (row.icons.length >= rdt_config.max_icons_in_row) {
                        alert('本行图标数超过限制(这个限制取决于此wiki系统的模板)');
                        return;
                    }
                    row.icons.splice(0, 0, $.extend(true, {}, icon_default));
                    $('.rdtui_map_icons', tr).empty().append(drawicon_row(row.icons));
                })).append(' ').append($('<a href="#" />').text('I-').click(function(event) {
                    event.preventDefault();
                    row.icons.splice(0, 1);
                    $('.rdtui_map_icons', tr).empty().append(drawicon_row(row.icons));
                })).append(' ').append($('<a href="#" />').text('+I').click(function(event) {
                    event.preventDefault();
                    if (row.icons.length >= rdt_config.max_icons_in_row) {
                        alert('本行图标数超过限制(这个限制取决于此wiki系统的模板)');
                        return;
                    }
                    row.icons.push($.extend(true, {}, icon_default));
                    $('.rdtui_map_icons', tr).empty().append(drawicon_row(row.icons));
                })).append(' ').append($('<a href="#" />').text('-I').click(function(event) {
                    event.preventDefault();
                    row.icons.pop();
                    $('.rdtui_map_icons', tr).empty().append(drawicon_row(row.icons));
                })).append(' ').append($('<a href="#" />').text('DEF').click(function(event) {
                    event.preventDefault();
                    maprow_default = $.extend(true, {}, row);
                })).appendTo(tr);
                $('<td />').addClass('rdtui_map_icons').append(drawicon_row(this.icons))
                    .css({
                        'padding': 0,
                        'background-color': this.backgroundColor
                    }).appendTo(tr);
                // no need to redraw if only text is changed
                $('<td />').addClass('rdtui_map_text rdtui_map_text1').append($('<input type="text" />').val(this.text1).change(function() {
                    row.text1 = $(this).val();
                })).appendTo(tr);
                $('<td />').addClass('rdtui_map_text rdtui_map_text2').append($('<input type="text" />').val(this.text2).change(function() {
                    row.text2 = $(this).val();
                })).appendTo(tr);
                $('<td />').addClass('rdtui_map_text rdtui_map_text3').append($('<input type="text" />').val(this.text3).change(function() {
                    row.text3 = $(this).val();
                })).appendTo(tr);
                $('<td />').addClass('rdtui_map_text rdtui_map_text4').append($('<input type="text" />').val(this.text4).change(function() {
                    row.text4 = $(this).val();
                })).appendTo(tr);
                $('<td />').addClass('rdtui_map_backgroundcolor').append($('<input type="text" />').val(this.backgroundColor).change(function() {
                    var color = $(this).val();
                    row.backgroundColor = color;
                    $('.rdtui_map_icons', tr).css('background-color', color);
                })).appendTo(tr);
                $('<td />').addClass('rdtui_map_textwidth').append($('<input type="text" />').val(this.textWidth).change(function() {
                    row.textWidth = $(this).val();
                })).appendTo(tr);
                return tr;
            };
            $.each(map, function(index) {
                genrow.call(this, index).appendTo('#rdtui_map > table');
            });
            $('<tr id="rdtui_map_newrow" />').append($('<td />').append($('<a href="#" />').text('+R').click(function(event) {
                event.preventDefault();
                var newrow = $.extend(true, {}, maprow_default);
                map.push(newrow);
                $('#rdtui_map_newrow').before(genrow.call(newrow, map.length - 1)); // avoid redrawing
            }))).appendTo('#rdtui_map > table');
        };
        $.ajax({
            type: 'GET',
            url: wgScript + '?action=render&title=' + encodeURIComponent(rdt_config.data_page),
            dataType: 'html',
            success: function(data, status) {
                var tmpdiv = $('<div />');
                tmpdiv.html(data);
                data = tmpdiv;
                $('.rdtdata_prefix', data).each(function() {
                    data_prefix.push({str: $('.rdtdata_prefix_str', this).text(), desc: $('.rdtdata_prefix_desc', this).text()});
                });
                $('.rdtdata_basesection', data).each(function() { // TODO: support subsections
                    var basesection = {desc: $('.rdtdata_basesection_desc', this).text(), data: []};
                    $('.rdtdata_base', this).each(function() {
                        var base_str = $('.rdtdata_base_str', this).text();
                        var base_desc = $('.rdtdata_base_desc', this).text();
                        basesection.data.push({str: base_str, desc: base_desc});
                        var base = this;
                        $.each(data_prefix, function() {
                            // seticondesc
                            data_reverse[this.str + base_str] =
                                this.desc + ' - ' + basesection.desc + ' - ' + base_desc;
                        });
                    });
                    data_base.push(basesection);
                });
                data.remove();
                $('#rdtui_wrapper').html('<div id="rdtui_tabs"><ul><li><a href="#rdtui_edit">编辑</a></li>' +
                    '<li><a href="#rdtui_source">代码</a></li><li><a href="' + wgScript + '?action=render&title=' +
                    encodeURIComponent(rdt_config.help_page) + '">帮助</a></li></ul>' +
                    '<div id="rdtui_edit"></div><div id="rdtui_source"></div>'
                );
                $('#rdtui_edit').html('<div id="rdtui_toolbar" /><div id="rdtui_iconselect" /><div id="rdtui_map" />');
                $('#rdtui_iconselect').html(
                    '选择一个图片:<select id="rdtui_iconselect_prefix"><option value="' +
                    rdt_config.html_unusedvalue + '">[前缀]</option></select>' +
                    '<select id="rdtui_iconselect_basesection"><option value="' +
                    rdt_config.html_unusedvalue + '">[基础节]</option></select>' +
                    '<select id="rdtui_iconselect_base"><option value="' +
                    rdt_config.html_unusedvalue + '">[基础]</option></select>' +
                    '<br />或自己输入一个图片名:<input type="text" id="rdtui_iconselect_own" />' +
                    '<span id="rdtui_iconselect_preview"></span>'
                );
                $.each(data_prefix, function() {
                    $('<option />').attr('value', this.str).text(this.desc).appendTo('#rdtui_iconselect_prefix');
                });
                $.each(data_base, function() {
                    var d = this.data;
                    $('<option />').text(this.desc).each(function() {
                        $.data(this, 'rdt_base', d);
                    }).appendTo('#rdtui_iconselect_basesection');
                });
                $('#rdtui_iconselect_basesection').change(function() {
                    $('#rdtui_iconselect_base').html('<option value="' + rdt_config.html_unusedvalue + '">[基础]</option>');
                    if ($(this).val() == rdt_config.html_unusedvalue) return;
                    $.each($.data(this.options[this.options.selectedIndex], 'rdt_base'), function() {
                        $('<option />').attr('value', this.str).text(this.desc).appendTo('#rdtui_iconselect_base');
                    });
                });
                var update_preview = function() {
                    $('#rdtui_iconselect_preview').empty();
                    var iconname = geticonname_cur();
                    if (iconname != null) {
                        $('#rdtui_iconselect_preview').append('<br />图片名:').append(iconname);
                        $('#rdtui_iconselect_preview').append(' 图片:').append(geticondesc(iconname));
                        $('#rdtui_iconselect_preview').append(' 预览:').append(geticon_img(iconname).attr(
                            'title', '点击以重叠于现有图片上,Shift-点击以替换现有图片'
                        ).error(function(event) {
                            $(this).replaceWith('载入失败,图片可能不存在');
                        })); // cannot use onload to show loading tip. non-exist images will be never onload.
                    }
                };
                $('#rdtui_iconselect select').change(function() {
                    $('#rdtui_iconselect_own').val('');
                    update_preview();
                });
                $('#rdtui_iconselect_own').change(update_preview);
                drawmap();
                $('#rdtui_source').html('Wiki代码:<textarea id="rdtui_wikitext" />');
                $('<a href="#" />').click(function(event) {
                    event.preventDefault();
                    var dialog = $('<div title="预览" />').text('请稍候').dialog({
                        close: function() {
                            $(this).remove();
                        },
                        modal: true
                    });
                    MediaWiki._request({
                        action: 'parse',
                        title: rdt_config.fake_title,
                        text: '{| {{Railway line header2 (center)}}\n' + $('#rdtui_wikitext').val() + '\n|}',
                        prop: 'text',
                        pst: ''
                    }, function(data) {
                        dialog.html($('api>parse>text', data).text());
                    }, function() {
                        dialog.text('读取失败');
                    });
                }).text('预览').appendTo('#rdtui_source');
                $('#rdtui_source').append(
                    '<hr />以下是路线图的转储格式,可能与将来的版本不兼容,仅供调试和临时保存使用。' +
                    '如果一个旧版本或格式错误的路线图被载入,可能导致编辑器不能工作:' +
                    '<textarea id="rdtui_json" />'
                );
                $('<a href="#" />').click(function(event) {
                    event.preventDefault();
                    map = JSON.parse($('#rdtui_json').val());
                    drawmap();
                    $('#rdtui_tabs').tabs('select', '#rdtui_edit');
                }).text('载入').appendTo('#rdtui_source');
                $('#rdtui_tabs').tabs({
                    select: function(event, ui) {
                        if ($(ui.panel).attr('id') == 'rdtui_source') {
                            $('#rdtui_wikitext').attr('rows', map.length + 2).val(getcode());
                            $('#rdtui_json').val(JSON.stringify(map));
                        }
                    }
                });
            },
            error: function() {
                $('#rdtui_wrapper').text('初始化失败');
            }
        });
        window.rdt_vars = {
            map: map,
            redraw: drawmap
        };
    }); })(jQuery);
});