update URL controller (handle hash, simplify getItem/getSpan/getHash)

This commit is contained in:
rlx 2013-03-04 10:06:32 +00:00
parent 1e9000c0c0
commit 0989a41c8e

View file

@ -7,22 +7,24 @@ Ox.URL <f> URL controller
findKeys <[o]> Find keys
id <s> Find key id
type <s> Value type (like "string" or "integer")
getHash <f> Takes a state object and normalizes its "hash" property
(o) -> <o> State object
getHash <f> Tests if a hash is valid
May modify the state's hash property
(state, callback) -> <u> undefined
state <o> State object
hash <o> The hash to be tested
callback <f> callback function
getItem <f> Tests if a string matches an item
(type, string, callback) -> <u> undefined
type <s> type
May modify the state's item property
(state, string, callback) -> <u> undefined
state <o> State object
string <s> The string to be tested
callback <f> callback function
id <s> Matching item id, or empty
getSpan <f> Tests if a string matches a span
(type, item, view, string, callback) -> <u> undefined
item <s> The item id, or empty
view <s> The view, or empty
May modify the state's view and span properties
(state, string, callback) -> <u> undefined
state <o> State object
string <s> The string to be tested
callback <f> Callback function
id <s> Matching span id, or empty
view <s> Matching view, or empty
pages <[s]> List of pages
sortKeys <o> Sort keys for list and item views for all types
typeA <o> Sort keys for this type
@ -53,16 +55,29 @@ Ox.URL <f> URL controller
{id: 'name', type: 'string'},
{id: 'population', type: 'integer'}
],
getItem: function(type, str, callback) {
callback(/^\d+$/.test(str) ? str : '');
},
getSpan: function(type, item, view, str, callback) {
if (!item && (!view || view == 'map')) {
callback(str.replace(/^@/, ''), 'map');
} else {
callback();
getHash: function(state, callback) {
if (
state.hash && state.hash.anchor
&& state.hash.anchor.length > 1
) {
if (state.hash.query) {
delete state.hash.anchor;
} else {
delete state.hash;
}
}
},
getItem: function(state, str, callback) {
state.item = /^\d+$/.test(str) ? str : '';
callback();
},
getSpan: function(state, str, callback) {
if (!state.item && (!state.view || state.view == 'map')) {
state.view = 'map';
state.span = str.replace(/^@/, '');
}
callback();
},
pages: ['about', 'faq', 'help'],
sortKeys: {
countries: {
@ -210,6 +225,14 @@ Ox.URL <f> URL controller
operator: '&'
}
},
'/#?k=v&l=w': {
hash: {
query: [
{key: 'k', value: 'v'},
{key: 'l', value: 'w'}
]
}
},
'/#a?k=v&l=w': {
hash: {
anchor: 'a',
@ -219,7 +242,7 @@ Ox.URL <f> URL controller
]
}
},
'/#?a=[1,2]&b=true&n=1.2&o={"k":"v"}&s1="foo"&s2=bar': {
'/#invalid?a=[1,2]&b=true&n=1.2&o={"k":"v"}&s1="foo"&s2=bar': {
hash: {
query: [
{key: 'a', value: [1, 2]},
@ -261,9 +284,11 @@ Ox.URL <f> URL controller
true
> !!Ox.test.url.parse('/population>0&(name=a*|name=*z)', function(o) { Ox.test(o, Ox.test.result['/population>0&(name=a*|name=*z)']); })
true
> !!Ox.test.url.parse('/#?k=v&l=w', function(o) { Ox.test(o, Ox.test.result['/#?k=v&l=w']); })
true
> !!Ox.test.url.parse('/#a?k=v&l=w', function(o) { Ox.test(o, Ox.test.result['/#a?k=v&l=w']); })
true
> !!Ox.test.url.parse('/#?a=[1,2]&b=true&n=1.2&o={"k":"v"}&s1="foo"&s2=bar', function(o) { Ox.test(o, Ox.test.result['/#?a=[1,2]&b=true&n=1.2&o={"k":"v"}&s1="foo"&s2=bar']); })
> !!Ox.test.url.parse('/#invalid?a=[1,2]&b=true&n=1.2&o={"k":"v"}&s1="foo"&s2=bar', function(o) { Ox.test(o, Ox.test.result['/#invalid?a=[1,2]&b=true&n=1.2&o={"k":"v"}&s1="foo"&s2=bar']); })
true
@*/
@ -445,8 +470,11 @@ Ox.URL = function(options) {
obj[condition.key] = condition.value;
});
}
return (hash.anchor || '')
+ (hash.query ? '?' + Ox.serialize(obj) : '');
return hash.anchor || hash.query
? '#' + hash.anchor + (
hash.query ? '?' + Ox.serialize(obj) : ''
)
: '';
}
function constructLocation(location) {
@ -508,8 +536,9 @@ Ox.URL = function(options) {
parts.push(constructFind(state.find));
}
}
return '/' + Ox.filter(parts).join('/')
+ (state.hash ? '#' + constructHash(state.hash) : '');
return '/' + Ox.filter(parts).join('/') + (
state.hash ? constructHash(state.hash) : ''
);
}
function constructValue(str, key) {
@ -671,7 +700,7 @@ Ox.URL = function(options) {
}
if (split[1]) {
Ox.forEach(Ox.unserialize(split[1], true), function(value, key) {
hash.query = (hash.query || [])
hash.query = hash.query || [];
hash.query.push({
key: key,
value: value
@ -718,7 +747,9 @@ Ox.URL = function(options) {
// fixme: removing trailing slash makes it impossible to search for '/'
var split = str.split('#'),
parts = split.shift().replace(/(^\/|\/$)/g, '').split('/'),
state = split.length ? {hash: parseHash(split.join('#'))} : {};
state = split.length && split[0].length
? {hash: parseHash(split.join('#'))}
: {};
if (parts[0] == '') {
// empty URL
getHash();
@ -745,9 +776,9 @@ Ox.URL = function(options) {
parseBeyondItem();
} else {
// test for item id or name
self.options.getItem(state.type, parts[0].replace(/%20/g, ' '), function(item) {
state.item = item;
if (item) {
self.options.getItem(state, parts[0].replace(/%20/g, ' '), function() {
// may have modified state.item
if (state.item) {
parts.shift();
}
parseBeyondItem();
@ -808,14 +839,9 @@ Ox.URL = function(options) {
}
if (!state.span && /^[A-Z@]/.test(parts[0])) {
// test for span id or name
self.options.getSpan(state.type, state.item, state.view, decodeValue(parts[0]), function(span, view) {
Ox.Log('Core', 'span/view', span, view)
if (span) {
if (!state.view) {
// set list or item view
state.view = view;
}
state.span = span;
self.options.getSpan(state, decodeValue(parts[0]), function() {
// may have modified state.view and state.span
if (state.span) {
parts.shift();
}
parseBeyondSpan();
@ -878,7 +904,10 @@ Ox.URL = function(options) {
}
function getHash() {
if (self.options.getHash) {
state = self.options.getHash(state);
self.options.getHash(state, function() {
// may have modified state.hash
callback(state);
});
}
callback(state);
}