[Notice] Announcing the End of Demo Server [Read me]
js: Upgrade jQuery to v3.3.1
Higher jQuery version is a prerequite of some front-end libraries. It is also related with Play upgrade. - Current: v1.9.0 - New: v3.3.1
@238481addf30cc721fd91be27ab06e41a0a353bc
--- minify-js.sh
+++ minify-js.sh
... | ... | @@ -1,15 +1,16 @@ |
1 |
+################# |
|
1 | 2 |
# yona-layout.js |
3 |
+################# |
|
2 | 4 |
|
3 | 5 |
CLOSURE_COMPILER="public/compiler.jar" |
4 | 6 |
OUT_DIR="public/javascripts" |
5 | 7 |
PUBLIC="public" |
6 | 8 |
PUBLIC_JAVASCRIPTS="public/javascripts" |
7 | 9 |
|
8 |
-java -jar $CLOSURE_COMPILER --js $PUBLIC_JAVASCRIPTS/lib/nprogress/nprogress.js $PUBLIC_JAVASCRIPTS/lib/jquery/jquery-1.9.0.js $PUBLIC_JAVASCRIPTS/lib/jquery/jquery.browser.js $PUBLIC_JAVASCRIPTS/lib/jquery/jquery.pjax.js $PUBLIC_JAVASCRIPTS/common/yobi.Common.js --js_output_file $OUT_DIR/yona-layout.js |
|
10 |
+java -jar $CLOSURE_COMPILER --js $PUBLIC_JAVASCRIPTS/lib/nprogress/nprogress.js $PUBLIC_JAVASCRIPTS/lib/jquery/jquery-3.3.1.js $PUBLIC_JAVASCRIPTS/lib/jquery/jquery.browser.js $PUBLIC_JAVASCRIPTS/lib/jquery/jquery.pjax.js $PUBLIC_JAVASCRIPTS/common/yobi.Common.js --js_output_file $OUT_DIR/yona-layout.js |
|
9 | 11 |
|
10 | 12 |
# for dev |
11 |
-# cat $PUBLIC_JAVASCRIPTS/lib/nprogress/nprogress.js $PUBLIC_JAVASCRIPTS/lib/jquery/jquery-1.9.0.js $PUBLIC_JAVASCRIPTS/lib/jquery/jquery.browser.js $PUBLIC_JAVASCRIPTS/lib/jquery/jquery.pjax.js $PUBLIC_JAVASCRIPTS/common/yobi.Common.js > $OUT_DIR/yona-layout.js |
|
12 |
- |
|
13 |
+#cat $PUBLIC_JAVASCRIPTS/lib/nprogress/nprogress.js $PUBLIC_JAVASCRIPTS/lib/jquery/jquery-3.3.1.js $PUBLIC_JAVASCRIPTS/lib/jquery/jquery.browser.js $PUBLIC_JAVASCRIPTS/lib/jquery/jquery.pjax.js $PUBLIC_JAVASCRIPTS/common/yobi.Common.js > $OUT_DIR/yona-layout.js |
|
13 | 14 |
|
14 | 15 |
# yona-common.js |
15 | 16 |
java -jar $CLOSURE_COMPILER --js $PUBLIC_JAVASCRIPTS/lib/jquery/jquery.tmpl.js $PUBLIC_JAVASCRIPTS/lib/jquery/jquery.form.js $PUBLIC_JAVASCRIPTS/lib/jquery/jquery.validate.js $PUBLIC_JAVASCRIPTS/lib/jquery/jquery.requestAs.js $PUBLIC_JAVASCRIPTS/lib/jquery/jquery.search.js $PUBLIC_JAVASCRIPTS/lib/jquery/jquery.zclip.min.js $PUBLIC_JAVASCRIPTS/lib/jquery/jquery.placeholder.min.js $PUBLIC/bootstrap/js/bootstrap.js $PUBLIC_JAVASCRIPTS/lib/rgbcolor.js $PUBLIC_JAVASCRIPTS/lib/humanize.js $PUBLIC_JAVASCRIPTS/lib/validate.js $PUBLIC_JAVASCRIPTS/lib/xss.js $PUBLIC_JAVASCRIPTS/lib/clipboard.min.js --js_output_file $OUT_DIR/yona-common.js |
+++ public/javascripts/lib/jquery/jquery-3.3.1.js
This file is too big to display. |
--- public/javascripts/lib/jquery/jquery.pjax.js
+++ public/javascripts/lib/jquery/jquery.pjax.js
... | ... | @@ -1,6 +1,8 @@ |
1 |
-// jquery.pjax.js |
|
2 |
-// copyright chris wanstrath |
|
3 |
-// https://github.com/defunkt/jquery-pjax |
|
1 |
+/*! |
|
2 |
+ * Copyright 2012, Chris Wanstrath |
|
3 |
+ * Released under the MIT License |
|
4 |
+ * https://github.com/defunkt/jquery-pjax |
|
5 |
+ */ |
|
4 | 6 |
|
5 | 7 |
(function($){ |
6 | 8 |
|
... | ... | @@ -17,9 +19,7 @@ |
17 | 19 |
// pjax specific options: |
18 | 20 |
// |
19 | 21 |
// |
20 |
-// container - Where to stick the response body. Usually a String selector. |
|
21 |
-// $(container).html(xhr.responseBody) |
|
22 |
-// (default: current jquery context) |
|
22 |
+// container - String selector for the element where to place the response body. |
|
23 | 23 |
// push - Whether to pushState the URL. Defaults to true (of course). |
24 | 24 |
// replace - Want to use replaceState instead? That's cool. |
25 | 25 |
// |
... | ... | @@ -28,11 +28,13 @@ |
28 | 28 |
// |
29 | 29 |
// Returns the jQuery object |
30 | 30 |
function fnPjax(selector, container, options) { |
31 |
- var context = this |
|
31 |
+ options = optionsFor(container, options) |
|
32 | 32 |
return this.on('click.pjax', selector, function(event) { |
33 |
- var opts = $.extend({}, optionsFor(container, options)) |
|
34 |
- if (!opts.container) |
|
35 |
- opts.container = $(this).attr('data-pjax') || context |
|
33 |
+ var opts = options |
|
34 |
+ if (!opts.container) { |
|
35 |
+ opts = $.extend({}, options) |
|
36 |
+ opts.container = $(this).attr('data-pjax') |
|
37 |
+ } |
|
36 | 38 |
handleClick(event, opts) |
37 | 39 |
}) |
38 | 40 |
} |
... | ... | @@ -50,16 +52,12 @@ |
50 | 52 |
// // is the same as |
51 | 53 |
// $(document).pjax('a') |
52 | 54 |
// |
53 |
-// $(document).on('click', 'a', function(event) { |
|
54 |
-// var container = $(this).closest('[data-pjax-container]') |
|
55 |
-// $.pjax.click(event, container) |
|
56 |
-// }) |
|
57 |
-// |
|
58 | 55 |
// Returns nothing. |
59 | 56 |
function handleClick(event, container, options) { |
60 | 57 |
options = optionsFor(container, options) |
61 | 58 |
|
62 | 59 |
var link = event.currentTarget |
60 |
+ var $link = $(link) |
|
63 | 61 |
|
64 | 62 |
if (link.tagName.toUpperCase() !== 'A') |
65 | 63 |
throw "$.fn.pjax or $.pjax.click requires an anchor element" |
... | ... | @@ -73,28 +71,28 @@ |
73 | 71 |
if ( location.protocol !== link.protocol || location.hostname !== link.hostname ) |
74 | 72 |
return |
75 | 73 |
|
76 |
- // Ignore anchors on the same page |
|
77 |
- if (link.hash && link.href.replace(link.hash, '') === |
|
78 |
- location.href.replace(location.hash, '')) |
|
74 |
+ // Ignore case when a hash is being tacked on the current URL |
|
75 |
+ if ( link.href.indexOf('#') > -1 && stripHash(link) == stripHash(location) ) |
|
79 | 76 |
return |
80 | 77 |
|
81 |
- // Ignore empty anchor "foo.html#" |
|
82 |
- if (link.href === location.href + '#') |
|
78 |
+ // Ignore event with default prevented |
|
79 |
+ if (event.isDefaultPrevented()) |
|
83 | 80 |
return |
84 | 81 |
|
85 | 82 |
var defaults = { |
86 | 83 |
url: link.href, |
87 |
- container: $(link).attr('data-pjax'), |
|
84 |
+ container: $link.attr('data-pjax'), |
|
88 | 85 |
target: link |
89 | 86 |
} |
90 | 87 |
|
91 | 88 |
var opts = $.extend({}, defaults, options) |
92 | 89 |
var clickEvent = $.Event('pjax:click') |
93 |
- $(link).trigger(clickEvent, [opts]) |
|
90 |
+ $link.trigger(clickEvent, [opts]) |
|
94 | 91 |
|
95 | 92 |
if (!clickEvent.isDefaultPrevented()) { |
96 | 93 |
pjax(opts) |
97 | 94 |
event.preventDefault() |
95 |
+ $link.trigger('pjax:clicked', [opts]) |
|
98 | 96 |
} |
99 | 97 |
} |
100 | 98 |
|
... | ... | @@ -108,8 +106,7 @@ |
108 | 106 |
// Examples |
109 | 107 |
// |
110 | 108 |
// $(document).on('submit', 'form', function(event) { |
111 |
-// var container = $(this).closest('[data-pjax-container]') |
|
112 |
-// $.pjax.submit(event, container) |
|
109 |
+// $.pjax.submit(event, '[data-pjax-container]') |
|
113 | 110 |
// }) |
114 | 111 |
// |
115 | 112 |
// Returns nothing. |
... | ... | @@ -117,16 +114,30 @@ |
117 | 114 |
options = optionsFor(container, options) |
118 | 115 |
|
119 | 116 |
var form = event.currentTarget |
117 |
+ var $form = $(form) |
|
120 | 118 |
|
121 | 119 |
if (form.tagName.toUpperCase() !== 'FORM') |
122 | 120 |
throw "$.pjax.submit requires a form element" |
123 | 121 |
|
124 | 122 |
var defaults = { |
125 |
- type: form.method.toUpperCase(), |
|
126 |
- url: form.action, |
|
127 |
- data: $(form).serializeArray(), |
|
128 |
- container: $(form).attr('data-pjax'), |
|
123 |
+ type: ($form.attr('method') || 'GET').toUpperCase(), |
|
124 |
+ url: $form.attr('action'), |
|
125 |
+ container: $form.attr('data-pjax'), |
|
129 | 126 |
target: form |
127 |
+ } |
|
128 |
+ |
|
129 |
+ if (defaults.type !== 'GET' && window.FormData !== undefined) { |
|
130 |
+ defaults.data = new FormData(form) |
|
131 |
+ defaults.processData = false |
|
132 |
+ defaults.contentType = false |
|
133 |
+ } else { |
|
134 |
+ // Can't handle file uploads, exit |
|
135 |
+ if ($form.find(':file').length) { |
|
136 |
+ return |
|
137 |
+ } |
|
138 |
+ |
|
139 |
+ // Fallback to manually serializing the fields |
|
140 |
+ defaults.data = $form.serializeArray() |
|
130 | 141 |
} |
131 | 142 |
|
132 | 143 |
pjax($.extend({}, defaults, options)) |
... | ... | @@ -142,8 +153,7 @@ |
142 | 153 |
// |
143 | 154 |
// Accepts these extra keys: |
144 | 155 |
// |
145 |
-// container - Where to stick the response body. |
|
146 |
-// $(container).html(xhr.responseBody) |
|
156 |
+// container - String selector for where to stick the response body. |
|
147 | 157 |
// push - Whether to pushState the URL. Defaults to true (of course). |
148 | 158 |
// replace - Want to use replaceState instead? That's cool. |
149 | 159 |
// |
... | ... | @@ -160,21 +170,32 @@ |
160 | 170 |
options.url = options.url() |
161 | 171 |
} |
162 | 172 |
|
163 |
- var target = options.target |
|
164 |
- |
|
165 | 173 |
var hash = parseURL(options.url).hash |
166 | 174 |
|
167 |
- var context = options.context = findContainerFor(options.container) |
|
175 |
+ var containerType = $.type(options.container) |
|
176 |
+ if (containerType !== 'string') { |
|
177 |
+ throw "expected string value for 'container' option; got " + containerType |
|
178 |
+ } |
|
179 |
+ var context = options.context = $(options.container) |
|
180 |
+ if (!context.length) { |
|
181 |
+ throw "the container selector '" + options.container + "' did not match anything" |
|
182 |
+ } |
|
168 | 183 |
|
169 | 184 |
// We want the browser to maintain two separate internal caches: one |
170 | 185 |
// for pjax'd partial page loads and one for normal page loads. |
171 | 186 |
// Without adding this secret parameter, some browsers will often |
172 | 187 |
// confuse the two. |
173 | 188 |
if (!options.data) options.data = {} |
174 |
- options.data._pjax = context.selector |
|
189 |
+ if ($.isArray(options.data)) { |
|
190 |
+ options.data.push({name: '_pjax', value: options.container}) |
|
191 |
+ } else { |
|
192 |
+ options.data._pjax = options.container |
|
193 |
+ } |
|
175 | 194 |
|
176 |
- function fire(type, args) { |
|
177 |
- var event = $.Event(type, { relatedTarget: target }) |
|
195 |
+ function fire(type, args, props) { |
|
196 |
+ if (!props) props = {} |
|
197 |
+ props.relatedTarget = options.target |
|
198 |
+ var event = $.Event(type, props) |
|
178 | 199 |
context.trigger(event, args) |
179 | 200 |
return !event.isDefaultPrevented() |
180 | 201 |
} |
... | ... | @@ -189,7 +210,7 @@ |
189 | 210 |
} |
190 | 211 |
|
191 | 212 |
xhr.setRequestHeader('X-PJAX', 'true') |
192 |
- xhr.setRequestHeader('X-PJAX-Container', context.selector) |
|
213 |
+ xhr.setRequestHeader('X-PJAX-Container', options.container) |
|
193 | 214 |
|
194 | 215 |
if (!fire('pjax:beforeSend', [xhr, settings])) |
195 | 216 |
return false |
... | ... | @@ -204,7 +225,9 @@ |
204 | 225 |
settings.timeout = 0 |
205 | 226 |
} |
206 | 227 |
|
207 |
- options.requestUrl = parseURL(settings.url).href |
|
228 |
+ var url = parseURL(settings.url) |
|
229 |
+ if (hash) url.hash = hash |
|
230 |
+ options.requestUrl = stripInternalParams(url) |
|
208 | 231 |
} |
209 | 232 |
|
210 | 233 |
options.complete = function(xhr, textStatus) { |
... | ... | @@ -226,15 +249,23 @@ |
226 | 249 |
} |
227 | 250 |
|
228 | 251 |
options.success = function(data, status, xhr) { |
252 |
+ var previousState = pjax.state |
|
253 |
+ |
|
229 | 254 |
// If $.pjax.defaults.version is a function, invoke it first. |
230 | 255 |
// Otherwise it can be a static string. |
231 |
- var currentVersion = (typeof $.pjax.defaults.version === 'function') ? |
|
256 |
+ var currentVersion = typeof $.pjax.defaults.version === 'function' ? |
|
232 | 257 |
$.pjax.defaults.version() : |
233 | 258 |
$.pjax.defaults.version |
234 | 259 |
|
235 | 260 |
var latestVersion = xhr.getResponseHeader('X-PJAX-Version') |
236 | 261 |
|
237 | 262 |
var container = extractContainer(data, xhr, options) |
263 |
+ |
|
264 |
+ var url = parseURL(container.url) |
|
265 |
+ if (hash) { |
|
266 |
+ url.hash = hash |
|
267 |
+ container.url = url.href |
|
268 |
+ } |
|
238 | 269 |
|
239 | 270 |
// If there is a layout version mismatch, hard load the new url |
240 | 271 |
if (currentVersion && latestVersion && currentVersion !== latestVersion) { |
... | ... | @@ -252,7 +283,7 @@ |
252 | 283 |
id: options.id || uniqueId(), |
253 | 284 |
url: container.url, |
254 | 285 |
title: container.title, |
255 |
- container: context.selector, |
|
286 |
+ container: options.container, |
|
256 | 287 |
fragment: options.fragment, |
257 | 288 |
timeout: options.timeout |
258 | 289 |
} |
... | ... | @@ -261,10 +292,22 @@ |
261 | 292 |
window.history.replaceState(pjax.state, container.title, container.url) |
262 | 293 |
} |
263 | 294 |
|
295 |
+ // Only blur the focus if the focused element is within the container. |
|
296 |
+ var blurFocus = $.contains(context, document.activeElement) |
|
297 |
+ |
|
264 | 298 |
// Clear out any focused controls before inserting new page contents. |
265 |
- document.activeElement.blur() |
|
299 |
+ if (blurFocus) { |
|
300 |
+ try { |
|
301 |
+ document.activeElement.blur() |
|
302 |
+ } catch (e) { /* ignore */ } |
|
303 |
+ } |
|
266 | 304 |
|
267 | 305 |
if (container.title) document.title = container.title |
306 |
+ |
|
307 |
+ fire('pjax:beforeReplace', [container.contents, options], { |
|
308 |
+ state: pjax.state, |
|
309 |
+ previousState: previousState |
|
310 |
+ }) |
|
268 | 311 |
context.html(container.contents) |
269 | 312 |
|
270 | 313 |
// FF bug: Won't autofocus fields that are inserted via JS. |
... | ... | @@ -274,32 +317,21 @@ |
274 | 317 |
// http://www.w3.org/html/wg/drafts/html/master/forms.html |
275 | 318 |
var autofocusEl = context.find('input[autofocus], textarea[autofocus]').last()[0] |
276 | 319 |
if (autofocusEl && document.activeElement !== autofocusEl) { |
277 |
- autofocusEl.focus(); |
|
320 |
+ autofocusEl.focus() |
|
278 | 321 |
} |
279 | 322 |
|
280 | 323 |
executeScriptTags(container.scripts) |
281 | 324 |
|
282 |
- // Scroll to top by default |
|
283 |
- if (typeof options.scrollTo === 'number') |
|
284 |
- $(window).scrollTop(options.scrollTo) |
|
325 |
+ var scrollTo = options.scrollTo |
|
285 | 326 |
|
286 |
- // If the URL has a hash in it, make sure the browser |
|
287 |
- // knows to navigate to the hash. |
|
288 |
- if ( hash !== '' ) { |
|
289 |
- // Avoid using simple hash set here. Will add another history |
|
290 |
- // entry. Replace the url with replaceState and scroll to target |
|
291 |
- // by hand. |
|
292 |
- // |
|
293 |
- // window.location.hash = hash |
|
294 |
- var url = parseURL(container.url) |
|
295 |
- url.hash = hash |
|
296 |
- |
|
297 |
- pjax.state.url = url.href |
|
298 |
- window.history.replaceState(pjax.state, container.title, url.href) |
|
299 |
- |
|
300 |
- var target = $(url.hash) |
|
301 |
- if (target.length) $(window).scrollTop(target.offset().top) |
|
327 |
+ // Ensure browser scrolls to the element referenced by the URL anchor |
|
328 |
+ if (hash) { |
|
329 |
+ var name = decodeURIComponent(hash.slice(1)) |
|
330 |
+ var target = document.getElementById(name) || document.getElementsByName(name)[0] |
|
331 |
+ if (target) scrollTo = $(target).offset().top |
|
302 | 332 |
} |
333 |
+ |
|
334 |
+ if (typeof scrollTo == 'number') $(window).scrollTop(scrollTo) |
|
303 | 335 |
|
304 | 336 |
fire('pjax:success', [data, status, xhr, options]) |
305 | 337 |
} |
... | ... | @@ -314,7 +346,7 @@ |
314 | 346 |
id: uniqueId(), |
315 | 347 |
url: window.location.href, |
316 | 348 |
title: document.title, |
317 |
- container: context.selector, |
|
349 |
+ container: options.container, |
|
318 | 350 |
fragment: options.fragment, |
319 | 351 |
timeout: options.timeout |
320 | 352 |
} |
... | ... | @@ -322,11 +354,7 @@ |
322 | 354 |
} |
323 | 355 |
|
324 | 356 |
// Cancel the current request if we're already pjaxing |
325 |
- var xhr = pjax.xhr |
|
326 |
- if ( xhr && xhr.readyState < 4) { |
|
327 |
- xhr.onreadystatechange = $.noop |
|
328 |
- xhr.abort() |
|
329 |
- } |
|
357 |
+ abortXHR(pjax.xhr) |
|
330 | 358 |
|
331 | 359 |
pjax.options = options |
332 | 360 |
var xhr = pjax.xhr = $.ajax(options) |
... | ... | @@ -334,9 +362,9 @@ |
334 | 362 |
if (xhr.readyState > 0) { |
335 | 363 |
if (options.push && !options.replace) { |
336 | 364 |
// Cache current container element before replacing it |
337 |
- cachePush(pjax.state.id, context.clone().contents()) |
|
365 |
+ cachePush(pjax.state.id, [options.container, cloneContents(context)]) |
|
338 | 366 |
|
339 |
- window.history.pushState(null, "", stripPjaxParam(options.requestUrl)) |
|
367 |
+ window.history.pushState(null, "", options.requestUrl) |
|
340 | 368 |
} |
341 | 369 |
|
342 | 370 |
fire('pjax:start', [xhr, options]) |
... | ... | @@ -367,7 +395,7 @@ |
367 | 395 |
// |
368 | 396 |
// Returns nothing. |
369 | 397 |
function locationReplace(url) { |
370 |
- window.history.replaceState(null, "", "#") |
|
398 |
+ window.history.replaceState(null, "", pjax.state.url) |
|
371 | 399 |
window.location.replace(url) |
372 | 400 |
} |
373 | 401 |
|
... | ... | @@ -393,7 +421,15 @@ |
393 | 421 |
// You probably shouldn't use pjax on pages with other pushState |
394 | 422 |
// stuff yet. |
395 | 423 |
function onPjaxPopstate(event) { |
424 |
+ |
|
425 |
+ // Hitting back or forward should override any pending PJAX request. |
|
426 |
+ if (!initialPop) { |
|
427 |
+ abortXHR(pjax.xhr) |
|
428 |
+ } |
|
429 |
+ |
|
430 |
+ var previousState = pjax.state |
|
396 | 431 |
var state = event.state |
432 |
+ var direction |
|
397 | 433 |
|
398 | 434 |
if (state && state.container) { |
399 | 435 |
// When coming forward from a separate history session, will get an |
... | ... | @@ -401,22 +437,24 @@ |
401 | 437 |
// page. |
402 | 438 |
if (initialPop && initialURL == state.url) return |
403 | 439 |
|
404 |
- // If popping back to the same state, just skip. |
|
405 |
- // Could be clicking back from hashchange rather than a pushState. |
|
406 |
- if (pjax.state.id === state.id) return |
|
440 |
+ if (previousState) { |
|
441 |
+ // If popping back to the same state, just skip. |
|
442 |
+ // Could be clicking back from hashchange rather than a pushState. |
|
443 |
+ if (previousState.id === state.id) return |
|
407 | 444 |
|
408 |
- var container = $(state.container) |
|
445 |
+ // Since state IDs always increase, we can deduce the navigation direction |
|
446 |
+ direction = previousState.id < state.id ? 'forward' : 'back' |
|
447 |
+ } |
|
448 |
+ |
|
449 |
+ var cache = cacheMapping[state.id] || [] |
|
450 |
+ var containerSelector = cache[0] || state.container |
|
451 |
+ var container = $(containerSelector), contents = cache[1] |
|
452 |
+ |
|
409 | 453 |
if (container.length) { |
410 |
- var direction, contents = cacheMapping[state.id] |
|
411 |
- |
|
412 |
- if (pjax.state) { |
|
413 |
- // Since state ids always increase, we can deduce the history |
|
414 |
- // direction from the previous state. |
|
415 |
- direction = pjax.state.id < state.id ? 'forward' : 'back' |
|
416 |
- |
|
454 |
+ if (previousState) { |
|
417 | 455 |
// Cache current container before replacement and inform the |
418 | 456 |
// cache which direction the history shifted. |
419 |
- cachePop(direction, pjax.state.id, container.clone().contents()) |
|
457 |
+ cachePop(direction, previousState.id, [containerSelector, cloneContents(container)]) |
|
420 | 458 |
} |
421 | 459 |
|
422 | 460 |
var popstateEvent = $.Event('pjax:popstate', { |
... | ... | @@ -428,7 +466,7 @@ |
428 | 466 |
var options = { |
429 | 467 |
id: state.id, |
430 | 468 |
url: state.url, |
431 |
- container: container, |
|
469 |
+ container: containerSelector, |
|
432 | 470 |
push: false, |
433 | 471 |
fragment: state.fragment, |
434 | 472 |
timeout: state.timeout, |
... | ... | @@ -438,9 +476,14 @@ |
438 | 476 |
if (contents) { |
439 | 477 |
container.trigger('pjax:start', [null, options]) |
440 | 478 |
|
441 |
- if (state.title) document.title = state.title |
|
442 |
- container.html(contents) |
|
443 | 479 |
pjax.state = state |
480 |
+ if (state.title) document.title = state.title |
|
481 |
+ var beforeReplaceEvent = $.Event('pjax:beforeReplace', { |
|
482 |
+ state: state, |
|
483 |
+ previousState: previousState |
|
484 |
+ }) |
|
485 |
+ container.trigger(beforeReplaceEvent, [contents, options]) |
|
486 |
+ container.html(contents) |
|
444 | 487 |
|
445 | 488 |
container.trigger('pjax:end', [null, options]) |
446 | 489 |
} else { |
... | ... | @@ -449,7 +492,7 @@ |
449 | 492 |
|
450 | 493 |
// Force reflow/relayout before the browser tries to restore the |
451 | 494 |
// scroll position. |
452 |
- container[0].offsetHeight |
|
495 |
+ container[0].offsetHeight // eslint-disable-line no-unused-expressions |
|
453 | 496 |
} else { |
454 | 497 |
locationReplace(location.href) |
455 | 498 |
} |
... | ... | @@ -485,13 +528,27 @@ |
485 | 528 |
var pair = value.split('=') |
486 | 529 |
form.append($('<input>', {type: 'hidden', name: pair[0], value: pair[1]})) |
487 | 530 |
}) |
531 |
+ } else if ($.isArray(data)) { |
|
532 |
+ $.each(data, function(index, value) { |
|
533 |
+ form.append($('<input>', {type: 'hidden', name: value.name, value: value.value})) |
|
534 |
+ }) |
|
488 | 535 |
} else if (typeof data === 'object') { |
536 |
+ var key |
|
489 | 537 |
for (key in data) |
490 | 538 |
form.append($('<input>', {type: 'hidden', name: key, value: data[key]})) |
491 | 539 |
} |
492 | 540 |
|
493 | 541 |
$(document.body).append(form) |
494 | 542 |
form.submit() |
543 |
+} |
|
544 |
+ |
|
545 |
+// Internal: Abort an XmlHttpRequest if it hasn't been completed, |
|
546 |
+// also removing its event handlers. |
|
547 |
+function abortXHR(xhr) { |
|
548 |
+ if ( xhr && xhr.readyState < 4) { |
|
549 |
+ xhr.onreadystatechange = $.noop |
|
550 |
+ xhr.abort() |
|
551 |
+ } |
|
495 | 552 |
} |
496 | 553 |
|
497 | 554 |
// Internal: Generate unique id for state object. |
... | ... | @@ -504,16 +561,22 @@ |
504 | 561 |
return (new Date).getTime() |
505 | 562 |
} |
506 | 563 |
|
507 |
-// Internal: Strips _pjax param from url |
|
564 |
+function cloneContents(container) { |
|
565 |
+ var cloned = container.clone() |
|
566 |
+ // Unmark script tags as already being eval'd so they can get executed again |
|
567 |
+ // when restored from cache. HAXX: Uses jQuery internal method. |
|
568 |
+ cloned.find('script').each(function(){ |
|
569 |
+ if (!this.src) $._data(this, 'globalEval', false) |
|
570 |
+ }) |
|
571 |
+ return cloned.contents() |
|
572 |
+} |
|
573 |
+ |
|
574 |
+// Internal: Strip internal query params from parsed URL. |
|
508 | 575 |
// |
509 |
-// url - String |
|
510 |
-// |
|
511 |
-// Returns String. |
|
512 |
-function stripPjaxParam(url) { |
|
513 |
- return url |
|
514 |
- .replace(/\?_pjax=[^&]+&?/, '?') |
|
515 |
- .replace(/_pjax=[^&]+&?/, '') |
|
516 |
- .replace(/[\?&]$/, '') |
|
576 |
+// Returns sanitized url.href String. |
|
577 |
+function stripInternalParams(url) { |
|
578 |
+ url.search = url.search.replace(/([?&])(_pjax|_)=[^&]*/g, '').replace(/^&/, '') |
|
579 |
+ return url.href.replace(/\?($|#)/, '$1') |
|
517 | 580 |
} |
518 | 581 |
|
519 | 582 |
// Internal: Parse URL components and returns a Locationish object. |
... | ... | @@ -525,6 +588,16 @@ |
525 | 588 |
var a = document.createElement('a') |
526 | 589 |
a.href = url |
527 | 590 |
return a |
591 |
+} |
|
592 |
+ |
|
593 |
+// Internal: Return the `href` component of given URL object with the hash |
|
594 |
+// portion removed. |
|
595 |
+// |
|
596 |
+// location - Location or HTMLAnchorElement |
|
597 |
+// |
|
598 |
+// Returns String |
|
599 |
+function stripHash(location) { |
|
600 |
+ return location.href.replace(/#.*/, '') |
|
528 | 601 |
} |
529 | 602 |
|
530 | 603 |
// Internal: Build options Object for arguments. |
... | ... | @@ -545,44 +618,14 @@ |
545 | 618 |
// |
546 | 619 |
// Returns options Object. |
547 | 620 |
function optionsFor(container, options) { |
548 |
- // Both container and options |
|
549 |
- if ( container && options ) |
|
621 |
+ if (container && options) { |
|
622 |
+ options = $.extend({}, options) |
|
550 | 623 |
options.container = container |
551 |
- |
|
552 |
- // First argument is options Object |
|
553 |
- else if ( $.isPlainObject(container) ) |
|
554 |
- options = container |
|
555 |
- |
|
556 |
- // Only container |
|
557 |
- else |
|
558 |
- options = {container: container} |
|
559 |
- |
|
560 |
- // Find and validate container |
|
561 |
- if (options.container) |
|
562 |
- options.container = findContainerFor(options.container) |
|
563 |
- |
|
564 |
- return options |
|
565 |
-} |
|
566 |
- |
|
567 |
-// Internal: Find container element for a variety of inputs. |
|
568 |
-// |
|
569 |
-// Because we can't persist elements using the history API, we must be |
|
570 |
-// able to find a String selector that will consistently find the Element. |
|
571 |
-// |
|
572 |
-// container - A selector String, jQuery object, or DOM Element. |
|
573 |
-// |
|
574 |
-// Returns a jQuery object whose context is `document` and has a selector. |
|
575 |
-function findContainerFor(container) { |
|
576 |
- container = $(container) |
|
577 |
- |
|
578 |
- if ( !container.length ) { |
|
579 |
- throw "no pjax container for " + container.selector |
|
580 |
- } else if ( container.selector !== '' && container.context === document ) { |
|
624 |
+ return options |
|
625 |
+ } else if ($.isPlainObject(container)) { |
|
581 | 626 |
return container |
582 |
- } else if ( container.attr('id') ) { |
|
583 |
- return $('#' + container.attr('id')) |
|
584 | 627 |
} else { |
585 |
- throw "cant get selector for pjax container!" |
|
628 |
+ return {container: container} |
|
586 | 629 |
} |
587 | 630 |
} |
588 | 631 |
|
... | ... | @@ -596,7 +639,7 @@ |
596 | 639 |
// |
597 | 640 |
// Returns a jQuery object. |
598 | 641 |
function findAll(elems, selector) { |
599 |
- return elems.filter(selector).add(elems.find(selector)); |
|
642 |
+ return elems.filter(selector).add(elems.find(selector)) |
|
600 | 643 |
} |
601 | 644 |
|
602 | 645 |
function parseHTML(html) { |
... | ... | @@ -615,18 +658,21 @@ |
615 | 658 |
// |
616 | 659 |
// Returns an Object with url, title, and contents keys. |
617 | 660 |
function extractContainer(data, xhr, options) { |
618 |
- var obj = {} |
|
661 |
+ var obj = {}, fullDocument = /<html/i.test(data) |
|
619 | 662 |
|
620 | 663 |
// Prefer X-PJAX-URL header if it was set, otherwise fallback to |
621 | 664 |
// using the original requested url. |
622 |
- obj.url = stripPjaxParam(xhr.getResponseHeader('X-PJAX-URL') || options.requestUrl) |
|
665 |
+ var serverUrl = xhr.getResponseHeader('X-PJAX-URL') |
|
666 |
+ obj.url = serverUrl ? stripInternalParams(parseURL(serverUrl)) : options.requestUrl |
|
623 | 667 |
|
668 |
+ var $head, $body |
|
624 | 669 |
// Attempt to parse response html into elements |
625 |
- if (/<html/i.test(data)) { |
|
626 |
- var $head = $(parseHTML(data.match(/<head[^>]*>([\s\S.]*)<\/head>/i)[0])) |
|
627 |
- var $body = $(parseHTML(data.match(/<body[^>]*>([\s\S.]*)<\/body>/i)[0])) |
|
670 |
+ if (fullDocument) { |
|
671 |
+ $body = $(parseHTML(data.match(/<body[^>]*>([\s\S.]*)<\/body>/i)[0])) |
|
672 |
+ var head = data.match(/<head[^>]*>([\s\S.]*)<\/head>/i) |
|
673 |
+ $head = head != null ? $(parseHTML(head[0])) : $body |
|
628 | 674 |
} else { |
629 |
- var $head = $body = $(parseHTML(data)) |
|
675 |
+ $head = $body = $(parseHTML(data)) |
|
630 | 676 |
} |
631 | 677 |
|
632 | 678 |
// If response data is empty, return fast |
... | ... | @@ -638,16 +684,15 @@ |
638 | 684 |
obj.title = findAll($head, 'title').last().text() |
639 | 685 |
|
640 | 686 |
if (options.fragment) { |
687 |
+ var $fragment = $body |
|
641 | 688 |
// If they specified a fragment, look for it in the response |
642 | 689 |
// and pull it out. |
643 |
- if (options.fragment === 'body') { |
|
644 |
- var $fragment = $body |
|
645 |
- } else { |
|
646 |
- var $fragment = findAll($body, options.fragment).first() |
|
690 |
+ if (options.fragment !== 'body') { |
|
691 |
+ $fragment = findAll($fragment, options.fragment).first() |
|
647 | 692 |
} |
648 | 693 |
|
649 | 694 |
if ($fragment.length) { |
650 |
- obj.contents = $fragment.contents() |
|
695 |
+ obj.contents = options.fragment === 'body' ? $fragment : $fragment.contents() |
|
651 | 696 |
|
652 | 697 |
// If there's no title, look for data-title and title attributes |
653 | 698 |
// on the fragment |
... | ... | @@ -655,7 +700,7 @@ |
655 | 700 |
obj.title = $fragment.attr('title') || $fragment.data('title') |
656 | 701 |
} |
657 | 702 |
|
658 |
- } else if (!/<html/i.test(data)) { |
|
703 |
+ } else if (!fullDocument) { |
|
659 | 704 |
obj.contents = $body |
660 | 705 |
} |
661 | 706 |
|
... | ... | @@ -699,7 +744,8 @@ |
699 | 744 |
if (matchedScripts.length) return |
700 | 745 |
|
701 | 746 |
var script = document.createElement('script') |
702 |
- script.type = $(this).attr('type') |
|
747 |
+ var type = $(this).attr('type') |
|
748 |
+ if (type) script.type = type |
|
703 | 749 |
script.src = $(this).attr('src') |
704 | 750 |
document.head.appendChild(script) |
705 | 751 |
}) |
... | ... | @@ -722,14 +768,11 @@ |
722 | 768 |
cacheMapping[id] = value |
723 | 769 |
cacheBackStack.push(id) |
724 | 770 |
|
725 |
- // Remove all entires in forward history stack after pushing |
|
726 |
- // a new page. |
|
727 |
- while (cacheForwardStack.length) |
|
728 |
- delete cacheMapping[cacheForwardStack.shift()] |
|
771 |
+ // Remove all entries in forward history stack after pushing a new page. |
|
772 |
+ trimCacheStack(cacheForwardStack, 0) |
|
729 | 773 |
|
730 | 774 |
// Trim back history stack to max cache length. |
731 |
- while (cacheBackStack.length > pjax.defaults.maxCacheLength) |
|
732 |
- delete cacheMapping[cacheBackStack.shift()] |
|
775 |
+ trimCacheStack(cacheBackStack, pjax.defaults.maxCacheLength) |
|
733 | 776 |
} |
734 | 777 |
|
735 | 778 |
// Shifts cache from directional history cache. Should be |
... | ... | @@ -754,8 +797,23 @@ |
754 | 797 |
} |
755 | 798 |
|
756 | 799 |
pushStack.push(id) |
757 |
- if (id = popStack.pop()) |
|
758 |
- delete cacheMapping[id] |
|
800 |
+ id = popStack.pop() |
|
801 |
+ if (id) delete cacheMapping[id] |
|
802 |
+ |
|
803 |
+ // Trim whichever stack we just pushed to to max cache length. |
|
804 |
+ trimCacheStack(pushStack, pjax.defaults.maxCacheLength) |
|
805 |
+} |
|
806 |
+ |
|
807 |
+// Trim a cache stack (either cacheBackStack or cacheForwardStack) to be no |
|
808 |
+// longer than the specified length, deleting cached DOM elements as necessary. |
|
809 |
+// |
|
810 |
+// stack - Array of state IDs |
|
811 |
+// length - Maximum length to trim to |
|
812 |
+// |
|
813 |
+// Returns nothing. |
|
814 |
+function trimCacheStack(stack, length) { |
|
815 |
+ while (stack.length > length) |
|
816 |
+ delete cacheMapping[stack.shift()] |
|
759 | 817 |
} |
760 | 818 |
|
761 | 819 |
// Public: Find version identifier for the initial page load. |
... | ... | @@ -824,15 +882,22 @@ |
824 | 882 |
|
825 | 883 |
// Add the state property to jQuery's event object so we can use it in |
826 | 884 |
// $(window).bind('popstate') |
827 |
-if ( $.inArray('state', $.event.props) < 0 ) |
|
885 |
+if ($.event.props && $.inArray('state', $.event.props) < 0) { |
|
828 | 886 |
$.event.props.push('state') |
887 |
+} else if (!('state' in $.Event.prototype)) { |
|
888 |
+ $.event.addProp('state') |
|
889 |
+} |
|
829 | 890 |
|
830 | 891 |
// Is pjax supported by this browser? |
831 | 892 |
$.support.pjax = |
832 | 893 |
window.history && window.history.pushState && window.history.replaceState && |
833 | 894 |
// pushState isn't reliable on iOS until 5. |
834 |
- !navigator.userAgent.match(/((iPod|iPhone|iPad).+\bOS\s+[1-4]|WebApps\/.+CFNetwork)/) |
|
895 |
+ !navigator.userAgent.match(/((iPod|iPhone|iPad).+\bOS\s+[1-4]\D|WebApps\/.+CFNetwork)/) |
|
835 | 896 |
|
836 |
-$.support.pjax ? enable() : disable() |
|
897 |
+if ($.support.pjax) { |
|
898 |
+ enable() |
|
899 |
+} else { |
|
900 |
+ disable() |
|
901 |
+} |
|
837 | 902 |
|
838 |
-})(jQuery);(No newline at end of file) |
|
903 |
+})(jQuery) |
--- public/javascripts/yona-layout.js
+++ public/javascripts/yona-layout.js
This diff is too big to display. |
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?