1

I have been trying to change the order of elements in this code so the Account Information, Statistics and Website Traffic dividers (in that order) are listed before the jump-search divider.

The target page HTML looks like this (the page is a HostGator control panel):

<div id="sub">
<!-- Jump Search Start -->
    <div id="jump-search">
       <h3 style="margin:0">Find</h3>
    </div>
<!-- Jump Search End -->

<!-- Website Traffic Start -->
    <div class="minititle">Website Traffic</div>
       <div class="trafficcontain"></div>
       <div style="height:10px;"></div>
<!-- Website Traffic End -->

<!-- New Stats Start -->
    <div class="minititle truncate-table" id="statsnew">Statistics</div>
       <div id="statscontain"></div>
    <div style="height:10px;"></div>
<!-- New Stats End -->

<!-- Account Info Start -->
    <div class="minititle">Account Information</div>
       <div class="accntcontain"></div>
       <div style="height:10px;"></div>
<!-- Account Info End -->
</div>

After more than an hour fiddling with Greasemonkey I have nothing to show for it. Any help is much appreciated.

Brock Adams
  • 90,639
  • 22
  • 233
  • 295
RobWhite
  • 13
  • 4
  • 1
    http://stackoverflow.com/questions/9732624/how-to-swap-dom-child-nodes-in-javascript – kavun Nov 19 '13 at 05:24
  • Please verify that those comments like ``, etc. appear ***exactly*** like that in the page. Also verify that this is static HTML. That is, these parts aren't set by javascript. – Brock Adams Nov 19 '13 at 07:21
  • @BrockAdams Yes, this is static HTML. I took the liberty to clear out unnecessary comments/codes in the original snippet I had posted. I have updated the original post to include everything. Is that what you were asking me to do? – RobWhite Nov 19 '13 at 08:25
  • No, you pared that code down just right, after seeing the full code. That extra stuff clutters the question and you trimmed it well so I reverted to the original Q. ... ... I just wanted to make sure that those comments could be trusted, and to see if the section commonalities might be relied on. (Yes and no.) I should have recognized this as HTML from a HostGator style control panel. ;) ... Anywho, scripting this is not hard but not as simple as I would have liked. I'll have an answer in the next 24 hours if nobody beats me to it. – Brock Adams Nov 19 '13 at 08:47

1 Answers1

0

This is tricky because the sections are marked out by comments and not by any trustworthy HTML structure (except, maybe, the contents of the .minititle divs).
On the plus side, some of my host control panels have the same problem, so I already had something like the following script. ;)

We need to search for comment strings and then a way to get all the nodes in between matched comments. Alas, jQuery does not handle HTML comments well, But the straight DOM approach is not too difficult (Just might not work on all browsers. The following code was only tested on Firefox and Chrome.).

Here's a complete userscript that will work on a static page. You can also see the code in action at jsFiddle:

// ==UserScript==
// @name    Hostgator control panel, prioritize status panel order
// @match   https://*.hostgator.com/frontend/*
// @match   https://*.hostgator.com:2083/*
// @match   http://*.hostgator.com:2082/*
// @grant   GM_addStyle
// ==/UserScript==

//-- IMPORTANT!  Add your ports, in the match statements above, as needed.

var contNode    = document.querySelector ("#sub");
var insPoint    = findHtmlCommentsByRegex (contNode, /Jump Search Start/i);
if (insPoint && insPoint.length) {
  insPoint      = insPoint[0];

  moveCommentBoundedNodesBefore (insPoint, contNode, "Account Info");
  moveCommentBoundedNodesBefore (insPoint, contNode, "New Stats");
  moveCommentBoundedNodesBefore (insPoint, contNode, "Website Traffic");
}
else {
  reportError ('"Jump Search Start" comment not found!');
}

function moveCommentBoundedNodesBefore (targetNode, contNode, idingString) {
  var srchRegEx   = new RegExp (idingString + ' (?:Start|End)', 'i');
  var nodesToMove = getNodesBoundedByStartEndComments (contNode, srchRegEx);
  var pNode       = targetNode.parentNode;

  for (var J = 0, L = nodesToMove.length;  J < L;  ++J) {
    pNode.insertBefore (nodesToMove[J], targetNode);
  }
}

function getNodesBoundedByStartEndComments (contNode, srchRegex) {
  var boundedNodes  = [];
  var borders       = findHtmlCommentsByRegex (
    contNode, srchRegex, false //-- This MUST be false.
  );
  if (borders  &&  borders.length === 2) {
    var bNode       = borders[0];
    do {
      boundedNodes.push (bNode);
      if (bNode == borders[1]) {
        break;
      }
      bNode         = bNode.nextSibling;

    } while (bNode);
  }
  else {
    reportError ("Error finding comment pairs with: " + srchRegex);
    console.log ("borders: ", borders);
  }

  return boundedNodes;
}

function findHtmlCommentsByRegex (contNode, srchRegex, recurse) {
  var recurse       = recurse || false;
  var matchingComments  = [];

  if (contNode) {
    var chldNodes   = contNode.childNodes;

    for (var J = 0, L = chldNodes.length;  J < L;  ++J) {
      var cNode     = chldNodes[J];

      if (cNode.nodeType === Node.COMMENT_NODE) {
        if (srchRegex.test (cNode.nodeValue) ) {
          matchingComments.push (cNode);
        }
      }
      else if (recurse  &&  cNode.nodeType === Node.ELEMENT_NODE) {
        var subFind = findHtmlCommentsByRegex (cNode, srchRegex, recurse);
        if (subFind.length) {
          matchingComments.push (subFind);
        }
      }
    }
  }

  return matchingComments;
}

function reportError (mess) {
  //alert ("Problem found by GM script: " + mess);
  console.log ("Problem found by GM script: " + mess);
}



Warning:

Since you indicated that this was for a HostGator control panel, beware that on my HG panel, there is no <!-- New Stats Start --> comment -- an obvious error; all the other comment boundaries were correct, including for the plethora of junk and advertizing sections.

If this is the case for you as well, add this code:

var fubarDiv        = document.getElementById ("statsnew");
var fixitComment    = document.createComment ("New Stats Start");
fubarDiv.parentNode.insertBefore (fixitComment, fubarDiv);

just before the

moveCommentBoundedNodesBefore (insPoint, contNode, "New Stats");

line.
When I do that, the script works perfectly on my HostGator panel.

Brock Adams
  • 90,639
  • 22
  • 233
  • 295
  • 1
    This works flawlessly. You are absolutely correct about the missing comment. I accidentally left that in there while I was cleaning the code up for submission. Thank you! – RobWhite Nov 23 '13 at 09:52