// $Id: jstools.js,v 1.1 2006/05/11 18:31:29 nedjo Exp $

/**
 * A set of helper functions, beyond the methods declared in drupal.js.
 */

function jsToolsHelpers() {};

/**
 * Return the path portion of an href.
 */
jsToolsHelpers.prototype.getPath = function(href) {
   return href.substring(jsTools.basePath.length + jsTools.query.length, href.length);
}

/**
 * Set a cookie.
 */
jsToolsHelpers.prototype.setCookie = function(sName, sValue, nDays) {
   var expires = "";
   if (nDays) {
      var d = new Date();
      d.setTime(d.getTime() + nDays * 24 * 60 * 60 * 1000);
      expires = '; expires=' + d.toGMTString();
   }

   document.cookie = sName + '=' + sValue + expires + '; path=/';
};

/**
 * Set a previously set cookie.
 */
jsToolsHelpers.prototype.getCookie = function(sName) {
   var re = new RegExp("(\;|^)[^;]*(" + sName + ")\=([^;]*)(;|$)");
   var res = re.exec(document.cookie);
   return res != null ? res[3] : null;
};

/**
 * Unset a cookie.
 */
jsToolsHelpers.prototype.removeCookie = function(name) {
   setCookie(name, '', -1);
};

/**
 * Attach an event to an element.
 */
jsToolsHelpers.prototype.addEvent = function(obj, type, fn) {
   if (!obj) {
      return;
   }
   if (obj.attachEvent) {
      obj['e'+type+fn] = fn;
      obj[type+fn] = function(){
         obj['e'+type+fn](window.event);
      }
      obj.attachEvent('on' + type, obj[type+fn]);
   }
   else if (obj.addEventListener) {
      obj.addEventListener(type, fn, false);
   }
   else {
      var originalHandler = obj['on' + type];
      if (originalHandler) {
         obj['on' + type] = function(e){
            originalHandler(e);
            fn(e);
         };
      }
      else {
         obj['on' + type] = fn;
      }
   }
}

/**
 * Remove an event from an element.
 */
jsToolsHelpers.prototype.removeEvent = function(obj, type, fn) {
   if (obj.detachEvent) {
      if(obj[type+fn]) {
         obj.detachEvent( 'on'+type, obj[type+fn] );
         obj[type+fn] = null;
      }
   }
   else if (obj.removeEventListener) {
      obj.removeEventListener( type, fn, false );
   }
   else {
      obj["on" + type] = null;
   }
}

/**
 * Returns an event's source element.
 */
jsToolsHelpers.prototype.getSourceElement = function(e) {	
   if (!e) e = window.event;
   var srcE = e.target ? e.target : e.srcElement
   if (!srcE) return null;
   if (srcE.nodeType == 3) srcE = srcE.parentNode; // safari weirdness
   if (srcE.tagName.toUpperCase()=='LABEL' && e.type=='click') {
      // When clicking a label, firefox fires the input onclick event
      // but the label remains the source of the event. In Opera and IE
      // the source of the event is the input element. Which is the
      // expected behavior, I suppose.
      if (srcE.getAttribute('for')) {
         srcE = document.getElementById(srcE.getAttribute('for'));
      }
   }
   return srcE;
}

/**
 * If a target element has not bee set, return the document object.
 */
jsToolsHelpers.prototype.getTarget = function(elt) {
   return elt ? elt : document;
}

/**
 * A set of effects. These 'vanilla' effects can be overridden by effects libraries.
 */
var jsToolsEffects = function() {};

/**
 * Hide or display an element.
 */
jsToolsEffects.prototype.collapse = function(node) {
   toggleClass(node, 'collapsed');
}

/**
 * Scroll to a given element's vertical page position.
 */
jsToolsEffects.prototype.scrollTo = function(node) {
   var pos = absolutePosition(node);
   window.scrollTo(0, pos.y);
}

/**
 * The jsTools object registers and calls behaviours and holds their associated properties.
 */

if (jsToolsHelpers && jsToolsEffects) {
   var jsTools = {
      behaviors: {},
      helpers: new jsToolsHelpers(),
      effects: new jsToolsEffects(),
      init: function() {
         jsTools.attachBehaviors();
         // We detect core behaviours after inital attachment because they already register themselves
         // as load events.
         jsTools.detectCoreBehaviors();
      },
      attachBehaviors: function(behaviors, elt) {
         if (behaviors) {
            for(i = 0; behaviorName = behaviors[i]; i ++) {
            //jsTools.behaviors[behaviorName](elt);
            }
         }
         else {
            for(var behaviorName in jsTools.behaviors) {
               jsTools.behaviors[behaviorName](elt);
            }
         }
      },
      detectCoreBehaviors: function() {
         var coreBehaviors = ['upload', 'autocomplete'];
         for (var i = 0; behaviorName = coreBehaviors[i]; i++) {
            if (eval('window.' + behaviorName + 'AutoAttach')) {
               jsTools.behaviors[behaviorName] = eval(behaviorName + 'AutoAttach');
            }
         }
      },
      behaviourInvoke: function(behaviourName, elt) {
         if (jsTools.behaviors[behaviourName]) {
            jsTools.behaviors[behaviorName](elt);
         }
      }
   };
}


// Killswitch for all jstools behaviours.
// jsTools.init calls all registered behaviours' attach methods.
if (isJsEnabled()) {
   addLoadEvent(jsTools.init);
}

/**
 * All functions from here to end are temporary fixes to issues in drupal.js.
 */

/**
 * Parse a JSON response.
 *
 * The result is either the JSON object, or an object with 'status' 0 and 'data' an error message.
 */
function parseJson(data) {
   if ((data.substring(0, 1) != '{') && (data.substring(0, 1) != '[')) {
      return {
         status: 0,
         data: data.length ? data : 'Unspecified error'
      };
   }
   return eval('(' + data + ');');
}

/**
 * Removes a class name from an element
 */
function removeClass(node, className) {
   if (!hasClass(node, className)) {
      return false;
   }
   node.className = eregReplace('(^| )'+ className, '', node.className);
   node.className = eregReplace(className +'($| )', '', node.className);
   return true;
}
