Lunarstorm canned guestbook replies

By Johan Sundström Last update Feb 13, 2007 — Installed 248 times.
// ==UserScript==
// @name	Lunarstorm canned guestbook replies
// @version	1.0: Initial version
// @namespace	http://www.lysator.liu.se/~jhs/userscript
// @description	Provide canned replies to canned guestbook queries comfily for Lunarstorm. Usage: Click the + buttom to name the present contents of the message box. Select a reply (by name) to replace the current contents of the message box from the canned reply. The - button purges a canned reply. (Canned replies are only available for the popup comment window.)
// @include	http://www.lunarstorm.se/gst/gst_compose.aspx?*
// ==/UserScript==

EventMgr = // avoid leaking event handlers
{
  _registry:null,
  initialize:function() {
    if(this._registry == null) {
      this._registry = [];
      EventMgr.add(window, "_unload", this.cleanup);
    }
  },
  add:function(obj, type, fn, useCapture) {
    this.initialize();
    if(typeof obj == "string")
      obj = document.getElementById(obj);
    if(obj == null || fn == null)
      return false;
    if(type=="unload") {
      // call later when cleanup is called. don't hook up
      this._registry.push({obj:obj, type:type, fn:fn, useCapture:useCapture});
      return true;
    }
    var realType = type=="_unload"?"unload":type;
    obj.addEventListener(realType, fn, useCapture||false);
    this._registry.push({obj:obj, type:type, fn:fn, useCapture:useCapture});
    return true;
  },
  cleanup:function() {
    if( !EventMgr._registry ) return;
    for(var i = 0; i < EventMgr._registry.length; i++) {
      with(EventMgr._registry[i]) {
        if(type=="unload")
	  fn();
        else {
	  if(type=="_unload") type = "unload";
	  obj.removeEventListener(type,fn,useCapture);
        }
      }
    }
    EventMgr._registry = null;
  }
};

var canned = eval( GM_getValue( 'canned', '([])' ) );
init_form();

function init_form( selected ) {
  var td = $X( '//td[@class="boxsep"]' ); if( !td ) return;
  var select = <select id="canned"/>, script;
  for( var i = 0; script = canned[i]; i++ )
    if( script.name == selected )
      select.option[i] = <option value={i} selected="">{script.name}</option>;
    else
      select.option[i] = <option value={i}>{script.name}</option>;
  select.option[i] = <option value="-1">-- Add canned reply --</option>;
  if( !selected )
    select.option[i].@selected = "";
  EventMgr.cleanup();
  td.innerHTML = '';
  append_to( <input type="button" id="delete" value={selected?"-":"+"}/>, td );
  append_to( select, td );
  EventMgr.add( $( 'delete' ), 'click', delete_canned_reply, false );
  EventMgr.add( $( 'canned' ), 'change', chose_canned_reply, false );

  if( typeof selected == 'undefined' )
    GM_addStyle( 'td.boxsep { text-align:center; padding-top:5px; }\n' +
		 '#delete { padding:0; width:auto; }\n' +
		 '#canned { margin-left:2px; }' );
}

function chose_canned_reply( e ) {
  var form = e.target.form;
  var script = form.elements.namedItem( 'canned' );
  var number = parseInt( script.value, 10 );
  $( 'delete' ).value = number == -1 ? '+' : '-';
  if( number == -1 ) { // add new
    return add_canned_reply( form );
  }
  var option = script.options[number];
  var message = form.elements.namedItem( 'sendGuestbook_txtMessage' );
  if( !message.value.replace( /\s/g, '' ).length ||
      message.value == canned[number].text ||
      confirm( 'Really discard this message?\n' + message.value ) )
    message.value = canned[number].text;
}

function delete_canned_reply( e ) {
  var form = e.target.form;
  if( e.target.value == "+" )
    return add_canned_reply( form );
  var script = form.elements.namedItem( 'canned' );
  var number = parseInt( script.value, 10 );
  if( !confirm( 'Really purge "'+ canned[number].name +'"?' ) ) return;
  canned.splice( number, 1 );
  save_replies();
  init_form( 0 );
}

function add_canned_reply( form ) {
  var scripts = {}, script, names = [], name, i;
  for( i=0; script = canned[i]; i++ ) {
    names.push( script.name );
    scripts[ script.name ] = script.text;
  }
  name = prompt( 'Name this reply (for your eyes only):', '' );
  if( !name ) return;
  scripts[name] = form.elements.namedItem( 'sendGuestbook_txtMessage' ).value;
  names.push( name );
  names.sort();
  for( i=0; script = names[i]; i++ )
    canned[i] = { name:script, text:scripts[script] };
  save_replies();
  init_form( name );
}

function save_replies() {
  GM_setValue( 'canned', canned.toSource() );
}

function trace() {
  unsafeWindow.console && unsafeWindow.console.trace();
}

function log() {
  unsafeWindow.console && unsafeWindow.console.log.apply( this, arguments );
}

function append_to( e4x, node, doc )
{
  return node.appendChild( import_node( e4x, doc || node.ownerDocument ) );
}

function import_node( e4x, doc )
{
  var me = import_node, xhtml, domTree, import_me;
  me.Const = me.Const || { mimeType: 'text/xml' };
  me.Static = me.Static || {};
  me.Static.parser = me.Static.parser || new DOMParser;
  xhtml = <testing xmlns="http://www.w3.org/1999/xhtml" />;
  xhtml.test = e4x;
  domTree = me.Static.parser.parseFromString( xhtml.toXMLString(),
           me.Const.mimeType );
  import_me = domTree.documentElement.firstChild;
  while( import_me && import_me.nodeType != 1 )
    import_me = import_me.nextSibling;
  if( !doc ) doc = document;
  return import_me ? doc.importNode( import_me, true ) : null;
}

function $( id ) {
  return document.getElementById( id );
}

function $X( xpath, root ) {
  var got = $x( xpath, root );
  return got instanceof Array ? got[0] : got;
}

function $x( xpath, root ) {
  try {
  var doc = root ? root.evaluate ? root : root.ownerDocument : document;
  var got = doc.evaluate( xpath, root||doc, null, 0, null ), next, result = [];
  switch( got.resultType )
  {
    case got.STRING_TYPE:
      return got.stringValue;
    case got.NUMBER_TYPE:
      return got.numberValue;
    case got.BOOLEAN_TYPE:
      return got.booleanValue;
    default:
      while( next = got.iterateNext() )
	      result.push( next );
      return result;
  }
  } catch( e ) {
    trace();
    log( e );
  }
}