(function($) {
		  
	$.fn.qp_countdown = function(options) {
	  var settings = $.extend({
      number: 1,                // Nummer (ID) des Countdowns im XML-File
      height: 110,               // Höhe einer Ziffer und des Countdowns (in Pixeln)
      width: 42,                // Breite einer Ziffer (in Pixeln)
      digitSpace: 1,            // Abstand der Digits innerhalb von Gruppen in Pixeln
      groupSpace: 12,           // Abstand zwischen Gruppen (Jahr-Monat-Tag-Stunde-Minute) in Pixeln
      format: 'ddd-hh-mm-ss',    // Ausgabeformat, default: tag-tag-tag stunde-stunde minute-minute sekunde-sekunde
      clDigit: null,            // Klasse für Ziffern
      xmlFile: 'date.xml',      // XML-File mit Countdown-Daten
      xmlType: 'get',           // Request-Methode (get/post)
      start: Math.round(new Date().getTime()/1000),
      img: ['0.jpg','1.jpg','2.jpg','3.jpg','4.jpg','5.jpg','6.jpg','7.jpg','8.jpg','9.jpg'],
      preload: [],
      imgPath: 'images/', 	// Verezeichnis vom aufrufenden/einbindenden Dokument aus gesehen
      onStart: null,            // Callback (bevor der Counter gestartet wird)
      afterCountdown: null,     // Callback (nachdem der Counter zurückgezählt wurde)
      time: [],
      countdownHTML: '<div id="countdownID"></div>'
	  }, options);

    // Falls es sich um ein Element-Array handelt -> nur das erste Element mit Countdown ausstatten
    if(this.length > 1)
      var _this = this[0];
		else
	    // this-Referenz closuren
	    var _this = this;

    function init(){
    	//if($(_this).find('span').length)
      //	return true;

      // HTML-Konstrukt einhängen und formatieren
      $(_this).html(settings.countdownHTML);
      $(_this).find('div').css({'height': settings.height+'px'});

      // Formatstring von ungültigen Zeichen reinigen
      settings.format = settings.format.trim();

      // Formatstring in Zeit-Gruppen teilen
      var arrSplit = settings.format.split("-");
      // Zeitgruppen durchlaufen
      for(var i=0; i<arrSplit.length; i++){
      	// Neuen Index (d, h, m oder s) in Zeitformat-Array anlegen
      	settings.time[arrSplit[i].charAt(0)] = [];
        // Für jede Stelle in Formatstring ein Digit-Span erstellen und in Zeitformat-Array speichern
        for(var j=0; j<arrSplit[i].length; j++){
        	settings.time[arrSplit[i].charAt(0)][j] = document.createElement("span");
          $(_this).find('div').append(settings.time[arrSplit[i].charAt(0)][j]);
          $(settings.time[arrSplit[i].charAt(0)][j]).css({'margin-right': ((j+1 == arrSplit[i].length)? (settings.groupSpace+'px') : (settings.digitSpace+'px'))})
        }
      }

      // Digits formatieren
      $(_this).find('span').each(function(i){
      	// Fall keine Klasse übergeben wurde
	      if(settings.clDigit == null){
	        $(this).css({
	          'background-image': 'url('+settings.imgPath+settings.img[0]+')',
	          height: settings.height+'px',
	          width: settings.width+'px',
	          display: 'block',
	          float: 'left'
	        });
        // Falls eine Klasse übergeben wurde
	      }else{
        	// Klasse zuweisen und Abstände zwischen den Gruppen zuweisen
        	this.className = settings.clDigit;
	        $(this).css({
	        });
        }
      });

      // Bilder preloaden
      settings.preload.length = 0;
      // Bildquellen-Array durchlaufen
      for(var i=0; i<settings.img.length; i++){
      	settings.preload[i] = new Image();
        settings.preload[i].src = settings.imgPath + settings.img[i];
      }

      // XML-File einlesen
      $.ajax({
      	url: settings.xmlFile,
        type: settings.xmlType, //'post',
        dataType: 'xml',
        success: function(data, txtStatus){
        	var objBody = null;
        	// Kollektion der event-Elemente
        	var arrEvent = data.getElementsByTagName("event");
          // event-Elemente durchlaufen und prüfen, ob ein übereinstimmende ID gefunden wurde
          for(var i=0; i<arrEvent.length; i++){
          	// Default-Wert
            if(i==0){
              objBody = data.getElementsByTagName("event")[i];
            }

            // Falls die übergebene ID mit der ID des gerade geprüften events übereinstimmt
          	if(data.getElementsByTagName("event")[i].getElementsByTagName("id")[0].firstChild.nodeValue == settings.number){
              objBody = data.getElementsByTagName("event")[i];
              break;
            }
          }

          //var objBody = data.getElementsByTagName("event")[settings.number-1];

          // Countdown-Details aus XML-File ermitteln
        	settings.countdown = {
          	year: parseInt(Number(objBody.getElementsByTagName("targetdate")[0].getAttribute('year'))),
          	month: parseInt(Number(objBody.getElementsByTagName("targetdate")[0].getAttribute('month'))),
          	day: parseInt(Number(objBody.getElementsByTagName("targetdate")[0].getAttribute('day'))),
          	hour: parseInt(Number(objBody.getElementsByTagName("targetdate")[0].getAttribute('hour'))),
          	minute: parseInt(Number(objBody.getElementsByTagName("targetdate")[0].getAttribute('minute'))),
          	title: objBody.getElementsByTagName("title")[0].firstChild.nodeValue,
          	target: objBody.getElementsByTagName("target")[0].firstChild.nodeValue,
          	id: objBody.getElementsByTagName("id")[0].firstChild.nodeValue
          }

          // Public-Informationen (Titel, Datum)
          _this.info ={
          	year: parseInt(Number(objBody.getElementsByTagName("targetdate")[0].getAttribute('year'))),
          	month: parseInt(Number(objBody.getElementsByTagName("targetdate")[0].getAttribute('month'))),
          	day: parseInt(Number(objBody.getElementsByTagName("targetdate")[0].getAttribute('day'))),
          	hour: parseInt(Number(objBody.getElementsByTagName("targetdate")[0].getAttribute('hour'))),
          	minute: parseInt(Number(objBody.getElementsByTagName("targetdate")[0].getAttribute('minute'))),
          	title: objBody.getElementsByTagName("title")[0].firstChild.nodeValue,
          	target: objBody.getElementsByTagName("target")[0].firstChild.nodeValue
          }

          // Endzeitpunkt
          settings.end = Math.round(new Date(settings.countdown.year,settings.countdown.month-1,settings.countdown.day,settings.countdown.hour,settings.countdown.minute).getTime()/1000);
          // Zeitdifferenz (in Sekunden)
          settings.diff = settings.end-settings.start;

          // Countdown starten
          if(settings.diff>0){
          	if($.isFunction(settings.onStart))
            	// Callback vor dem Countdown mit Infos zu Datum, Titel und ID eines Zielelements
            	settings.onStart(_this.info);
	          countdown();
          //else if(typeof settings.afterCountdown == 'function')
          }else if($.isFunction(settings.afterCountdown))
          	settings.afterCountdown(_this.info);
        },
        error: function(){
      		$(_this).empty();
        	alert("FEHLER:\nXML-File ("+settings.xmlFile+") konnte nicht geladen werden");
        }
      });
    }

    function countdown(){
      var intDiff = settings.diff;

      // Tage
      var intHelp = (60*60*24);
      var intDays = Math.floor(intDiff/intHelp);
      intDiff = intDiff%intHelp;
      // Stunden
      intHelp = (60*60);
      var intHours = Math.floor(intDiff/intHelp);
      intDiff = intDiff%intHelp;
      // Minuten
      intHelp = 60;
      var intMinutes = Math.floor(intDiff/intHelp);
      // Sekunden
      intDiff = intDiff%intHelp;

      // Für jede Zeitgruppe einen Ziffernstring erstellen
      var parts = [];
      parts['d'] = String((intDays<10)?"00"+intDays:((intDays<100)?"0"+intDays: intDays));
      parts['h'] = String((intHours<10)? "0"+intHours : intHours);
      parts['m'] = String((intMinutes<10)? "0"+intMinutes : intMinutes);
      parts['s'] = String((intDiff<10)? "0"+intDiff : intDiff);

      // Digits-Array durchlaufen
      for(var strEntry in settings.time){
      	// Jede Zeitgruppe rückwärts durchlaufen und enthaltenes Element mit entsprechendem Hintergrundbild versehen
        for(var i=settings.time[strEntry].length-1, j=parts[strEntry].length-1; i>=0; i--, j--){
          $(settings.time[strEntry][i]).css({'background-image': 'url('+settings.preload[parts[strEntry].charAt(j)].src+')'});
        }
      }

      if(settings.diff--){
      	hCountdownTimerHandle = _this.hCountdownTimerHandle = window.setTimeout(function(){ countdown()}, 1000);
      }else if($.isFunction(settings.afterCountdown)){
        settings.afterCountdown(_this.info);
      }
    }

    // Public
    _this.stop = function(){
    	window.clearTimeout(_this.hCountdownTimerHandle);
    }

    _this.restart = function(){
    	_this.stop();
      settings.start = Math.round(new Date().getTime()/1000),
      settings.diff = settings.end-settings.start;

      countdown();
    }

	  String.prototype.trim = function(){
	    var strHelp = this;
	    strHelp = strHelp.replace(/[^dhms-]/, '');
	    return strHelp.replace(/^\s+|^[^dhms]+|[^dhms]+$|\s+$/g, '');
	  }

    init();

	  return this;
	};

})(jQuery);
