vojtech-dobes / nette.ajax.js Goto Github PK
View Code? Open in Web Editor NEWFlexible AJAX for Nette Framework. Supports snippets, redirects etc.
Home Page: https://componette.org/vojtech-dobes/nette.ajax.js/
License: MIT License
Flexible AJAX for Nette Framework. Supports snippets, redirects etc.
Home Page: https://componette.org/vojtech-dobes/nette.ajax.js/
License: MIT License
I need put input.ajax
into my .ajax
form, but due to this code:
$(this.buttonSelector).each(function () {
$(this).closest('form').off('click.nette', this.buttonSelector, rh)
.on('click.nette', this.buttonSelector, rh);
});
it causes, that all the form is clickable and sends ajax requests.
There is an event, that get's called after everything is loaded and executed. I use it without problems to init $.nette
ajax.
jQuery(window).load(function () {
jQuery.nette.init();
});
Please consider doing it automatically
There is nothing going on between them. They should be probably merged and called in beforeSend
. And called before
to avoid confusing naming.
Complete
event gets fired only for successful requests. For failed requests e.g. due syntax error on server only error
is triggerred
simple test case:
$.nette.ext({
complete: function() { console.log('complete'); },
error: function() { console.log('error'); },
success: function() { console.log('success'); }
});
"The problem is well-known — Chrome and Firefox treat that popstate event differently. While Firefox doesn't fire it up on the first load, Chrome does." (see http://stackoverflow.com/questions/6421769/popstate-on-pages-load-in-chrome for example). Although the problem is well-know, it's not handled properly in history.ajax.js (or at least it seems to me). In my case, this results in an extra Ajax call when using history.ajax.js. When I load a page in Chrome, it gets immediately refreshed using Ajax.
I'm not familiar with History API or history.ajax.js so I'm not able to suggest a solid working solution. As a workaround, I added a simple counter of events for webkit based browsers and using this counter, I'm able to ignore the first event.
If I create some component-level extension I don't want to add data-ajax-off="..."
to every .ajax
element on the page.
Alternatively I could validate the firing element to be the desired one in the extension code, but such element marking could be more straightforward.
It would be nice to be able to add a "sleeping" extension - disabled by default - and enabled only for marked elements.
What do you thing?
Mám usecase: "Smazání řádku, souboru ..."
Tak nechci snippet překreslovat něčím co bude prázdné ale rovnou ho smazat už ho nepotřebuji.
updateSnippet: function ($el, html, back) {
if(html === 'remove') {
return $el.remove();
}
Když mám například snippet jako tag li tak tímto se mi smaže a nezůstane prázdná tečka v seznamu.
I can't figure out how to make my custom callbacks work.
Anything like
Inside the function I need to work with $(this) (the element clicked). Thanks for your advice...
Create jQuery extension that would simplify the use of $.nette.ajax()
and allow custom handler.
$('#element').click(function (e) {
$(this).netteAjax(e, function () { ... });
});
$('[type=checkbox]').click(function (e) {
$(this).netteAjax(e);
});
Event will get killed and checkbox won't change its status. There probably should be way how to allow the event to continue.
When you create an extension, you might wanna do something, before the "native" extensions get called. The problem with javascript is, that it does sort object properties randomly. If you'd create a array queue from each event, the callbacks would sort in the way they were added. When they sort, you can than reverse the order, to make the later added callback get invoked first. (Nette does this with it's macros)
So the result would be, I'd add my extension, that would manipulate snippets and handle proper discard of objects and events attached to elements, before they get replaced. And could, after the snippet gets replaced, in complete
event create the new objects.
maybe bug? thanks
Now when the project contains PHP classes it is good time to add Composer (and it's autoload feature) support.
I am trying to manually submit form using nette.ajax but it only gets submitted first time. Other times it ends on this condition because statusText
is set to cancelled - magic for me. I don't really have any idea what's wrong or where I should start digging. Any help will be appreciated!
Code I use:
fileUploadForm.on('submit.file-upload', function(e) {
$(this).netteAjax(e, {
complete: function(payload, status, xhr) {
basicFileUploadHandler._successCb(payload, status, xhr, uploadRow, filesize);
}
});
fileUploadForm.off('submit.file-upload');
e.stopImmediatePropagation();
e.preventDefault();
return false;
}).trigger('submit.file-upload');
When HTML is loaded by jQuery, callbacks that programmers attached to some elements on page load are not automatically attached to the new html, which is often a problem. I'd welcome a feature that allows me to easily re-initialize javascript on HTML in snippets, I solved it by adding this code into snippets.applySnippet method:
if ($.nette.ext('reset-snippet-js')) {
html = $(html);
$.nette.ext('reset-snippet-js').resetSnippet(html);
}
Then I call this on document load:
$.nette.ext('reset-snippet-js', {}, {
resetSnippet: function($snippet) {
initToggleBox($snippet.find('.c-box')); //some my function to add some behavior
}
});
You can integrate these simple lines if you agree with me or maybe even more robust solution with some event raised for each refreshed snippet...
thanks
Hashbang based on http://benalman.com/projects/jquery-bbq-plugin/
There is caching bug in IE - it's the reason of using date time variable in the request
$(document).ready(function() {
// AJAX submit with .ajaxhash - saving the history
var domain = 'http://' + document.location.host;
var url = '';
var counter = 0;
var link = '';
$("a.ajaxhash").live("click", function (event) {
// HTML5 pushState compatible browsers
if (history.pushState) {
// if we call replaceState on load there will be first url two times in history - but we need the rest of this function
if (counter == 0) {
window.history.replaceState({
href: window.location.toString()
}, "", window.location);
counter = counter + 1;
}
window.history.pushState({
href: this.href
}, "", this.href);
event.preventDefault();
$.get(this.href);
} else {
url = this.href.substring(domain.length, this.href.length);
$.bbq.pushState('#!' + url);
event.preventDefault();
}
// showing the spinner and settings his position
$("#ajax-spinner").show().css({
position: "absolute",
left: event.pageX - 24,
top: event.pageY + 10
}).ajaxStop(function() {
$(this).hide();
});
});
// on document load
// pustState HTML5
if (history.pushState) {
$(window).bind('popstate', function(event) {
$.post(event.originalEvent.state.href, $.nette.success);
});
// hashbang HTML4
} else {
$(window).trigger("hashchange");
}
// load AJAX content depending on hashbang
$(window).bind("hashchange", function(e) {
url = '';
for(key in $.bbq.getState()) {
if ($.bbq.getState()[key] == '') {
url = key.substring(1, key.length);
} else if (url == '') {
url = key.substring(1, key.length) + '=' + $.bbq.getState()[key];
} else {
url = url + '&' + key.substring(0, key.length) + '=' + $.bbq.getState()[key];
}
}
if (url == undefined) {
link = location.href;
if ((link.split('?').length - 1) > 0) {
link = location.href + '&cache=' + new Date().getTime();
} else {
link = location.href + '?cache=' + new Date().getTime();
}
} else if (url == '') {
link = document.location.toString();
if ((link.split('?').length - 1) > 0) {
link = document.location + '&cache=' + new Date().getTime();
} else {
link = document.location + '?cache=' + new Date().getTime();
}
} else {
link = url;
if ((link.split('?').length - 1) > 0) {
link = domain + url + '&cache=' + new Date().getTime();
} else {
link = domain + url + '?cache=' + new Date().getTime();
}
}
$.get(link);
});
});
Ahoj,
od tohoto commitu:
00c144b
mi nefunguje překreslování snippetů. Hodnota xhr.status je undefined.
I have this is my composer in my require section:
"venne/nette-ajax": "dev-master",
Time to time it happens that composer outputs something like this on update or even install:
- Updating venne/nette-ajax dev-master (3017278 => 05e46ff)
Checking out 05e46ff7523c6f0397d6ee61169d5552e5e23316
05e46ff7523c6f0397d6ee61169d5552e5e23316 is gone (history was rewritten?), recovered by checking out 30172784e595c65ea9f06653c62d2c7487b61367
And .js files keep jumping between root and client-side directories so that application doesn't work.
$.nette.ext({
load: function () { ...
});
Zjistil jsem jednu chybu na řádku 384:
Pokud nechávám při ajaxových requestech přepisovat URL a pak dám refresh stránky a použiji ajaxov request znovu, vypíše se mi chyba "$el.get(0) is undefined".
Pokud přidám do podmínky navíc $el.get(0)!==undefined tak je vše (zdá se) v pořádku.
Ale neznám celý skript tak důkladně, takže nevím zda je to skutečné řešení problému nebo jen berlička...
Stáhl jsem si současnou verzi a konzoli mi to hází chybu:
TypeError: function (a) {var b = "[data-dismiss="alert"]", c = function (c) {a(c).on("click", b, this.close);};c.prototype.close = function (b) {
function f() {e.trigger("closed").remove();}
var c = a(this), d = c.attr("data-target"), e;d || (d = c.attr("href"), d = d && d.replace(/.(?=#[^\s]$)/, "")), e = a(d), b && b.preventDefault(), e.length || (e = c.hasClass("alert") ? c : c.parent()), e.trigger(b = a.Event("close"));if (b.isDefaultPrevented()) {return;}e.removeClass("in"), a.support.transition && e.hasClass("fade") ? e.on(a.support.transition.end, f) : f();}, a.fn.alert = function (b) {return this.each(function () {var d = a(this), e = d.data("alert");e || d.data("alert", e = new c(this)), typeof b == "string" && e[b].call(d);});}, a.fn.alert.Constructor = c, a(function () {a("body").on("click.alert.data-api", b, c.prototype.close);});}(window.jQuery) is not a function
Není to bug?
Hi, when i use bootstrap datepicker and paginator and history.ajax.js i have problem with NS_ERROR_ILLEGAL_VALUE: Component returned failure code: 0x80070057 (NS_ERROR_ILLEGAL_VALUE) [nsIDOMHistory.pushState].
Is nessecerary to use in row 86 on success metohod ui: findSnippets()? When i comment work it perfect.
success: function (payload) {
var redirect = payload.redirect || payload.url; // backwards compatibility for 'url'
if (redirect) {
var regexp = new RegExp('//' + window.location.host + '($|/)');
if ((redirect.substring(0,4) === 'http') ? regexp.test(redirect) : true) {
this.href = redirect;
} else {
window.location.href = redirect;
}
}
if (this.href && this.href != window.location.href) {
history.pushState({
nette: true,
href: this.href,
title: document.title,
ui: findSnippets()
}, document.title, this.href);
}
this.href = null;
}
Je to drobnost, ale hodilo by se mít někde (například i v úvodním komentáři) informaci o verzi.
Skript úspěšně provozuju v několika větvích, někde testím, někde zkouším nové fíčury a podobně, a ztrácím přehled o tom, kde mám kterou verzi, resp. který commit.
Hash commitu by byl možná ještě lepší, ale obyčejná číselná verze by bohatě stačila :-)
I have a library where I can't use $.nette.ajax
directly, but I would still like to trigger events for updating snippets etc. Currently it is not possible at all. The only dirty solution is to patch nette.ajax.js itself, e.g. by adding:
this.fakeSuccess = function (payload, status, xhr, off) {
inner.fire({
name: 'success',
off: off || {}
}, payload, status, xhr);
};
Please, try it here http://jsbin.com/ofezad/1
In Chrome, request will run in background. In IE 8, request opens new window.
I haven't been tried it in other IEs.
Let's have a presenter
class HomepagePresenter extends BasePresenter
{
/** @persistent */
public $locale = 'cs';
}
When you send ajax to
/homepage?locale=en
the value for locale
will be en
and the returne state from Nette contains
{"state":{"locale":"en","backlink":null}}
Which is fine, but the next request looks like this
/homepage/?locale=en&locale=en&backlink=
Which is obviousely not right. But that would be the better part, because this still work. What is not fine, that when you send a request on
/homepage
the value for locale
will be cs
and Nette will return
{"state":{"locale":null,"backlink":null}}
And the next request will look like this
/homepage/?locale=&backlink=
And now the application is broken.
TL;DR not even assumed sanitized HTML and CSS can be trusted in el.innerHTML
or $(el).html()
. Increase security by using JavaScript sanitizer like Google Caja.
More info:
http://www.nds.rub.de/research/publications/mXSS-Attacks/
http://www.slideshare.net/x00mario/the-innerhtml-apocalypse
Original issue nette/nette#1496
I would suggest delegating $(el).html(snippet)
to separate method and by default using secure implementation via TrueHTML or at least sanitizing the input.
I haven't done enough research on this topic and futher research is necessary. Known affected are old versions of IE (8, 9), Firefox, Chrome. IE 11 XSS filter shows warning even for false positives which might break trust between user and site.
https://github.com/vojtech-dobes/nette.ajax.js/blob/master/history/history.ajax.js#L45 is called for 3rd party requests, such as embedded Youtube player and Google custom search.
The 3rd party content is immediately overwritten by original cached snippets or new ajax request if caching is disabled.
IE8 vyhazuje chybu při validaci formuláře - asi neumí převzít cizí event v metodě onsubmit (viz řádek 313 https://github.com/vojtech-dobes/nette.ajax.js/blob/master/nette.ajax.js#L313).
Tenhle problém se mi podařil nasimulovat čistě v IE8, novější IE s přepnutím režimu do IE8 jsou ok.
I'll try to make further exploration later, because I am not sure if it is bad use, bug or even a feature ;)
Update:
Version: ALL
<form class="ajax" method="post">
is forced to be be sent via GET method
Query string parameter with the same name as the form field is not overwritten, so it is impossible to send form[q]
if q
is already present in URL.
Post data are not serialized within the POST request.
I have been experiencing wird behaviour lately. While I'm used to close firefox browser with several tabs open, sometimes I have noticed the backed of application I'm working on has rendered json to browser instead of redirecting to login page. I was trying to fix the problem on php side, but there was nothing wrong. It took me quite a while to figure out where the problem is and when exactly is happennig.
The main reason is the ajax calls are cached by default. In my case after reopening tabs browser did not even try to make single request to server and displayed last json response instead.
After quick reasearch I have found out it's quite common issue and there are other related. Of course ii could be handled on server side by sending correct headers, but adding "cache:false" option to ajax request seems to me by far more efficient. see http://stackoverflow.com/questions/168963/stop-jquery-load-response-from-being-cached/168977#168977
Navrhuji do nette.ajax.js umistovat verzi aby bylo videt jakou mam aktualne verzi nasazenou a jakou verzi si mohu stahnout
After testing history extension for nette.ajax.js I've encountered an unwanted feature in fix discussed here: #73.
When I click through some sections the plugin works just fine but when I navigate back through those sections I'm not able to load the initial page.
This part of 'popstate' handler is suspicious:
var initialPop = (popped && initialUrl == state.href);
// console.log('popped: ' + popped + '\ninitialUrl: ' + initialUrl + '\nstate.href: ' + state.href);
popped = true;
if (initialPop) {
return;
}
https://github.com/vojtech-dobes/nette.ajax.js/blob/master/history/history.ajax.js#L45
Explained:
My solution would be to add another variable containing true/false indication whether user has already loaded another page or not.
If ajax form is invalid and stopped by nette JS validation, nette.ajax start
function is called after complete
function.
So, for example, spinner is displayed again.
Is it possible to add functionality, which will disable the button, that fired the ajax event?
JS error: "TypeError: name is undefined"
Line 375: if (name.indexOf('[', 0) !== -1) { // inside a container
Clicking on submit button works fine.
<input onchange="this.form.submit()">
won't initiate AJAX request. Is it bug or appreciated behavior?
Pri použití unique: false v konkrétnom rozšírení, naďalej zabíja predchádzajúce requesty.
Navrhuji, že by mohl být přidán history.repaceState pro zlikvidování nehezkých url vytvářených v nette. Čili _fid, do a další by mohli být odstraněny, u replace state není třeba řešit tlačítko zpět v prohlížeči jako u pushState, takže by to mohlo být ok, co myslíte?
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
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.
See working example here: http://vaclavsir.php5.cz/ajax-pokus/www/
And its source code here: https://gist.github.com/3193886
I tried it in Chrome, IE9 and Firefox and these pending requests are not aborted in neither of them.
In history.ajax is selector for finding all snippets on page $('[id^="snippet--"]')
, but when any snippet is placed inside component, id is generated as snippet-{componentName}-{snippetName}
. Therefore no snippets in components are updated when back button is pressed.
Code was added in 29acff0#diff-f59d393841fff5c3fdbd278aae594f24R10
I enter
bower install nette.ajax.js#master --save
and i will get
bower nette-forms#~0.0.3 ENORESTARGET No tag found that was able to satisfy ~0.0.3
Today I have noticed quite complex problem. As I tried to implement state save/load for Datatables and display some debug messages using barDump. They did not display. The reason is
I have not figured out optimal solution yet. This case can be solved when DebugBar supports ajax itself, but I think this is a topic to keep in mind generally for any ajax communication. There can be some situations, when requests are running paralel and this might cause unexpected behaviour.
Hi,
data-ajax-off is a cool feature, but it's kinda pain to write when you want to disable more than one extension. In that case, it has to be a valid JSON, otherwise it fails to parse and returns just string. So the definition looks like:
<a href="..." class="ajax" data-ajax-off='["snippets", "history", "ga"]'>...</a>
It'd be cool if it was possible to define it just like:
<a href="..." class="ajax" data-ajax-off="snippets, history, ga">...</a>
ahoj, v google chrome nefunguje history.ajax.js společně s javascriptovou validací. (live-form-validation ani netteForms) Nevyhazuje to v konzoli žádnou chybu (event vůbec nereaguje)
Hi, I've just spent about an hour debugging why my ajax link doesn't work. I had an anchor:
<a href="#">Foo</a>
And I was dynamically changing its href after click on another element. I was using .prop() to change anchor's href. After changing it to .attr(), ajax started working.
Really a WTF. My question is: Is it a bug or a hidden feature with no warning?
Will be nice to have support for sending file with ajax (e.g. with jQuery Form)
Some ideas is described in: http://forum.nette.org/cs/15283-nette-ajax-jquery-form-soubory-pomoci-ajaxu
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.