/**
 * Date picker script
 *
 * This script should be linked to the calling page at the end (just before the </body>). 
 *
 * Upon loading, it will scan the page for every input fields in form that has
 * a class of "datepicker", and hook to it to add an interactive calendar.
 *
 * Author : NBI SARL / Nicolas BOUTHORS <nicolas@bouthors.org>
 * $Id: datepicker.js,v 1.2 2007/12/11 17:04:58 nico Exp $ 
 *
 * You can use script under the terms of the MIT Licence
 */

var modified_input_elemnt = null; // Holds a reference to the input field modified
var stupid_offset=1900; // Gecko JS Date objects ofsets years by 1900. 

/* Finds the horizontal position of the designated object in pixel, relative to the page */
function findPosX(obj)
{
  var curleft = 0;
  if (obj.offsetParent) {
    while (obj.offsetParent) {
      curleft += obj.offsetLeft
      obj = obj.offsetParent;
    }
  }
  else if (obj.x)
    curleft += obj.x;
  return curleft;
}

/* Finds the vertical position of the designated object in pixel, relative to the page */
function findPosY(obj)
{
  var curtop = 0;
  if (obj.offsetParent) {
    while (obj.offsetParent) {
      curtop += obj.offsetTop
      obj = obj.offsetParent;
    }
  }
  else if (obj.y)
    curtop += obj.y;

  return curtop;
}

function JSDateToSQL(jsdt) {

  y = jsdt.getYear()+stupid_offset;
  m = jsdt.getMonth()+1;  if (m < 10) m = '0'+m;
  d = jsdt.getDate();     if (d < 10) d = '0'+d;
  return y+'-'+m+'-'+d;
}

/* Translate the input content to "french" format : DD/MM/YYYY if possible */
function normalizeDateValue(input) {
  newvalue = input.value;

  if (m = newvalue.match(/^([0-9]{4})-([0-9]{2})-([0-9]{2})$/)) {
    newvalue = m[3] + '/' + m[2] + '/' + m[1];
  }

  input.value = newvalue;
}

/* Translates an arbitrary date to SQL92 format : YYYY-MM-DD */
function dateToSQL(val) {
  if (m = val.match(/^([0-9]{4})-([0-9]{2})-([0-9]{2})$/)) {
    return val;
  }
  if (m = val.match(/^([0-9]{2})\/([0-9]{2})\/([0-9]{4})$/)) {
    return m[3] + '-' + m[2] + '-' + m[1];
  }
}

function month(dt) {
  tmp = dateToSQL(dt);
  m = tmp.match(/^([0-9]{4})-([0-9]{2})-([0-9]{2})/)
  return parseInt( m[2], 10 );
}
function year(dt) {
  tmp = dateToSQL(dt);
  m = tmp.match(/^([0-9]{4})-([0-9]{2})-([0-9]{2})/)
  return parseInt(m[1], 10);
}
function day(dt) {
  tmp = dateToSQL(dt);
  m = tmp.match(/^([0-9]{4})-([0-9]{2})-([0-9]{2})/)
  return parseInt(m[3], 10);
}


function redraw(dt) {
  d=document.getElementById('caldiv');
  d.innerHTML = buildHTMLCalendar(dt);
}

function pickDate(dt) {
  modified_input_element.value = dt;
  normalizeDateValue(modified_input_element);
  div = document.getElementById('caldiv');
  document.body.removeChild(div);

  // Fire a "changed" event upwards
  //On IE
  if(modified_input_element.fireEvent) {
    modified_input_element.fireEvent('onchange');
  }
  //On Gecko based browsers
  if(document.createEvent) {
    var evt = document.createEvent('HTMLEvents');
    if(evt.initEvent) {
      evt.initEvent('change', true, true);
    }
    if(modified_input_element.dispatchEvent) {
      modified_input_element.dispatchEvent(evt);
    }
  }


  modified_input_element = null;
}

function hideCal() {
  modified_input_element = null;
  div = document.getElementById('caldiv');
  document.body.removeChild(div);
}

/* Creates an HTML table to represent a calendar for the given date (SQL
 * format). The table is returned as a string
 */
function buildHTMLCalendar(dt) {
  var daysInMonth = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
  var daysName = new Array('Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi', 'Dimanche');
  var shortDaysName = new Array('Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam', 'Dim');
  var monthNames = new Array('Janvier', 'F&eacute;vrier', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Ao&ucirc;t', 'Septembre', 'Octobre', 'Novembre', 'D&eacute;cembre');

  // Get the date that is passed
  curdate = new Date( year(dt), month(dt)-1, 1);

  // Previous and next month
  prev = JSDateToSQL( new Date( year(dt), month(dt)-2, 1) );
  next = JSDateToSQL( new Date( year(dt), month(dt), 1) );

  // Leap years
  if (curdate.getYear()%4 == 0 && curdate.getYear()%100 != 0) 
    daysInMonth[1] = 29;

  html = '<table class="caltable" border="0" cellspacing="0" cellpadding="2">';
  html += '<tr class="monthname"><td id="prev_month" onclick="redraw(\''+prev+'\');">&lt;</td><td colspan="4">';
  html += monthNames[ curdate.getMonth() ] + ' ' + (curdate.getYear()+stupid_offset);
  html += '</td><td id="next_month" onclick="redraw(\''+next+'\');">&gt;</td><td id="close" onclick="hideCal();">X</td></tr>';

  // One row for day names
  html += '<tr class="daynames">';
  for (i=0 ; i<7 ; i++) {
    html += '<td>'+shortDaysName[i]+'</td>';
  }
  html += '</tr>';

  // Then the calendar
  html += '<tr>';


  week=0;
  for (i = 1 ; i<=daysInMonth[ curdate.getMonth() ] ; i++) {
    curdate = new Date( curdate.getYear()+stupid_offset, curdate.getMonth(), i);
    if (week == 0) {
      // Offset for first week
      if (curdate.getDay() > 1) 
        html += '<td colspan="'+(curdate.getDay()-1)+'">&nbsp;</td>';
      if (curdate.getDay() == 0) 
        html += '<td colspan="6">&nbsp;</td>';
      week++;
    }
    if (curdate.getDay() == 1) {
      html += '</tr><tr>';
      week++;
    }

    className='day';
    if (JSDateToSQL(curdate) == dt) {
      className='selected_day';
    }
    if (curdate.getDay()==0||curdate.getDay()==6) {
      className += ' weekend';
    } 

    html += '<td onclick="pickDate(\''+ JSDateToSQL(curdate) +'\');" class="'+className+'">'+i+'</td>';
  }
  html += '</tr>';

  html += '</table>';

  return html;
}

/* Creates and display a div containing the calendar just under the input passed as a parameter */
function displayCalForInput(input) {
  caldiv = document.createElement('div');
//   caldiv.style.display='none';
  document.body.appendChild(caldiv);
  caldiv.className='calDiv';
  caldiv.style.position='absolute';
  caldiv.id='caldiv';

  posx = findPosX(input); posy = findPosY(input);
  posy+=20;

  if (input.value != '') {
    caldiv.innerHTML = buildHTMLCalendar( dateToSQL(input.value) );
  } else {
    dt = new Date;
    caldiv.innerHTML = buildHTMLCalendar(  JSDateToSQL(dt) );
  }
  caldiv.style.left = posx+'px';
// This should be necessary, but bugs in firefox and yet the div show on the right spot
  caldiv.style.top = posy+'px';

  // Show the cal
}

// Toggle the display of the calendar under any input
function clickDateField(e) {
  if (e) 
    i = e.target;
  else // IE
    i = window.event.srcElement;

  i.focus();
  // Look for the div holding the calendar. 
  div = document.getElementById('caldiv');
  if (!div) {
    // Show 
    modified_input_element = i;
    displayCalForInput(i);
  } else {
    // Hide
    modified_input_element = null;
    document.body.removeChild(div);
  }
}

/**
 * The init functions hooks to every field in the page with a class containing
 * datepicker, it overwrites the onclick hook to add the dhtml popup calendar
 */
function init() {
  if (!document.all) 
    stupid_offset=1900; // Gecko JS Date objects ofsets years by 1900. 

  inputs = document.getElementsByTagName('input');
  for (i = 0 ; i<inputs.length ; i++) {
    if (inputs[i].className.match(/datepicker/)) {
      normalizeDateValue(inputs[i]);
      inputs[i].onclick = clickDateField;
      if (document.all) {
        inputs[i].ondoubleclick = clickDateField;
      }
    }
  }
  document.write(
    '<style type="text/css">'+
    'table.caltable { font-family: arial, helvetica; font-size: 11px; background: white; }'+
    'table.caltable { border: solid 1px black; }'+
    'table.caltable td { text-align: center; }'+
    'table.caltable td.weekend { background: #eeffee; }'+
    'table.caltable td.day { cursor: pointer; }'+
    'table.caltable td.selected_day { cursor: pointer; background: #ff7700; }'+
    'table.caltable td.day:hover { background: #6886c4; color: white; font-weight: bold; cursor: pointer; }'+
    'tr.daynames td { background: black; color: white; }'+
    'tr.monthname td { background: #777; color: white; font-weight: bold;}'+
    'td#prev_month { cursor: pointer; }'+
    'td#next_month { cursor: pointer; }'+
    'td#close { cursor: pointer; }'+
    '</style>');
}

init();


