Skip to content

Commit 0019136

Browse files
committed
Fix executing SCRIPT tags on pjax back/forward
After jQuery eval's a SCRIPT tag for the first time, it tags it with an internal flag "globalEval" that is kept even after cloning and prevents the same script from getting executed again. Now reset that property when writing to pjax cache, so that back/forward navigation properly re-executes inline SCRIPT tags.
1 parent 56b950b commit 0019136

File tree

3 files changed

+45
-15
lines changed

3 files changed

+45
-15
lines changed

jquery.pjax.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ function pjax(options) {
364364
if (xhr.readyState > 0) {
365365
if (options.push && !options.replace) {
366366
// Cache current container element before replacing it
367-
cachePush(pjax.state.id, context.clone().contents())
367+
cachePush(pjax.state.id, cloneContents(context))
368368

369369
window.history.pushState(null, "", options.requestUrl)
370370
}
@@ -447,7 +447,7 @@ function onPjaxPopstate(event) {
447447

448448
// Cache current container before replacement and inform the
449449
// cache which direction the history shifted.
450-
cachePop(direction, pjax.state.id, container.clone().contents())
450+
cachePop(direction, pjax.state.id, cloneContents(container))
451451
}
452452

453453
var popstateEvent = $.Event('pjax:popstate', {
@@ -544,6 +544,16 @@ function uniqueId() {
544544
return (new Date).getTime()
545545
}
546546

547+
function cloneContents(container) {
548+
var cloned = container.clone()
549+
// Unmark script tags as already being eval'd so they can get executed again
550+
// when restored from cache. HAXX: Uses jQuery internal method.
551+
cloned.find('script').each(function(){
552+
if (!this.src) jQuery._data(this, 'globalEval', false)
553+
})
554+
return cloned.contents()
555+
}
556+
547557
// Internal: Strips named query param from url
548558
//
549559
// url - String

test/unit/pjax.js

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -125,12 +125,31 @@ if ($.support.pjax) {
125125
var frame = this.frame
126126

127127
frame.evaledScriptLoaded = function() {
128-
equal(2, frame.evaledSrcScriptNum)
129-
equal(true, frame.evaledInlineScript)
130-
start()
128+
equal(frame.evaledSrcScriptNum, 2)
129+
deepEqual(frame.evaledInlineLog, ["one"])
130+
131+
frame.$.pjax({
132+
url: "scripts.html?name=two",
133+
container: "#main"
134+
})
135+
136+
frame.$("#main").one("pjax:end", function() {
137+
deepEqual(frame.evaledInlineLog, ["one", "two"])
138+
139+
goBack(frame, function() {
140+
deepEqual(frame.evaledInlineLog, ["one", "two", "one"])
141+
142+
goForward(frame, function() {
143+
deepEqual(frame.evaledInlineLog, ["one", "two", "one", "two"])
144+
equal(frame.evaledSrcScriptNum, 2)
145+
start()
146+
})
147+
})
148+
})
131149
}
150+
132151
frame.$.pjax({
133-
url: "scripts.html",
152+
url: "scripts.html?name=one",
134153
container: "#main"
135154
})
136155
})
@@ -927,7 +946,6 @@ if ($.support.pjax) {
927946
})
928947
})
929948

930-
// Test is fragile
931949
asyncTest("no initial pjax:popstate event", function() {
932950
var frame = this.frame
933951
var count = 0
@@ -944,19 +962,16 @@ if ($.support.pjax) {
944962
} else if (count == 3) {
945963
equal(frame.location.pathname, "/env.html")
946964
frame.history.back()
947-
setTimeout(function() { window.iframeLoad(frame) }, 1000)
948965
} else if (count == 4) {
949966
equal(frame.location.pathname, "/hello.html")
950967
frame.history.back()
951-
setTimeout(function() { window.iframeLoad(frame) }, 1000)
952968
} else if (count == 5) {
953969
equal(frame.location.pathname, "/home.html")
954970
frame.history.forward()
955-
setTimeout(function() { window.iframeLoad(frame) }, 1000)
956971
} else if (count == 6) {
957-
// Should skip pjax:popstate since there's no initial pjax.state
958972
frame.$('#main').on('pjax:popstate', function(event) {
959973
if (count == 6) {
974+
// Should skip pjax:popstate since there's no initial pjax.state
960975
ok(event.state.url.match("/hello.html"), event.state.url)
961976
ok(false)
962977
} else if (count == 7) {
@@ -969,11 +984,13 @@ if ($.support.pjax) {
969984
if (count == 6) {
970985
count++
971986
frame.history.forward()
972-
setTimeout(function() { window.iframeLoad(frame) }, 1000)
973-
} else {
974-
setTimeout(function() { start() }, 1000)
975987
}
976988
})
989+
990+
// Browsers that don't fire initial "popstate" should just resume
991+
setTimeout(function() {
992+
start()
993+
}, 100)
977994
}
978995
}
979996

test/views/scripts.erb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
<p>Got some script tags here</p>
22
<script type="text/javascript" src="/test/evaled.js"></script>
33
<script src="/test/evaled.js"></script>
4-
<script type="text/javascript">window.evaledInlineScript = true</script>
4+
<script type="text/javascript">
5+
window.evaledInlineLog = window.evaledInlineLog || []
6+
window.evaledInlineLog.push('<%= params[:name] %>')
7+
</script>
58
<script type="text/javascript">window.parent.iframeLoad(window)</script>

0 commit comments

Comments
 (0)