Kako da kreirate tabelu sadržaja u WordPress-u (bez plugina) Idi do glavnog sadržaja

Kako da kreirate tabelu sadržaja u WordPress-u (bez plugina)

Tabela sadržaja u vašim blog postovima može da ima dobar efekat na posetioce vašeg sajta, jer im omogućava bolju preglednost sadržaja teksta i ujedno omogućava lakšu navigaciju. Ukoliko posetioca zanima samo neki konkretan deo vašeg teksta, lakše će doći do njega putem tabele sadržaja. Na taj način ćete svojim posetiocima omogućiti bolje korisničko iskustvo, što na kraju dovodi i do boljeg SEO skora. Dvostruka korist uz samo malo dodatnog truda sa vaše strane.

Srećom, tabela sadržaja se kreira relativno lako, pa ćemo mi u ovom tekstu objasniti kako da je kreirate u WordPress-u i to bez korišćenja plugina. Uz malo dodatnog PHP, CSS i JS koda, kreiraćete tabelu sadržaja na koju ćete biti ponosni.

Generišite tabelu sadržaja

Napomena: Kao što uvek preporučujemo, pre bilo kakvog dodavanja ili izmene koda na vašem WordPress sajtu, preporučujemo da obavezno uradite backup celog sajta. Na taj način ćete obezbediti da imate rezervnu kopiju sajta, u slučaju da dođe do nekih problema.

Ulogujte se na admin nalog vašeg WordPress sajta i u dashboard-u pronađite opciju pod nazivom Appearance → Theme Editor, a zatim sa desne strane pod menijem Theme Files, odaberite fajl pod nazivom functions.php. Skrolujte do kraja tog fajla i na sam kraj zalepite kod ispod:

function get_toc($content) {
  // uzima naslove
  $headings = get_headings($content, 1, 6);

  // parsira tablicu sadržaja
  ob_start();
  echo "<div class='table-of-contents'>";
  echo "<span class='toc-headline'>Table Of Contents</span>";
  echo "<!-- Table of contents -->";
  echo "<span class='toggle-toc custom-setting' title='collapse'>−</span>";
  parse_toc($headings, 0, 0);
  echo "</div>";
  return ob_get_clean();
}

function parse_toc($headings, $index, $recursive_counter) {
  // prevent errors

  if($recursive_counter > 60 || !count($headings)) return;

  // uzima sve potrebne elemente
  $last_element = $index > 0 ? $headings[$index - 1] : NULL;
  $current_element = $headings[$index];
  $next_element = NULL;
  if($index < count($headings) && isset($headings[$index + 1])) {
    $next_element = $headings[$index + 1];
  }

  // i rekurizivne pozive
  if($current_element == NULL) return;

  // uzima sve dostupne promenljive
  $tag = intval($headings[$index]["tag"]);
  $id = $headings[$index]["id"];
  $classes = isset($headings[$index]["classes"]) ? $headings[$index]["classes"] : array();
  $name = $headings[$index]["name"];

  // elementi koji nisu u tablici sadržaja
  if(isset($current_element["classes"]) && $current_element["classes"] && in_array("nitoc", $current_element["classes"])) {
    parse_toc($headings, $index + 1, $recursive_counter + 1);
    return;
  }

  // parsira početak tablice sadržaja ili podmenija tablice sadržaja
  if($last_element == NULL) echo "<ul>";
  if($last_element != NULL && $last_element["tag"] < $tag) {
    for($i = 0; $i < $tag - $last_element["tag"]; $i++) {
      echo "<ul>";
    }
  }

  // kreira list(li) klasu
  $li_classes = "";
  if(isset($current_element["classes"]) && $current_element["classes"] && in_array("toc-bold", $current_element["classes"])) $li_classes = " class='bold'";

  // parsira početak linije
  echo "<li" . $li_classes .">";

  // parsira samo ime, kada li element nije bold
  if(isset($current_element["classes"]) && $current_element["classes"] && in_array("toc-bold", $current_element["classes"])) {
    echo $name;
  } else {
    echo "<a href='#" . $id . "'>" . $name . "</a>";
  }
  if($next_element && intval($next_element["tag"]) > $tag) {
    parse_toc($headings, $index + 1, $recursive_counter + 1);
  }

  // parsira kraj linije
  echo "</li>";

  // parsira sledeću liniju
  if($next_element && intval($next_element["tag"]) == $tag) {
    parse_toc($headings, $index + 1, $recursive_counter + 1);
  }

  // parsira kraj tablice sadržaja ili podmenija tablice sadržaja
  if ($next_element == NULL || ($next_element && $next_element["tag"] < $tag)) {
    echo "</ul>";
    if ($next_element && $tag - intval($next_element["tag"]) >= 2) {
      echo "</li>";
      for($i = 1; $i < $tag - intval($next_element["tag"]); $i++) {
        echo "</ul>";
      }
    }
  }

  // parsira vrh podmenija
  if($next_element != NULL && $next_element["tag"] < $tag) {
    parse_toc($headings, $index + 1, $recursive_counter + 1);
  }
}

function get_headings($content, $from_tag = 1, $to_tag = 6) {
  $headings = array();
  preg_match_all("/<h([" . $from_tag . "-" . $to_tag . "])([^<]*)>(.*)<\/h[" . $from_tag . "-" . $to_tag . "]>/", $content, $matches);
  
  for($i = 0; $i < count($matches[1]); $i++) {
    $headings[$i]["tag"] = $matches[1][$i];
    // get id
    $att_string = $matches[2][$i];
    preg_match("/id=\"([^\"]*)\"/", $att_string , $id_matches);
    $headings[$i]["id"] = $id_matches[1];
    // get classes
    $att_string = $matches[2][$i];
    preg_match_all("/class=\"([^\"]*)\"/", $att_string , $class_matches);
    for($j = 0; $j < count($class_matches[1]); $j++) {
      $headings[$i]["classes"] = explode(" ", $class_matches[1][$j]);
    }
    $headings[$i]["name"] = strip_tags($matches[3][$i]);
  }
  return $headings;
}

Ovaj kod će pročitati sve heading-e (naslove), a zatim ih ispisati u vidu tabele sadržaja.

Podrazumevano, čita sve heading-e (od H1 do H6). Ukoliko želite da ovo izmenite, možete podesiti parametre u liniji 3 ( $headings = get_headings($content, 1, 6);)

Ubacite tabelu sadržaja u stranice

Tabelu sadržaja možete ubaciti u stranice na dva različita načina. 

Način 1: Ukoliko želite da u svakom postu podesite poziciju tabele pomoću shortcode-a TOC, onda dodajte i ovaj kod:

// tablica sadržaja
function toc_shortcode() {
    return get_toc(get_the_content());
}
add_shortcode('TOC', 'toc_shortcode');

Način 2: Ukoliko želite da tabela sadržaja, nakon prvog paragrafa bude automatski ubačena u svaki post, onda dodajte i ovaj kod:

function add_table_of_content($content) {
  if (!is_single()) return $content;

    $paragraphs = explode("</p>", $content);
    $paragraphs_count = count($paragraphs);
    $middle_index= absint(floor($paragraphs_count / 2));
    $new_content = '';

    for ($i = 0; $i < $paragraphs_count; $i++) {
        if ($i === 1) {
          $new_content .= get_toc($content);
        }

        $new_content .= $paragraphs[$i] . "</p>";
    }
    return $new_content;
}
// add our table of contents filter
add_filter('the_content', 'add_table_of_content');

Ukoliko želite da prikažete tabelu sadržaja samo nakon drugog paragrafa, onda treba da prilagodite kod u liniji 10 (if ($i === 1)).

Nakon što ste dodali kod i izvršili sva podešavanja, kliknite na dugme Save file.

Stilizujte svoju tabelu sadržaja (pomoću CSS koda)

Pomoću svog do sada dodatog koda, vaša tabela sadržaja je već generisana. Nažalost, ona neće biti automatski stilizovana, već će biti prikazana kao obična nenumerisana lista (unoredered list), odnosno kao <ul> tag. Da bismo je ulepšali potrebno je stilizujemo, odnosno da dodamo nekoliko linija CSS koda.

Ponovo se ulogujte se na admin nalog vašeg WordPress sajta i u dashboard-u pronađite opciju pod nazivom Appearance → Theme Editor, a zatim sa desne strane pod menijem Theme Files, odaberite fajl pod nazivom style.css.

Skrolujte do kraja ovog fajla i tu zalepite sledeći kod:

/* Ove promenljive mozete prilagoditi prema svom dizajnu */
:root {
  --dark-grey: #333333;
  --main-color: #036773;
  --font-size: 16px;
  --line-height: 1.2;
}

.table-of-contents {
  margin: 4rem 0;
  position: relative;
}

.table-of-contents .toc-headline {
  font-size: 22px;
  color: var(--dark-grey);
  font-weight: 600;
  display: block;
  cursor: pointer;
}

.table-of-contents .toggle-toc {
  position: absolute;
  top: 0;
  right: 1rem;
  font-size: 30px;
  cursor: pointer;
  font-weight: 800;
  color: var(--main-color);
}

.table-of-contents ul {
  padding: 0;
  padding-left: 1rem;
}

.table-of-contents li {
  position: relative;
  padding-left: 1rem;
  list-style: none;
  line-height: var(--line-height);
  font-weight: 400;
  margin: .3rem 0;
  transition: .2s ease all;
}

.table-of-contents li:hover {
  padding-left: 1.1rem;
}

.table-of-contents li a {
  font-size: var(--font-size);
  line-height: var(--line-height);
  text-decoration: none;
  color: var(--main-color);
}

.table-of-contents li:before {
  content: '';
  -webkit-transform: translateX(-0.75em) rotate(45deg);
  transform: translateX(-0.75em) rotate(45deg);
  height: 0.5em;
  width: 0.5em;
  border-top: solid 2px var(--dark-grey);
  border-right: solid 2px var(--dark-grey);
  border-radius: 0;
  background: 0 0;
  position: absolute;
  display: block;
  top: 7px;
  left: 0;
}

.table-of-contents li>ul {
  padding-left: 0.7rem;
  padding-bottom: 1rem;
}

Ovo je jednostavan stil, koji naravno možete po želji izmeniti. Za izmenu i drugačiji prikaz biće neophodno da znate CSS i da vam je poznato pisanje koda u ovom jeziku.

Proširite i skupite tabelu sadržaja (pomoću JavaScript koda)

Tabela sadržaja koju smo do sada napravili ima sve bitno, ali nema mogućnost proširivanja i skupljanja, radi prikazivanja hijerarhije sadržaja.

Da biste dodali ovu funkcionalnost potrebno je da znate gde se u vašoj aktivnoj temi nalazi fajl sa JavaScript kodom. 

Napomena: Ukoliko se na lokaciji gde ste pronašli functions.php fajl i style.css fajl ne nalazi i neki fajl sa ekstenzijom .js, biće potrebno da konsultujete dokumentaciju developera i pronađete lokaciju na kojoj se ovaj fajl nalazi.

Nakon toga potrebno je da sledeći kod zalepite na kraj tog .js fajla:

document.querySelectorAll('.table-of-contents .toggle-toc, .table-of-contents .toc-headline').forEach(toggler => {
  toggler.addEventListener('click', function() {
    let tocList = document.querySelectorAll('.table-of-contents ul')[0];
    let toggler = document.querySelectorAll('.table-of-contents .toggle-toc')[0];
    if(tocList.style.display == 'none') {
      tocList.style.display = 'block';
      toggler.innerHTML = '-';
    } else {
      tocList.style.display = 'none';
      toggler.innerHTML = '+';
    }
  });
});

Podrazumevano skupljena tabela sadržaja

Ukoliko želite da vaša tabela sadržaja bude podrazumevano skupljena, dodajte sledeću liniju koda nakon malopre dodatog koda:

document.querySelectorAll('.table-of-contents .toggle-toc, .table-of-contents .toc-headline')[0].click();

Dodajte tabelu sadržaja na stranicu pomoću shortcode-a

Ako ste prethodno odabrali Način 1 (da u svakom postu podesite poziciju tabele pomoću shortcode-a TOC), sada samo treba da ubacite shortcode TOC u backend editor nekog konkretnog posta.

Da biste obezbedili da su linkovani svi pojedinačni naslovi (heading), biće vam potreban takozvani HTML anchor. I ovde imate dve opcije: da ga skripta automatski učita (opcija 1) ili da ga ručno ubacite (opcija 2).

Opcija 1

Napomena: ovaj kod treba da ubacite u functions.php fajl, pre koda sa početka ovog teksta:

/**
 * Automatski dodaje ID-eve za heading <h2></h2>
 */
function auto_id_headings( $content ) {
  $content = preg_replace_callback('/(\<h[1-6](.*?))\>(.*)(<\/h[1-6]>)/i', function( $matches ) {
    if(!stripos($matches[0], 'id=')) {
      $matches[0] = $matches[1] . $matches[2] . ' id="' . sanitize_title( $matches[3] ) . '">' . $matches[3] . $matches[4];
    }
    return $matches[0];
  }, $content);
    return $content;

}
add_filter('the_content', 'auto_id_headings');

Ukoliko ste izabrali da ga ubacite putem shortcode-a, potrebno je da podesite funkciju toc_shortcode() iz prvog koda:

// tablica sadržaja
function toc_shortcode() {
    return get_toc(auto_id_headings(get_the_content()));
}
add_shortcode('TOC', 'toc_shortcode');

Opcija 2

Da biste ubacili anchor-e ručno, kliknite na naslov i pod opcijom Advanced ubacite anchor. Podesite naziv prema želji, ali gledajte da odgovara naslovu.

Time ste ujedno i završili kreiranje i podešavanje tabele sadržaja.

Sada možete da proverite stranicu na kojoj ste radili, da biste proverili kako izgleda vaša tabela sadržaja.

Nenad Mihajlović


Ostavite odgovor