Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

API Provide a thin alternative to loadPanel/submitForm.

This is needed in some situations when we only want to update a
small single component, sometimes even using a different controller to
the one implied in the URL.

An example here is reloading dynamically the subsite dropdown without
reloading the entire page, updating a filter sidebar or suchlike.
  • Loading branch information...
commit 1f8feb5efcb77eb83036baaa70205c864420af3e 1 parent 4af619e
Mateusz U mateusz authored
84 admin/javascript/LeftAndMain.js
View
@@ -115,7 +115,15 @@ jQuery.noConflict();
*/
$('.cms-container').entwine({
- CurrentXHR: null,
+ /**
+ * Tracks current panel request.
+ */
+ StateChangeXHR: null,
+
+ /**
+ * Tracks current fragment-only parallel PJAX requests.
+ */
+ FragmentXHR: {},
StateChangeCount: 0,
@@ -419,7 +427,7 @@ jQuery.noConflict();
*/
handleStateChange: function() {
// Don't allow parallel loading to avoid edge cases
- if(this.getCurrentXHR()) this.getCurrentXHR().abort();
+ if(this.getStateChangeXHR()) this.getStateChangeXHR().abort();
var self = this, h = window.History, state = h.getState(),
fragments = state.data.pjax || 'Content', headers = {},
@@ -455,7 +463,7 @@ jQuery.noConflict();
headers: headers,
url: state.url,
complete: function() {
- self.setCurrentXHR(null);
+ self.setStateChangeXHR(null);
// Remove loading indication from old content els (regardless of which are replaced)
contentEls.removeClass('loading');
},
@@ -465,7 +473,75 @@ jQuery.noConflict();
}
});
- this.setCurrentXHR(xhr);
+ this.setStateChangeXHR(xhr);
+ },
+
+ /**
+ * ALternative to loadPanel/submitForm.
+ *
+ * Triggers a parallel-fetch of a PJAX fragment, which is a separate request to the
+ * state change requests. There could be any amount of these fetches going on in the background,
+ * and they don't register as a HTML5 history states.
+ *
+ * This is meant for updating a PJAX areas that are not complete panel/form reloads. These you'd
+ * normally do via submitForm or loadPanel which have a lot of automation built in.
+ *
+ * On receiving successful response, the framework will update the element tagged with appropriate
+ * data-pjax-fragment attribute (e.g. data-pjax-fragment="<pjax-fragment-name>"). Make sure this element
+ * is available.
+ *
+ * Example usage:
+ * $('.cms-container').loadFragment('admin/foobar/', 'FragmentName');
+ *
+ * @param url string Relative or absolute url of the controller.
+ * @param pjaxFragments string PJAX fragment(s), comma separated.
+ */
+ loadFragment: function(url, pjaxFragments) {
+
+ var self = this,
+ xhr,
+ headers = {},
+ baseUrl = $('base').attr('href'),
+ fragmentXHR = this.getFragmentXHR();
+
+ // Make sure only one XHR for a specific fragment is currently in progress.
+ if(
+ typeof fragmentXHR[pjaxFragments]!=='undefined' &&
+ fragmentXHR[pjaxFragments]!==null
+ ) {
+ fragmentXHR[pjaxFragments].abort();
+ fragmentXHR[pjaxFragments] = null;
+ }
+
+ url = $.path.isAbsoluteUrl(url) ? url : $.path.makeUrlAbsolute(url, baseUrl);
+ headers['X-Pjax'] = pjaxFragments;
+
+ xhr = $.ajax({
+ headers: headers,
+ url: url,
+ success: function(data, status, xhr) {
+ var elements = self.handleAjaxResponse(data, status, xhr, null);
+
+ // We are fully done now, make it possible for others to hook in here.
+ self.trigger('afterloadfragment', { data: data, status: status, xhr: xhr, elements: elements });
+ },
+ error: function(xhr, status, error) {
+ self.trigger('loadfragmenterror', { xhr: xhr, status: status, error: error });
+ },
+ complete: function() {
+ // Reset the current XHR in tracking object.
+ var fragmentXHR = self.getFragmentXHR();
+ if(
+ typeof fragmentXHR[pjaxFragments]!=='undefined' &&
+ fragmentXHR[pjaxFragments]!==null
+ ) {
+ fragmentXHR[pjaxFragments] = null;
+ }
+ }
+ });
+
+ // Store the fragment request so we can abort later, should we get a duplicate request.
+ fragmentXHR[pjaxFragments] = xhr;
},
/**
41 docs/en/reference/cms-architecture.md
View
@@ -287,6 +287,47 @@ tracked in the browser history, use the `pjax` attribute on the state data.
$('.cms-container').loadPanel('admin/pages', null, {pjax: 'Content'});
+## Loading lightweight PJAX fragments
+
+Normal navigation between URLs in the admin section of the Framework occurs through `loadPanel` and `submitForm`.
+These calls make sure the HTML5 history is updated correctly and back and forward buttons work. They also take
+care of some automation, for example restoring currently selected tabs.
+
+However there are situations when you would like to only update a small area in the CMS, and when this operation should
+not trigger a browser's history pushState. A good example here is reloading a dropdown that relies on backend session
+information that could have been updated as part of action elsewhere, updates to sidebar status, or other areas
+unrelated to the main flow.
+
+In this case you can use the `loadFragment` call supplied by `LeftAndMain.js`. You can trigger as many of these in
+parallel as you want. This will not disturb the main navigation.
+
+ $('.cms-container').loadFragment('admin/foobar/', 'Fragment1');
+ $('.cms-container').loadFragment('admin/foobar/', 'Fragment2');
+ $('.cms-container').loadFragment('admin/foobar/', 'Fragment3');
+
+The ongoing requests are tracked by the PJAX fragment name (Fragment1, 2, and 3 above) - resubmission will
+result in the prior request for this fragment to be aborted. Other parallel requests will continue undisturbed.
+
+You can also load multiple fragments in one request, as long as they are to the same controller (i.e. URL):
+
+ $('.cms-container').loadFragment('admin/foobar/', 'Fragment2,Fragment3');
+
+This counts as a separate request type from the perspective of the request tracking, so will not abort the singular
+`Fragment2` nor `Fragment3`.
+
+Upon the receipt of the response, the fragment will be injected into DOM where a matching `data-pjax-fragment` attribute
+has been found on an element (this element will get completely replaced). Afterwards a `afterloadfragment` event
+will be triggered. In case of a request error a `loadfragmenterror` will be raised and DOM will not be touched.
+
+You can hook up a response handler that obtains all the details of the XHR request like this:
+
+ 'from .cms-container': {
+ onafterloadfragment: function(e, data) {
+ // Say 'success'!
+ alert(data.status);
+ }
+ }
+
## Ajax Redirects
Sometimes, a server response represents a new URL state, e.g. when submitting an "add record" form,
Please sign in to comment.
Something went wrong with that request. Please try again.