// Drupal Undesirable String Bar
// Version 1.0
// 2007-12-19
// Released under the GPL license
// http://www.gnu.org/copyleft/gpl.html
// Based on the GPL'd Access Bar from http://diveintogreasemonkey.org/casestudy/accessbar.html
//
// --------------------------------------------------------------------
//
// This is a Greasemonkey user script.  To install it, you need
// Greasemonkey 0.3 or later: http://greasemonkey.mozdev.org/
// Then restart Firefox and revisit this script.
// Under Tools, there will be a new menu item to "Install User Script".
// Accept the default configuration and install.
//
// To uninstall, go to Tools/Manage User Scripts,
// select "Drupal Undesirable String Bar", and click Uninstall.
//
// To add to the list of undesirable phrases, append them to the list below:
// (regular expressions allowed, for example \\W is a word boundry, ? makes the previous character optional, etc.)
var bad_phrases = new Array();
bad_phrases.push('(^|\\W)nodes?($|\\W)');
// End of list
// Colour configuration (currently black background, white text, highlighting in yellow):
var bar_colour_back = 'black';
var bar_colour_fore = 'white';
var highlight_colour = 'yellow';
// End of colours
//
// --------------------------------------------------------------------
// ==UserScript==
// @name          Drupal Undesirable String Bar
// @namespace     http://www.corsix.org/drupal_string_bar.html
// @description   Alerts drupal developers to undesirable phrases present on pages
// @include       http://drupal.org/*
// ==/UserScript==

// Helper function to add CSS to a page within the head element
function addGlobalStyle(css) {
  var head, style;
  head = document.getElementsByTagName('head')[0];
  if (!head) {
    return;
  }
  style = document.createElement('style');
  style.type = 'text/css';
  style.innerHTML = css;
  head.appendChild(style);
}

var descriptions, desc, body, phase_regexp, phrase_match;

// Check for a page body. Without it, there is no point checking for phrases
body = document.getElementsByTagName('body')[0];
if (!body) {
  return;
}

// Prepare the text output varialbes
descriptions = new Array();
desc = '';

// For each of the disallowed phrases, search for it and add any instances of it to the descriptions array
function scan_for_bad_phrases(elem, regexp, elemname) {
  regexp.lastIndex = 0;
  if (regexp.exec(elem.textContent) == null) {
    return;
  }
  if (elem.hasChildNodes() == false) {
    regexp.lastIndex = 0;
    var anchor_name = 'drupalbadstring_'+ descriptions.length.toString();
    while ((phrase_match = regexp.exec(elem.textContent)) != null) {
      var txt = ''+ phrase_match;
      descriptions.push("<a href='#"+ anchor_name + "'><abbr title='"+ elemname +"'>"+ txt.replace(/[^a-z ]/gi, '') +'</abbr></a>');
    }
    elem.parentNode.innerHTML = elem.parentNode.innerHTML.replace(regexp, "<a name='"+ anchor_name + "'></a><span class='drupalstringbar-highlight'>$&</span>");
    return true;
  }
  else {
    var thiselemname = elem.nodeName.toLowerCase();
    if (elem.id != '') {
      thiselemname = thiselemname +'.'+ elem.id;
    }
    if (elem.className != '') {
      thiselemname = thiselemname +'&#35;'+ elem.className;
    }
    elemname = thiselemname +' &lt; '+ elemname;
    for (var i = 0; i < elem.childNodes.length; i++) {
      if (scan_for_bad_phrases(elem.childNodes[i], regexp, elemname)) {
        break;
      }
    }
  }
  return false;
}
for (var i = 0; i < bad_phrases.length; i++) {
  var phase_regexp = new RegExp(bad_phrases[i], 'gim');
  scan_for_bad_phrases(document.documentElement, phase_regexp, 'document');
}

// If no bad phrases were found, then stop the script.
if (descriptions.length == 0) {
  return;
}

// Create an alert bar at the bottom of the screen alerting the user to the phrases
div = document.createElement('div');
div.id = 'drupalstringbar-div-0';
desc = '<div><b>Drupal undesirable string(s)</b> <ul>';
for (var i = 0; i < descriptions.length; i++) {
  desc = desc +'<li>'+ descriptions[i] +'</li>';
}
desc = desc +'</ul></div>';
div.innerHTML = desc;
document.body.style.paddingBottom = '4em';
window.addEventListener('load',
  function () {
    document.body.appendChild(div);
  }
  , true);
  
// Styling for the alert bar
addGlobalStyle(
  '#drupalstringbar-div-0 {'+
  '  position: fixed;'+
  '  left: 0;'+
  '  right: 0;'+
  '  bottom: 0;'+
  '  top: auto;'+
  '  border-top: 1px solid silver;'+
  '  background: '+ bar_colour_back +';'+
  '  color: '+ bar_colour_fore + ';'+
  '  margin: 1em 0 0 0;'+
  '  padding: 5px 0 0.4em 0;'+
  '  width: 100%;'+
  '  font-family: Verdana, sans-serif;'+
  '  font-size: small;'+
  '  line-height: 160%;'+
  '}'+
  '#drupalstringbar-div-0 a,'+
  '#drupalstringbar-div-0 li,'+
  '#drupalstringbar-div-0 span,'+
  '#drupalstringbar-div-0 b,'+
  '#drupalstringbar-div-0 strong {'+
  '  background-color: transparent;'+
  '  color: '+ bar_colour_fore + ';'+
  '}'+
  '#drupalstringbar-div-0 div {'+
  '  margin: 0 1em 0 1em;'+
  '}'+
  '#drupalstringbar-div-0 div ul {'+
  '  margin-left: 0;'+
  '  margin-bottom: 5px;'+
  '  padding-left: 0;'+
  '  display: inline;'+
  '  list-style: none;'+
  '}'+
  '#drupalstringbar-div-0 div ul li {'+
  '  margin-left: 0;'+
  '  padding: 3px 10px;'+
  '  list-style: none;'+
  '  display: inline;'+
  '}'+
  '.drupalstringbar-highlight {'+
  '  background-color: '+ highlight_colour +';'+
  '}');

