diff --git a/source/Ox.UI/js/Core/URL.js b/source/Ox.UI/js/Core/URL.js index 2d84eec9..16646974 100644 --- a/source/Ox.UI/js/Core/URL.js +++ b/source/Ox.UI/js/Core/URL.js @@ -302,7 +302,7 @@ Ox.URL URL controller example.com[/page][#hash] or -example.com[/type][/item][/view][/span][/sort][/find][#hash] +example.com[/type][/item][/view][/sort][/span][/find][#hash] page Special page, like "about" or "contact". part Part (section) of a page, like in "help/accounts". @@ -311,12 +311,12 @@ item Item id or title, like in '/movies/0060304', '/movies/inception' or 'texts/ABC'. Testing this is asynchonous. view List or item view, like "clips" or "map". Both list and item views are per type. +sort Sort, like "title" or "-director" or "country,year,-language,+runtime" span Position or selection in a view, either one or two coordinates or one id, like in "video/01:00", "video/-01:00", "video/01:00,-01:00", "video/@annotationABC", "video/@subtitles:23", "text/@chapter42", "map/0,0", "map/-45,-90,45,90", "map/@barcelona", "image/100,100" etc. Testing id is asynchronous. -sort Sort, like "title" or "-director" or "country,year,-language,+runtime" find Query, like a=x or a=x&b=y or a=x&(b=y|c=z). A query object has the form {conditions: [], operator: ''} (logical operator), and a condition object has the form {key: '', value: '' or ['', ''], operator: ''} @@ -363,12 +363,12 @@ example.com/clip/+clip.duration/subtitles=foo in ascending order. (In pan.do/ra's clip view, annotation=foo is always per clip. There is no way to show all clips of all items where any clip matches subtitles=foo, this doesn't seem to be needed.) -example.com/map/@paris/duration/title!=london +example.com/map/duration/@paris/title!=london If "map" is a default type list view and "paris" is a place name, this will zoom the map to Paris, show all places of items that match title!=london, and when a place is selected sort matching clips by item duration in default order. -example.com/calendar/1900,2000/clip:duration/event=hiroshima +example.com/calendar/clip:duration/1900,2000/event=hiroshima If "calendar" is a default type list view, this will zoom the calendar to the 20th century, show all events of all items that match event=hiroshima, and when an event is selected sort matching clips by clip duration in @@ -544,12 +544,12 @@ Ox.URL = function(options) { ].indexOf(state.view) > -1) { parts.push(state.view); } - if (state.span && state.span.length) { - parts.push(constructSpan(state.span, state)); - } if (state.sort && state.sort.length) { parts.push(constructSort(state.sort, state)); } + if (state.span && state.span.length) { + parts.push(constructSpan(state.span, state)); + } if (state.find) { parts.push(constructFind(state.find)); } @@ -825,7 +825,7 @@ Ox.URL = function(options) { } function parseBeyondItem() { Ox.Log('Core', 'pBI', state, parts.join('/')); - var span, spanType, spanTypes; + var sortKeyIds, sortParts, span, spanType, spanTypes; if ( parts.length && state.item && self.options.views[state.type].item.indexOf(parts[0]) > -1 @@ -836,6 +836,38 @@ Ox.URL = function(options) { } else if (state.item && self.options.views[state.type].item.length == 1) { state.view = self.options.views[state.type].item[0]; } + // sort + if (parts.length) { + sortParts = parts[0].split(','); + sortKeyIds = Ox.map(self.options.sortKeys[state.type][ + !state.item ? 'list' : 'item' + ], function(sortKeys) { + return sortKeys.map(function(sortKey) { + return sortKey.id; + }); + }); + // test if sort keys match the given view, + // or any view if no view is given + Ox.forEach( + state.view ? [state.view] + : self.options.views[state.type][!state.item ? 'list' : 'item'], + function(view) { + if (sortKeyIds[view] && sortParts.every(function(part) { + return sortKeyIds[view].indexOf(part.replace(/^[\+-]/, '')) > -1; + })) { + if (!state.view) { + // set list or item view + state.view = view; + } + // sort + state.sort = parseSort(parts[0], state); + parts.shift(); + return false; // break + } + } + ); + } + // span if (parts.length) { spanTypes = self.options.spanType[state.type][ !state.item ? 'list' : 'item' @@ -898,37 +930,6 @@ Ox.URL = function(options) { } function parseBeyondSpan() { Ox.Log('Core', 'pBS', state, parts) - var sortKeyIds, sortParts; - if (parts.length) { - sortParts = parts[0].split(','); - sortKeyIds = Ox.map(self.options.sortKeys[state.type][ - !state.item ? 'list' : 'item' - ], function(sortKeys) { - return sortKeys.map(function(sortKey) { - return sortKey.id; - }); - }); - // test if sort keys match the given view, - // or any view if no view is given - Ox.forEach( - state.view ? [state.view] - : self.options.views[state.type][!state.item ? 'list' : 'item'], - function(view) { - if (sortKeyIds[view] && sortParts.every(function(part) { - return sortKeyIds[view].indexOf(part.replace(/^[\+-]/, '')) > -1; - })) { - if (!state.view) { - // set list or item view - state.view = view; - } - // sort - state.sort = parseSort(parts[0], state); - parts.shift(); - return false; // break - } - } - ); - } if (!state.view) { // set to default list or item view state.view = self.options.views[state.type][