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

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

Tohle unique neumí. Napsal bych si na to vlastní extension:

$.nette.ext('masskiller', {
	start: function (xhr, settings) {
		if (this.enabled) {
			this.requests.push(xhr);
		}
	}
}, {
	requests: [],
	enabled: false,
	enable: function () {
		this.enabled = true;
	},
	disable: function () {
		this.enabled = false;
		$.each(requests, function (i, xhr) {
			xhr.abort();
		});
	}
});

Užití:

$.nette.ajax({..., off: ['unique']});
$.nette.ajax({..., off: ['unique']});
$.nette.ajax({..., off: ['unique']});

$.nette.ajax({..., off: ['masskiller']}).success(function () {
	$.nette.ext('masskiller').disable();
	// redirect...
});

Editoval vojtech.dobes (22. 4. 2013 16:58)

pepakriz
Člen | 246
+
0
-

@vojtech.dobes: Na základě tvé ukázky jsem vytvořil řešení, jaké bych si představoval. (Za kvalitu JS se omlouvám)

$.nette.ext('unique', {
	start: function (xhr) {
		var logger = this.ext('uniqueLogger', true);
		$.each(logger.requests, function (i, xhr) {
			xhr.abort();
		});
		logger.reset();
	},
	complete: function () {
		this.ext('uniqueLogger', true).reset();
	}
});
$.nette.ext('uniqueLogger', {
	start: function (xhr) {
		this.requests.push(xhr);
	}
}, {
	requests: [],
	reset: function() {
		this.requests = new Array();
	}
});

V podstatě jsem jen vyjmul logování do samostatné extense, což přináší širší prostor k nastavení:

  • $.nette.ajax({…}); – přeruší předešlé zalogované požadavky a spustí nový
  • $.nette.ajax({…, off: [‚unique‘]}); – spustí nový požadavek, nepřeruší ostatní
  • $.nette.ajax({…, off: [‚uniqueLogger‘]}); – přeruší předešlé zalogované požadavky a spustí nový, sám sebe neloguje, garance, že nebude přerušen
  • $.nette.ajax({…, off: [‚uniqueLogger‘, ‚unique‘]}); – spustí požadavek, nepřeruší ostatní a sám sebe nezaloguje

Co si o tom myslíš?

czheeek
Člen | 17
+
0
-

Pokud někdo má aplikaci v AJAXU a má nastavenou expedici session třeba na 10 minut a chce pokud nastane AJAX požadavek na invalidaci snippetu, tak aby se udělal automaticky reload na LOGIN PAGE

<script>
	/**
	 * backlink reload
	 */
	$.nette.ext('backlink', {
		complete: function() {
		    var regex = new RegExp("[\\?&]backlink=([^&#]*)");
		    if (regex.exec(window.location.href) != null) {
		    	alert('Byl jste z důvodu neaktivity odhlášen');
		        location.reload();
		    }
		}
	});
</script>
David Ďurika
Člen | 328
+
0
-

Zdravim, vopred sa ospravedlnujem ze noobsku otazku, ale v JS sa moc neviznem…

mam rozbehane nette.ajax.js, vsetko funguje jak ma!
avsak potreboval by som dorobit takuto vec: ak kliknem na link kt. ma classu fooBar tak nech sa mu pred odoslanim ajaxu prida dalsia class fooBaz

dakujem

Glottis
Člen | 129
+
0
-

cao, nejak takto. pisu to zhlavy tak tam mozna bude nejaka ta chyba

$.nette.ext('onclick', {
	load: function () {
		$('a .fooBar').click(function(){
			$(this).addClass('fooBaz');
		});
	}
});

achtan napsal(a):

Zdravim, vopred sa ospravedlnujem ze noobsku otazku, ale v JS sa moc neviznem…

mam rozbehane nette.ajax.js, vsetko funguje jak ma!
avsak potreboval by som dorobit takuto vec: ak kliknem na link kt. ma classu fooBar tak nech sa mu pred odoslanim ajaxu prida dalsia class fooBaz

dakujem

David Ďurika
Člen | 328
+
0
-

Glottis napsal(a):

cao, nejak takto

aha dik… ja som sa to snazil napchat do toho ‚before‘ eventu…

akadlec
Člen | 1326
+
0
-

@vojtech.dobes
plánuješ update na nové jQuery 2.0?

viktor.babjak
Člen | 2
+
0
-

Ahoj,

mam problem s viacnasobnou validaciou AJAXovych formularov. Chcel by som sa opytat na riesenie tohto problemu.

  • stiahnem sandbox (Nette 2.1-dev, z 2013–04–26 10:47:21)
  • HomepagePresenter.php vytvorim formular, ktory ma iba $form->addText("text")->setRequired(); a submit
  • v @layout.latte je nalinkovane zo sandboxu jQuery (1.8.2), netteForms.js, nette.ajax.js (1.2.2), main.js, v ktorom je inicializacia $(function () { $.nette.init(); });

Pri neAJAXovom odosielani prebehne vsetko v poriadku, ked je input prazdny, validacia sa vykona len raz.

No pri AJAXovom odosielani a prazdnom inpute sa validacia vykona trikrat a z toho dvakrat v console je chyba

ReferenceError: event is not defined @ .../sandbox/www/js/netteForms.js:336

Ku chybe dochadza na riadku e = e || event; v Nette.initForm = function(form) { ... };

Tu je sandbox.

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

Děkuji za nahlášené potíže a dotazy, snad se k tomu brzy dostanu.

@achtan Ja tvoje zadání taky pochopil tak, že bych ho řešil s využitím before. Pokud se ta class má ale vždycky přidat jen pokud se request opravdu spustí, a nevadí ti, že to bude milivteřinku po jeho zahájení, použij událost start.

jannemec
Člen | 78
+
0
-

eval before and eval after
Zdravím, rád bych si napsal doplněk, který by vykonal něco „před updatem snippetů“ a druhý „po updatu“. Ale skončil jsem na
$.nette.ext(‚evalAfter‘, {
success: function (payload) {
if (payload.evalAfter) {
eval(payload.evalAfter);
return false;
}
}
});

  • provede evalAfter, ale nejsem schopen řídit, jestli před/po update snippetů – nějaký nápad, jak to zajistit/ovlivnit pořadí průběhu doplňků?

Díky
JN

duke
Člen | 650
+
0
-

@jannemec Podívejte se pro inspiraci na rozšíření scrollTo. Podobně jako before, lze volat after či complete.

Nicméně u onoho rozšíření mám sám dotaz k autorovi a sice, zda toto rozšíření bude fungovat správně, pokud bude načteno až po rozšíření snippets. Proměnná shouldTrysuccess handleru se totiž dle mého názoru nastaví na true až poté, co proběhnou všechna volání before (protože before fronta se zpracovává v success handleru rozšíření snippets, který má přednost před success handlerem rozříření scrollTo)…

jannemec
Člen | 78
+
0
-

@duke no právě na tom jsem ztroskotal, jak zajistit, aby se událost success zpracovala nejprve novým rozšířením před frontou u snippets … a nevím co s tím

duke
Člen | 650
+
0
-

Jako dočasné řešení můžete zkusit vyjmout rozšíření „snippets“ z nette.ajax.js a vložit jej do zvláštního .js souboru a ten načítat až po ostatních rozšířeních.

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

@duke To nastavení v success je spíš takový reset. Trik je v tom, že při zpracování snippetů bude shouldTry na začátku vždycky true. Pokud se podaří scroll, tak se nastaví na false (aby se nescrollovalo víckrát), a v success už se hodnota zase jen nastaví na true pro další budoucí request.

Tomáš Votruba
Moderator | 1114
+
0
-

1. Jak na připojení rozšíření history.ajax.js? Stačí přilinkovat a nechat:

$(function () {
    $.nette.init();
});

Hned po přilinkování history.ajax.js přestane ajax fungovat úplně.

2. Také mám problém s tím, že pokud invaliduji určitý snippet (klikem na prvek s class='ajax'), už nefunguje další ajaxizace v tomto snippetu.

Předem díky

Mr.Phoenixxx
Člen | 1
+
0
-

Zdravim,
pouzivam History extension a nasledujúcu fintu pri zmene obsahu snippetu:

<script>
$.nette.ext('snippets').applySnippet = function ($el, html) {
   $el.fadeTo("fast", 0.01, function () {
      $el.html(html).fadeTo("fast", 1);
   });
};
</script>

Vsetko funguje jak ma. Problem nastane ak v historii prehliadaca pouzijem BACK a nasledne FORWARD.
Pri pouziti BACK sa zobrazi predchadzajuci obsah presne tak, jak ma. No pri FORWARD sa uz ale nezobrazi ten povodny, ktory bol v snippete pred pouzitim BACK.

Problem je zrejme v tom, ze snippet zmeni svoj obsah az po case potrebnom na vykonanie prvej funkcie fadeTo(). History extension si ale zaznamena obsah snippetov este pred tym ako sa tato funkcia/animacia ukonci.

Nechce sa mi verit ze som sam co to spozoroval. Preto dufam, ze už dávno máte jednoduché riešenie ako túto situáciu eliminovať.

ji_ri_k
Člen | 44
+
0
-

Já jsem při používání History extension narazil na jiný problém – týká se to prohlížečů s jádrem Webkit (Chrome, Safari). Request proběhne v těchto prohlížečích dvakrát. Mám to jen špatně nakonfigurované, nebo je to bug? (první request na stránku je klasický, druhý na pozadí je XMLHttpRequest)

Vyzkoušet to můžete zde: http://pine.web-egen.cz/ (ve Firefoxu vše proběhne OK – pouze jeden request, v Chrome jsou requesty 2 – klasický + XMLHttpRequest)

akadlec
Člen | 1326
+
0
-

Takový rychlý dotaz ohledně data atributů. Mám odkaz u kterého potřebuju vypnout jak history tak i scroll tak sem zadal:

<a href="#" class="btn btn-primary btn-icon glyphicons pencil pull-right ajax" data-ajax-off="history scroll"><i></i>Add or edit</a>

a nežere to. když vypnu jen history či jen scroll tak je to ok ale dva to neveme. Co dělám blbě?

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

akadlec: Aktuálně je třeba uvést do toho datového atributu korektní JSON.

<a data-ajax-off="['history','scroll']">

Podporu pro oddělovač ve formě mezer je ale supr nápad, to přidám.

Editoval vojtech.dobes (3. 6. 2013 20:37)

akadlec
Člen | 1326
+
0
-

Perfektní, funguje. Já zkusil verzi se složenýma závorkama ale s hranatýma mě nenapadla ;)

JakubJarabica
Gold Partner | 184
+
0
-

Podarilo sa vyriešiť problém, ktorý má @viktor.babjak? Tiež sa mi objavil, vo FF, v Chrome sa to tvári OK.

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

JAM3SoN: Ta chyba, kterou popisuje, byla vyvolána změnou netteForms.js, a je aktuálně opravena jak na straně tohoto skriptu, tak na straně Nette. Takže doufám, že je to ok.

JakubJarabica
Gold Partner | 184
+
0
-

Vďaka, s novým netteforms to jecha správne.

duskohu
Člen | 778
+
0
-

Ahoj, mam otazku. Neviem ci idem spravnou cestou. Mam komponentu ktora sa v intervale invaliduje. Problem je v tom ze pri invalidovani sa automaticky invaliduju aj dalsie snippety ktore su na stranke. Napr mam modalne okno v snippete vyvolam Ho handle s nejakym parametrom a vykreslim. Ale ked sa mi nasledne invalidne ta komponenta ktora sa invaliduje v intervaloch, prirodzene mi to okno zmizne. A ja neviem ako tomu zabranit. Da da nastavit komponenta aby invalidovala len jeden snippet na stranke a ostatne neriesila? Alebo to mam riesit inak?
// komponenta ktora sa v intervaloch invaliduje

(function ($, undefined) {
    $.nette.ext({
        success: function (payload) {
            if (typeof payload.checkNewOrderCount !== 'undefined') {
                var count = $('[data-order-notification]').find('.count');
                if (count.html() != payload.checkNewOrderCount) {
                    count.html(payload.checkNewOrderCount);
                }
            }
        },
        load: function () {
            var obj = $('[data-order-notification]').data('orderNotification');
            setTimeout(function () {
                $.nette.ajax({
                    url: obj.handle
                });
            }, 60000);
        }
    });
})(jQuery);
Glottis
Člen | 129
+
0
-

a jak v nette invalidujes tu jednu komponentu?

duskohu
Člen | 778
+
0
-

v render mam:

if ($this->isAjax()) {
	$this->invalidateControl();
}

este som uvazoval skor nad tym ci sa neda nastavit aby pri ajax volani neinvalidovalo nijaky snippet.

Glottis
Člen | 129
+
0
-

jestli chces invalidovat jen jednu musis rict jakou

$this->invalidateControl(‚mujSnipet‘);

a komponentu do toho snipetu obalit

akadlec
Člen | 1326
+
0
-

A kdyby se ti i přes postup co píše @Glottis nějaké invalidovali tak je můžeš zase zpětně validovat

$this->validateControl("mujSnipet");
duskohu
Člen | 778
+
0
-

takze ked ich tam mam 5 tak 5×, tomu som sa chcel vyhnut :-)

duskohu
Člen | 778
+
0
-

@akadlec dik, toto sa mi viac paci :-)

duskohu
Člen | 778
+
0
-

Ahoj, mam este taky problem, rozchodil som si extenziu spinner.ajax.js

$.nette.ext('spinner', {
    init: function () {
        this.spinner = this.createSpinner();
        this.spinner.appendTo('body');
    },
    before: function (jqXHR, settings) {
        console.log(settings);
        this.spinner.css({
            left: settings.nette.e.pageX+20,
            top: settings.nette.e.pageY
        });
        this.spinner.show(this.speed);
    },
    complete: function () {
        this.spinner.hide(this.speed);
    }
}, {
    createSpinner: function () {
        return $('<div>', {
            id: 'ajax-spinner',
            css: {
                display: 'none'
            }
        });
    },
    spinner: null,
    speed: undefined
});

vsetko je fajn pokial urobim takuto poziadavku:

<a n:href="myHandle!" class="ajax">Handle</a>

ale pokial urobim nieco taketo, volanie cez $.nette.ajax, tak v settings.nette nemem nic, takze neviem zistit poziciu kurzora. V com je rozdiel? A ako by sa to dalo riesit?

$.nette.ext({
    load: function () {
        $('a[data-add-shopping-cart]').off('click');
        $('a[data-add-shopping-cart]').on("click", function(e){
            e.preventDefault();

            var obj = $(this).data('addShoppingCart');
            var quantity = $('#'+obj.id).val();

            var urlObj = {};
            urlObj[obj.paramPrefix+"quantity"] = quantity;
            $.nette.ajax({
                url: obj.handle,
                data: urlObj
            });

        });
    }
});
Stic
Člen | 28
+
0
-

Zdarec,

tak nejak som narazil na problem – mam twitter bootstrap modal okno kde mam formular, ktory sa ma odoslat Ajax-ovo.

Ked vsak pouzijem nette.ajax.js kniznicu, spolu s bootstrap.js a nette.forms.js, tak nette forms sa pravdepodobne snazi validovat inputy ihned ako niekde kliknem.

Teda v praxi to vyzera tak, ze hned prvy ipnut je povinny, no neda sa do neho ani kliknut lebo hned vyskoci pop-up okno ze som nevyplnil title. pre ostatne inputy sa to opakuje, je to teda uplne nepouzitelne…

Teraz neviem ci je problem v nette.forms ktory koliduje s bootstrapom, alebo nette.ajax ktory koliduje s bootstrapom (ked odstranim .ajax triedu z tlacitka na odoslanie, vsetko funguje ako ma, teda samozrejme okrem ajax-odoslania :) )

EDIT: nevermind, vyriesene prechodom na najnovsiu verziu

Editoval Stic (6. 6. 2013 23:21)

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

duskohu: Na to nette.ajax.js myslí :). Je ale třeba předat dál objekt události a HTML elementu. Uprav tedy volání takto:

$.nette.ajax({
	url: obj.handle,
	data: urlObj
}, this, e);
Vojtěch Dobeš
Gold Partner | 1316
+
0
-

Stic: Tak to jsem rád, znělo to děsivě :).

duskohu
Člen | 778
+
0
-

@vojtech.dobes dakujem, len jeden problem mam este, ako sa to da aplikovat u pluginov, napr mam nestedSortable a pouzivam tam nette ajax "priklad riadok: 90 pouzivam , this, event ":http://pastebin.com/MRQhRqnk, problem je v tom ze vsetko sa vykona, ale po presunuti polozky mi neostane na tom mieste kde som ju dal ale vrati sa spat, ajax poziadavok prebehne, robi to od vtedy co posielam this, event predpokladam ze mu to nejako skodi. V takomto pripade je aj dalsia moznost posielat this, event?

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

duskohu: To bude asi kvůli tomu, že nette.ajax.js tu událost automaticky zabíjí, očekává, že je to událost kliknutí na odkaz nebo tak něco. To lze obejít pomocí datového atributu, což by neměl být takový problém obejít. Stačí před tím voláním přidat:

$(this).attr('data-ajax-pass', true);

Editoval vojtech.dobes (7. 6. 2013 19:48)

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

duskohu: Anebo ještě jeden způsob, vzhledem k tomu, že tam asi nepotřebuješ žádné validaci kliknutí s Ctrl či pravidel formuláře… volej to bez validation rozšíření.

$.nette.ajax({
	url: extensionSetup.handleUrl,
	data: urlObj,
	off: ['validation']
}, this, event);

Pak nemusíš nastavovat ten datový atribut.

duskohu
Člen | 778
+
0
-

@vojtech.dobes dakujem, toto ide paradne :-)

Gaprielko
Člen | 42
+
0
-

Zdravim, ajaxovym poziadavkom zobrazujem bootstrap modalne okno (loadujem jeho obsah) a pokial sa don snazim vyrenderovat najaky formular, tak v nette.ajax.js sa nevykona complete v:

<script>
$.nette.ext('snippets').complete(function (payload) {
	// nevykona sa
})
</script>

napr. pri obycajnom texte to ide.. viete poradit?

Editoval Gaprielko (11. 6. 2013 16:13)

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

Úplně nechápu, co by ten kód měl dělat? Na extenzi se nedá volat žádné complete.

Gaprielko
Člen | 42
+
0
-

Konkretne, pouzivam rozsirenie pre spinner takto

<script>
$.nette.ext('spinner').complete(function (payload) {
	// skryjem spinner
})
</script>

a ked ajaxom nacitavam formular, tak sa to nevykona a spinner mi ostane zobrazeny.. obdobne, tak pre snippets (vid. prikl. vyssie) mam nastavenu reinicializaciu live validacie.

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

Volání $.nette.ext('spinner') přece ale nevrací nic, na čem by se dala volat metoda complete.

Gaprielko
Člen | 42
+
0
-

sorry, som to zle napisal, ja mam spravene rozsirenie pre spinner takto:

<script>
$.nette.ext('spinner', {
	init: function () {
                ...
        },
        start: function (xhr, settings) {
                ...
        },
        complete: function (payload){
                this.spinner.hide()
                    .css({
                        position: 'fixed',
                        left: '50%',
                        top: '50%'
                    });
        }
}, {
        // spinner element
        spinner: null
});
</script>

a problem je v tom, ze complete sa nevykona po loadovani formulara

mcmatak
Člen | 504
+
0
-

nejsem si jisty jestli tento plugin umi něco takového

<script>

jQuery(document).ready(function($) {
	$('input.onEnterFireMe').each(function() {
		var element = $(this);
		var form = $(element).parents('form').get(0);
		$(form).keypress(function (e) {
			if (e.keyCode == $.ui.keyCode.ENTER) {
				e.preventDefault();
				element.trigger('click');
			}
		});
	});
});

</script>

jde o to, že google chrome a safari, neumí identifikovat button kterým má odeslat formulář při stisknutí enteru, nějaké verze IE s tím mají problém, ostatní prohlížeče zvolí jako cílový submit ten první v kódu, což také nemusí být žádoucí, řeším tedy něco co už je vyřešeno, nebo tohle patří do skriptu?

Majkl578
Moderator | 1364
+
0
-

@mcmatak: Tohle s AJAXem nijak nesouvisí.

mcmatak
Člen | 504
+
0
-

hm no tak bez tohodle enterem formular neodesles, pripada mi ze to patri k obsluze formularu, ale tak ok, me prislo vyhodne to dat k tomuto skriptu, protoze vsude kde nacitam tento skript tak to potrebuji

ale pochopil jsem že ten plugin nic takoveho neresi

akadlec
Člen | 1326
+
0
-

@All: Měl bych tady takový menší špíček ;)

Mám stránku kde mám několik datagridu (pro jejich zobrazení využívám DataTables) a u každého gridu je button na přidání nové položky a také kažád položka v gridu má zase editační button.

Klikem na jeden z buttonů, se zavolá patřišný presenter a jeho action pro přidání či editaci záznamu. Vzhledem k tomu že to sou malé formulářky o několika málo inputech tak sem se rozhodl je dávat do modal okna. Takže je to řešeno tak že po kliku na button mi přijde zpět response s obsahem onoho okna, to se vloží do stránky a otevře. Až po sem je to ok a bez problému.

Co ale potřebuju vyřešit je, že po kliku na save button v tom okně bych potřeboval zavolat refresh onoho datagridu. tj. napojit na ten button nějakou extension, co bude mit v onSuccess callback na refresh datagridu.

Nemá někdo tip jak to správně vyřešit aby to bylo uni a ne kilometry kodu co budou nějak navazovat udalosti atd. Rád bych totiž zachoval celé zpracování přes nette.ajax.

akadlec
Člen | 1326
+
0
-

Nikdo žáden tip?

mcmatak
Člen | 504
+
0
-

akadlec wrote:

Nikdo žáden tip?

neřeši tohle snippety? asi bych volal handle co ten datagrid invaliduje a asi by editace mela byt ve stejnem presenteru jako grid

akadlec
Člen | 1326
+
0
-

@mcmatak: ne, to není to co potřebuju, nechci nahrazovat celý kus kodu ale zavolat si nějakou akci. Libilo by se mě kdyby se dalo pomocí nějakého data atributu definovat jaka extension nette.ajax by se měla spustit po vykonani třeba nějak takto:

<a href="zpracuj!" class="ajax" data-onsuccess="mojeext">zpracuj</a>

a pak mít v js:

$.nette.ext('mojeext', {
    type: lazy,
    success: function () {
	alert('Já jsem se spustil až po ajaxu');
    }
});