最新服务器上的版本,以后用这个
wangzhenxin
2023-11-19 bc164b8bdbfbdf1d8229a5ced6b08d7cb8db7361
commit | author | age
2207d6 1 # pjax = pushState + ajax, Yii 2.0 fork with enhancements
W 2
3 pjax is a jQuery plugin that uses ajax and pushState to deliver a fast browsing experience with real permalinks, page titles, and a working back button.
4
5 pjax works by fetching HTML from your server via ajax and replacing the content
6 of a container element on your page with the loaded HTML. It then updates the
7 current URL in the browser using pushState. This results in faster page
8 navigation for two reasons:
9
10 * No page resources (JS, CSS) get re-executed or re-applied;
11 * If the server is configured for pjax, it can render only partial page
12   contents and thus avoid the potentially costly full layout render.
13
14 ### Status of this project
15
16 jquery-pjax is **largely unmaintained** at this point. It might continue to
17 receive important bug fixes, but _its feature set is frozen_ and it's unlikely
18 that it will get new features or enhancements.
19
20 ## Installation
21
22 pjax depends on jQuery 1.8 or higher.
23
24 ### Yii 2.0
25
26 There's no need to install library manually since it comes pre-installed with Yii 2.0.
27
28 ### bower
29
30 ```
31 $ bower install yii2-pjax
32 ```
33
34 ### standalone script
35
36 Or, add `yii2-pjax` to your app's `bower.json`.
37
38 ``` json
39   "dependencies": {
40     "yii2-pjax": "latest"
41   }
42 ```
43
44 ### standalone
45
46 pjax can be downloaded directly into your app's public directory - just be sure you've loaded jQuery first.
47 Download and include `jquery.pjax.js` in your web page:
48
49 ```
50 curl -LO https://raw.github.com/yiisoft/jquery-pjax/master/jquery.pjax.js
51 ```
52
53 ## Usage
54
55 ### `$.fn.pjax`
56
57 The simplest and most common use of pjax looks like this:
58
59 ``` javascript
60 $(document).pjax('a', '#pjax-container')
61 ```
62
63 This will enable pjax on all links on the page and designate the container as `#pjax-container`.
64
65 If you are migrating an existing site, you probably don't want to enable pjax
66 everywhere just yet. Instead of using a global selector like `a`, try annotating
67 pjaxable links with `data-pjax`, then use `'a[data-pjax]'` as your selector. Or,
68 try this selector that matches any `<a data-pjax href=>` links inside a `<div
69 data-pjax>` container:
70
71 ``` javascript
72 $(document).pjax('[data-pjax] a, a[data-pjax]', '#pjax-container')
73 ```
74
75 #### Server-side configuration
76
77 Ideally, your server should detect pjax requests by looking at the special
78 `X-PJAX` HTTP header, and render only the HTML meant to replace the contents of
79 the container element (`#pjax-container` in our example) without the rest of
80 the page layout. Here is an example of how this might be done in Ruby on Rails:
81
82 ``` ruby
83 def index
84   if request.headers['X-PJAX']
85     render :layout => false
86   end
87 end
88 ```
89
90 If you'd like a more automatic solution than pjax for Rails check out [Turbolinks][].
91
92 [Check if there is a pjax plugin][plugins] for your favorite server framework.
93
94 Also check out [RailsCasts #294: Playing with PJAX][railscasts].
95
96 #### Arguments
97
98 The synopsis for the `$.fn.pjax` function is:
99
100 ``` javascript
101 $(document).pjax(selector, [container], options)
102 ```
103
104 1. `selector` is a string to be used for click [event delegation][$.fn.on].
105 2. `container` is a string selector that uniquely identifies the pjax container.
106 3. `options` is an object with keys described below.
107
108 ##### pjax options
109
110 key | default | description
111 ----|---------|------------
112 `timeout` | 650 | ajax timeout in milliseconds after which a full refresh is forced
113 `push` | true | use [pushState][] to add a browser history entry upon navigation
114 `replace` | false | replace URL without adding browser history entry
115 `maxCacheLength` | 20 | maximum cache size for previous container contents
116 `version` | | a string or function returning the current pjax version
117 `scrollTo` | 0 | vertical position to scroll to after navigation. To avoid changing scroll position, pass `false`. If set to `true` page will scroll to the pjax container. Can also be be a callback function with context and current hash passed in as parameters. E.g. `function (context, hash) { if (!hash) return $(context).offset().top; }`
118 `scrollOffset` | 0 | vertical offset that gets added to `scrollTo`. Can be a callback function with the current `scrollTo` value passed as a parameter.
119 `type` | `"GET"` | see [$.ajax][]
120 `dataType` | `"html"` | see [$.ajax][]
121 `container` | | CSS selector for the element where content should be replaced
122 `url` | link.href | a string or function that returns the URL for the ajax request
123 `target` | link | eventually the `relatedTarget` value for [pjax events](#events)
124 `fragment` | | CSS selector for the fragment to extract from ajax response
125 `pushRedirect` | false | whether to add a browser history entry upon redirect
126 `replaceRedirect` | true | whether to replace URL without adding a browser history entry upon redirect
127 `skipOuterContainers` | false | When pjax containers are nested and this option is true, the closest pjax block will handle the event. Otherwise, the top container will handle the event
128 `ieRedirectCompatibility` | true | Whether to add `X-Ie-Redirect-Compatibility` header for the request on IE. Fixes IE error on 302 redirect without `Location` header
129
130 You can change the defaults globally by writing to the `$.pjax.defaults` object:
131
132 ``` javascript
133 $.pjax.defaults.timeout = 1200
134 ```
135
136 ### `$.pjax.click`
137
138 This is a lower level function used by `$.fn.pjax` itself. It allows you to get a little more control over the pjax event handling.
139
140 This example uses the current click context to set an ancestor element as the container:
141
142 ``` javascript
143 if ($.support.pjax) {
144   $(document).on('click', 'a[data-pjax]', function(event) {
145     var container = $(this).closest('[data-pjax-container]')
146     var containerSelector = '#' + container.id
147     $.pjax.click(event, {container: containerSelector})
148   })
149 }
150 ```
151
152 **NOTE** Use the explicit `$.support.pjax` guard. We aren't using `$.fn.pjax` so we should avoid binding this event handler unless the browser is actually going to use pjax.
153
154 ### `$.pjax.submit`
155
156 Submits a form via pjax.
157
158 ``` javascript
159 $(document).on('submit', 'form[data-pjax]', function(event) {
160   $.pjax.submit(event, '#pjax-container')
161 })
162 ```
163
164 ### `$.pjax.reload`
165
166 Initiates a request for the current URL to the server using pjax mechanism and replaces the container with the response. Does not add a browser history entry.
167
168 ``` javascript
169 $.pjax.reload('#pjax-container', options)
170 ```
171
172 ### `$.pjax`
173
174 Manual pjax invocation. Used mainly when you want to start a pjax request in a handler that didn't originate from a click. If you can get access to a click `event`, consider `$.pjax.click(event)` instead.
175
176 ``` javascript
177 function applyFilters() {
178   var url = urlForFilters()
179   $.pjax({url: url, container: '#pjax-container'})
180 }
181 ```
182
183 ## Events
184
185 All pjax events except `pjax:click` & `pjax:clicked` are fired from the pjax
186 container element.
187
188 <table>
189 <tr>
190   <th>event</th>
191   <th>cancel</th>
192   <th>arguments</th>
193   <th>notes</th>
194 </tr>
195 <tr>
196   <th colspan=4>event lifecycle upon following a pjaxed link</th>
197 </tr>
198 <tr>
199   <td><code>pjax:click</code></td>
200   <td>✔︎</td>
201   <td><code>options</code></td>
202   <td>fires from a link that got activated; cancel to prevent pjax</td>
203 </tr>
204 <tr>
205   <td><code>pjax:beforeSend</code></td>
206   <td>✔︎</td>
207   <td><code>xhr, options</code></td>
208   <td>can set XHR headers</td>
209 </tr>
210 <tr>
211   <td><code>pjax:start</code></td>
212   <td></td>
213   <td><code>xhr, options</code></td>
214   <td></td>
215 </tr>
216 <tr>
217   <td><code>pjax:send</code></td>
218   <td></td>
219   <td><code>xhr, options</code></td>
220   <td></td>
221 </tr>
222 <tr>
223   <td><code>pjax:clicked</code></td>
224   <td></td>
225   <td><code>options</code></td>
226   <td>fires after pjax has started from a link that got clicked</td>
227 </tr>
228 <tr>
229   <td><code>pjax:beforeReplace</code></td>
230   <td></td>
231   <td><code>contents, options</code></td>
232   <td>before replacing HTML with content loaded from the server</td>
233 </tr>
234 <tr>
235   <td><code>pjax:success</code></td>
236   <td></td>
237   <td><code>data, status, xhr, options</code></td>
238   <td>after replacing HTML content loaded from the server</td>
239 </tr>
240 <tr>
241   <td><code>pjax:timeout</code></td>
242   <td>✔︎</td>
243   <td><code>xhr, options</code></td>
244   <td>fires after <code>options.timeout</code>; will hard refresh unless canceled</td>
245 </tr>
246 <tr>
247   <td><code>pjax:error</code></td>
248   <td>✔︎</td>
249   <td><code>xhr, textStatus, error, options</code></td>
250   <td>on ajax error; will hard refresh unless canceled</td>
251 </tr>
252 <tr>
253   <td><code>pjax:complete</code></td>
254   <td></td>
255   <td><code>xhr, textStatus, options</code></td>
256   <td>always fires after ajax, regardless of result</td>
257 </tr>
258 <tr>
259   <td><code>pjax:end</code></td>
260   <td></td>
261   <td><code>xhr, options</code></td>
262   <td></td>
263 </tr>
264 <tr>
265   <th colspan=4>event lifecycle on browser Back/Forward navigation</th>
266 </tr>
267 <tr>
268   <td><code>pjax:popstate</code></td>
269   <td></td>
270   <td></td>
271   <td>event <code>direction</code> property: &quot;back&quot;/&quot;forward&quot;</td>
272 </tr>
273 <tr>
274   <td><code>pjax:start</code></td>
275   <td></td>
276   <td><code>null, options</code></td>
277   <td>before replacing content</td>
278 </tr>
279 <tr>
280   <td><code>pjax:beforeReplace</code></td>
281   <td></td>
282   <td><code>contents, options</code></td>
283   <td>right before replacing HTML with content from cache</td>
284 </tr>
285 <tr>
286   <td><code>pjax:end</code></td>
287   <td></td>
288   <td><code>null, options</code></td>
289   <td>after replacing content</td>
290 </tr>
291 </table>
292
293 `pjax:send` & `pjax:complete` are a good pair of events to use if you are implementing a
294 loading indicator. They'll only be triggered if an actual XHR request is made,
295 not if the content is loaded from cache:
296
297 ``` javascript
298 $(document).on('pjax:send', function() {
299   $('#loading').show()
300 })
301 $(document).on('pjax:complete', function() {
302   $('#loading').hide()
303 })
304 ```
305
306 An example of canceling a `pjax:timeout` event would be to disable the fallback
307 timeout behavior if a spinner is being shown:
308
309 ``` javascript
310 $(document).on('pjax:timeout', function(event) {
311   // Prevent default timeout redirection behavior
312   event.preventDefault()
313 })
314 ```
315
316 ## Advanced configuration
317
318 ### Reinitializing plugins/widget on new page content
319
320 The whole point of pjax is that it fetches and inserts new content _without_
321 refreshing the page. However, other jQuery plugins or libraries that are set to
322 react on page loaded event (such as `DOMContentLoaded`) will not pick up on
323 these changes. Therefore, it's usually a good idea to configure these plugins to
324 reinitialize in the scope of the updated page content. This can be done like so:
325
326 ``` js
327 $(document).on('ready pjax:end', function(event) {
328   $(event.target).initializeMyPlugin()
329 })
330 ```
331
332 This will make `$.fn.initializeMyPlugin()` be called at the document level on
333 normal page load, and on the container level after any pjax navigation (either
334 after clicking on a link or going Back in the browser).
335
336 ### Response types that force a reload
337
338 By default, pjax will force a full reload of the page if it receives one of the
339 following responses from the server:
340
341 * Page content that includes `<html>` when `fragment` selector wasn't explicitly
342   configured. Pjax presumes that the server's response hasn't been properly
343   configured for pjax. If `fragment` pjax option is given, pjax will extract the
344   content based on that selector.
345
346 * Page content that is blank. Pjax assumes that the server is unable to deliver
347   proper pjax contents.
348
349 * HTTP response code that is 4xx or 5xx, indicating some server error.
350
351 ### Affecting the browser URL
352
353 If the server needs to affect the URL which will appear in the browser URL after
354 pjax navigation (like HTTP redirects work for normal requests), it can set the
355 `X-PJAX-URL` header:
356
357 ``` ruby
358 def index
359   request.headers['X-PJAX-URL'] = "http://example.com/hello"
360 end
361 ```
362
363 ### Layout Reloading
364
365 Layouts can be forced to do a hard reload when assets or html changes.
366
367 First set the initial layout version in your header with a custom meta tag.
368
369 ``` html
370 <meta http-equiv="x-pjax-version" content="v123">
371 ```
372
373 Then from the server side, set the `X-PJAX-Version` header to the same.
374
375 ``` ruby
376 if request.headers['X-PJAX']
377   response.headers['X-PJAX-Version'] = "v123"
378 end
379 ```
380
381 Deploying a deploy, bumping the version constant to force clients to do a full reload the next request getting the new layout and assets.
382
383
384 [$.fn.on]: http://api.jquery.com/on/
385 [$.ajax]: http://api.jquery.com/jQuery.ajax/
386 [pushState]: https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history#Adding_and_modifying_history_entries
387 [plugins]: https://gist.github.com/4283721
388 [turbolinks]: https://github.com/rails/turbolinks
389 [railscasts]: http://railscasts.com/episodes/294-playing-with-pjax