/* hafas_standard_calendar_utilties.js */
/* built: 05.11.2007 by MHEI */

// extracted from prototype framework - BEGIN
if(typeof $=='undefined'){
  function $() {
     return document.getElementById(arguments[0]);
  }
}
if(typeof Class=='undefined'){
  var Class = {
    create: function() {
      return function() {
        this.initialize.apply(this, arguments);
      }
    }
  }
}
// extracted from prototype framework - END

String.prototype.leftPad = function (l, c) { return new Array(l - this.length + 1).join(c || '0') + this; }

// some more Date object enhancements (see hafas_utilities.js):
Date.prototype.shiftD = function(value) {
   this.setDate(this.getDate()+value);
}

Date.prototype.shiftM = function(value) {
   this.setMonth(this.getMonth()+value);
}

Date.prototype.shiftY = function(value) {
   this.setYear(this.getYear()+value);
}
// Date object enhancements:
Date.prototype.getDaysInMonth = function() {
   return new Date(this.getFullYear(),this.getMonth()+1,1,-1).getDate();
}


//dateFormat

function parseUserDateInput(userInput,weekdaysTexts,format) {
   //format = "%m/%d/%Y";
   if (typeof(format) == "undefined") {
   format = dateFormat;
   }
   if (isString(userInput) && (userInput.length>0) && !isDate(userInput)) {

      if ((userInput.length > 2) || (userInput.indexOf("+") != -1)) {
         return dateinterpret(userInput, format);
      }
      // else if (userInput.length == 2) {
      //   this.mydoWeekday(userInput);
      //}
   } else if (isDate(userInput)) {
      return userInput;
   }
   return new Date();
}

function dateinterpret(str, format) {
    // Loop throught the format string, and build the regex pattern
    // for extracting the date elements.
    var pattern = "";
    var position = 1;
    var c = "";
    for (var i = 0, len = format.length; i < len; i++) {
       c = format.charAt(i);
       //if (format.charAt(i-1) == "%") {
       //   continue;
       //}

       if (c == "%") {
          c = format.substring(i,i+2);
          i++;
       }
       switch (c) {
            case '%Y' :
            case '%y' :
                pattern += '(\\d{4}|\\d{2})';
                yearPos = position++;
                break;
            case '%m' :
                pattern += '(\\d{1,2})';
                monthPos = position++;
                monthStyle = 'm'
                break;
            case '%d' :
                pattern += '(\\d{1,2})';
                dayPos = position++;
                break;
            default :
                pattern += (c == '^' ? format.charAt(++i) : c);
        }
    }
    //console.log("Pattern: "+pattern);

    // Pull out the date elements from the input string
    var matches = str.match(new RegExp(pattern));
    if (!matches)
        return null;

     // Now we have to interpret each of those parts...

    if (yearPos > -1) {
        year = parseInt(matches[yearPos], 10);
        year = (year < 50 ? year + 2000 : (year < 100 ? year + 1900 : year));
    }

    if (monthPos > -1) {
        switch (monthStyle) {
            case 'm':
                month = parseInt(matches[monthPos], 10) - 1;    // JavaScript months are zero based, user input generally is not.
                if (month > 11)
                    return null;
                break;
            case 'N':
                month = parseInt(Date.monthNumbers[matches[monthPos]], 10);
                if (isNaN(month))
                    return null;
                break;
            case 'n':
                month = parseInt(Date.shortMonthNumbers[matches[monthPos]], 10);
                if (isNaN(month))
                    return null;
                break;
        }
    }

    if (dayPos > -1) {
        day = parseInt(matches[dayPos], 10);
        var dt = new Date(year, month, 1);
        if ((day < 1) || (day > dt.getDaysInMonth()))
            return null;
    }

    return new Date(year, month, day);
}

function isFunction(o) {
  return (typeof(o)=="function");
}

function isObject(a)
{
  return (typeof a == 'object' && !!a) || isFunction(a);
}

function isArray(a)
{
  return isObject(a) && a.constructor == Array;
}

function isDate(a)
{
  return isObject(a) && a.constructor == Date;
}

function isString(a)
{
  return typeof a == 'string';
}

function inherits(base, extension)
{
   for ( var property in base )
   {
      try
      {
         extension[property] = base[property];
      }
      catch( warning ){}
   }
}

function inheritsPartly(base, extension, properties)
{
   for ( var i = 0; i < properties.length; i++ )
   {
      try
      {
         extension[properties[i]] = base[properties[i]];
      }
      catch( warning ){}
   }
}

function makeObservable (obj, observer) {
   inherits(new Observable(), obj);
   if (observer != undefined) {
      obj.addObserver(observer);
   }
}

Array.prototype.forEach = function(fn, thisObj) {
    var scope = thisObj || window;
    for ( var i=0, j=this.length; i < j; ++i ) {
        fn.call(scope, this[i], i, this);
    }
};

Array.prototype.filter = function(fn, thisObj) {
    var scope = thisObj || window;
    var a = [];
    for ( var i=0, j=this.length; i < j; ++i ) {
        if ( !fn.call(scope, this[i], i, this) ) {
            continue;
        }
        a.push(this[i]);
    }
    return a;
};

Observer = Class.create();
Observer.prototype = {

      initialize: function() {
         // intentionally left blank
      },
      observe: function() {
      }

}

function Observable() {
    this.fns = [];
}

Observable.prototype = {
    addObserver : function(fn) {
        this.fns.push(fn);
    },
    removeObserver : function(fn) {
        this.fns = this.fns.filter(
            function(el) {
                if ( el !== fn ) {
                    return el;
                }
            }
        );
    },
    notify : function(o, thisObj) {
        var scope = thisObj || window;
        this.fns.forEach(
            function(el) {
                //el.call(scope, o);
                el.observe(o);
            }
        );
    }
};

CalUtils = Class.create();
CalUtils.prototype =
{

    initialize : function() { // intentionally left blank
    },

    getDimensions : function(el) {
       var display = el.style.display;
       var ret = new Object();
       var e = el;

       for ( ret.x = 0, ret.y = 0; e != null; ret.x += e.offsetLeft, ret.y += e.offsetTop, e = e.offsetParent)
          ;

       /* Safari bug */
       if (display != 'none' && display != null) {

          ret.w = el.offsetWidth;
          ret.h = el.offsetHeight;
       } else {

          /*
           *  All *Width and *Height properties give 0 on els with display none, so enable the el temporarily
           */
          var els = el.style;
          var orgVisibility = els.visibility;
          var orgPosition = els.position;
          var orgDisplay = els.display;
          els.visibility = 'hidden';
          els.position = 'absolute';
          els.display = 'block';

          ret.w = el.clientWidth;
          ret.h = el.clientHeight;

          els.display = orgDisplay;
          els.position = orgPosition;
          els.visibility = orgVisibility;
       }
       return ret;
    },

  getWindowSize: function (w) {
    var array = [];

    w = w ? w : window;
    array.width = array[0] = w.innerWidth || (w.document.documentElement.clientWidth || w.document.body.clientWidth);
    array.height = array[1] = w.innerHeight || (w.document.documentElement.clientHeight || w.document.body.clientHeight);

    return array;
  }

}

// removes given element from position in DOM tree and appends it to the body
// (good for absolute positioning, ...)
function moveToBody(element) {
   if (isObject(element)) {
      // is object already in DOM tree?
      if (element.parentNode != null) {
         var child = element.parentNode.removeChild(element);
      } else {
         var child = element;
      }
      document.body.appendChild(child);
      return child;
   } else {
      return element;
   }
}

function safeAttachEvent(el, event, func) {
   // IE Safe
   if (el.addEventListener){
      el.addEventListener(event, func, false);
  } else if (el.attachEvent){
      el.attachEvent('on'+event, func);
   }
}

function putIFrameBehind(div, iframeid) {
   if (typeof(iframeid) == "undefined") {
       iframeid = div.id+"_iframe";
   }
   if (isObject(div)) {
     var iframe = document.getElementById(iframeid);
     if (iframe == null) {
        iframe = cEl("iframe");
        document.body.appendChild(iframe);
        iframe.id = iframeid;
     }
     iframe.className = div.className;
     iframe.style.position = "absolute";
     calUtils = new CalUtils();

     var divDim = calUtils.getDimensions(div);

     iframe.width = divDim.w + "px";
     iframe.height = (divDim.h - div.style.border)+ "px";
     iframe.style.top = divDim.y + "px";
     iframe.style.left = divDim.x + "px";
     iframe.style.border = "none";
     iframe.style.display = div.style.display;
   }
}

function modifyClassName(element, classname, activate) {
    /* de-/activates given classname in element*/
   var css = " "+element.className+" ";
   if (activate) {
      // not present -> append
      if (css.search(" "+classname+" ") > -1) {
      } else {
         css = css+classname;
      }
   } else {
      css = css.replace(" "+classname+" ", " ");
   }
   css = css.replace(/^\s+/, "").replace(/\s+$/, "");
   element.className = css;
}


