Yearly Archives :

2024

Saját sticky menü készítése JavaScript görgetés figyeléssel és HTML elem magyarázó

Saját sticky menü készítése JavaScript görgetés figyeléssel és HTML elem magyarázó 2000 1258 bacsoa

Gyakran szembe jött már velem az a probléma, hogy több sticky, azaz ragadós menüre volt szükség. Sokan, sokféle eszközt használnak erre, de sokszor legegyszerűbb a saját. Most leírom hogyan kell egy ilyet megcsinálni.

A sticky menü általában akkor kell, ha a főmenüt, vagy annak egy részét fixen oda akarjuk ragasztani, amikor görgetés közben a böngészőben elértük annak pozícióját. Ehhez a generált HTML kód vizsgálatára és megváltoztatására van szükség, amit Javascript-ben fogok megírni. A PHP-vel ellentétben, ami szerveroldalon fut, a Javascript-et a kliensoldalon használjuk. A kliens oldal maga a böngésző, amit a weboldalunk látogatója lát és, azaz kattint, görget és úgy általában használ. A kliens oldal elemei a böngésző által feldolgozott és megjelenített, generált HTML kód. Ebben szeretnénk most és tudunk is turkálni a JavaScripttel.

Ahhoz, hogy a JavaScriptet hatékonyan tudjuk használni természetesen elengedhetetlen a HTML és a CSS használata. Mindezekről most nem írok hosszan, de akit érdekel az erről szóló cikkem, az ezt olvassa el.

A feladat tehát annyi, hogy egy oldal adott eleméhez érve azt „odaragasztjuk” a képernyő tetejére, tehát a látogató ezt mindig eléri akkor is, így kényelmesen tud navigálni az egyes lehetőségek között és nem kell mindig visszagörgetnie ehhez a részhez. Meg kell csinálnunk természetesen visszafelé is, ha felfelé hagyjuk el ezt a részt, akkor visszatesszük a normál, azaz a „ragadásmentes”, eredeti állapotába.

Mi kell ehhez? Azért szeretem a fejlesztői munkát, mert nagyon kreatív. Ezt a feladatot ugyanis többféleképpen meg lehet oldani, és mi tudjuk kiválasztani, hogy melyik a szimpatikus. Nem az a lényeg, hogy mennyire elegáns a kód, hanem az, hogy működjön, az ügyfél pedig elégedett legyen. Persze, ha fenntartható kódot szeretnénk, akkor erre is figyeljünk, de ez a cikk most nem erről szól.

  1. Kiszámoljuk az összes olyan elem magasságát az oldal tetejétől addig a pontig, ahol a sticky menü elkezdődik.
  2.  Inicializálunk az onscroll eseményfigyelőt (ún. event listener), ami folyamatosan figyel méghozzá csak akkor, ha görgetünk, egyébként nem csinál semmit. A Javascriptben vannak beépített, a HTML szabványhoz tartozó, és az adott böngészőben működő és vannak az egyedi, általunk írt eseményfigyelők. Mi most az alapértelmezett, minden böngészőben elérhető onscroll eseményfigyelőt fogjuk használni.
  3. A görgetés közben figyeljük hol áll a pozíció és ha elérte a kívánt magasságot (azaz a látogató scrollozás közben odaért a kívánt elemhez), akkor hozzáadunk a body DOM elemhez valamilyen egyedi osztályt, hogy majd CSS-sel tudjunk rá hivatkozni. Ha újra elhagyta a látogató ezt a pozíciót, tehát fölfelé görgetett, akkor pedig levesszük róla ugyanezt az osztályt. Így a kétféle állapotot meg tudjuk majd különböztetni egymástól, így annak pozícióját is el tudjuk különíteni.

Csinálhatjuk jQuery-vel, vagy normál Javascripttel is. Én most az utóbbit fogom bemutatni, mert az mindenhol működik, és nem kell hozzá semmi, bárhol, bármilyen környezetben alkalmazható, dependency, azaz függőség nélkül. A dependency azt jelenti, hogy egy adott metódus csak egy másik metódussal együtt működik. Ilyen a jQuery is, ahhoz, hogy az általa megadott egyszerűsített eszközöket használni tudjuk, előbb be kell tölteni a böngészőnek a jQuery-t. A Javascript történetéről most nem írok le egy regényt, akit érdekel, az erre nézelődjön., de ez az oldal is jó kiindulópont lehet.


// Definiáljuk a DOM elemet, hogy később hivatkozhassunk rá.
// Ehhez az elemhez fogjuk később az egyedi osztályt (class) adni
// Azért a elemhez adjuk, mert ez van majdnem legfelül a HTML hierarchiában, így az ez alatti bármely elemre tudunk hivatkozhatunk
const theBody = document.querySelector(`body`);

// Képernyő szélessége: ez opcionális, használhatjuk pl. egy feltételnél, hogy az egész csak akkor fusson le, ha pl. mobilnézetben vagyunk
var screenWidth = window.innerWidth;

// Az első elem, aminek az oldal tetejétől ki kell számolnunk a magasságát
var headerDiv = document.querySelector(`#header-outer`);

// A többi kiszámolandó elem ez alatt az elem alatt található, ami alatt ki kell számoljuk az összes elem magasságát
var mainDiv = document.querySelector(`#ajax-content-wrap .container-wrap .container.main-content div.row`);

// Az előző elem alatti két gyerek elem, mindkettő magassága kell, mivel ez után következik maga a menü
var firstChildDiv = mainDiv.children[0];
var secondChildDiv = mainDiv.children[1];

// Mivel megvan minden elem, kiszámoljuk ki az összes magasságát és összeadjuk
var totalHeight = headerDiv.offsetHeight + firstChildDiv.offsetHeight + secondChildDiv.offsetHeight;

// Görgetés eseményfigyelő (scroll event listener), ez csak akkor fut, amikor görgetünk
window.onscroll = function()
{
  // Ez a böngészőablak oldal tetejétől számolt magassága pixelben
  var windowPageOffset = window.pageYOffset;

  // Ha az oldal tetejétől legörgetett magasság nagyobb, mint az összeszámolt elemek magassága,
  // akkor elértük a sticky menüt, azaz azt az elemet, amit oda akarunk ragasztani
  if ( windowPageOffset >= totalHeight ) {
    theBody.classList.add("sticky_submenu");
  } else {
    // Ha ennek ellenkezője igaz, tehát elhagytuk fölfelé scrollozás közben ezt a területet
    // akkor visszaállítjuk az eredeti állapotot
    theBody.classList.remove("sticky_submenu");
  }

};

Ezeken a képernyőmentéseken elmagyarázom melyik rész, mit csinál. Van benne egy kis HTML alapozó is, aki még mindig nem értené, hogyan kell hivatkozni egy adott HTML elemre.

Annyit csinálok, amit a háromlépéses részben már leírtam, megnézem az elemek magasságát, összeadom, majd a görgetésfigyelővel megnézem elérte már az adott pozíció ezt az értéket vagy már meg is haladta. Ha ez igaz, akkor hozzáadom a body elemhez a `sticky_submenu` nevű osztályt, amit CSS-ben előzőleg már definiáltam. Innentől kezdve, ha a body elem rendelkezik ezzel az osztállyal, akkor az lesz rá érvényes, egyébként nem.

body.sticky_submenu .nectar-sticky-row-wrap.nectar-sticky-row-wrap--top_after_nav {
position: fixed;
top: 44px;
z-index: 99;
width: 100%;
left: 0;
}

Remélem mindenkiben sikerült felkelti az érdeklődést hogyan is működnek a DOM manipulációk és innen megnyílik egy új fejezet a Javascript metódusok és a HTML elemek módosításának fejezetében. Rövid és eredményes kódolást!

WordPress egyedi felhasználói szintek és admin felületre belépés utáni alapértelmezett oldal megváltoztatása

WordPress egyedi felhasználói szintek és admin felületre belépés utáni alapértelmezett oldal megváltoztatása 960 600 bacsoa

Egyedi felhasználói szintet kellett létrehozzak és mivel ennek a felhasználó típusnak egy csomó mindent nem szabad látnia, kézen fekvő volt máshova irányítani őt bejelentkezés után, hogy ne is keresgéljen a WordPress vezérlőpulton.

A WordPress admin felületen (hívhatnám egyszerűsítve backendnek is, de azért ez nem teljesen azt jelenti) egy külön világ van, mint a frontenden (amit a látogató lát), külön CSS beállítással, sokszor elkülönített lekérdezésekkel és sok minden mással is. Aki bele akar mélyedni a felhasználói szintekbe, az itt tudja ezt megtenni.

Első lépésben csináljunk egy új felhasználói szintet. Ehhez az add_role metódust használjuk, aminek három paramétere van:

  • egyedi azonosító slug (ékezetek és szóköz nélkül), itt organizer
  • felhasználó szint neve, ez jelenik majd meg az admin felületen a felhasználóknál, itt Szervező
  • jogok, vagyis képességek, hogy az adott felhasználó mihez férhet hozzá, itt az adminisztrátori jogokat kapja meg. Ez egy elég bonyolult képességfa, akit érdekel az összes, az erre nézelődjön
add_role(
    'organizer',
    __( 'Szervező'  ),
    get_role( 'administrator' )->capabilities
);

A fenti kód csinál egy ‘organizer’ nevű felhasználói szintet, aki gyakorlatilag egy adminisztrátori jogkörrel (aka képességekkel) rendelkező felhasználótípus.

Sok bővítménnyel, vagy egyedi eszközzel meg lehet azt csinálni, hogy mit lásson ez a felhasználó és mit sem, erre jó például a remove_menu_page, vagy a remove_submenu_page metódusok, de egy sima admin oldali inline CSS-sel is el tudunk tüntetni szinte minden menüt attól függően, hogy ki van bejelentkezve.

$user = wp_get_current_user();
$roles = ( array ) $user->roles;
$role = $roles[0];

// Megvizsgálja, hogy a bejelentkezett felhasználó típusa 'organizer' és ha igen, akkor az azon belüli rész fut le
if ( $role == "organizer" ) {

	// Elrejti a felső fekete adminisztrációs sávot
	show_admin_bar(false);

	// Beállítja az alább megadott inline CSS-t, az admin_head action csak az adminisztrációs felületen érvényes CSS stíluslapokat állítja be, tehát ennek nincs határsa a frontenden lévő sablonra
	add_action('admin_head', 'my_custom_css');
	function my_custom_css() {
	  echo '<style>
			li#menu-media, li#menu-settings {display:none;}
	  </style>';
	}

	// Ez teszi lehetővé, ha a bejelentkezett felhasználó 'organizer' típusú, akkor az itt található két speciális metódusban lévő dolgok fussanak le
	add_action( 'admin_init', 'stop_access_profile_organizer' );
	add_action( 'admin_enqueue_scripts', 'load_defaults_prevents_organizer' );

}

// Ez a rész megtiltja a hozzáférést néhány admin felületen található oldalhoz. Az előző rész csak elrejti CSS segítségével a menüpontokat, ez viszont azt akadályozza meg, ha valaki szemfüles és tudja az URL-eket fejből és oda próbál menni, akkor egy hibaüzenet kíséretében megtiltja azt
function load_defaults_prevents_organizer($hook)
{
	if ( $hook=="options-general.php" || $hook=="options-writing.php" || $hook=="options-reading.php" || $hook=="options-discussion.php" || $hook=="options-media.php" || $hook=="options-permalink.php" || $hook=="tools.php" || $hook=="widgets.php" || $hook=="customize.php" || ($hook=="post-new.php" && $_GET['post_type']=="page") || $hook=="themes.php" ) {
		wp_die( 'Nincs jogod megtekinteni ezt az oldalt.' );
	}
}

// Ezek le fogják szedni az admin felületről a bal oldalon megjelenő menüpontokat, az első a Megjelenés / Sablonok részt, a második az Oldalak menüt fogja eltüntetni
function stop_access_profile_organizer()
{
    remove_menu_page( 'themes.php' );
    remove_menu_page( 'edit.php?post_type=page' );
}

Nézzük azt a részt, hogy mit csináljunk az ‘organizer’ típusú felhasználókkal, miután sikeresen bejelentkezett. Mondjuk a Hozzászólások részhez. Ez azért jó, mert így nem egyből a Vezérlőpult részre kerül (ahova alapból mindenki), ahol még vagy 100 minden WordPress telepítésnél más és más részt kell elrejteni, hanem oda, ahova mi akarjuk:

add_action('wp_login', 'ba_new_dashboard_home', 10, 2);
function ba_new_dashboard_home($username, $user)
{
  if (array_key_exists('organizer', $user->caps)) {
    wp_redirect(admin_url('edit-comments.php', 'http'), 301);
    exit;
  }
}

Ha nem akarunk annyit inline CSS-ezni, akkor hasznos lehet, ha az ‘organizer’ típusú felhasználók esetén az admin oldal body elem osztályát kiegészítjük valamivel, így könnyebb lesz rá hivatkozni. Erre van egy speciális filter, az admin_body_class nevű. Ez teljesen ugyanazt csinálja, mint a body_class nevű filter, csak míg utóbbi a frontenden módosítja a body tag osztályait, előbb az admin felületen csinálja ugyanezt.

// Hozzáad egy egyedi osztályt a body taghez, ha egy organizer típusú felhasználó van bejelentkezve

add_filter( 'admin_body_class', 'ba_admin_body_classes' );
function ba_admin_body_classes( $classes )
{  
	$user = wp_get_current_user();
	$roles = ( array ) $user->roles;
	$user_role = $roles[0];

	if ( $user_role == 'organizer' ) {
		$classes .= ' logged_organizer ';
	}

  return $classes;
}

Ez a pár hasznos kódrészlet kiválóan alkalmas arra, hogy 2-5 féle plugin feltelepítése helyett saját kóddal, elegánsan és gyorsan oldjuk meg pontosan azt a problémát, amit akarunk, és ne szemeteljük tele a WordPress oldalunkat szuper, mindent megoldó bloatware pluginokkal.