    // -------------------------------------------------
    // gallery.js
    //
    // author:  Joachim Wendenburg, kgde@wendenburg.de
    // date:    16.09.2007
    //
    // needs lib.js for some helpfull functions
    //
    // mod:     jo@kgde.de
    // date:    13.10.2009
    // item:    image_fader.prototype.create_img_div
    //          add missing "px"
    //
    // -------------------------------------------------
    
    // some default vars to override in the html file
    //
    var def_div_img_padding =  "10px";
    var def_div_img_bgcolor =  "#fff";
    var def_div_img_border  =  "1px solid #333";
    var def_fade_steps      =  10;          // number of fading steps
    var def_shadow_max      =  50;          // shadow opacity in %
    var def_navi_width      =  false;       // distance between past/next button or image width 
    
    
    // if .gif or .jpg use image
    // else use string within p
    //
    var def_buttons          =  {
        auto        :  "/gfx/auto.gif",
        download    :  "/gfx/download.gif",
        close       :  "/gfx/close.gif",
        past        :  "/gfx/past.gif",
        next        :  "/gfx/next.gif"
    };
    
    var def_buttons_title    =  {
        auto        :  "Präsentation starten oder stoppen",
        download    :  "Druckversion herunterladen",
        close       :  "Bild schliessen",
        past        :  "Zurück zum letzten Bild",
        next        :  "Weiter zum nächsten Bild"
    };    

    // little helper, splits src-string
    // returns array containing
    // album, basename, suffix, dir
    //
    function $plit (str) {
    
        var base_start  =  str.lastIndexOf("/") +1;
        var base_end    =  str.lastIndexOf(".");
        var basename    =  str.substring(base_start, base_end).replace("thumb_","");            
        var suffix      =  str.substr(base_end +1);
        var dir         =  str.substr(0, base_start -1);
        var album_start =  dir.lastIndexOf("/") +1;
        var album       =  dir.substr(album_start);  
        var id          =  album + "/" + basename;
        var src_thumb   =  str;
        var src_view    =  dir + "/view_" + basename + "." + suffix;
        var src_org     =  dir + "/org_" + basename + "." + suffix;
        
        return {
            "id"        :  id,
            "album"     :  album,
            "basename"  :  basename,
            "src_thumb" :  src_thumb,
            "src_view"  :  src_view,
            "src_org"   :  src_org            
        }
    }

    // fade-image object
    //
    var _img =  {
    
        data_by_index   :  [],
        data_by_id      :  [],
        image_objects   :  [],
        run_fader       :  [],
        run_counter     :  [],
        fade_obj        :  false,   
        view_wd         :  [],
        view_ht         :  [],
        download        :  [],
        imgtitle        :  [],
        imgdivpos       :  [],
        run_autorun     :  false,

        fade :  function (el, args) {

            var el_info         =  $plit (el.src);
            var id              =  el_info["id"];
            this.download[id]   =  false;
            this.imgtitle[id]   =  false;
            this.imgdivpos[id]  =  false;

            try {
            
                // loop args if available and set some vars 
                //                 
                for (var i in args) {                    
                    switch (i) {

                        case "dl":
                            this.download[id]   =  args[i];
                            break; 
                        case "title":
                            this.imgtitle[id]   =  args[i];
                            break;
                        case "pos":
                            this.imgdivpos[id]  =  args[i];
                            break;                       
                    }            
                } 
                
                // init array of fading steps if not done yet
                //
                this.fadesteps      = this.fadesteps?   this.fadesteps      : false;
                this.shadowsteps    = this.shadowsteps? this.shadowsteps    : false;                
            
            } catch (err) {
                // alert (err);
            }
            
            this.fade_obj   =  new image_fader (id);
            return false;
        }
    
    }

    function image_fader (id) {

        try {
        
            // do nothin if there is a current fading processes
            //
            if (_img.current_fading && _img.current_fading.length) {
                return false;
            } else {
                _img.current_fading =  [];
            }
        
            this.id         =  id;
            this.onload_run =  false;
            this.onload_cnt =  0;
            
            this.img_div_defaults =  {
                position        :  "absolute",
                top             :  "0",
                left            :  "0",            
                padding         :  def_div_img_padding,  
                backgroundColor :  def_div_img_bgcolor,
                border          :  def_div_img_border,
                zIndex          :  "2000",
                filter          :  "alpha(opacity = 0)",
                opacity         :  "0" 
            }
            
            this.shadow_div_defaults =  {        
                filter          :  "alpha(opacity = 0)",
                opacity         :  "0", 
                position        :  "absolute",
                top             :  "0",
                left            :  "0",
                backgroundColor :  "#000",
                zIndex          :  "1999",
                width           :  "100%",
                height          :  this.get_client_info().sht + "px"
            }        
        
            // get all images containing class "thumb" 
            // if no collection avaiable yet
            //
            if (_img.data_by_index.length < 1) this.get_all_thumbs ();
            
            // array of fading steps?
            //
            if (!_img.fadesteps) this.create_fade_steps ();
            
            // add data passed as arguments
            //
            var idx  =  _img.data_by_id[id]["idx"];
            if (_img.download[id]) {
                _img.data_by_index[idx]["download"] =  _img.download[id];
                _img.data_by_id[id]["download"]     =  _img.download[id];
            }
            if (_img.imgtitle[id]) {
                _img.data_by_index[idx]["title"]    =  _img.imgtitle[id];
                _img.data_by_id[id]["title"]        =  _img.imgtitle[id];
            }            

            // create image object
            // load and check if loaded
            //
            if (!_img.image_objects[id]) this.create_image_object (this.id);            
            this.onload_run =  window.setInterval(this.onload_check.bind(this), 100);
            
            // ok, done
            // now preload next/past image
            //
            var next_id =  this.get_next_image_idx ();  
            var past_id =  this.get_past_image_idx (); 
            
            // create image object, preload
            //
            if (!_img.image_objects[next_id]) this.create_image_object (next_id);  
            if (!_img.image_objects[past_id]) this.create_image_object (past_id);
 
        } catch (err) {
            alert ("image_fader: " + err);
        }
    }
    
    
    // store all available thumbs 
    //
    image_fader.prototype.get_all_thumbs =  function () {
    
        var el_info, thumb  =  $cm("img", "thumb");        
        for (i = 0; i < thumb.length; i++) {
        
            el_info                         =  $plit (thumb[i].src);
            el_info["idx"]                  =  i;  
            el_info["onclick"]              =  thumb[i].onclick;
            el_info["ref_thumb"]            =  thumb[i];
            el_info["title"]                =  thumb[i].title;
            _img.data_by_index[i]           =  el_info;
            _img.data_by_id[el_info["id"]]  =  el_info;
        }
        
        // _img.data_by_id.print_r();
    }
    
    
    image_fader.prototype.create_fade_steps =  function () {

        var temp            =  0;
        _img.fadesteps      =  {af:[],ar:[],of:[],or:[]};
        _img.shadowsteps    =  {af:[],ar:[],of:[],or:[]};
        
        for (var i = 0; i < def_fade_steps +1; i++) {
        
            temp =  Math.round(100/def_fade_steps *i);
            _img.fadesteps["af"][i]     =  temp;
            _img.fadesteps["ar"][i]     =  100 -temp;
            _img.fadesteps["of"][i]     =  temp /100;
            _img.fadesteps["or"][i]     =  (100 -temp) / 100;
            
            if (temp > def_shadow_max) continue;
            
            _img.shadowsteps["af"][i]   =  temp;
            _img.shadowsteps["ar"][i]   =  def_shadow_max -temp;
            _img.shadowsteps["of"][i]   =  temp /100;
            _img.shadowsteps["or"][i]   =  (def_shadow_max -temp) /100;         
        }

        //_img.fadesteps.print_r();
    } 


    image_fader.prototype.create_image_object =  function (id) {
        _img.image_objects[id]     =  new Image ();
        _img.image_objects[id].src =  _img.data_by_id[id]["src_view"]; 
    } 
    
    // find out if image is complete 
    // by checking height and width
    // stop if max of 50 intervalls is done
    // 
    image_fader.prototype.onload_check =  function () {

        _img.view_wd[this.id]   =  _img.image_objects[this.id].width;
        _img.view_ht[this.id]   =  _img.image_objects[this.id].height;
        
        if (_img.view_wd[this.id] && _img.view_ht[this.id]) {
        
            clearInterval(this.onload_run);
            this.onload_cnt =  0;
            this.fade_controller ();
            
        } else if (this.onload_cnt < 50) {
        
            this.onload_cnt ++;
            return;
            
        } else {
        
            clearInterval(this.onload_run);
            this.onload_cnt =  0;
            this.cancel_fade ();
        }
    }
    
    // decide what to do
    // if current image is displayed
    // create new image and fade in and out
    // else create shadow and image div
    // fade in shadow and image
    //
    image_fader.prototype.fade_controller =  function () {

        try {
        
            if (_img.current_image == this.id) {
        
                this.end_fade ();
                return false;
        
            } else if (_img.current_image) {

                this.create_img_div ();
                this.start_fade(_img.current_image, 0);
                this.start_fade(this.id, 1);
                this.resize_shadow_div ();
            
            } else {
            
                this.create_img_div ();
                this.create_shadow_div ();            

                this.start_fade("shadow", 1);
                this.start_fade(this.id, 1);
            }
            
            // remember current image
            //
            _img.current_image =  this.id;
            
        } catch (err) {
            //alert("fade_controller: " + err);
        }
    }
    
    // create image div
    // set image div styles
    //
    image_fader.prototype.create_img_div =  function () {

        // now create dom elements and add default css styles 
        // 
        var obj                 =  this; 
        var body                =  document.getElementsByTagName("body")[0];
        var image               =  document.createElement("img");
        var div_img             =  document.createElement("div");
        var title_h             =  document.createElement("h3");    
        var title_str           =  document.createTextNode(_img.data_by_id[this.id]["title"]);
        var next_id             =  this.get_next_image_idx ();
        var past_id             =  this.get_past_image_idx ();
        var div_navi            =  this.create_div_navi (next_id, past_id);

        div_img.id              =  "div-" + this.id;  
        div_img.className       =  "gallery-view-image"; 
        
        for (i in this.img_div_defaults) {
            div_img.style[i] = this.img_div_defaults[i];
        }   

        image.src               =  _img.data_by_id[this.id]["src_view"];
        image.style.width       =  _img.view_wd[this.id] + "px";
        image.style.height      =  _img.view_ht[this.id] + "px";

        // execute method of thumbnail by clicking the view image or p-tags
        // function-reference, call and the calling object as param
        //
        image.onclick =  function () {           
           _img.data_by_id[next_id]["onclick"].call(_img.data_by_id[next_id]["ref_thumb"]);
        }
      
        title_h.appendChild(title_str); 
        div_img.appendChild(div_navi);
        div_img.appendChild(image);
        div_img.appendChild(title_h);
        body.appendChild(div_img);
        
        // after image div was appended get sizes
        // set positions depending on size
        //
        var div_img_wd                  =  div_img.offsetWidth;
        var div_img_ht                  =  div_img.offsetHeight;
        var ypos                        =  (_img.imgdivpos[this.id]? _img.imgdivpos[this.id] : this.get_client_info().cht/2 - div_img_ht/2) + this.get_client_info().pyo;
        var xpos                        =  this.get_client_info().cwd/2 - div_img_wd/2;
        div_img.style.top               =  (ypos > 0)? ypos + "px" : 0;
        div_img.style.left              =  (xpos > 0)? xpos + "px" : 0;         
    }
    
    // create image div navigation
    // use either 4 image sources
    // or 4 strings i a p-tag
    // order of appearance: next, past, close, download
    //
    image_fader.prototype.create_div_navi =  function (next_id, past_id) {
   
        var obj         =  this;
        var div_navi    =  document.createElement("div");       
        var url, el, str, type;
        
        for (i in def_buttons) {

            // make sure only these attributes
            //
            if (i != "next" && i != "past" && i != "close" && i != "download" && i != "auto")  continue;
            if (i == "download" && !_img.data_by_id[this.id]["download"])       continue;

            if (def_buttons[i].toLowerCase().lastIndexOf(".gif") == -1 && def_buttons[i].toLowerCase().lastIndexOf(".jpg") == -1) {
                str     =  document.createTextNode(def_buttons[i]);
                el      =  document.createElement("p");
                el.appendChild(str);
            } else {
                el      =  document.createElement("img");
                el.src  =  def_buttons[i];
            }
            
            // each button gets an onclick
            //
            switch (i) {
                case "next":
                    el.onclick  =  function () {_img.data_by_id[next_id]["onclick"].call(_img.data_by_id[next_id]["ref_thumb"])}
                    break;
                case "past":
                    el.onclick  =  function () {_img.data_by_id[past_id]["onclick"].call(_img.data_by_id[past_id]["ref_thumb"])}
                    break; 
                case "close":
                    el.onclick  =  function () {obj.end_fade()} 
                    break; 
                case "download":                               
                    url         =  _img.data_by_id[this.id]["src_org"];
                    el.onclick  =  function () {self.location.href=url}
                    break; 
                case "auto":                    
                    el.onclick  =  function () {obj.start_autorun()}
                    break;                      
            } 
            el.title =  def_buttons_title[i];
            div_navi.appendChild(el);
        }
        
        div_navi.className  =  "gallery-navi"; 
        return div_navi;
        
    }    
    
    // create shadow div
    // set shadow styles
    //
    image_fader.prototype.create_shadow_div =  function () {
   
        var body                        =  document.getElementsByTagName("body")[0];
        var div_shade                   =  document.createElement("div");
        var obj                         =  this;
        div_shade.id                    =  "div-shadow";
        
        for (i in this.shadow_div_defaults) {
            div_shade.style[i] = this.shadow_div_defaults[i]
        }

        div_shade.onclick =  function () {
           obj.end_fade(); 
        }        

        body.appendChild(div_shade);          
    }
    
    
    // resize shadow div
    //
    image_fader.prototype.resize_shadow_div =  function () {
        for (i in this.shadow_div_defaults) {
            $("div-shadow").style.height = this.get_client_info().sht + "px";
        }      
    }
    
    // this is the end...
    //
    image_fader.prototype.end_fade =  function () {

        // already running, don't be so nervous
        //
        if (!_img.current_image) return false;
        
        this.start_fade("shadow", 0);
        this.start_fade(_img.current_image, 0);
        _img.current_image =  false;  
    }    
    
    // start fading interval
    //
    image_fader.prototype.start_fade =  function (id, stat) {        

        // stop running process if same id is called again
        // add id to collection of current fading processes
        // reset counter and go for it
        //
        if (_img.run_fader[id]) clearInterval(_img.run_fader[id]);        
        _img.current_fading.push(id);        
        _img.run_counter[id]    =  0;
        _img.run_fader[id]      =  window.setInterval(this.run_fade.bind(this, [id, stat]), 10);
    } 
    
    // run fading
    // stop interval when fading is done
    // remove shadow and image div when fade-out is done 
    //
    image_fader.prototype.run_fade =  function (args) {  
    
        var id      =  args[0];
        var stat    =  args[1];
        var alpha_opacity, moz_opacity;
        var i       =  _img.run_counter[id];        
        var steps   =  (id == "shadow")? _img.shadowsteps : _img.fadesteps; 

        if (_img.run_counter[id] < steps["af"].length) { 

            alpha_opacity   =  stat? steps["af"][i] : steps["ar"][i];
            moz_opacity     =  stat? steps["of"][i] : steps["or"][i]; 
            _img.run_counter[id] ++; 

            $("div-" + id).style.filter     =  "alpha(opacity = " + alpha_opacity + ")";
            $("div-" + id).style.opacity    =  moz_opacity;  
            
        } else {
            
            // clear and delete id from collection of current fading processes
            //
            clearInterval(_img.run_fader[id]);
            this.pop_id (id);
            _img.run_counter[id]    =  0;
            _img.run_fader[id]      =  false;
            if (!stat) {
                $("div-" + id).parentNode.removeChild($("div-" + id));
            }
        }
    }
    
    image_fader.prototype.pop_id =  function (id) {
        
        var temp = [];
        for (var i = 0; i < _img.current_fading.length; i++) {
            if (_img.current_fading[i] == id) continue;
            temp.push (_img.current_fading[i]);
        }
        _img.current_fading =  temp;
    }
    
    
    
    // get some info about browser and document
    //
    image_fader.prototype.get_client_info =  function () {
    
        var scroll_height   =  document.documentElement.scrollHeight;
        var scroll_top      =  document.documentElement.scrollTop;         
        var client_width    =  document.documentElement.clientWidth;
        var client_height   =  document.documentElement.clientHeight;
        var y_offset        =  (typeof pageYOffset != "undefined")? pageYOffset : scroll_top;

        return {sht:scroll_height,cht:client_height,cwd:client_width,pyo:y_offset}
    }

    // get id of next image
    //
    image_fader.prototype.get_next_image_idx =  function () {
    
        var index       =  _img.data_by_id[this.id]["idx"];
        var next_index  =  (index < _img.data_by_index.length -1)? index +1 : 0;
        var next_id     =  _img.data_by_index[next_index]["id"];
        return next_id;
    } 
    
    // get id of past image
    //
    image_fader.prototype.get_past_image_idx =  function () {
    
        var index       =  _img.data_by_id[this.id]["idx"];
        var past_index  =  (index > 0)? index -1 : _img.data_by_index.length -1;
        var past_id     =  _img.data_by_index[past_index]["id"];
        return past_id;
    }     

    image_fader.prototype.cancel_fade =  function () {    
        alert (_img.data_by_id[this.id]["src_view"] + " konnte nicht geladen werden!");
    }
    
    // autorun
    //
    image_fader.prototype.start_autorun =  function () {
    
        if (_img.run_autorun) {        
            this.cancel_autorun ();            
        } else {        
            _img.run_autorun    =  window.setInterval(this.do_autorun.bind(this), 3000);
            this.do_autorun ();
        }
    }
    
    // autorun
    //
    image_fader.prototype.do_autorun =  function () {
    
        // fade out? No more current image? 
        // stop autorun
        //
        if (!_img.current_image) {
            this.cancel_autorun();
            return false;
        }
        
        this.id     =  _img.current_image;
        var next_id =  this.get_next_image_idx ();
        
        // in case there is only one image
        // cancel autorun
        //
        if (this.id == next_id) {
            this.cancel_autorun();
            return false;
        }

       _img.data_by_id[next_id]["onclick"].call(_img.data_by_id[next_id]["ref_thumb"]);
    }
    
    // stop autorun and reset
    //
    image_fader.prototype.cancel_autorun =  function () {
        clearInterval (_img.run_autorun);
        _img.run_autorun =  false;
    }    
    
    

    