1
/* YUI 3.9.1 (build 5852) Copyright 2013 Yahoo! Inc. http://yuilibrary.com/license/ */
2
YUI.add('pjax-content', function (Y, NAME) {
5
`Y.Router` extension that provides the content fetching and handling needed to
6
implement the standard pjax (HTMP5 pushState + Ajax) functionality.
9
@submodule pjax-content
14
`Y.Router` extension that provides the content fetching and handling needed to
15
implement the standard pjax (HTMP5 pushState + Ajax) functionality.
17
This makes it easy to fetch server rendered content for URLs using Ajax. By
18
helping the router to fulfill the "request" for the content you can avoid full
21
The `PjaxContent` class isn't useful on its own, but can be mixed into a
22
`Router`-based class along with the `PjaxBase` class to add Pjax functionality
23
to that Router. For a pre-made standalone Pjax router, see the `Pjax` class.
25
var MyRouter = Y.Base.create('myRouter', Y.Router, [
36
function PjaxContent() {}
38
PjaxContent.prototype = {
39
// -- Public Methods -------------------------------------------------------
42
Extracts and returns the relevant HTML content from an Ajax response. The
43
content is extracted using the `contentSelector` attribute as a CSS
44
selector. If `contentSelector` is `null`, the entire response will be
47
The return value is an object containing two properties:
49
* `node`: A `Y.Node` instance for a document fragment containing the
50
extracted HTML content.
52
* `title`: The title of the HTML page, if any, extracted using the
53
`titleSelector` attribute (which defaults to looking for a `<title>`
54
element). If `titleSelector` is not set or if a title could not be
55
found, this property will be `undefined`.
58
@param {String} responseText Raw Ajax response text.
59
@return {Object} Content object with the properties described above.
62
getContent: function (responseText) {
64
contentSelector = this.get('contentSelector'),
65
frag = Y.Node.create(responseText || ''),
66
titleSelector = this.get('titleSelector'),
69
if (contentSelector && frag) {
70
content.node = frag.all(contentSelector).toFrag();
75
if (titleSelector && frag) {
76
titleNode = frag.one(titleSelector);
79
content.title = titleNode.get('text');
87
Pjax route middleware to load content from a server. This makes an Ajax
88
request for the requested URL, parses the returned content and puts it on
89
the route's response object.
91
This is route middleware and not intended to be the final callback for a
92
route. This will add the following information to the route's request and
95
- `req.ioURL`: The full URL that was used to make the `Y.io()` XHR. This
96
may contain `"pjax=1"` if the `addPjaxParam` option is set.
98
- `res.content`: An object containing `node` and `title` properties for
99
the content extracted from the server's response. See `getContent()` for
102
- `res.ioResponse`: The full `Y.io()` response object. This is useful if
103
you need access to the XHR's response `status` or HTTP headers.
106
router.route('/foo/', 'loadContent', function (req, res, next) {
107
Y.one('container').setHTML(res.content.node);
108
Y.config.doc.title = res.content.title;
112
@param {Object} req Request object.
113
@param {Object} res Response Object.
114
@param {Function} next Function to pass control to the next route callback.
118
loadContent: function (req, res, next) {
121
// If there's an outstanding request, abort it.
123
this._request.abort();
126
// Add a 'pjax=1' query parameter if enabled.
127
if (this.get('addPjaxParam')) {
128
// Captures the path with query, and hash parts of the URL. Then
129
// properly injects the "pjax=1" query param in the right place,
130
// before any hash fragment, and returns the updated URL.
131
url = url.replace(/([^#]*)(#.*)?$/, function (match, path, hash) {
132
path += (path.indexOf('?') > -1 ? '&' : '?') + 'pjax=1';
133
return path + (hash || '');
138
this._request = Y.io(url, {
150
headers: {'X-PJAX': 'true'},
151
timeout: this.get('timeout'),
154
complete: this._onPjaxIOComplete,
155
end : this._onPjaxIOEnd
160
// -- Event Handlers -------------------------------------------------------
163
Handles IO complete events.
165
This parses the content from the `Y.io()` response and puts it on the
166
route's response object.
168
@method _onPjaxIOComplete
169
@param {String} id The `Y.io` transaction id.
170
@param {Object} ioResponse The `Y.io` response object.
171
@param {Object} details Extra details carried through from `loadContent()`.
175
_onPjaxIOComplete: function (id, ioResponse, details) {
176
var content = this.getContent(ioResponse.responseText),
177
route = details.route,
181
// Put the URL requested through `Y.io` on the route's `req` object.
182
req.ioURL = details.url;
184
// Put the parsed content and `Y.io` response object on the route's
186
res.content = content;
187
res.ioResponse = ioResponse;
193
Handles IO end events.
196
@param {String} id The `Y.io` transaction id.
197
@param {Object} details Extra details carried through from `loadContent()`.
201
_onPjaxIOEnd: function () {
202
this._request = null;
206
PjaxContent.ATTRS = {
208
If `true`, a "pjax=1" query parameter will be appended to all URLs
211
Browsers ignore HTTP request headers when caching content, so if the
212
same URL is used to request a partial Pjax page and a full page, the
213
browser will cache them under the same key and may later load the
214
cached partial page when the user actually requests a full page (or vice
217
To prevent this, we can add a bogus query parameter to the URL so that
218
Pjax URLs will always be cached separately from non-Pjax URLs.
220
@attribute addPjaxParam
230
CSS selector used to extract a specific portion of the content of a page
233
For example, if you wanted to load the page `example.html` but only use
234
the content within an element with the id "pjax-content", you'd set
235
`contentSelector` to "#pjax-content".
237
If not set, the entire page will be used.
239
@attribute contentSelector
249
CSS selector used to extract a page title from the content of a page
252
By default this is set to extract the title from the `<title>` element,
253
but you could customize it to extract the title from an `<h1>`, or from
254
any other element, if that's more appropriate for the content you're
257
@attribute titleSelector
267
Time in milliseconds after which an Ajax request should time out.
279
Y.PjaxContent = PjaxContent;
282
}, '3.9.1', {"requires": ["io-base", "node-base", "router"]});