2

I'm trying to build a script that alters the coloring/layout of tags on the tag page in the user-profile section of Stack Overflow.

I tested the script and it runs. The problem is that I would like to re-run it when I click on the sort options [votes] and [name].

I have tried:

  1. Triggering off the jQuery ready event.
  2. Attaching an onclick handler (which is useless since it runs before the page reloads).
  3. Attaching a load event listener to the table with the tags, etc., to no avail.

I am sure I am missing something very obvious here. I suspect that there is some async reload involved, but I can't understand what the required action to make this work is.

Can anyone explain what I am missing (or point me to some documentation that explains it)?

Community
  • 1
  • 1
SPArcheon
  • 1,273
  • 1
  • 19
  • 36

1 Answers1

4

This is a common problem. That page is using AJAX to replace just part of its content. Therefore triggering off of jQuery's ready event won't work, as that only fires after the initial, full page load.

Here are the usual workarounds/approaches for reference. I only recommend the first one:

  1. Use a robust polling utility like waitForKeyElements(). This requires loading an external script (not normally a problem), and it requires jQuery, which you should be using anyway. This approach is detailed below.

  2. Trigger off the hashchange event. Some pages are nice enough to fire this event when AJAX changes the page. Unfortunately, Stack Overflow is not one of those "polite" sites. ;-)

  3. Trigger off other changes to the URL. Some pages are nice enough to change the URL when AJAX changes the content. Stack Overflow does do this.
    Unfortunately, the URL changes immediately in SO's case, while the actual page changes occur after a variable (unpredictable) delay. Meaning you must also use one of the other techniques.

  4. Intercept the page's AJAX. This can get complicated and messy, and often times a poll or delay is still needed, as the actual page changes may occur a variable interval after the AJAX request has finished. Identifying the correct AJAX request, out of the many types the page may make, can also be tiresome.

  5. Use MutationObservers. This can be the most powerful technique, and is change driven versus polling. But it's overkill in most situations, can be tricky to implement, and can "freeze" computers with CPU spikes.

  6. Note that an older technique, Mutation Events, is obsolete and deprecated for good reasons. Do not attempt to use it, although some browsers haven't removed this functionality yet.


In almost all scripting against AJAX-driven pages, all we really want is to act on certain kinds of content. The art is to identify that content, then it's easy to use a utility like waitForKeyElements() to fire whenever our targeted payload is added or replaced.

In your case, the content appears to be the tag listing which appears in this HTML:

<div id="user-tab-tags">
    ...
    <div class="user-tab-content">
        <table class="user-tags">
            ...
        </table>
    </div>
    ...
</div>

With table.user-tags being replaced every time you change that tab's sort/pagination options.

So the jQuery selector for that content would be:

"#user-tab-tags div.user-tab-content table.user-tags"

and a complete script to change the styling would be:

// ==UserScript==
// @name     _AJAX_compensation techniques
// @include  http://stackoverflow.com/users/*
// @require  http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js
// @require  https://gist.github.com/raw/2625891/waitForKeyElements.js
// @grant    GM_addStyle
// ==/UserScript==
/*- The @grant directive is needed to work around a design change
    introduced in GM 1.0.   It restores the sandbox.
*/

waitForKeyElements (
    "#user-tab-tags div.user-tab-content table.user-tags",
    customStyleUserTags
);

function customStyleUserTags (jNode) {
    jNode.css ("background", "lime");
    //***** YOUR CODE HERE *****
}
Brock Adams
  • 90,639
  • 22
  • 233
  • 295
  • Didn't know about the waitForKeyElements utility. Will have a go at it and see if it help - reporting soon. – SPArcheon Dec 21 '12 at 07:59
  • Just tested it - it works just fine (I will only have to add a little check to avoid the "customStyleUserTags" function to get called twice, once before the table get populated and one after - but I can work alone on this). Again, thanks for the explanation. – SPArcheon Dec 21 '12 at 08:07
  • You're welcome. If you have an issue, you can always open a new question and include your script code. – Brock Adams Dec 21 '12 at 08:12