Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
YUI.add('pjax-content', function (Y, NAME) {
2
 
3
/**
4
`Y.Router` extension that provides the content fetching and handling needed to
5
implement the standard pjax (HTMP5 pushState + Ajax) functionality.
6
 
7
@module pjax
8
@submodule pjax-content
9
@since 3.7.0
10
**/
11
 
12
/**
13
`Y.Router` extension that provides the content fetching and handling needed to
14
implement the standard pjax (HTMP5 pushState + Ajax) functionality.
15
 
16
This makes it easy to fetch server rendered content for URLs using Ajax. By
17
helping the router to fulfill the "request" for the content you can avoid full
18
page loads.
19
 
20
The `PjaxContent` class isn't useful on its own, but can be mixed into a
21
`Router`-based class along with the `PjaxBase` class to add Pjax functionality
22
to that Router. For a pre-made standalone Pjax router, see the `Pjax` class.
23
 
24
    var MyRouter = Y.Base.create('myRouter', Y.Router, [
25
        Y.PjaxBase,
26
        Y.PjaxContent
27
    ], {
28
        // ...
29
    });
30
 
31
@class PjaxContent
32
@extensionfor Router
33
@since 3.7.0
34
**/
35
function PjaxContent() {}
36
 
37
PjaxContent.prototype = {
38
    // -- Public Methods -------------------------------------------------------
39
 
40
    /**
41
    Extracts and returns the relevant HTML content from an Ajax response. The
42
    content is extracted using the `contentSelector` attribute as a CSS
43
    selector. If `contentSelector` is `null`, the entire response will be
44
    returned.
45
 
46
    The return value is an object containing two properties:
47
 
48
      * `node`: A `Y.Node` instance for a document fragment containing the
49
        extracted HTML content.
50
 
51
      * `title`: The title of the HTML page, if any, extracted using the
52
        `titleSelector` attribute (which defaults to looking for a `<title>`
53
        element). If `titleSelector` is not set or if a title could not be
54
        found, this property will be `undefined`.
55
 
56
    @method getContent
57
    @param {String} responseText Raw Ajax response text.
58
    @return {Object} Content object with the properties described above.
59
    @since 3.5.0
60
    **/
61
    getContent: function (responseText) {
62
        var content         = {},
63
            contentSelector = this.get('contentSelector'),
64
            frag            = Y.Node.create(responseText || ''),
65
            titleSelector   = this.get('titleSelector'),
66
            titleNode;
67
 
68
        if (contentSelector && frag) {
69
            content.node = frag.all(contentSelector).toFrag();
70
        } else {
71
            content.node = frag;
72
        }
73
 
74
        if (titleSelector && frag) {
75
            titleNode = frag.one(titleSelector);
76
 
77
            if (titleNode) {
78
                content.title = titleNode.get('text');
79
            }
80
        }
81
 
82
        return content;
83
    },
84
 
85
    /**
86
    Pjax route middleware to load content from a server. This makes an Ajax
87
    request for the requested URL, parses the returned content and puts it on
88
    the route's response object.
89
 
90
    This is route middleware and not intended to be the final callback for a
91
    route. This will add the following information to the route's request and
92
    response objects:
93
 
94
      - `req.ioURL`: The full URL that was used to make the `Y.io()` XHR. This
95
        may contain `"pjax=1"` if the `addPjaxParam` option is set.
96
 
97
      - `res.content`: An object containing `node` and `title` properties for
98
        the content extracted from the server's response. See `getContent()` for
99
        more details.
100
 
101
      - `res.ioResponse`: The full `Y.io()` response object. This is useful if
102
        you need access to the XHR's response `status` or HTTP headers.
103
 
104
    @example
105
        router.route('/foo/', 'loadContent', function (req, res, next) {
106
            Y.one('container').setHTML(res.content.node);
107
            Y.config.doc.title = res.content.title;
108
        });
109
 
110
    @method loadContent
111
    @param {Object} req Request object.
112
    @param {Object} res Response Object.
113
    @param {Function} next Function to pass control to the next route callback.
114
    @since 3.7.0
115
    @see Router.route()
116
    **/
117
    loadContent: function (req, res, next) {
118
        var url = req.url;
119
 
120
        // If there's an outstanding request, abort it.
121
        if (this._request) {
122
            this._request.abort();
123
        }
124
 
125
        // Add a 'pjax=1' query parameter if enabled.
126
        if (this.get('addPjaxParam')) {
127
            // Captures the path with query, and hash parts of the URL. Then
128
            // properly injects the "pjax=1" query param in the right place,
129
            // before any hash fragment, and returns the updated URL.
130
            url = url.replace(/([^#]*)(#.*)?$/, function (match, path, hash) {
131
                path += (path.indexOf('?') > -1 ? '&' : '?') + 'pjax=1';
132
                return path + (hash || '');
133
            });
134
        }
135
 
136
        // Send a request.
137
        this._request = Y.io(url, {
138
            'arguments': {
139
                route: {
140
                    req : req,
141
                    res : res,
142
                    next: next
143
                },
144
 
145
                url: url
146
            },
147
 
148
            context: this,
149
            headers: {'X-PJAX': 'true'},
150
            timeout: this.get('timeout'),
151
 
152
            on: {
153
                complete: this._onPjaxIOComplete,
154
                end     : this._onPjaxIOEnd
155
            }
156
        });
157
    },
158
 
159
    // -- Event Handlers -------------------------------------------------------
160
 
161
    /**
162
    Handles IO complete events.
163
 
164
    This parses the content from the `Y.io()` response and puts it on the
165
    route's response object.
166
 
167
    @method _onPjaxIOComplete
168
    @param {String} id The `Y.io` transaction id.
169
    @param {Object} ioResponse The `Y.io` response object.
170
    @param {Object} details Extra details carried through from `loadContent()`.
171
    @protected
172
    @since 3.7.0
173
    **/
174
    _onPjaxIOComplete: function (id, ioResponse, details) {
175
        var content = this.getContent(ioResponse.responseText),
176
            route   = details.route,
177
            req     = route.req,
178
            res     = route.res;
179
 
180
        // Put the URL requested through `Y.io` on the route's `req` object.
181
        req.ioURL = details.url;
182
 
183
        // Put the parsed content and `Y.io` response object on the route's
184
        // `res` object.
185
        res.content    = content;
186
        res.ioResponse = ioResponse;
187
 
188
        route.next();
189
    },
190
 
191
    /**
192
    Handles IO end events.
193
 
194
    @method _onPjaxIOEnd
195
    @param {String} id The `Y.io` transaction id.
196
    @param {Object} details Extra details carried through from `loadContent()`.
197
    @protected
198
    @since 3.5.0
199
    **/
200
    _onPjaxIOEnd: function () {
201
        this._request = null;
202
    }
203
};
204
 
205
PjaxContent.ATTRS = {
206
    /**
207
    If `true`, a "pjax=1" query parameter will be appended to all URLs
208
    requested via Pjax.
209
 
210
    Browsers ignore HTTP request headers when caching content, so if the
211
    same URL is used to request a partial Pjax page and a full page, the
212
    browser will cache them under the same key and may later load the
213
    cached partial page when the user actually requests a full page (or vice
214
    versa).
215
 
216
    To prevent this, we can add a bogus query parameter to the URL so that
217
    Pjax URLs will always be cached separately from non-Pjax URLs.
218
 
219
    @attribute addPjaxParam
220
    @type Boolean
221
    @default true
222
    @since 3.5.0
223
    **/
224
    addPjaxParam: {
225
        value: true
226
    },
227
 
228
    /**
229
    CSS selector used to extract a specific portion of the content of a page
230
    loaded via Pjax.
231
 
232
    For example, if you wanted to load the page `example.html` but only use
233
    the content within an element with the id "pjax-content", you'd set
234
    `contentSelector` to "#pjax-content".
235
 
236
    If not set, the entire page will be used.
237
 
238
    @attribute contentSelector
239
    @type String
240
    @default null
241
    @since 3.5.0
242
    **/
243
    contentSelector: {
244
        value: null
245
    },
246
 
247
    /**
248
    CSS selector used to extract a page title from the content of a page
249
    loaded via Pjax.
250
 
251
    By default this is set to extract the title from the `<title>` element,
252
    but you could customize it to extract the title from an `<h1>`, or from
253
    any other element, if that's more appropriate for the content you're
254
    loading.
255
 
256
    @attribute titleSelector
257
    @type String
258
    @default "title"
259
    @since 3.5.0
260
    **/
261
    titleSelector: {
262
        value: 'title'
263
    },
264
 
265
    /**
266
    Time in milliseconds after which an Ajax request should time out.
267
 
268
    @attribute timeout
269
    @type Number
270
    @default 30000
271
    @since 3.5.0
272
    **/
273
    timeout: {
274
        value: 30000
275
    }
276
};
277
 
278
Y.PjaxContent = PjaxContent;
279
 
280
 
281
}, '3.18.1', {"requires": ["io-base", "node-base", "router"]});