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