/**
 * @fileOverview Kapitola 9 – skript příkladu Fotogalerie.
 * V tomto skriptu se nachází komentáře ve formátu dokumentačních bloků
 * nástroje JsDoc Toolkit.
 * Oficiální stránky projektu JsDoc Toolkit jsou k dispozici na adrese
 * http://code.google.com/p/jsdoc-toolkit/.
 * @author Ondřej Baše
 */

/**
 * Jmenný prostor pro funkčnost fotogalerie.
 * @namespace
 */
var fotogalerie = {
  /**
   * Selektor elementu, který obaluje definici fotografie.
   * @constant
   * @type String
   * @default 'a.fotogalerie'
   */
  SELEKTOR_ELEMENTU_DEFINUJICIHO_FOTOGRAFII: 'a.fotogalerie',

  /**
   * Objekt okna webového prohlížeče uložený v objektu knihovny jQuery.
   * @type Object
   * @default $(window),
   */
  $oknoProhlizece: $(window),

  /**
   * Předpona skupiny fotografií.
   * @constant
   * @type String
   * @default 'fotogalerie-'
   */
  PREDPONA_SKUPINY_FOTOGRAFII: 'fotogalerie-',

  /**
   * Počet fotografií ve skupině.
   * @type Number
   * @default 0
   */
  pocetFotografiiVeSkupine: 0,

  /**
   * Pořadí aktuální fotografie.
   * @type Number
   * @default null
   */
  poradiAktualniFotografie: null,

  /**
   * Skupina fotografií. Prvky tohoto pole jsou objekty s následujícími
   * vlastnostmi:
   * src – adresa URL dané fotografie pro atribut src obrázku,
   * alt – alternativní text pro atribut alt obrázku,
   * title – popisný text pro atribut title obrázku,
   * $obrazek – obrázek fotografie uložený v objektu knihovny jQuery,
   * zpracovana – obsahuje hodnotu true, když kompletně vytvoříme obrázek
   *   pro danou fotografii; jinak obsahuje hodnotu false.
   * @type Array
   * @default []
   */
  skupinaFotografii: [],

  /**
   * Třída pro obrázky fotografií.
   * @constant
   * @type String
   * @default 'fotogalerie'
   */
  TRIDA_OBRAZKU_FOTOGRAFIE: 'fotogalerie',

  /**
   * Počet fotografií zpracovaných metodou
   * {@link fotogalerie.nactiFotografii()}.
   * @type Number
   * @default 0
   */
  pocetZpracovanychFotografii: 0,

  /**
   * Adresa URL k obrázku označujícímu chybu při načítání obrázku.
   * @constant
   * @type String
   * @default 'obrazky/chybejici-obrazek.png'
   */
  ADRESA_URL_K_CHYBOVEMU_OBRAZKU: 'obrazky/chybejici-obrazek.png',

  /**
   * Inicializuje fotogalerii.
   */
  inicializuj: function() {
    fotogalerie.radic.svazUdalostiSElementyDefinujicimiFotografieAOknem();
  },

  /**
   * Určí, jakou třídu má aktuální skupina fotografií, a to na základě
   * elementu, s nímž definujeme fotografii.
   * @param {Object} elementDefinujiciFotografii Element, jenž definuje
   *   fotografii.
   * @returns {String|Boolean} Třída aktuální skupiny fotografií, nebo
   *   hodnota false, pokud ji nemůže určit.
   */
  urciTriduSkupinyFotografii: function(elementDefinujiciFotografii) {
    var hodnotaAtributuClass = $(elementDefinujiciFotografii).attr('class'),
      vysledkyHledani = hodnotaAtributuClass.match(new RegExp(
        '\\b' + fotogalerie.PREDPONA_SKUPINY_FOTOGRAFII + '.+?\\b'));

    if (vysledkyHledani) {
      return vysledkyHledani[0];
    } else {
      return false;
    }
  },

  /**
   * Zjistí všechny nezbytné informace o aktuální skupině fotografií
   * z dokumentu HTML a zahájí načítání jednotlivých fotografií. Tuto metodu
   * voláme, když uživatel klepne na element definující fotografii, takže
   * objekt this odpovídá tomuto elementu.
   */
  nactiSkupinuFotografii: function() {
    var tridaSkupiny = fotogalerie.urciTriduSkupinyFotografii(this),
      $fotografieVeSkupine,
      fotografie,
      $obrazekFotografie;

    if (tridaSkupiny) {
      $fotografieVeSkupine = $(
        fotogalerie.SELEKTOR_ELEMENTU_DEFINUJICIHO_FOTOGRAFII + '.' +
          tridaSkupiny);
    } else {
      $fotografieVeSkupine = $(this);
    }

    fotogalerie.pocetFotografiiVeSkupine = $fotografieVeSkupine.length;
    for (var poradiFotografie = 0;
      poradiFotografie < fotogalerie.pocetFotografiiVeSkupine;
      poradiFotografie++) {
      fotografie = $fotografieVeSkupine[poradiFotografie];
      if (fotografie == this) {
        fotogalerie.poradiAktualniFotografie = poradiFotografie;
      }

      $obrazekFotografie = $(fotografie).children('img');
      fotogalerie.skupinaFotografii.push({
        src: fotografie.href,
        alt: $obrazekFotografie.attr('alt'),
        title: $obrazekFotografie.attr('title'),
        $obrazek: null,
        zpracovana: false
      });
    }

    if (fotogalerie.pocetFotografiiVeSkupine < 2) {
      fotogalerie.uzivatelskeRozhrani.$tlacitka =
        fotogalerie.uzivatelskeRozhrani.$tlacitkoZavrit;
    }

    fotogalerie.nactiFotografii(fotogalerie.poradiAktualniFotografie, -1);

    return false;
  },

  /**
   * Načte fotografii tak, že vytvoří nový obrázek s příslušnou adresou URL
   * v atributu src. V této metodě rovněž nastavujeme obsluhu událostí pro
   * tento nový obrázek. Fotografie načítáme takovým způsobem, že střídáme
   * směr dopoředu a dozadu od aktuální fotografie, dokud nezpracujeme
   * všechny fotografie. Pokud v některém směru dojdeme na konec skupiny
   * fotografií dříve, přesuneme se na druhý konec této skupiny.
   * @param {Number} poradiFotografie Pořadí aktuální fotografie ve skupině
   *   fotografií.
   * @param {Number} smer Směr procházení skupiny fotografií; číslo 1
   *   označuje směr dopředu, zatímco číslo -1 směr dozadu.
   */
  nactiFotografii: function(poradiFotografie, smer) {
    if (fotogalerie.pocetZpracovanychFotografii <
      fotogalerie.pocetFotografiiVeSkupine) {
      poradiFotografie = (fotogalerie.pocetFotografiiVeSkupine +
        poradiFotografie + smer * fotogalerie.pocetZpracovanychFotografii) %
        fotogalerie.pocetFotografiiVeSkupine;

      var aktualniFotografie =
        fotogalerie.skupinaFotografii[poradiFotografie],
        argumenty = {
          poradiFotografie: poradiFotografie,
          smer: smer
        },
        $novyObrazek = $(new Image());

      if (aktualniFotografie['alt']) {
        $novyObrazek.attr('alt', aktualniFotografie['alt']);
      }
      if (aktualniFotografie['title']) {
        $novyObrazek.attr('title', aktualniFotografie['title']);
      }

      $novyObrazek
        .addClass(fotogalerie.TRIDA_OBRAZKU_FOTOGRAFIE)
        .appendTo($('<div></div>').appendTo($('body')))
        .load(argumenty, fotogalerie.fotografieSeNacetla)
        .error(argumenty, fotogalerie.nastalaChybaPriNacitaniFotografie);

      aktualniFotografie.$obrazek = $novyObrazek;
      $novyObrazek.attr('src', aktualniFotografie['src']);

      fotogalerie.pocetZpracovanychFotografii++;
    }
  },

  /**
   * Obsluhující funkce pro událost načtení (load) obrázku fotografie.
   * @param {Object} ev Objekt události.
   */
  fotografieSeNacetla: function(ev) {
    var argumenty = ev.data,
      ur = fotogalerie.uzivatelskeRozhrani;

    if (argumenty.poradiFotografie == fotogalerie.poradiAktualniFotografie) {
      fotogalerie.radic.svazUdalostiSAktualniFotografii();
      ur.zobrazZakladniRozvrzeni();
    }

    fotogalerie.skupinaFotografii[argumenty.poradiFotografie].zpracovana =
      true;
    ur.prizpusobStavTlacitekPredchoziNasledujici();
    fotogalerie.nactiFotografii(argumenty.poradiFotografie, -argumenty.smer);
  },

  /**
   * Obsluhující funkce pro událost error, která nastává při chybě načítání
   * obrázku fotografie.
   * @param {Object} ev Objekt události.
   */
  nastalaChybaPriNacitaniFotografie: function(ev) {
    var argumenty = ev.data,
      ur = fotogalerie.uzivatelskeRozhrani,
      $obrazek = fotogalerie.skupinaFotografii[argumenty.poradiFotografie]
        .$obrazek;

    $obrazek
      .unbind('load error')
      .attr('src', fotogalerie.ADRESA_URL_K_CHYBOVEMU_OBRAZKU);

    if (argumenty.poradiFotografie == fotogalerie.poradiAktualniFotografie) {
      fotogalerie.radic.svazUdalostiSAktualniFotografii();
      ur.zobrazZakladniRozvrzeni();
    }

    fotogalerie.skupinaFotografii[argumenty.poradiFotografie]['zpracovana'] =
      true;
    ur.prizpusobStavTlacitekPredchoziNasledujici();
    fotogalerie.nactiFotografii(argumenty.poradiFotografie, -argumenty.smer);
  },

  /**
   * Zobrazí aktuální fotografii. Snažíme se umístit aktuální fotografii na
   * střed okna, ale pokud to není možné, tak ji přesouváme k levému nebo
   * hornímu okraji.
   * @param {Boolean} umistitPouzeNaStred Pokud má tento parametr hodnotu
   *   true, tak změníme pozici fotografie jen v případě, že ji lze zobrazit
   *   do okna celou.
   */
  zobrazAktualniFotografii: function(umistitPouzeNaStred) {
    var $obrazekAktualniFotografie =
      fotogalerie.skupinaFotografii[fotogalerie.poradiAktualniFotografie]
        .$obrazek;

    $obrazekAktualniFotografie.show();

    var vodorovne = 'center',
      svisle = 'center';
    if ($obrazekAktualniFotografie.outerWidth() >
      fotogalerie.$oknoProhlizece.width()) {
      vodorovne = 'left';
    }
    if ($obrazekAktualniFotografie.outerHeight() >
      fotogalerie.$oknoProhlizece.height()) {
      svisle = 'top';
    }

    if (!umistitPouzeNaStred ||
      (vodorovne == 'center' && svisle == 'center')) {
      $obrazekAktualniFotografie.position({
        of: window,
        my: vodorovne + ' ' + svisle,
        at: vodorovne + ' ' + svisle,
        collision: 'none'
      });
    }
  },

  /**
   * Zjišťuje, jestli je následující fotografie k dispozici.
   * @returns {Boolean} Hodnota true, pokud je následující fotografie
   *   k dispozici; jinak hodnota false.
   */
  jeNasledujiciFotografieKDispozici: function() {
    var nasledujiciFotografie = fotogalerie.skupinaFotografii[
      (fotogalerie.poradiAktualniFotografie + 1) %
      fotogalerie.pocetFotografiiVeSkupine];

    return nasledujiciFotografie['zpracovana'];
  },

  /**
   * Zjišťuje, jestli je předchozí fotografie k dispozici.
   * @returns {Boolean} Hodnota true, pokud je předchozí fotografie
   *   k dispozici; jinak hodnota false.
   */
  jePredchoziFotografieKDispozici: function() {
    var predchoziFotografie = fotogalerie.skupinaFotografii[
      (fotogalerie.pocetFotografiiVeSkupine +
      fotogalerie.poradiAktualniFotografie - 1) %
      fotogalerie.pocetFotografiiVeSkupine];

    return predchoziFotografie['zpracovana'];
  },

  /**
   * Zavře fotogalerii, přičemž odstraní dynamicky vytvořené elementy
   * a nastaví výchozí hodnoty.
   */
  zavri: function() {
    var ur = fotogalerie.uzivatelskeRozhrani;
    ur.$tlacitkoZavrit.remove();
    ur.$tlacitkoZavrit = null;
    ur.$tlacitkoPredchozi.remove();
    ur.$tlacitkoPredchozi = null;
    ur.$tlacitkoNasledujici.remove();
    ur.$tlacitkoNasledujici = null;
    ur.$tlacitka = null;
    ur.$prekryvnaVrstva.remove();
    ur.$prekryvnaVrstva = null;

    for (var poradiFotografie = 0;
      poradiFotografie < fotogalerie.pocetFotografiiVeSkupine;
      poradiFotografie++) {
      if (fotogalerie.skupinaFotografii[poradiFotografie].$obrazek) {
        fotogalerie.skupinaFotografii[poradiFotografie].$obrazek.parent()
          .remove();
      }
    }

    fotogalerie.skupinaFotografii = [];
    fotogalerie.pocetFotografiiVeSkupine = 0;
    fotogalerie.poradiAktualniFotografie = null;
    fotogalerie.pocetZpracovanychFotografii = 0;
  },

  /**
   * Zobrazí předchozí fotografii (animovaně).
   */
  zobrazPredchoziFotografii: function() {
    if (fotogalerie.pocetFotografiiVeSkupine > 1) {
      var dataFotografii =
        fotogalerie.pripravFotografieNaAnimaciPresunu(true);
      fotogalerie.provedAnimaciPresunuFotografii(dataFotografii);
    }
  },

  /**
   * Zobrazí následující fotografii (animovaně).
   */
  zobrazNasledujiciFotografii: function() {
    if (fotogalerie.pocetFotografiiVeSkupine > 1) {
      var dataFotografii = fotogalerie.pripravFotografieNaAnimaciPresunu();
      fotogalerie.provedAnimaciPresunuFotografii(dataFotografii);
    }
  },

  /**
   * Připraví fotogalerii na animaci předchodu na předchozí nebo následující
   * fotografii. V této metodě generujeme všechna nezbytná data pro animaci.
   * @param {Boolean} predchozi Pokud má hodnotu true, tak tato metoda
   *   připraví fotogalerii na animaci přechodu na předchozí fotografii;
   *   v opačném případě ji připraví na animaci přechodu na následující
   *   fotografii.
   * @returns {Object} Data obou fotografií (pro animaci).
   */
  pripravFotografieNaAnimaciPresunu: function(predchozi) {
    var $obrazekAktualniFotografie = fotogalerie.skupinaFotografii[
        fotogalerie.poradiAktualniFotografie].$obrazek,
      posunVPoradi = predchozi ? -1 : 1,
      poradiDalsiFotografie = (fotogalerie.pocetFotografiiVeSkupine +
        fotogalerie.poradiAktualniFotografie + posunVPoradi) %
        fotogalerie.pocetFotografiiVeSkupine,
      $obrazekDalsiFotografie = fotogalerie.skupinaFotografii[
        poradiDalsiFotografie].$obrazek,
      cilovaVodorovnaCastAPoziceDalsiFotografie = 'center',
      cilovaSvislaCastAPoziceDalsiFotografie = 'center';

    if ($obrazekDalsiFotografie.outerWidth() >
      fotogalerie.$oknoProhlizece.width()) {
      cilovaVodorovnaCastAPoziceDalsiFotografie = 'left';
    }
    if ($obrazekDalsiFotografie.outerHeight() >
      fotogalerie.$oknoProhlizece.height()) {
      cilovaSvislaCastAPoziceDalsiFotografie = 'top';
    }

    if (predchozi) {
      var vychoziVodorovnaCastDalsiFotografie = 'right',
        vychoziVodorovnaPoziceDalsiFotografie = 'left',
        cilovaVodorovnaCastAktualniFotografie = 'left',
        cilovaVodorovnaPoziceAktualniFotografie = 'right';
    } else {
      var vychoziVodorovnaCastDalsiFotografie = 'left',
        vychoziVodorovnaPoziceDalsiFotografie = 'right',
        cilovaVodorovnaCastAktualniFotografie = 'right',
        cilovaVodorovnaPoziceAktualniFotografie = 'left';
    }

    fotogalerie.radic.odstranUdalostiAktualniFotografie();
    fotogalerie.uzivatelskeRozhrani.skryjTlacitka(true);

    return {
      $obrazekAktualniFotografie: $obrazekAktualniFotografie,
      poradiDalsiFotografie: poradiDalsiFotografie,
      $obrazekDalsiFotografie: $obrazekDalsiFotografie,
      cilovaVodorovnaCastAPoziceDalsiFotografie:
        cilovaVodorovnaCastAPoziceDalsiFotografie,
      cilovaSvislaCastAPoziceDalsiFotografie:
        cilovaSvislaCastAPoziceDalsiFotografie,
      vychoziVodorovnaCastDalsiFotografie:
        vychoziVodorovnaCastDalsiFotografie,
      vychoziVodorovnaPoziceDalsiFotografie:
        vychoziVodorovnaPoziceDalsiFotografie,
      cilovaVodorovnaCastAktualniFotografie:
        cilovaVodorovnaCastAktualniFotografie,
      cilovaVodorovnaPoziceAktualniFotografie:
        cilovaVodorovnaPoziceAktualniFotografie
    };
  },

  /**
   * Provede animaci přesunu fotografií – nahrazuje aktuální fotografii
   * předchozí nebo následující fotografií.
   * @param {Object} dataFotografii Data fotografií získaná metodou
   *   {@link fotogalerie.pripravFotografieNaAnimaciPresunu()}.
   */
  provedAnimaciPresunuFotografii: function(dataFotografii) {
    var animaceProbehla = false;

    dataFotografii.$obrazekDalsiFotografie
      .show()
      .position({
        of: window,
        my: dataFotografii.vychoziVodorovnaCastDalsiFotografie + ' ' +
          dataFotografii.cilovaSvislaCastAPoziceDalsiFotografie,
        at: dataFotografii.vychoziVodorovnaPoziceDalsiFotografie + ' ' +
          dataFotografii.cilovaSvislaCastAPoziceDalsiFotografie,
        collision: 'none'
      });

    $('body').addClass('fotogalerie-probiha-animace');

    dataFotografii.$obrazekDalsiFotografie.position({
      of: window,
      my: dataFotografii.cilovaVodorovnaCastAPoziceDalsiFotografie,
      at: dataFotografii.cilovaVodorovnaCastAPoziceDalsiFotografie,
      collision: 'none',
      using: function(pozadovanyPosun) {
        delete pozadovanyPosun.top;
        dataFotografii.$obrazekDalsiFotografie.animate(pozadovanyPosun, {
            complete: function() {
              if (animaceProbehla) {
                fotogalerie.dokonciAnimaciPresunuFotografii(dataFotografii)
              } else {
                animaceProbehla = true;
              }
            },
            duration: 'slow'
          });
      }
    });

    dataFotografii.$obrazekAktualniFotografie.position({
      of: window,
      my: dataFotografii.cilovaVodorovnaCastAktualniFotografie,
      at: dataFotografii.cilovaVodorovnaPoziceAktualniFotografie,
      collision: 'none',
      using: function(pozadovanyPosun) {
        delete pozadovanyPosun.top;
        dataFotografii.$obrazekAktualniFotografie.animate(pozadovanyPosun, {
            complete: function() {
              if (animaceProbehla) {
                fotogalerie.dokonciAnimaciPresunuFotografii(dataFotografii)
              } else {
                animaceProbehla = true;
              }
            },
            duration: 'slow'
          });
      }
    });
  },

  /**
   * Po provedení záměny obou fotografií uvádí fotogalerii do běžného stavu.
   * To znamená, že dříve aktuální fotografii schováme a prohlásíme novou
   * fotografii za aktuální. Dále svážeme události s novou fotografií
   * a znovu zobrazíme základní rozvržení fotogalerie.
   * @param {Object} dataFotografii Data fotografií získaná metodou
   *   {@link fotogalerie.pripravFotografieNaAnimaciPresunu()}.
   */
  dokonciAnimaciPresunuFotografii: function(dataFotografii) {
    var ur = fotogalerie.uzivatelskeRozhrani;
    $('body').removeClass('fotogalerie-probiha-animace');
    dataFotografii.$obrazekAktualniFotografie
      .hide()
      .css({left: 0, top: 0});
    fotogalerie.poradiAktualniFotografie =
      dataFotografii.poradiDalsiFotografie;
    fotogalerie.radic.svazUdalostiSAktualniFotografii();
    ur.zobrazZakladniRozvrzeni();
    ur.prizpusobStavTlacitekPredchoziNasledujici();
  }
}

/**
 * Jmenný prostor pro řídicí metody fotogalerie.
 * @namespace
 */
fotogalerie.radic = {
  /**
   * Sváže události se všemi elementy, které definují fotografie, a také
   * s objektem okna webového prohlížeče.
   */
  svazUdalostiSElementyDefinujicimiFotografieAOknem: function() {
    var ur = fotogalerie.uzivatelskeRozhrani;
    $(fotogalerie.SELEKTOR_ELEMENTU_DEFINUJICIHO_FOTOGRAFII)
      .click(ur.vygenerujOvladaciPrvky)
      .click(fotogalerie.nactiSkupinuFotografii);

    fotogalerie.$oknoProhlizece.bind('scroll resize',
      ur.zobrazZakladniRozvrzeni);
  },

  /**
   * Sváže události s aktuální fotografií.
   */
  svazUdalostiSAktualniFotografii: function() {
    var $obrazekAktualniFotografie = fotogalerie.skupinaFotografii[
      fotogalerie.poradiAktualniFotografie].$obrazek,
      ur = fotogalerie.uzivatelskeRozhrani;

    $obrazekAktualniFotografie
      .parent()
        .hover(ur.zobrazTlacitka, ur.skryjTlacitka)
        .one('mousemove', ur.zobrazTlacitka);
  },

  /**
   * Sváže události s tlačítky fotogalerie.
   */
  svazUdalostiSTlacitky: function() {
    var ur = fotogalerie.uzivatelskeRozhrani;
    ur.$tlacitkoZavrit.click(fotogalerie.zavri);
    ur.$tlacitkoPredchozi.click(fotogalerie.zobrazPredchoziFotografii);
    ur.$tlacitkoNasledujici.click(fotogalerie.zobrazNasledujiciFotografii);
  },

  /**
   * Odstraní všechny události svázané s aktuální fotografií.
   */
  odstranUdalostiAktualniFotografie: function() {
    var $obrazekAktualniFotografie = fotogalerie.skupinaFotografii[
      fotogalerie.poradiAktualniFotografie].$obrazek;

    $obrazekAktualniFotografie
      .parent()
        .unbind('mouseenter mouseleave mousemove');
  }
}

/**
 * Jmenný prostor pro uživatelské rozhraní fotogalerie a jeho funkčnost.
 * @namespace
 */
fotogalerie.uzivatelskeRozhrani = {
  /**
   * Element překryvné vrstvy uložený v objektu knihovny jQuery.
   * @type Object
   * @default null
   */
  $prekryvnaVrstva: null,

  /**
   * Tlačítko pro zavření fotogalerie uložené v objektu knihovny jQuery.
   * @type Object
   * @default null
   */
  $tlacitkoZavrit: null,

  /**
   * Tlačítko pro zobrazení předchozí fotogalerie uložené v objektu
   * knihovny jQuery.
   * @type Object
   * @default null
   */
  $tlacitkoPredchozi: null,

  /**
   * Tlačítko pro zobrazení následující fotografie uložené v objektu
   * knihovny jQuery.
   * @type Object
   * @default null
   */
  $tlacitkoNasledujici: null,

  /**
   * Objekt knihovny jQuery obsahující všechna tlačítka, s nimiž aktuálně
   * pracujeme v metodách uživatelského rozhraní.
   * @type Object
   * @default null
   */
  $tlacitka: null,

  /**
   * Vygeneruje všechny ovládací prvky uživatelského rozhraní fotogalerie.
   */
  vygenerujOvladaciPrvky: function() {
    var ur = fotogalerie.uzivatelskeRozhrani;

    ur.$prekryvnaVrstva =
      $('<div class="ui-widget-overlay"></div>')
        .appendTo($('body'))
        .css('top', fotogalerie.$oknoProhlizece.scrollTop());
    ur.$tlacitkoZavrit =
      $('<button class="fotogalerie-tlacitko-zavrit">Zavřít</button>');
    ur.$tlacitkoPredchozi =
      $('<button class="fotogalerie-tlacitko-predchozi">Předchozí' +
        '</button>');
    ur.$tlacitkoNasledujici =
      $('<button class="fotogalerie-tlacitko-nasledujici">Následující' +
        '</button>');
    ur.$tlacitka = $([ur.$tlacitkoZavrit[0], ur.$tlacitkoPredchozi[0],
      ur.$tlacitkoNasledujici[0]]);

    ur.$tlacitkoZavrit
      .button({
        icons: {
          primary: 'ui-icon-closethick'
        },
        text: false
      });

    ur.$tlacitkoPredchozi
      .button({
        icons: {
          primary: 'ui-icon-carat-1-w'
        },
        text: false,
        disabled: true
      });

    ur.$tlacitkoNasledujici
      .button({
        icons: {
          primary: 'ui-icon-carat-1-e'
        },
        text: false,
        disabled: true
      });

    fotogalerie.radic.svazUdalostiSTlacitky();
  },

  /**
   * Zobrazí základní rozvržení fotogalerie. To znamená, že zobrazí aktuální
   * fotografii a správně umístí ovládací prvky uživatelského rozhraní. Tuto
   * funkci voláme přímo, nebo v reakci na události resize a scroll objektu
   * okna.
   * @param {Object} ev Objekt události.
   */
  zobrazZakladniRozvrzeni: function(ev) {
    if (fotogalerie.pocetZpracovanychFotografii > 0) {
      if (ev && ev.type == 'scroll') {
        fotogalerie.zobrazAktualniFotografii(true);
      } else {
        fotogalerie.zobrazAktualniFotografii();
      }
      fotogalerie.uzivatelskeRozhrani.rozmistiOvladaciPrvky();
    }
  },

  /**
   * Povoluje tlačítka pro přechod na předchozí a následující fotografii na
   * základě toho, zda je daná fotografie k dispozici.
   */
  prizpusobStavTlacitekPredchoziNasledujici: function() {
    var ur = fotogalerie.uzivatelskeRozhrani;
    if (fotogalerie.jeNasledujiciFotografieKDispozici()) {
      ur.$tlacitkoNasledujici.button('enable');
    } else {
      ur.$tlacitkoNasledujici.button('disable');
    }
    if (fotogalerie.jePredchoziFotografieKDispozici()) {
      ur.$tlacitkoPredchozi.button('enable');
    } else {
     ur.$tlacitkoPredchozi.button('disable');
    }
  },

  /**
   * Zobrazí tlačítka fotogalerie.
   * @param {Boolean} bezAnimace Standardně se tlačítka zobrazují v animaci,
   *   ale pokud tomuto parametru přidělíme hodnotu true, tlačítka se zobrazí
   *   okamžitě.
   */
  zobrazTlacitka: function(bezAnimace) {
    var ur = fotogalerie.uzivatelskeRozhrani;
    ur.$tlacitka.stop(true, true);
    if (ur.$tlacitka.is(':hidden')) {
      var efekt = bezAnimace == true ? undefined: 'scale';
      ur.$tlacitka.show(efekt);
    }
  },

  /**
   * Skryje tlačítka fotogalerie.
   * @param {Boolean} bezAnimace Standardně se tlačítka skrývají v animaci,
   *   ale pokud tomuto parametru přidělíme hodnotu true, tlačítka se skryjí
   *   okamžitě.
   */
  skryjTlacitka: function(bezAnimace) {
    var ur = fotogalerie.uzivatelskeRozhrani;
    ur.$tlacitka.stop(true, true);
    if (ur.$tlacitka.is(':visible')) {
      var efekt = bezAnimace == true ? undefined : 'scale';
      ur.$tlacitka.hide(efekt);
    }
  },

  /**
   * Rozmístí ovládací prvky uživatelského rozhraní. Tlačítka umísťujeme do
   * aktuální fotografie.
   */
  rozmistiOvladaciPrvky: function() {
    var $obrazekAktualniFotografie =
      fotogalerie.skupinaFotografii[fotogalerie.poradiAktualniFotografie]
        .$obrazek,
      ur = fotogalerie.uzivatelskeRozhrani,
      tlacitkaJsouSkryta = ur.$tlacitka.is(':hidden');

    ur.$tlacitka
      .detach()
      .appendTo($obrazekAktualniFotografie.parent());

	ur.$prekryvnaVrstva.css('top', fotogalerie.$oknoProhlizece.scrollTop());

    ur.zobrazTlacitka(true);

    ur.$tlacitkoZavrit
      .position({
        of: $obrazekAktualniFotografie,
        my: 'right top',
        at: 'right top',
        offset: '-10 10',
        collision: 'fit'
      });

    if (fotogalerie.pocetFotografiiVeSkupine > 1) {
      ur.$tlacitkoPredchozi
        .position({
          of: $obrazekAktualniFotografie,
          my: 'left center',
          at: 'left center',
          offset: '10 0',
          collision: 'fit'
        });

      ur.$tlacitkoNasledujici
        .position({
          of: $obrazekAktualniFotografie,
          my: 'right center',
          at: 'right center',
          offset: '-10 0',
          collision: 'fit'
        });
    }

    if (tlacitkaJsouSkryta) {
      ur.skryjTlacitka(true);
    }
  }
};

$(fotogalerie.inicializuj);