我写了一些代码,基于Json对象生成了一堆html元素。我通过JQuerys.append().after()将其添加到页面中。
它确实经常工作得很好,但有时外部循环只执行一次,并在$( '#'+inputname ).entityselector()处停止。

function addlinks(qid, prop) {
    html="<fieldset id=\"quickpresets\">" +
         "<legend>Quick Presets (" + prop.name + ")</legend></fieldset>";
     $('.wikibase-statementgrouplistview').first().after( html );
    for( var p = 0; p < prop.defaults.length; p++ ) {
        pid=prop.defaults[p].pid;
        pname=prop.defaults[p].name;
        pvalues=prop.defaults[p].values;
        inputname="input"+pname;
        pclass="addstatement";
        if($('#P'+pid).find(".wikibase-snakview-value a").length !== 0) {
            pclass += " disabled";
        }
        str="<p class='"+pclass+"'>Add "+pname+":";
        for( var i = 0; i < pvalues.length; i++) {
            toqid=pvalues[i].qid;
            toname=pvalues[i].name;
            str += "&nbsp;<a href='javascript:void(0);' onclick=\""+
                   "additemstatement("+qid+","+pid+",'"+pname+"',"+ toqid +",'" + toname+ "')\">" + toname+ "</a>"+
                   "&nbsp;∙";
        }
        str += "<span class=\"quickpresetsinput\"><input id='"+inputname+"'/>&nbsp;";
        str += "<a href=\'javascript:void(0);\' onclick=\""+
                "onselectitem("+qid+","+pid+",'"+pname+"','"+ inputname +"')\">✔</a>";
        str += "</span></p>";
        $('#quickpresets').append( str );

        input = $( '#'+inputname ).entityselector( {
            url: 'https://www.wikidata.org/w/api.php',
            language: mw.config.get('wgUserLanguage')
        } );

    }
}

如何解决此问题?还有什么我应该做的来改进这个难看的代码呢?
更新:
控制台中出现以下错误:
类型错误:$(…)。entityselector不是函数[Weitere
信息en]
full code可以在这里找到。
我得用ES5。
数据总是相同的(“硬编码”)JSON。
关于Roamer-1888的可读性更好的版本,请参见下面的内容——它仍然会导致相同的错误。

最佳答案

在代码中不清楚为什么.entityselector()在某些情况下应该抛出。最可能的原因是您试图在加载插件之前调用它。
为了解决这个问题,您可以尝试在一次点击中初始化所有输入,而不是在循环中单独初始化。
另外,通过将一个相当简单的片段附加到DOM,然后立即添加链接并使用jQuery附加事件处理程序,可以使代码更具可读性。
这是我写的方式(整理一下):

function addlinks(qid, prop) {

    // compose and intert fieldset.
    var $fieldset = $("<fieldset><legend>Quick Presets (" + prop.name + ")</legend></fieldset>")
        .insertAfter($('.wikibase-statementgrouplistview').first());

    // loop through prop.defaults
    prop.defaults.forEach(function(dflt) {
        // compose and append a basic fragment ...
        var $fragment = $("<p class='addstatement'>Add " + dflt.pname + ":<span class=\"links\"></span>"
            + "<span class=\"quickpresetsinput\"><input />&nbsp;<a href=\"#\">✔</a></span></p>")
            .appendTo($fieldset);

        // ... then allow jQuery to augment the appended fragment :
        // i) conditionally addClass('disabled')
        if($('#P' + dflt.pid).find(".wikibase-snakview-value a").length !== 0) {
            $fragment.addClass('disabled');
        }

        // ii) loop through dflt.values and add links.
        dflt.values.forEach(function(val) {
            $("<span>&nbsp;<a href=\"#\"></a>&nbsp;∙</span>")
            .appendTo($fragment.find('span.links'))
            .find('a')
            .text(val.name)
            .on('click', function(e) {
                e.preventDefault();
                additemstatement(qid, dflt.pid, dflt.pname, val.qid, val.name);
            });
        });

        // iii) attach click handlers to the quickpresets inputs
        $fragment.find('.quickpresetsinput').find('a').on('click', function(e) {
            e.preventDefault();
            var selection = $(this).prev('input').data('entityselector').selectedEntity();
            additemstatement(qid, dflt.pid, dflt.pname, selection.id.substring(1), selection.label);
        });
    });

    // invoke .entityselector() on all the quickpresets inputs in one hit
    $('.quickpresetsinput input').entityselector({
        'url': 'https://www.wikidata.org/w/api.php',
        'language': mw.config.get('wgUserLanguage')
    });
}

除语法外未测试
这当然是整洁,虽然没有正确的理解原来的问题,.entityselector()仍然可能抛出。

08-17 22:30