Commit 8cc54cb5 authored by S Anand's avatar S Anand

ENH: urlchange() emits #? event. Fixes #168

parent 9bac9dcc
Pipeline #87264 passed with stage
in 2 minutes
......@@ -38,15 +38,18 @@ $(window)
Examples:
- `#?x=1` triggers 2 events on `window`:
- `#?x=1` triggers 3 events on `window`:
- `.on('#', function(e) { e.hash.searchKey.x == '1' }`
- `.on('#?', function(e) { e.hash.searchKey.x == '1' }`
- `.on('#?x', function(e, val) { val == '1' && && e.old == [] })`
- When the URL changes from `#?x=1` to `#?x=1&y=2`, it triggers 2 events on `window`:
- When the URL changes from `#?x=1` to `#?x=1&y=2`, it triggers 3 events on `window`:
- `.on('#', function(e) { e.hash.searchKey == {x: '1', y: '2'} }`
- `.on('#?', function(e) { e.hash.searchKey == {x: '1', y: '2'} }`
- `.on('#?y', function(e, val) { val == '2' && e.old == [] })`
- No `#?x` event is fired, since x has not changed
- When the URL changes from `#?x=1` to `#?x=1&x=2`, it triggers 2 events on `window`:
- When the URL changes from `#?x=1` to `#?x=1&x=2`, it triggers 3 events on `window`:
- `.on('#', function(e) { e.hash.searchKey == {x: '1', y: '2'} }`
- `.on('#?', function(e) { e.hash.searchKey == {x: '1', y: '2'} }`
- `.on('#?x', function(e, val) { val == '1' && && e.old == ['1'] })`
- The `#?x` event is fired since x has a new value
- When the URL changes from `#a` to `#b`, it triggers 2 events on `window`:
......@@ -61,17 +64,22 @@ Examples:
## $.urlchange events
- `.on('#', function(e, val) {}` is fired when any part of the URL hash changes.
- `val` is the changed hash as a [URL](#urlparse) object.
- `val` is the changed hash as a [URL](#urlparse) object
- `e.change` is a dict with the changed key-values
For example, if the hash changes from `#a?x=1&y=1` to `#b?x=1&y=2`,
then `change={'/':'b', 'y': ['2']}`
- `e.hash` is the [parsed URL hash](#urlparse) object
- `e.old` is the previous [parsed URL hash](#urlparse) object
- `.on('#?', function(e, val) {}` is fired when *any* URL hash **key** changes.
- `val` is the changed hash as a [URL](#urlparse) object
- `e.change` is a dict with the changed key-values
- `e.hash` is the [parsed URL hash](#urlparse) object
- `e.old` is the previous [parsed URL hash](#urlparse) object
- `.on('#/', function(e, val) {}` is fired when the URL hash **path** changes.
- `val` is the changed path
- `e.hash` is the [parsed URL hash](#urlparse) object
- `e.old` is the previous [parsed URL hash](#urlparse) object
- `.on('#?<key>', function(e, val) {}` is fired when *any* URL hash **key** changes.
- `.on('#?<key>', function(e, val) {}` is fired when the specified URL hash **key** changes.
- `val` is the changed hash value
- `e.vals` is the list of new hash values -- same as `e.hash.searchList[<key>]`
- `e.hash` is the [parsed URL hash](#urlparse) object
......
......@@ -12,6 +12,7 @@ export function urlchange() {
return $self.on('hashchange.urlchange', function () {
var url = parse(loc.hash.replace(/^#/, ''))
var change = {}
var change_query = 0
// Parse keys in old & new URL hash. Trigger "#?<key>" if a key has changed
for (var key in $.extend({}, url.searchList, oldhash)) {
var vals = url.searchList[key] || []
......@@ -20,6 +21,7 @@ export function urlchange() {
var val = vals.length > 0 ? vals[0] : ''
$self.trigger({ type: '#?' + key, hash: url, vals: vals, old: oldurl }, val)
oldhash[key] = change[key] = vals
change_query += 1
}
}
// If the path has changed, trigger a "#/" event
......@@ -27,10 +29,12 @@ export function urlchange() {
$self.trigger({ type: '#/', hash: url, old: oldurl }, url.pathname)
change['/'] = oldpath = url.pathname
}
// If any part of the hash has changed, trigger a "#?"" event with all info
if (!$.isEmptyObject(change)) {
// If any query has been changed, trigger a "#?" event with all info
if (change_query)
$self.trigger({ type: '#?', hash: url, change: change, old: oldurl }, url)
// If any part of the hash has changed, trigger a "#" event with all info
if (!$.isEmptyObject(change))
$self.trigger({ type: '#', hash: url, change: change, old: oldurl }, url)
}
oldurl = url
}).trigger('hashchange')
}
......@@ -4,6 +4,7 @@
<meta charset="utf-8">
<title>urlchange tests</title>
<script src="../node_modules/jquery/dist/jquery.min.js"></script>
<script src="../node_modules/lodash/lodash.js"></script>
<script src="../dist/event.min.js"></script>
<script src="../dist/urlfilter.min.js"></script>
<script src="../dist/urlchange.min.js"></script>
......@@ -23,15 +24,17 @@
</script>
<script>
tape('#?高 triggers # and #?高 events', function(t) {
tape('#?高 triggers #, #? and #?高 events', function(t) {
reset()
t.plan(9)
$(window).one('#.test', function(e, hash) {
t.deepEqual(hash, e.hash)
t.deepEqual(hash.searchList, { '高': [''] })
t.equal(e.old.pathname, '')
t.deepEqual(e.old.searchList, {})
t.deepEqual(e.change, { '高': [''] })
t.plan(14)
_.each(['#.test', '#?.test'], function(trigger) {
$(window).one(trigger, function (e, hash) {
t.deepEqual(hash, e.hash)
t.deepEqual(hash.searchList, { '高': [''] })
t.equal(e.old.pathname, '')
t.deepEqual(e.old.searchList, {})
t.deepEqual(e.change, { '高': [''] })
})
})
$(window).one('#?高.test', function(e, val) {
t.equal(val, '')
......@@ -42,15 +45,17 @@
window.location.hash = '#?高'
})
tape('#?高=λ&►=σ trigges #, #?高 and #?► events', function(t) {
tape('#?高=λ&►=σ trigges #, #?, #?高 and #?► events', function(t) {
reset()
t.plan(13)
$(window).one('#.test', function (e, hash) {
t.deepEqual(hash, e.hash)
t.deepEqual(hash.searchList, { '高': ['λ'], '►': ['σ'] })
t.equal(e.old.pathname, '')
t.deepEqual(e.old.searchList, {})
t.deepEqual(e.change, { '高': ['λ'], '►': ['σ'] })
t.plan(18)
_.each(['#.test', '#?.test'], function (trigger) {
$(window).one(trigger, function (e, hash) {
t.deepEqual(hash, e.hash)
t.deepEqual(hash.searchList, { '高': ['λ'], '►': ['σ'] })
t.equal(e.old.pathname, '')
t.deepEqual(e.old.searchList, {})
t.deepEqual(e.change, { '高': ['λ'], '►': ['σ'] })
})
})
$(window).one('#?高.test', function (e, val) {
t.equal(val, 'λ')
......@@ -69,13 +74,15 @@
tape('Adding #?y=2 on triggers #?y events, not #?x', function(t) {
reset('#?x=1')
t.plan(9) // One less than no. of tests. #?x.test should not be fired
$(window).one('#.test', function (e, hash) {
t.deepEqual(hash, e.hash)
t.deepEqual(e.hash.searchList, { 'x': ['1'], 'y': ['2'] })
t.equal(e.old.pathname, '')
t.deepEqual(e.old.searchList, { 'x': ['1'] })
t.deepEqual(e.change, { 'y': ['2'] })
t.plan(14) // One less than no. of tests. #?x.test should not be fired
_.each(['#.test', '#?.test'], function (trigger) {
$(window).one(trigger, function (e, hash) {
t.deepEqual(hash, e.hash)
t.deepEqual(e.hash.searchList, { 'x': ['1'], 'y': ['2'] })
t.equal(e.old.pathname, '')
t.deepEqual(e.old.searchList, { 'x': ['1'] })
t.deepEqual(e.change, { 'y': ['2'] })
})
})
$(window).one('#?y.test', function (e, val) {
t.equal(val, '2')
......@@ -89,9 +96,9 @@
window.location.hash = '#?x=1&y=2'
})
tape('clearing x should still trigger an event', function(t) {
tape('clearing x should still trigger #?x', function(t) {
reset('#?x=1')
t.plan(2) // One less than no. of tests. #?x.test should not be fired
t.plan(2)
$(window).one('#?x', function (e, val) {
t.deepEqual(e.hash.searchList, {})
t.deepEqual(e.old.searchList, {'x': ['1']})
......@@ -99,9 +106,9 @@
window.location.hash = ''
})
tape('Adding #?abc=1&xyz=2 triggers on both abc and xyz events', function(t) {
tape('On #?abc=1&xyz=1, changing xyz=2 triggers only xyz event', function(t) {
reset('#?abc=1&xyz=1')
t.plan(3) // One less than no. of tests. #?x.test should not be fired
t.plan(3)
$(window).one('#?abc #?xyz', function (e, val) {
t.equal(val, '2')
t.deepEqual(e.hash.searchList, { 'abc': ['1'], 'xyz': ['2'] })
......@@ -110,16 +117,37 @@
window.location.hash = '#?abc=1&xyz=2'
})
tape('#a?x=1&y=2&z=3 -> #b?x=1&x=2&y=3', function(t) {
reset('#a?x=1&y=2&z=3')
t.plan(18)
tape('#a -> #b triggers only #/ and #', function (t) {
reset('#a')
t.plan(6)
$(window).one('#?.test', function () {
t.fail('#? should not be triggered')
})
$(window).one('#/.test', function (e, val) {
t.equal(val, 'b')
t.equal(e.hash.pathname, 'b')
t.equal(e.old.pathname, 'a')
})
$(window).one('#.test', function (e, hash) {
t.deepEqual(hash, e.hash)
t.equal(e.old.pathname, 'a')
t.equal(hash.pathname, 'b')
t.deepEqual(e.old.searchList, { 'x': ['1'], 'y': ['2'], 'z': ['3'] })
t.deepEqual(hash.searchList, { 'x': ['1', '2'], 'y': ['3'] })
t.deepEqual(e.change, { 'x': ['1', '2'], 'y': ['3'], 'z': [], '/': 'b' })
})
window.location.hash = '#b'
})
tape('#a?x=1&y=2&z=3 -> #b?x=1&x=2&y=3', function(t) {
reset('#a?x=1&y=2&z=3')
t.plan(24)
_.each(['#.test', '#?.test'], function (trigger) {
$(window).one(trigger, function (e, hash) {
t.deepEqual(hash, e.hash)
t.equal(e.old.pathname, 'a')
t.equal(hash.pathname, 'b')
t.deepEqual(e.old.searchList, { 'x': ['1'], 'y': ['2'], 'z': ['3'] })
t.deepEqual(hash.searchList, { 'x': ['1', '2'], 'y': ['3'] })
t.deepEqual(e.change, { 'x': ['1', '2'], 'y': ['3'], 'z': [], '/': 'b' })
})
})
$(window).one('#?x.test', function (e, val) {
t.equal(val, '1')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment