Nekonečné rolování v nette; aka infinite scrol, či endless scrolling z databáze + pár drobností

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
czhyenacz
Člen | 12
+
0
-

Heavy metal, právě dodělávám svůj první projekt v Nette.f a uživatelé tohoto fóra mi dost pomohli s řešením dvou problémů. Proto jsem se v tu chvíli zavázal sám sobě, že se podělím o pár poznatků, co jsem způsobem pokus-omyl objevil AND o nich nikdo nepsal, nebo když psal, tak blbě a snad tím někomu pomohu..


Jde hlavně o zprovoznění nekonečného rolování .
Co potřebujete :

  • Nette Framework 2.0 a PHP 5.3 //které už asi máte taky
  • Jquery //které už asi máte taky
  • Script z jqueryscrollpagination
  • Pouvám DIBI, tak si to dyštak upravte )

Princip
Script načítá ze „zdrojového souboru A“ data a postupně je zobrazuje v „cílovém souboru B“ na základě toho, v jaké pozici na stránce jsme. Docela dobře je to vidět na ukázkovém příkladu na domovských stránkách scriptu.

Problémy

  • V ukázkové verzi je zdrojový soubor A statický html/textový soubor.
  • Potřebujeme načítat data dynamicky z databáze
  • Problémy s MVC architekturou , které budou mít začátečníci

Řešení

  • Náš cílový soubor bude přes script tahat data z latte souboru, který se bude postupně načítat z databázi při kadém renderu šablony.
  • dem na to. Samotný kód to vysvětlí lépe než já

Model – funkce co tahá data z databáze – najednou maximálně 9 položek. Poslední pozice bude udávána hodnotou $poradi.

public static function fetchVysledek($poradi) {
       return dibi::fetchAll('
            SELECT *
            FROM [tabulka]  %lmt %ofs '
                , 9, $poradi
                );
             }

Presenter // hodnota poradi se uklada do lazy

public function renderCilovysoubor($hledany_vyraz) {
       $section = $this->session->getSection('lazy');
       $poradi=0; // pocatecni hodnoty
       $section->poradi=$poradi;
       $this->template->vypis = ProjektModel::fetchVysledek($poradi); // vypise prvnich 9 hodnot
          }
public function renderZdrojovysoubor() {
       $section = $this->session->getSection('lazy');
       $poradi=$section->poradi;
        $darkys=ProjektModel::fetchVysledek($poradi);
       $this->template->vypis=$vypis;
       section->poradi=$poradi+9;
         // zvýšení poradi o 9 - pocet vypsaných prvků
   }

Zdrojový soubor – bude nazvaný zdrojovysoubor.latte a vytvoril jsem ho ve slozce Templates/Projekt
bude v něm to, co chceme vypisovat – i jak !!! (nezapomenout ostylovat)

   {if count($vypis)}

       {foreach $vypis as $vypisy}
   <div class="vypis" style="opacity:0;-moz-opacity: 0;filter: alpha(opacity=0);"> // efekt pro načítání scriptu
       <h3>{$vypisy['polozkavypisuformatovanajakoH3']}</h3>


   </div>

       {/foreach}

{else}

   {/if}

Bootstrap

  • vytvoříme novou rouru, kterou bude zdrojový soubor dostupný na xxx.cz/zdrojovysoubor (localhost/zdrojovysoubor)
$container->router[] = new Route('zdrojovysoubor', 'Projekt:zdrojovysoubor');

Cílový soubor
sem vložíme jquery script,sp a upravený nastavovací scroll-skript do hlavičky – odkaz musí být opravdu bez uvozovek, i když v netbeans chází chybu .

<head>
 <script type="text/javascript" src="{$basePath}/js/jquery.js"></script>
 <script type="text/javascript" src="{$basePath}/js/scrollpagination.js"></script>
<script type="text/javascript">
$(function(){
	$('#content').scrollPagination({
		'contentPage': {link Projekt:zdrojovysoubor}, // the page where you are searching for results
		'contentData': '', // you can pass the children().size() to know where is the pagination
		'scrollTarget': $(window), // who gonna scroll? in this example, the full window
		'heightOffset': 2200, // how many pixels before reaching end of the page would loading start? positives numbers only please
		'beforeLoad': function(){ // before load, some function, maybe display a preloader div
			$('#loading').fadeIn();
		},
		'afterLoad': function(elementsLoaded){ // after loading, some function to animate results and hide a preloader div
			 $('#loading').fadeOut();
                        	$('#content').fadeIn();
			 var i = 0;
			 $(elementsLoaded).fadeInWithDelay();
			 if ($('#content').children().size() > 120 ){ // nastvavení maximálného počtu zobrazených položek
			 	$('#nomoreresults').fadeIn();
				$('#content').stopScrollPagination();
			 }
		}
	});

	// code for fade in element by element with delay
	$.fn.fadeInWithDelay = function(){
		var delay = 500;
		return this.each(function(){
			$(this).delay(delay).animate({ opacity:1 }, 200);
			delay += 200;
		});
	};
	});
</script>
</head>
<body>
/// dotohohle rámu se bude zobrazovat výsledek
 <div id="content"  >

</div>



</body>

Zhodnocení
Nejspíš je ještě nějaká jiné řešení, já to udělal takto. Nejsem grafik, tak mě nekritizujte za úpravu textu, bitte. Snad tam nemám moc chyb. Heavy metal.

Editoval czhyenacz (6. 8. 2012 13:37)

redhead
Člen | 1313
+
0
-

Hm, celý mi to přijde takový zmatený. Jak bych to udělal já:

Předně bych to postavil na Nette snippetech a mělo by jít stránkovat i bez JS, tedy založit to na VisualPaginatoru, který by se při podpoře JS prostě jen skryl. Nevím přesně jak funguje onen jQuery plugin, ale asi by to šlo postavit i na Nettí ajax podpoře – když scrollnu sem, udělej ajax request pro snippet s další stránkou paginatoru – s tím rozdílem, že místo nahrazení celého snippetu, jak se to děje normálně, se akorát přidá (appendne) na konec onoho snippetu (upravením funkce $.nette.updateSnippet).

livthomas
Člen | 24
+
0
-

Už dávnejšie som si urobil infinite scroll približne na štýl toho, čo tu popísal redhead. No teraz prichádzam na to, že to asi nie je najšťastnejšie riešenie. Na stránku som totiž pridal komponentu, ktorá pri každom príspevku vykresľuje panel pre hodnotenie +/-. Po ohodnotení príspevku mi to však neobnoví obsah snippetu tejto komponenty, ale na koniec stránky pridá znovu načítanú poslednú (aktuálnu) stránku paginatora. To celkom dáva zmysel, keďže funkcia $.nette.updateSnippet u mňa vyzerá nasledovne:

			if (id == "snippet--posts") {
				$("#" + id).append(html);
			} else {
				$("#" + id).html(html);
			}

Zaujímalo by ma teda, či neexistuje aj nejaký „čistejší“ spôsob ako urobiť infinite scroll.

JakubTN
Bronze Partner | 49
+
0
-

Osobne infinite scroll riesim velmi jednoduchym sposobom, pouzivam tento skript.

Staci nahodit klasicky VisualPaginator, pridat skriptik a Infinite Scroll je na svete.

Vojtěch Dobeš
Gold Partner | 1316
+
+5
-

V nette.ajax.js je k dispozici datový atribut data-ajax-append, kterým lze vynutit právě appendování místo nahrazení původního obsahu. Stačí udělat něco takového:

<div n:snippet="posts" data-ajax-append="true">
	{foreach $infiniteListOfArticles as $article}
		<h1>{$article->title}</h1>
		{$article->content}
	{/foreach}
</div>

Editoval vojtech.dobes (15. 4. 2013 11:46)