2 YUI 3.13.0 (build 508226d)
3 Copyright 2013 Yahoo! Inc. All rights reserved.
4 Licensed under the BSD License.
5 http://yuilibrary.com/license/
8 YUI.add('pjax-content', function (Y, NAME) {
11 `Y.Router` extension that provides the content fetching and handling needed to
12 implement the standard pjax (HTMP5 pushState + Ajax) functionality.
15 @submodule pjax-content
20 `Y.Router` extension that provides the content fetching and handling needed to
21 implement the standard pjax (HTMP5 pushState + Ajax) functionality.
23 This makes it easy to fetch server rendered content for URLs using Ajax. By
24 helping the router to fulfill the "request" for the content you can avoid full
27 The `PjaxContent` class isn't useful on its own, but can be mixed into a
28 `Router`-based class along with the `PjaxBase` class to add Pjax functionality
29 to that Router. For a pre-made standalone Pjax router, see the `Pjax` class.
31 var MyRouter = Y.Base.create('myRouter', Y.Router, [
42 function PjaxContent() {}
44 PjaxContent.prototype = {
45 // -- Public Methods -------------------------------------------------------
48 Extracts and returns the relevant HTML content from an Ajax response. The
49 content is extracted using the `contentSelector` attribute as a CSS
50 selector. If `contentSelector` is `null`, the entire response will be
53 The return value is an object containing two properties:
55 * `node`: A `Y.Node` instance for a document fragment containing the
56 extracted HTML content.
58 * `title`: The title of the HTML page, if any, extracted using the
59 `titleSelector` attribute (which defaults to looking for a `<title>`
60 element). If `titleSelector` is not set or if a title could not be
61 found, this property will be `undefined`.
64 @param {String} responseText Raw Ajax response text.
65 @return {Object} Content object with the properties described above.
68 getContent: function (responseText) {
70 contentSelector = this.get('contentSelector'),
71 frag = Y.Node.create(responseText || ''),
72 titleSelector = this.get('titleSelector'),
75 if (contentSelector && frag) {
76 content.node = frag.all(contentSelector).toFrag();
81 if (titleSelector && frag) {
82 titleNode = frag.one(titleSelector);
85 content.title = titleNode.get('text');
93 Pjax route middleware to load content from a server. This makes an Ajax
94 request for the requested URL, parses the returned content and puts it on
95 the route's response object.
97 This is route middleware and not intended to be the final callback for a
98 route. This will add the following information to the route's request and
101 - `req.ioURL`: The full URL that was used to make the `Y.io()` XHR. This
102 may contain `"pjax=1"` if the `addPjaxParam` option is set.
104 - `res.content`: An object containing `node` and `title` properties for
105 the content extracted from the server's response. See `getContent()` for
108 - `res.ioResponse`: The full `Y.io()` response object. This is useful if
109 you need access to the XHR's response `status` or HTTP headers.
112 router.route('/foo/', 'loadContent', function (req, res, next) {
113 Y.one('container').setHTML(res.content.node);
114 Y.config.doc.title = res.content.title;
118 @param {Object} req Request object.
119 @param {Object} res Response Object.
120 @param {Function} next Function to pass control to the next route callback.
124 loadContent: function (req, res, next) {
127 // If there's an outstanding request, abort it.
129 this._request.abort();
132 // Add a 'pjax=1' query parameter if enabled.
133 if (this.get('addPjaxParam')) {
134 // Captures the path with query, and hash parts of the URL. Then
135 // properly injects the "pjax=1" query param in the right place,
136 // before any hash fragment, and returns the updated URL.
137 url = url.replace(/([^#]*)(#.*)?$/, function (match, path, hash) {
138 path += (path.indexOf('?') > -1 ? '&' : '?') + 'pjax=1';
139 return path + (hash || '');
144 this._request = Y.io(url, {
156 headers: {'X-PJAX': 'true'},
157 timeout: this.get('timeout'),
160 complete: this._onPjaxIOComplete,
161 end : this._onPjaxIOEnd
166 // -- Event Handlers -------------------------------------------------------
169 Handles IO complete events.
171 This parses the content from the `Y.io()` response and puts it on the
172 route's response object.
174 @method _onPjaxIOComplete
175 @param {String} id The `Y.io` transaction id.
176 @param {Object} ioResponse The `Y.io` response object.
177 @param {Object} details Extra details carried through from `loadContent()`.
181 _onPjaxIOComplete: function (id, ioResponse, details) {
182 var content = this.getContent(ioResponse.responseText),
183 route = details.route,
187 // Put the URL requested through `Y.io` on the route's `req` object.
188 req.ioURL = details.url;
190 // Put the parsed content and `Y.io` response object on the route's
192 res.content = content;
193 res.ioResponse = ioResponse;
199 Handles IO end events.
202 @param {String} id The `Y.io` transaction id.
203 @param {Object} details Extra details carried through from `loadContent()`.
207 _onPjaxIOEnd: function () {
208 this._request = null;
212 PjaxContent.ATTRS = {
214 If `true`, a "pjax=1" query parameter will be appended to all URLs
217 Browsers ignore HTTP request headers when caching content, so if the
218 same URL is used to request a partial Pjax page and a full page, the
219 browser will cache them under the same key and may later load the
220 cached partial page when the user actually requests a full page (or vice
223 To prevent this, we can add a bogus query parameter to the URL so that
224 Pjax URLs will always be cached separately from non-Pjax URLs.
226 @attribute addPjaxParam
236 CSS selector used to extract a specific portion of the content of a page
239 For example, if you wanted to load the page `example.html` but only use
240 the content within an element with the id "pjax-content", you'd set
241 `contentSelector` to "#pjax-content".
243 If not set, the entire page will be used.
245 @attribute contentSelector
255 CSS selector used to extract a page title from the content of a page
258 By default this is set to extract the title from the `<title>` element,
259 but you could customize it to extract the title from an `<h1>`, or from
260 any other element, if that's more appropriate for the content you're
263 @attribute titleSelector
273 Time in milliseconds after which an Ajax request should time out.
285 Y.PjaxContent = PjaxContent;
288 }, '3.13.0', {"requires": ["io-base", "node-base", "router"]});