NOBUG: Fixed file access permissions
[moodle.git] / lib / yuilib / 3.13.0 / pjax-content / pjax-content-debug.js
blob57552731c50ef8b0c12af6c009ad69c2b2695a8d
1 /*
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/
6 */
8 YUI.add('pjax-content', function (Y, NAME) {
10 /**
11 `Y.Router` extension that provides the content fetching and handling needed to
12 implement the standard pjax (HTMP5 pushState + Ajax) functionality.
14 @module pjax
15 @submodule pjax-content
16 @since 3.7.0
17 **/
19 /**
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
25 page loads.
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, [
32         Y.PjaxBase,
33         Y.PjaxContent
34     ], {
35         // ...
36     });
38 @class PjaxContent
39 @extensionfor Router
40 @since 3.7.0
41 **/
42 function PjaxContent() {}
44 PjaxContent.prototype = {
45     // -- Public Methods -------------------------------------------------------
47     /**
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
51     returned.
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`.
63     @method getContent
64     @param {String} responseText Raw Ajax response text.
65     @return {Object} Content object with the properties described above.
66     @since 3.5.0
67     **/
68     getContent: function (responseText) {
69         var content         = {},
70             contentSelector = this.get('contentSelector'),
71             frag            = Y.Node.create(responseText || ''),
72             titleSelector   = this.get('titleSelector'),
73             titleNode;
75         if (contentSelector && frag) {
76             content.node = frag.all(contentSelector).toFrag();
77         } else {
78             content.node = frag;
79         }
81         if (titleSelector && frag) {
82             titleNode = frag.one(titleSelector);
84             if (titleNode) {
85                 content.title = titleNode.get('text');
86             }
87         }
89         return content;
90     },
92     /**
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
99     response objects:
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
106         more details.
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.
111     @example
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;
115         });
117     @method loadContent
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.
121     @since 3.7.0
122     @see Router.route()
123     **/
124     loadContent: function (req, res, next) {
125         var url = req.url;
127         // If there's an outstanding request, abort it.
128         if (this._request) {
129             this._request.abort();
130         }
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 || '');
140             });
141         }
143         // Send a request.
144         this._request = Y.io(url, {
145             'arguments': {
146                 route: {
147                     req : req,
148                     res : res,
149                     next: next
150                 },
152                 url: url
153             },
155             context: this,
156             headers: {'X-PJAX': 'true'},
157             timeout: this.get('timeout'),
159             on: {
160                 complete: this._onPjaxIOComplete,
161                 end     : this._onPjaxIOEnd
162             }
163         });
164     },
166     // -- Event Handlers -------------------------------------------------------
168     /**
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()`.
178     @protected
179     @since 3.7.0
180     **/
181     _onPjaxIOComplete: function (id, ioResponse, details) {
182         var content = this.getContent(ioResponse.responseText),
183             route   = details.route,
184             req     = route.req,
185             res     = route.res;
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
191         // `res` object.
192         res.content    = content;
193         res.ioResponse = ioResponse;
195         route.next();
196     },
198     /**
199     Handles IO end events.
201     @method _onPjaxIOEnd
202     @param {String} id The `Y.io` transaction id.
203     @param {Object} details Extra details carried through from `loadContent()`.
204     @protected
205     @since 3.5.0
206     **/
207     _onPjaxIOEnd: function () {
208         this._request = null;
209     }
212 PjaxContent.ATTRS = {
213     /**
214     If `true`, a "pjax=1" query parameter will be appended to all URLs
215     requested via Pjax.
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
221     versa).
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
227     @type Boolean
228     @default true
229     @since 3.5.0
230     **/
231     addPjaxParam: {
232         value: true
233     },
235     /**
236     CSS selector used to extract a specific portion of the content of a page
237     loaded via Pjax.
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
246     @type String
247     @default null
248     @since 3.5.0
249     **/
250     contentSelector: {
251         value: null
252     },
254     /**
255     CSS selector used to extract a page title from the content of a page
256     loaded via Pjax.
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
261     loading.
263     @attribute titleSelector
264     @type String
265     @default "title"
266     @since 3.5.0
267     **/
268     titleSelector: {
269         value: 'title'
270     },
272     /**
273     Time in milliseconds after which an Ajax request should time out.
275     @attribute timeout
276     @type Number
277     @default 30000
278     @since 3.5.0
279     **/
280     timeout: {
281         value: 30000
282     }
285 Y.PjaxContent = PjaxContent;
288 }, '3.13.0', {"requires": ["io-base", "node-base", "router"]});