使用waitForKeyElements,是否可以防止显示关键元素,只有在我的代码修改后才显示?

Using waitForKeyElements, is it possible to prevent the key element from being displayed, and only display it after it's modified by my code?

我有 this userscript (在 Stack Overflow 的大力帮助下编写) 用于网站 metal-archives.com.

它的结构是这样的:

function appendColumn(...) {
    // code for appending column
    // code for making the table sortable   
}

waitForKeyElements ("table", appendColumn);        

除了在您切换子选项卡 (tables) 时 视觉效果 glitch/delay 外,脚本工作正常。

切换时,额外的(第 6 列)最初会按预期显示。但是,table 暂时以其原始形式显示,然后最终显示第 6 列。

要查看此内容,请安装脚本,访问 this typical target page,然后切换子选项卡(在 Complete Discography、Main、Lives、Demos、Misc 之间等)。
它看起来像这样:


我试图通过添加以下内容来使初始 table 不出现:

GM_addStyle(".display.discog {display: none;} ");

appendColumn() 的开头并且:

GM_addStyle(".display.discog {display: inline !important;} "); 

appendColumn() 结束。
但这没有任何区别。


我在该页面上使用了 Firefox Network Monitor,当您切换标签时似乎:

如何更改代码(使用waitForKeyElements时)以防止显示关键元素,并且仅在我的代码修改后才显示?

或者如何加快响应速度?

谢谢。

waitForKeyElements 是一种缓慢的插入内容的方式。这是您看到所看到的呈现行为的原因之一。

第一次切换时选项卡呈现正确的原因是因为它是隐藏的,并且在隐藏时正确调整。显示选项卡时,内容会更新以反映服务器的最新信息,该信息尚未调整。 waitForKeyElements 然后注意到更改并再次触发以更正。

使用 ajaxComplete 您可以在首次加载内容时隐藏面板。

数据优先时隐藏面板returns:

$(document).ajaxComplete(function(e, xhr, config){
   if(config.url.indexOf('/tab/') != -1){                     // Because the tables URLs are like `www.metal-archives.com/band/discography/id/xxx/tab/lives`
       $('.ui-tabs-panel').css('visibility', 'hidden');
   }
});

在您的 appendColumn 函数中显示面板:

function appendColumn(...) {
    // code for appending column
    // code for making the table sortable   
    $('.ui-tabs-panel').css('visibility', 'visible');
}

编码愉快!

我加载了你的脚本,添加了时间线,并进行了测试。从 AJAX-complete 到 table 修复并完成的时间只有 400 到 500 毫秒!对于大多数人和情况来说,这已经足够快了。

但是,对于那些绝对想挤出毫秒的时间,您可以切换到 MutationObservers。这些是挑剔的、脆弱的,并且不太跨浏览器 portable,但它们很快。
在这种情况下,MutationObservers 将 AJAX-to-fixed-table 时间缩短到 20 到 40 毫秒范围。

我建议使用像 Mutation Summary 这样的库来减轻这个过程的痛苦。

要从 简单 waitForKeyElements() 实现转换为突变摘要:

  1. 添加

    @require https://raw.githubusercontent.com/rafaelw/mutation-summary/master/src/mutation-summary.js
    

    到您的元数据块。

  2. 将您的 waitForKeyElements 回调和 simple 选择器插入此结构:

    var muteObserver = new MutationSummary ( {
        callback: handleDiscographyChanges,
        rootNode: $( {ANY-JQUERY-SELECTOR} )[0],
        queries: [ {element: {A-SIMPLE-SELECTOR}} ]
    } );
    
    function handleDiscographyChanges (muteSummaries) {
        var mSummary    = muteSummaries[0];
        if (mSummary.added.length) {
            {YOUR-CALLBACK} ( $(mSummary.added[0]) );
        }
    }
    

例如在这种情况下,更改:

waitForKeyElements (".display.discog", appendColumn);

收件人:

var muteObserver = new MutationSummary ( {
    callback: handleDiscographyChanges,
    rootNode: $("#band_disco")[0],
    queries: [ {element: ".discog"} ]
} );

function handleDiscographyChanges (muteSummaries) {
    var mSummary    = muteSummaries[0];
    if (mSummary.added.length) {
        appendColumn ( $(mSummary.added[0]) );
    }
}

其中 rootNode 是通过检查页面结构确定的。




作为参考,下面是具有 3 种可选方法和计时记录的完整脚本。它仅在 Firefox 上进行了测试,但应该也可以与 Tampermonkey 一起使用(也许)。

查看每行正上方的 //OPTION n 行以选择性地注释掉。

// ==UserScript==
// @name        Metal Archives (discography pages) - Reviews column split and sortable tables
// @include     http://www.metal-archives.com/bands/*
// @include     http://www.metal-archives.com/band/*
// @grant       none
// @require     http://code.jquery.com/ui/1.9.1/jquery-ui.min.js
// @require     https://greasyfork.org/scripts/2199-waitforkeyelements/code/waitForKeyElements.js?version=6349
// @require     https://greasyfork.org/scripts/5844-tablesorter/code/TableSorter.js?version=21758
// @require     https://raw.githubusercontent.com/rafaelw/mutation-summary/master/src/mutation-summary.js
// ==/UserScript==

function appendColumn(jNode) {
    logTime ("Table fixed");

    // STEP 1+2: SPLIT THE 'REVIEWS' COLUMN INTO A 'REVIEWS' COLUMN AND A 'RATINGS' COLUMN
    var tbl = jNode[0];     // table reference

    // If the current sub-table has no data, then stop the execution of the function
    if (tbl.rows[1].cells[0].innerHTML == '<em>Nothing entered yet. Please add the releases, if applicable. </em>') {
        return;
    }

    var newCell, newText;

    const cols = tbl.rows[0].cells.length - 1;

    var tr = tbl.tHead.children[0],
    th = document.createElement('th');

    th.innerHTML = "Ratings";
    th.className = "ratingsCol";
    tr.appendChild(th);

    for (i = 1; i < tbl.rows.length; i++) {
        k = tbl.rows[i].cells[cols].innerHTML;    // Retrieve the content of the current cell of the Review column and store it to variable k


        re1 = /<a [^>]*>[^(]*[(]([^)]+)/ ;        // (RegEx which matches the 'Ratings' percentage(incl.the % symbol)
        l = re1.exec(k);                          // (Execute the RegEx and store it to variable l)

        newCell = tbl.rows[i].insertCell(-1);     // Add a new cell (for the new 'Ratings' column ) -for each row-

        if (re1.test(k) != 0){                    // If the RegEx has matches, (only) then create new cells with...

            re0 = /(<a [^>]*>)[0-9]*[^(]/ ;       // (RegEx which matches the reviews URL)
            url = re0.exec(k);                    // (Execute the RegEx and store it to variable url)

            newCell.innerHTML = url[1] + l[1] + '</url>'; // ...the Ratings percentage (which is also a link to the Reviews)...


            re2 = /<a [^>]*>([0-9]*)[^(]/ ;       // (RegEx which matches the 'Reviews' number)
            m = re2.exec(k);                      // (Execute the RegEx and store it to variable m)

            newCell = tbl.rows[i].cells[cols];    //
            newCell.innerHTML = url[1] + m[1] + '</url>'; // ...and the Reviews number (which is also a link to the Reviews)
        }
    }

    //  STEP 3: MAKE THE DISCOGRAPHY TABLE SORTABLE  (using the jQuery plugin "tablesorter")
    $(tbl).tablesorter ( {
        cssAsc: 'up',
        cssDesc: 'down',
        headers: {
              0: {sorter: false}
        }
    } );
}

//OPTION 1
//waitForKeyElements (".display.discog", appendColumn);

$(document).ajaxComplete (function (e, xhr, config){
    logTime ("Ajax complete");
    //OPTION 2
    return; //-- For compare test

    if (config.url.indexOf ('/tab/') != -1){
        $(".display.discog").each ( function () {
            appendColumn ( $(this) );
        } );
    }
} );

$("#band_disco > ul > li").on ("click", "a.ui-tabs-anchor", function (zEvent) {
    logTime (zEvent.target.textContent + " tab was clicked.");
} );

function logTime (lableTxt) {
    var tNow    = new Date ();
    console.log (tNow.toLocaleFormat ('%H:%M:%S') + "." + tNow.getMilliseconds (), " <== " + lableTxt);
}

//OPTION 3
//*--- Remove leading slash, from this line, to comment out block, below.
var muteObserver = new MutationSummary ( {
    callback: handleDiscographyChanges,
    rootNode: $("#band_disco")[0],
    queries: [ {element: ".discog"} ]
} );
//*/ -- Tail end of optional comment block

function handleDiscographyChanges (muteSummaries) {
    var mSummary    = muteSummaries[0];
    if (mSummary.added.length) {
        appendColumn ( $(mSummary.added[0]) );
    }
}

请注意,此示例中省略了样式代码和一些原始注释。