nette.ajax.js – alt. obsluha pro AJAX s jQuery

Kaspis
Člen | 13
+
0
-

@vojtech.dobes: Super! nádhera! krása! díky moc! Šlape jako hodinky!

Editoval Kaspis (15. 9. 2012 0:25)

na1k
Člen | 288
+
0
-

Všiml jsem si pull requestu na podporu History API. Můžu se zeptat v jakém je to stádiu? Je to funkční nebo zatím jen prototyp?

Před časem jsem si něco podobného splácal sám, ale moc spokojený s tím nejsem. Kromě obsluhy history ale potřebuji mít možnost navázat na dokončení popstate eventu vlastní obsluhu (tj. snippety se obnoví na předchozí hodnoty a já s nimi chci ještě manipulovat). To zmiňuju jen pokud by taková možnost nebyla, takový lehký feature request :-)

Lopo
Člen | 277
+
0
-

tak som sa dnes konecne dostal aj k tejto vecicke a hned som zbuchal jednu malu konverziu dostupnu tu

dufam ze sa aspon niekomu hodi

peter.z
Člen | 37
+
0
-

Dakujem za pomoc :) Ale problem je, ze napriek tomu ze mi vyskoci confirm dialog, ajax sa spracuje, aj ked confirm zamietnem :/

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

@peter.z bacha, aktuálně na masteru jsem prohodil události before a start. Doporučuju použít poslední stabilní verzi a doplnit si do ní tu úpravu předaných parametrů (viz výše), master se ještě může změnit :).

To confirmovací rozšíření musí využívat ve stabilní verzi událost start (na masteru to teď musí být before).

pekelnik
Člen | 462
+
0
-
<script type="text/javascript">
// the easiest way to open debugger bluescreen in browser (local filesystems only)
$(function() {
        $.nette.ext({
		error: function(request) {
            		window.open(request.getResponseHeader('X-Nette-Error-Log'));
        	}
	});
});
</script>
David Zadražil
Člen | 62
+
0
-

@pekelnik – tohle by byla skvělá funkce, nicméně se mi jí nedaří rozjet. Okno se sice při chybě otevře, ale je prázdné a bez obsahu.

pekelnik
Člen | 462
+
0
-

to je skvela funkce :)

podivej se jestli je ta hlavicka v te odpovedi

Editoval pekelnik (19. 9. 2012 19:16)

David Zadražil
Člen | 62
+
0
-

Tak hlavička tam není, můžu nějak ovlivnit její zobrazení?

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

Je třeba nemít Firelogger. Pokud je zapnutý, tak Nette tuto hlavičku bohužel neposílá.

Editoval vojtech.dobes (19. 9. 2012 19:34)

David Zadražil
Člen | 62
+
0
-

Firelogger nemám a přesto v chybové hlášce hlavičku nevidím.

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

O jakou vyjímku/chybu v jaké fázi aplikace jde? Při vykreslování se už také neodešle.

David Zadražil
Člen | 62
+
0
-

V handleru záměrně volám neexistující funkci. Pokud vypnu ajax, laděnka normálně vyskočí a jsou tam tyto hlavičky – http://imgur.com/A4ELM

Děkuji za pomoc.

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

Nechceš poslat klikatelnou laděnku? V handleru jako ve zpracování signálu, jo?

David Zadražil
Člen | 62
+
0
-

Přesně tak ve zpracování signálu. Klikatelná laděnka je zde.

pekelnik
Člen | 462
+
0
-

Mozna by nebylo od veci posilat tu hlavicku v development modu vzdycky.

pepakriz
Člen | 246
+
0
-

Mám takový malý problém. U vlastních doplňků dochází k volání události success až po load. Děje se tak proto, že základní init rozšíření volá load v success callbacku. Z jakého důvodu se load nevolá až při complete události? Případně dá se nějak ovlivnit pořadí extenzí?

klasyc
Člen | 14
+
0
-

pepakriz napsal(a):
Případně dá se nějak ovlivnit pořadí extenzí?

Obávám se, že aspoň moje (asi 3 týdny stará verze) to neumožňuje. Pokud potřebuješ, aby se Tvá extenze provedla až nakonec (což byl můj případ), můžeš v příslušném handleru použít

setTimeout (function() { ... }, 0);

ale moc čisté řešení to není (co kdyby tohle dělaly nezávisle na sobě dvě extenze, mezi kterými bys potřeboval určit pořadí…).

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

Ten load by se měl ošetřit, dobrý point. Podívám se na to… pořadí bohužel ovlivnit nelze.

klasyc
Člen | 14
+
0
-

Ahoj pánové,

před časem jsem tady psal o myšlence propojení zde probíraného ajaxového rozšíření s modálními formuláři, které umí vyrobit jquery UI. Před několika dny jsem se dostal k celkem funkčnímu kódu, tak ho dávám k dobru a třeba se bude někomu hodit nebo mi napíše, jak by se to nechalo udělat lépe.

Tady je odkaz: http://pastebin.com/wPnybT9v

A ještě nějaký krátký popis:

Jedná se o 3 extenze (dialogy vyžadují ty dvě zbývající):

  • extrapost – vyrobí metody $.nette.post a $.nette.get, které funkčně odpovídají

    klasickým $.post a $.get, ale navíc volají i handlery všech zbylých extenzí. Je

    to spíš jenom usnadnění pro toho, kdo není zvyklý na metodu ajax.

  • watchdog – přidává metodu $.nette.watchSnippet(name, callback), která umožňuje

    přidat sledování určitého snippetu. Pokud pošle server novou verzi snippetu, zavolá se

    daný callback. To se hodí pokud máte navěšené nějaké události na vnitřku snippetu. Pokud

    nová verze snippetu, je potřeba znovu navěsit tyto události a k tomu používám zmíněnou

    metodu.

  • dialogs – umožňuje poměrně snadno vyrobit z normální aplikace ajaxovou pomocí

    modálních oken. Výchozím stavem je funkční neajaxová aplikace, dejme tomu telefonní

    seznam. Při editaci jména nás Nette přesměruje na novou stránku s formulářem, který

    vyplníme, a pak nás hodí zase zpátky na seznam. Pokud chceme, aby probíhala editace

    jména v modálním okně, uděláme následující:

  • Nalinkovat jQuery UI + pohrát si se styly
  • Editační formulář vložíme do snippetu a také tabulku s telefonním seznamem dáme do

    snippetu:

{snippet renameFormSnippet}
  {control renameForm}
{/snippet}

{snippet phoneBookSnippet}
  <table> ... </table>
{/snippet}
  • V presenteru přidáme do akce edit následující. Díky tomu nám přijde na ajaxový

    požadavek místo celé stránky jenom snippet s formulářem.

if ($this->isAjax()) {
  $this->invalidateControl("renameFormSnippet");
}
  • Upravíme událost renameFormSubmitted tak, že místo přesměrování zavoláme metodu

    podobnou té níže. Pokud se nejedná o ajaxový požadavek, proběhne obyčejné

    přesměrování. V opačném případě se zavolá výchozí akce, která naplní šablonu,

    a invaliduje se snippet s tabulkou jmen. Do payloadu se ještě přidá příznak

    dialogs["all"] = "close", který říká javascriptové části, že má zavřít všechna okna

    (místo all můžeme použít název snippetu, který okno obsahuje). Výsledkem ajaxového

    požadavku je tak opět json odpověď s novou verzí tabulky.

private function redirectOrAjax()
{
  // Redirect if this is not ajax call:
  if (!$this->isAjax()) {
    $this->redirect('default');
  } else {
    $this->actionDefault();
    $this->template->setFile($this->getContext()->params['appDir'] . '/templates/Homepage/default.latte');
    // Invalidate necessary snippets:
    $this->invalidateControl('phoneBookSnippet');
    $this->payload->dialogs["all"] = "close";
  }
}
  • Příslušným odkazům vedoucím na editační formulář přidáme událost onclick,

    ve které zavoláme metodu $.nette.showDialog(url, snippet, args, options).

    Snippet je jméno snippetu, který obsahuje editační formulář, args jsou

    parametry, které se předají v POSTu, options je objekt, který obsahuje

    konfiguraci jquery dialogu (viz nápověda k jquery ui). Může to vypadat třeba

    takto:

<a href="..." onclick="$.nette.showDialog({link //edit $person_id}, 'renameFormSnippet', {}, { width: 600 }); return false;">Upravit</a>

S trochou štěstí by se po kliknutí na editační odkaz měl objevit hezký modální formulář. Pokud nebude povolený javascript, aplikace se bude chovat jako dříve.

Snad se bude tohle rozšíření někomu hodit. Pokud ne, tak se omlouvám za spam a přeju hezký večer.

Honza

Editoval klasyc (20. 9. 2012 22:02)

LeonardoCA
Člen | 296
+
0
-

@**vojtech.dobes**: Pořád nevím jak čistě vyřešit spolupráci nette.ajax.js a bootstrap from twitter.
Týká se to všech ajaxových odkazů, pokud je takový odkaz v dropdown tak se dropdown po kliknutí nezavře, týká se to různých komponent, volání ajaxu prostě zruší funkčnost protože obsahuje stopPropagination() (v projektu jsem si prozatím ten řádek zakomentoval)

Chtělo by to asi možnost přidat volitelný parametr do settings povolující propagination? Máš nápad jak to vyřešit nějak jednoduše, ať se to nemusí řešit pro každý odkaz?

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

LeonardoCA Mrknu na to, kompatibilita s Bootstrapem je moc hezká feature :).

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

Zatím jsem přidal podporu pro dropdowny – v téhle větvi přibyla extenze twitterBootstrap (v samostatném souboru). Ta se o vše automaticky postará.

Zítra mrknu na ostatní Bootstrapové komponenty, jestli to nějak potřebují, a snad se to brzy dostane do stabilní verze.

h4kuna
Backer | 740
+
0
-

Zdravím, včera jsem aktualizoval z masteru a přestal mi fungovat košík. $_POST hodnoty se vůbec nevyplnily a firebug ukazoval request na správnou adresu a vracel 200 OK. Udělal jsem downgrade a vše funguje. Něco se někde musí nově nastavit?

Editoval h4kuna (24. 9. 2012 10:04)

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

@h4kuna Refaktoring API zanesl do kódu chybu, kdy se formulářová data zpracovala až po odeslání requestu. Fixed.

LeonardoCA
Člen | 296
+
0
-

vojtech.dobes napsal(a):

Zatím jsem přidal podporu pro dropdowny – v téhle větvi přibyla extenze twitterBootstrap (v samostatném souboru). Ta se o vše automaticky postará.

Zítra mrknu na ostatní Bootstrapové komponenty, jestli to nějak potřebují, a snad se to brzy dostane do stabilní verze.

Díky, jak bude čas tak to vyzkouším, případně rozšířím, teď pár dnů asi moc nebude.

LeonardoCA
Člen | 296
+
0
-

@vojtech.dobes: zvážil bych přidání cache: false do standartního ajax requestu.

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

LeonardoCA Kdyžtak otevírej issuečka, bylo by to supr. Rád vedu diskuse na Githubu :).

Konkrétně k tomuto, nevím jestli nestačí, aby si to každý pohlídal sám… jak přesně se to chová s tou zapnutou cachí? PJAX to kupříkladu automaticky nenastavuje.

motorcb
Člen | 551
+
0
-

Zdravim. Stáhl jsem poslední verzi ale nefunguje mi v Multiplier.
Formulář se vůbec neodešle. Na chvilku problikne spinner ale nic se neděje.
Když odeberu formuláři $form->getElementPrototype()->class(‚ajax‘);, tak vše funguje.
Dělám něco špatně?

HomepagePresenter.php

<?php

use Nette\Application\UI\Form;
use Nette\Application\UI\Multiplier;

class HomepagePresenter extends BasePresenter
{

	public function renderDefault()
	{
	}

  protected function createComponentShopForm()
  {
      $neco = $this;
      return new Multiplier(function ( $id ) use ( $neco ) {
          $form = new Nette\Application\UI\Form;
          $form->getElementPrototype()->class('ajax');
          $form->addText('count', 'Počet zboží:')
              ->addRule($form::FILLED)
              ->addRule($form::INTEGER);
          $form->addHidden('id', $id);
          $form->onSuccess[] = $neco->shopFormSubmitted;
          $form->addSubmit('create', 'Přidat do košiku');

          $form->setDefaults( array( 'count' => 1 ) );

          return $form;
      });
  }

  public function shopFormSubmitted(Form $form)
  {
      sleep(10);

      $aValues = $form->getValues(TRUE); // same as: (array) $form->values;

      $this->flashMessage("Přidáno do košíku id: ".$aValues["id"]." Kusu:".$aValues["count"], 'success');

      if (!$this->presenter->isAjax()) {
        $this->redirect('this');
      } else {
        $this->invalidateControl("flashMessage");
      }
  }

}

@layout.latte

...
  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
  <script type="text/javascript" src="{$basePath}/js/netteForms.js"></script>
  <script type="text/javascript" src="{$basePath}/js/nette.ajax.js"></script>
  <script type="text/javascript" src="{$basePath}/js/extensions/spinner.ajax.js"></script>
  <script type="text/javascript" src="{$basePath}/js/ajax.js"></script>
...
  {snippet flashMessage}
	   <div n:foreach="$flashes as $flash" class="flash {$flash->type}">{$flash->message}</div>
  {/snippet}
...

default.latte

{block content}

{snippet matches}
  {for $i=0; $i<10; $i++}
      {snippet match-$i}
          {$i}
          {control shopForm-$i}
      {/snippet}
  {/for}
{/snippet}

{/block}

Na obyčejný formulář bez Multiplier vše funguje

leninzprahy
Člen | 150
+
0
-

vojtech.dobes napsal(a):

@h4kuna Refaktoring API zanesl do kódu chybu, kdy se formulářová data zpracovala až po odeslání requestu. Fixed.

skoro mi přijde že se fix ještě nedostal na https://github.com/…ette.ajax.js

motorcb
Člen | 551
+
0
-

Jak udělám efekt při update snippetu?
Jako v https://componette.org/search/?…

jQuery.nette.updateSnippet = function (id, html) {
    $("#" + id).fadeTo("fast", 0.01, function () {
        $(this).html(html).fadeTo("fast", 1);
    });
};

Děkuji za nápady

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

@motorcb This way :)

$.nette.ext('snippets').applySnippet = function ($el, html) {
	$el.fadeTo("fast", 0.01, function () {
		$el.html(html).fadeTo("fast", 1);
	});
};
Vojtěch Dobeš
Gold Partner | 1316
+
0
-

@leninzprahy, @h4kuna To je pravda. Ještě jsem to přepracoval, zítra večer pushnu aktualizovanou verzi. S beforeSend callbackem se to ukázalo být krapet složitější… jinak odporúčám stabilní verzi 1.1.2, a samozřejmě díky všem, kteří testují vývojový master.

motorcb
Člen | 551
+
0
-

@vojtech.dobes: Díky, fadeTo funguje bezvadně :)
Mohl by ses prosím kouknout na ten Multiplier

Editoval motorcb (27. 9. 2012 9:16)

motorcb
Člen | 551
+
0
-

@vojtech.dobes
Ještě mne napadla jedna věc :) Bylo by možné ihned po požadavku na update snippetu, snipet nejprve zneviditelnit – $el.fadeTo(„fast“, 0.1);
A až po jeho obnovení ho zobrazit – $el.fadeTo(„fast“, 1);

Takhle se skreje a následně ihned zobrazí až když jsou data připravena k zobrazení.

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

@motorcb To je složitější – klient neví, které snippety pošle server k obnovení. Můžeš si napsat vlastní rozšíření, snippetové kontejnery najdeš pomocí tohoto selektoru:

[id^="snippet--"]
motorcb
Člen | 551
+
0
-

@vojtech.dobes:
Je možnost jak zjistim id prvku, který spustil vykonavani tohot kodu?

(function($, undefined) {

    $.nette.ext('my-ext', {
        before: function()
        {
            alert("before");
        }
    });

})(jQuery);
Vojtěch Dobeš
Gold Partner | 1316
+
0
-

motorcb Myslíš třeba linku, na který bylo kliknuto? Jo. V poslední stabilní verzi takto:

$.nette.ext('my-ext', {
	before: function (settings) {
		if (settings.nette) {
			var id = settings.nette.el.attr('id');
		}
	}
});

Update: omlouvám se, autor skriptu neví, jak ho používat :). Tento kód nemůže fungovat na žádné verzi.

Editoval vojtech.dobes (2. 10. 2012 18:31)

motorcb
Člen | 551
+
0
-

@vojtech.dobes

Ano, presne tak.
Bohuzel nefunguje. Neni zobrazen alert:

(function($, undefined) {

$.nette.ext('my-ext', {
    before: function (settings) {
        if (settings.nette) {
            var id = settings.nette.el.attr('id');
            alert( id );
        }
    }
});

})(jQuery);

Odkud vezmu to settings ?

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

Ty callbacky volá samotné nette.ajax.js, přičemž s těmito parametry. Volal jsi to na poslední stabilní verzi? Na masteru musí být to settings až druhý argument.

motorcb
Člen | 551
+
0
-

@vojtech.dobes:
Ano, mám poslední verzi nette.ajax.js

To moc dobře nechápu…
Mám soubor: www\js\extensions\muj.js:

(function($, undefined) {

$.nette.ext('my-ext', {
    before: function (settings) {
        alert("xxx");
        if (settings.nette) {
            var id = settings.nette.el.attr('id');
            alert( id );
        }
    }
});

})(jQuery);

Ten mam naincludovany do sablony:

<script type="text/javascript" src="{$basePath}/js/extensions/muj.js"></script>

Po kliknutí na tlačítko pro odeslání formuláře vyskočí alert „xxx“ ale nevyskočí alert s ID buttonu.

Nevěděl by někdo co dělám špatně?

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

Máš skutečně 1.1.2? Protože v ní tento kód nebude fungovat. Události before se předává pouze jqXHR objekt. Tento kód ti nebude fungovat na žádné verzi, ale pokud posuneš ten parametr settings na druhou pozici, tak ti fungovat bude na masteru.

Omlouvám se, před tím jsem mystifikoval, příspěvek jsem doplnil.

Editoval vojtech.dobes (2. 10. 2012 18:31)

motorcb
Člen | 551
+
0
-

@**vojtech.dobes**:
Ano mám poslední verzi: https://github.com/…ette.ajax.js

Prosím o bližší vysvětlení :) Jak je odkaz na verzi ve které mi to bude fungovat?

Kam na druhou pozici? Co bude na prvni pozici?

Diky

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

Ano, použij verzi z masteru (poslední stabilní verze je z tagu 1.1.2, tedy tato). A použij tento kód:

(function($, undefined) {

$.nette.ext('my-ext', {
    before: function (xhr, settings) {
        alert("xxx");
        if (settings.nette) {
            var id = settings.nette.el.attr('id');
            alert( id );
        }
    }
});

})(jQuery);

Změnily se parametry, které jsou tomuhle callbacku předávány, dříve se settings vůbec nepředávalo, jen xhr.

motorcb
Člen | 551
+
0
-

@**vojtech.dobes**: Funguje. Díky, díky, díky. Máš u mne pivo :)

cafesk8
Člen | 103
+
0
-

Zdravím,
pokud se zde něco takového již řešilo, tak se omlouvám, ale nic jsem nenašel.
Asi jsem správně nepochopil jak se používají extensions.

Dejme tomu, že mám na stránce několik ajaxových odkazů s třídou .ajax, které po kliknutí správně provedou akci a aktualizují snippet. No problem.

Problém nastává v momentě, když bych si chtěl u některých odkazů napsat vlastní extension.

<script>
$.nette.init();
$.nette.ext('confirmBeforeSend',{
	before: function() {
		// potvrdit akci, pokud ne, return false
	},
	success: function(payload) {
		.....
	}
});
</script>

Lze a pokud ano, tak jakým způsobem tuto extension napojit pouze na některé ajaxové odkazy?
Např. že odkazy, kde bych chtěl provést callbacky z „confirmBeforeSend“, bych označil třídou „.confirmAjax“ a poté si do JS napsal něco jako

<script>
$.nette.init();
$.nette.ext('confirmBeforeSend', { /* callbacky */  });
$(document).on('click','.confirmAjax',function(){
	// zde docílit toho aby ".confirmAjax" využil mé extension 'confirmBeforeSend'
});
</script>

Takže prostě aby se zachovala původní funkcionalita u „.ajax“ odkazů a u „.confirmAjax“ se spustily nějaké mé předem definované callbacky.

Pokud jsem to celé nějak špatně pochopil, tak se omlouvám, za přihlouplý dotaz.

Díky

pekelnik
Člen | 462
+
0
-

Uz jsem neco takovyho taky promyslel… https://github.com/…js/issues/35 – zatim je nejlepsi validovat elementy primo v kodu rozsireni nebo pouzit $.nette.ajax().

duskohu
Člen | 778
+
0
-

Zdravím, mam jeden problém:

$.nette.ext('data-click-handle',{
		init: function(){
			var visibleDiv = 'default'; // default
		},
		before: function(){
			if(!$(".presenter-rightContent").is(":visible")){ //ak nie je element visible
				visibleDiv = 'none';
			}
		},
		load: function () {
			$('tr[data-click-handle]').click(function(e){
				e.preventDefault();
				var obj = $(this).data('clickHandle');
				if (obj.type == 'ajax') {
					$.nette.ajax({
						url: obj.url
					});
                                // ajaxové volanie handle
				} else {
					window.location = obj.url;
				}
			});
		},
		success: function () {
			if(visibleDiv == 'none'){ // ak nieje element visible zobraz ho
				$(".presenter-rightContent").show("slide", { direction: "right" }, 700);
			}
		}
});

chcel by som si pred vykonaním požiadavku zapamatovat .presenter-rightContent či je visible alebo nie, a po požiadavke spracovať, ale neviem ako si mám prenášať visibleDiv?

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

@duskohu Všechny callbacky mají sdílený kontext, což znamená, že přiřazení property do this v jednom callbacku zpřístupní tuto property i v ostatních.

Takže:

$.nette.ext('data-click-handle', {
	init: function () {
		this.visibleDiv = 'default'; // default
	},
	before: function () {
		this.rightContent = $(".presenter-rightContent");
		if (!this.rightContent.is(":visible")) {
			this.visibleDiv = 'none';
		}
	},
	success: function () {
		if (this.visibleDiv == 'none') {
			this.rightContent.show("slide", { direction: "right" }, 700);
		}
	}
});
duskohu
Člen | 778
+
0
-

Supis, dakujem.