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

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

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