diff --git a/pandora/0xdb.json b/pandora/0xdb.json index 0640dfe7..eb794af1 100644 --- a/pandora/0xdb.json +++ b/pandora/0xdb.json @@ -6,13 +6,13 @@ "canSeeFiles": {"guest": -1, "member": -1, "staff": 3, "admin": 4} }, "clipKeys": [ - {"id": "clip:text", "title": "Clip Text", "type": "string"}, - {"id": "clip:position", "title": "Clip Position", "type": "float"}, - {"id": "clip:duration", "title": "Clip Duration", "type": "float"}, - {"id": "clip:hue", "title": "Clip Hue", "type": "hue"}, - {"id": "clip:saturation", "title": "Clip Saturation", "type": "float"}, - {"id": "clip:lightness", "title": "Clip Lightness", "type": "float"}, - {"id": "clip:volume", "title": "Clip Volume", "type": "float"} + {"id": "clip:text", "title": "Text", "type": "string"}, + {"id": "clip:position", "title": "Position", "type": "float"}, + {"id": "clip:duration", "title": "Duration", "type": "float"}, + {"id": "clip:hue", "title": "Hue", "type": "hue"}, + {"id": "clip:saturation", "title": "Saturation", "type": "float"}, + {"id": "clip:lightness", "title": "Lightness", "type": "float"}, + {"id": "clip:volume", "title": "Volume", "type": "float"} ], "groups": [ {"id": "director", "title": "Director", "type": "string"}, @@ -543,7 +543,13 @@ "preferences": {}, "ui": { "annotationsSize": 256, - "find": {"index": -1, "key": "", "value": ""}, + "columns": { + "Colors": { + "columns": ["title", "director", "country", "year", "hue", "saturation", "brightness"], + "columnWidth": {} + } + }, + "find": {"conditions": [], "operator": "&"}, "groups": [ {"id": "director", "sort": [{"key": "items", "operator": "-"}]}, {"id": "country", "sort": [{"key": "items", "operator": "-"}]}, @@ -555,20 +561,15 @@ "icons": "posters", "infoIconSize": 256, "item": "", + "itemSort": [{"key": "clip:position", "operator": ""}], "itemView": "info", "list": "", - "lists": { - "": { - "columns": ["title", "director", "country", "year", "language", "runtime", "genre"], - "columnWidth": {}, - "listView": "grid", - "selected": [], - "sort": [ - {"key": "director", "operator": ""} - ] - } - }, - "query": {"conditions": [], "operator": ""}, + "listColumns": ["title", "director", "country", "year", "language", "runtime", "genre"], + "listColumnWidth": {}, + "listSelection": [], + "listSort": [{"key": "director", "operator": ""}], + "listView": "grid", + "lists": {}, "section": "items", "showAnnotations": true, "showControls": true, @@ -586,8 +587,8 @@ } }, "showSidebar": true, + "showSitePosters": false, "sidebarSize": 256, - "sitePage": "home", "theme": "modern", "videoPoints": {}, "videoScale": "fit", diff --git a/pandora/urls.py b/pandora/urls.py index fe53cc5b..4b6c3457 100644 --- a/pandora/urls.py +++ b/pandora/urls.py @@ -50,6 +50,7 @@ urlpatterns += patterns('', (r'^[A-Z0-9].*$', 'app.views.index'), (r'^[a-z0-9].+$', 'app.views.index'), (r'^$', 'app.views.index'), + (r'^.*$', 'app.views.index'), ) urlpatterns += patterns('django.views.generic.simple', diff --git a/static/js/pandora.js b/static/js/pandora.js index 1dc27b63..b0403c2b 100644 --- a/static/js/pandora.js +++ b/static/js/pandora.js @@ -61,6 +61,7 @@ Ox.load({ findKeys: Ox.map(data.site.itemKeys, function(key) { return key.find ? key : null; }), + itemsSection: pandora.site.itemName.plural.toLowerCase(), sectionFolders: { items: [ {id: 'personal', title: 'Personal Lists'}, @@ -79,22 +80,32 @@ Ox.load({ {id: 'featured', title: 'Featured Texts', showBrowser: false} ] }, - sortKeys: Ox.map(data.site.itemKeys, function(key) { + sortKeys: Ox.map(pandora.site.itemKeys, function(key) { return key.columnWidth ? Ox.extend(key, { operator: pandora._getSortOperator(key.type) }) : null; }) }); + + pandora.site.listSettings = {}; + Ox.map(pandora.site.user.ui, function(val, key) { + if (/^list[A-Z]/.test(key)) { + pandora.site.listSettings[key] = key[0].toLowerCase() + key.substr(1); + } + }); + if (Ox.isEmpty(pandora.user.ui.lists)) { + var listSettings = {}; + Ox.forEach(pandora.site.listSettings, function(listSetting, setting) { + listSettings[listSetting] = pandora.site.user.ui[setting]; + }); + pandora.UI.set('lists|', listSettings); + } + Ox.extend(pandora.user, { sectionElement: 'buttons', - selectedMovies: [], + selectedMovies: [], // fixme: used for what? videoFormat: Ox.UI.getVideoFormat(pandora.site.video.formats) }); - // fixme: this should not happen - if (!pandora.user.ui.lists[pandora.user.ui.list]) { - Ox.print('THIS SHOULD NOT HAPPEN', pandora.site.user.ui.lists['']) - pandora.user.ui.lists[pandora.user.ui.list] = pandora.site.user.ui.lists['']; - } if (data.user.level == 'guest' && $.browser.mozilla) { pandora.user.ui.theme = 'classic'; @@ -106,78 +117,7 @@ Ox.load({ // set up url controller - var itemsName = pandora.site.itemName.plural.toLowerCase(), - sortKeys = {}, spanType = {}, views = {}; - views[itemsName] = { - list: Ox.merge( - // 'grid' is the default view - ['grid'], - Ox.map(pandora.site.listViews, function(view) { - return view.id == 'grid' ? null : view.id; - }) - ), - item: Ox.merge( - // 'info' is the default view, pandora.user.ui.videoView - // is the default view if there is a duration - ['info', pandora.user.ui.videoView], - pandora.site.itemViews.map(function(view) { - return [ - 'info', pandora.user.ui.videoView - ].indexOf(view.id) > -1 ? null : view.id; - }) - ) - }; - sortKeys[itemsName] = {list: {}, item: {}}; - views[itemsName].list.forEach(function(view) { - sortKeys[itemsName].list[view] = Ox.merge( - pandora.isClipView(view) ? Ox.clone(pandora.site.clipKeys) : [], - // 'director' is the default sort key - [Ox.getObjectById(pandora.site.sortKeys, 'director')], - Ox.map(pandora.site.sortKeys, function(key) { - return key.id == 'director' ? null : key; - }) - ); - }); - views[itemsName].item.forEach(function(view) { - if (pandora.isClipView(view, true)) { - sortKeys[itemsName].item[view] = Ox.merge( - // 'clip:position' is the default sort key - [Ox.getObjectById(pandora.site.clipKeys, 'clip:position')], - Ox.map(pandora.site.clipKeys, function(key) { - return key.id == 'clip:position' ? null : key; - }) - ); - } - }); - spanType[itemsName] = { - list: { - map: 'location', - calendar: 'date' - }, - item: { - video: 'duration', - timeline: 'duration', - map: 'location', - calendar: 'date' - } - }; - - pandora._URL = Ox.URL({ - findKeys: pandora.site.findKeys, - getItem: pandora.getItemByIdOrTitle, - getSpan: pandora.getMetadataByIdOrName, - pages: [ - 'about', 'contact', 'faq', 'help', 'home', 'news', - 'preferences', 'signin', 'signout', 'signup', - 'software', 'terms', 'tour' - ], - sortKeys: sortKeys, - spanType: spanType, - types: [pandora.site.itemName.plural.toLowerCase(), 'edits', 'texts'], - views: views - }); - - pandora.URL.parse(function() { + pandora.URL.init().parse(function() { Ox.UI.hideLoadingScreen(); @@ -251,13 +191,13 @@ Ox.load({ function unloadWindow() { // fixme: ajax request has to have async set to false for this to work - pandora.user.ui.section == 'items' && - ['player', 'timeline'].indexOf(pandora.user.ui.itemView) > -1 && - pandora.user.ui.item && - pandora.UI.set( - 'videoPosition|' + pandora.user.ui.item, + pandora.user.ui.section == 'items' + && pandora.user.ui.item + && ['video', 'timeline'].indexOf(pandora.user.ui.itemView) > -1 + && pandora.UI.set( + 'videoPosition.' + pandora.user.ui.item, pandora.$ui[ - pandora.user.ui.itemView == 'player' ? 'player' : 'editor' + pandora.user.ui.itemView == 'video' ? 'player' : 'editor' ].options('position') ); } diff --git a/static/js/pandora/UI.js b/static/js/pandora/UI.js index 2521aabb..a43dab86 100644 --- a/static/js/pandora/UI.js +++ b/static/js/pandora/UI.js @@ -1,38 +1,69 @@ // vim: et:ts=4:sw=4:sts=4:ft=javascript pandora.UI = (function() { - // fixme: why do we use '|', and not '.', as a separator? - var previousUI = {}; - return { - // sets pandora.user.ui.key to val - // key foo|bar|baz sets pandora.user.ui.foo.bar.baz - // val null removes a key - getPrevious: function() { - return previousUI; - }, - set: function(/*{key: val} or key, val*/) { - var obj = Ox.makeObject(arguments); - previousUI = Ox.clone(pandora.user.ui, true); - Ox.forEach(obj, function(val, key) { - Ox.print('UI.set key', key, 'val', val); - var i = 0, - keys = key.split('|'), - ui = pandora.user.ui; - while (i < keys.length - 1) { - ui = ui[keys[i]]; - i++; - } - if (ui[keys[i]] !== val) { - if (val === null) { - delete ui[keys[i]] - } else { - ui[keys[i]] = val; - } + var self = {}, that = {}; + self.previousUI = {}; + that.bind = function() { + Ox.Event.bind.apply(null, arguments); + }; + that.encode = function(val) { + return val.replace(/\./g, '\\.'); + }; + that.getPrevious = function(key) { + return !key ? self.previousUI : self.previousUI[key]; + }; + // sets pandora.user.ui.key to val + // key foo.bar.baz sets pandora.user.ui.foo.bar.baz + // val null removes a key + that.set = function(/*{key: val} or key, val*/) { + var obj = Ox.makeObject(arguments), + set = {}; + self.previousUI = Ox.clone(pandora.user.ui, true); + Ox.forEach(obj, function(val, key) { + var listSettings = pandora.site.listSettings + if (key == 'list' && !pandora.user.ui.lists[val]) { + // add default list settings + obj['lists.' + that.encode(val)] = {}; + Ox.forEach(listSettings, function(listSetting, setting) { + obj['lists.' + that.encode(val)][listSetting] = pandora.site.user.ui[setting]; + }); + } else if (Object.keys(listSettings).indexOf(key) > -1) { + // add list setting + obj['lists.' + that.encode(pandora.user.ui.list) + '.' + listSettings[key]] = val; + } else if ( + key == 'itemView' + && ['video', 'timeline'].indexOf(val) > -1 + && !pandora.user.ui.videoPoints[pandora.user.ui.item] + ) { + // add default videoPoints + obj['videoPoints.' + pandora.user.ui.item] = {'in': 0, out: 0, position: 0}; + } + }); + Ox.forEach(obj, function(val, key) { + var i = 0, + keys = key.split('.'), + ui = pandora.user.ui; + while (i < keys.length - 1) { + ui = ui[keys[i]]; + i++; + } + if (!Ox.isEqual(ui[keys[i]], val)) { + if (val === null) { + delete ui[keys[i]] } else { - delete obj[key]; + ui[keys[i]] = val; } + // set[key] = val; + // fixme: remove later + set[key.replace(/\./g, '|')] = val; + } + }); + if (Ox.len(set)) { + Ox.forEach(set, function(val, key) { + Ox.Event.trigger(key, val); }); - Ox.len(obj) && pandora.api.setUI(obj); + pandora.api.setUI(set); } - } + }; + return that; }()); diff --git a/static/js/pandora/URL.js b/static/js/pandora/URL.js index e237fe5f..fa4517de 100644 --- a/static/js/pandora/URL.js +++ b/static/js/pandora/URL.js @@ -1,220 +1,416 @@ // vim: et:ts=4:sw=4:sts=4:ft=javascript - -/* -FIXME: -we may want slashes in list names, and ampersands in queries - -*/ - pandora.URL = (function() { - var previousURL = '', - regexps = { - '^$': function(pathname, search, callback) { - if (/^\?url=/.test(search)) { - document.location = decodeURIComponent(search.substr(5)); + var self = {}, that = {}; + + /* + function foundItem() { + pandora.UI.set(Ox.extend({ + section: 'items', + item: item, + itemView: view + }, ['video', 'timeline'].indexOf(view) > -1 ? { + videoView: view + } : {})); + if (time) { + points = time[0].split(','); + if ( + points.length == 2 + && (points = Ox.flatten([points[0], points[1].split('-')]))[2] == '' + ) { + pandora.api.get({ + id: item, + keys: ['duration'] + }, function(result) { + points[2] = result.data.duration.toString(); + foundTime(); + }); + } else { + foundTime(); + } + } else { + if (!pandora.user.ui.videoPoints[item]) { + pandora.UI.set('videoPoints|' + item, { + 'in': 0, out: 0, position: 0 + }); + } + foundTime(); + } + function foundTime() { + if (time) { + // fixme: this is duplicated, see Ox.VideoPlayer() parsePositionInput() + points = points.map(function(point, i) { + var parts = point.split(':').reverse(); + while (parts.length > 3) { + parts.pop(); + } + return parts.reduce(function(prev, curr, i) { + return prev + (parseFloat(curr) || 0) * Math.pow(60, i); + }, 0); + }); + pandora.UI.set('videoPoints|' + item, { + 'in': points.length == 1 ? 0 : points[points.length - 2], + out: points.length == 1 ? 0 : points[points.length - 1], + position: points[0], + }); + points = points.map(function(point) { + return point == -1 ? '' : Ox.formatDuration(point, 3).replace(/\.000$/, ''); + }); + split[split.length - 1] = points[0] + ( + points.length == 1 ? '' : ',' + points[1] + '-' + points[2] + ); + } + pandora.URL.replace(split.join('/')); + // on page load, we have to check if the item is in the previously selected list + // if it is not, the movie browser has to be reloaded + if (pandora.user.ui.list) { + pandora.user.ui.query = { + conditions: [{key: 'list', value: pandora.user.ui.list, operator: ''}], + operator: '&' + }; + pandora.api.find({ + query: pandora.user.ui.query, + positions: [pandora.user.ui.item], + sort: [{key: 'id', operator: ''}] + }, function(result) { + if (Ox.isUndefined(result.data.positions[pandora.user.ui.item])) { + pandora.UI.set({list: ''}); + pandora.user.ui.query = {conditions:[], operator: '&'}; + } + callback(); + }); + } else { + callback(); + } + } + } + */ + + function everyCondition(conditions, key, operator) { + // If every condition has the given key and operator + // (excluding conditions where all subconditions match) + // returns true, otherwise false + return Ox.every(conditions, function(condition) { + return condition.key == key && condition.operator == operator; + }); + } + + function getFindState(find, listsState, groupsState) { + // The find element is populated if exactly one condition in an & query + // has a findKey as key and "=" as operator (and all other conditions + // are either list or groups), or if all conditions in an | query have + // the same group id as key and "==" as operator + var conditions, indices, state = {index: -1, key: '*', value: ''}; + if (find.operator == '&') { + // number of conditions that are not list or groups + conditions = find.conditions.length + - (listsState != '') + - groupsState.filter(function(group) { + return group.index > -1; + }).length; + // indices of non-advanced find queries + indices = Ox.map(pandora.site.findKeys, function(findKey) { + var index = oneCondition(find.conditions, findKey.id, '='); + return index > -1 ? index : null; + }); + state = conditions == 1 && indices.length == 1 ? { + index: indices[0], + key: find.conditions[indices[0]].key, + value: decodeURIComponent(find.conditions[indices[0]].value) + } : { + index: -1, + key: conditions == 0 && indices.length == 0 ? '*' : 'advanced', + value: '' + }; + } else { + state = { + index: -1, + key: 'advanced', + value: '' + }; + Ox.forEach(pandora.user.ui.groups, function(key) { + if (everyCondition(find.conditions, key, '==')) { + state.key = '*'; + return false; + } + }); + } + return state; + } + + function getGroupsState(find) { + // A group is selected if exactly one condition in an & query or every + // condition in an | query has the group id as key and "==" as operator + return pandora.user.ui.groups.map(function(group) { + // FIXME: cant index be an empty array, instead of -1? + var key = group.id, + state = {index: -1, find: Ox.clone(find, true), selected: []}; + if (find.operator == '&') { + // include conditions where all subconditions match + state.index = oneCondition(find.conditions, key, '==', true); + if (state.index > -1) { + state.selected = find.conditions[state.index].conditions + ? find.conditions[state.index].conditions.map(function(condition) { + return condition.value; + }) + : [find.conditions[state.index].value]; + } + } else { + if (everyCondition(find.conditions, key, '==')) { + state.index = Ox.range(find.conditions.length); + state.selected = find.conditions.map(function(condition) { + return condition.value; + }); + } + } + if (state.selected.length) { + if (Ox.isArray(state.index)) { + // every condition in an | query matches this group + state.find = {conditions: [], operator: ''}; } else { - if (!search && pandora.user.ui.showHome) { - pandora.$ui.home = pandora.ui.home().showScreen(); - Ox.print('LIST', pandora.user.ui.list) - pandora.user.ui.list && pandora.Query.fromString( - 'find=list:' + pandora.user.ui.list - ); - } else { - pandora.Query.fromString(search); - pandora.UI.set({ - section: 'items', - item: '' - }); - } - } - callback(); - }, - '^home$': function(pathname, search, callback) { - pandora.$ui.home = pandora.ui.home().showScreen(); - callback(); - }, - '^(items|edits|texts)$': function(pathname, search, callback) { - pandora.UI.set({ - section: pathname - }); - callback(); - }, - '^(about|contact|faq|news|software|terms|tour)$': function(pathname, search, callback) { - pandora.$ui.siteDialog = pandora.ui.siteDialog(pathname).open(); - callback(); - }, - '^help$': function(pathname, search, callback) { - pandora.$ui.helpDialog = pandora.ui.helpDialog().open(); - callback(); - }, - '^(signin|signout|signup)$': function(pathname, search, callback) { - if ((pathname == 'signout') == (pandora.user.level != 'guest')) { - pandora.$ui.accountDialog = ( - pandora.user.level == 'guest' - ? pandora.ui.accountDialog(pathname) - : pandora.ui.accountSignoutDialog() - ).open(); - } - callback(); - }, - '^preferences$': function(pathname, search, callback) { - pandora.$ui.preferencesDialog = pandora.ui.preferencesDialog().open(); - callback(); - }, - '^(calendar|calendars|clip|clips|flow|grid|list|map|maps|timelines)$': function(pathname, search, callback) { - pandora.UI.set({ - section: 'items', - item: '' - }); - pandora.UI.set('lists|' + pandora.user.ui.list + '|listView', pathname); - pandora.Query.fromString(search); - callback(); - }, - '.*': function(pathname, search, callback) { - var split = pathname.split('/'), - item = decodeURI(split[0]), - points, - time = split.length > 1 - ? /[\d\.:,-]+/.exec(split[split.length - 1]) - : null, - view = new RegExp( - '^(' + pandora.site.itemViews.map(function(v) { - return v.id; - }).join('|') + ')$' - ).exec(split[1]); - view = view ? view[0] - : time ? pandora.user.ui.videoView - : pandora.user.ui.itemView; - pandora.api.get({id: item, keys: ['id']}, function(result) { - if (result.status.code == 200) { - foundItem(); - } else { - pandora.api.find({ - query: { - conditions: [{key: 'title', value: item, operator: ''}], - operator: '&' - }, - sort: [{key: 'votes', operator: ''}], // fixme: not all systems have "votes" - range: [0, 100], - keys: ['id', 'title', 'votes'] - }, function(result) { - if (result.data.items.length) { - var re = { - exact: new RegExp('^' + item + '$', 'i'), - word: new RegExp('\\b' + item + '\\b', 'i') - }; - item = result.data.items.sort(function(a, b) { - return (parseInt(b.votes) || 0) - + re.word.test(b.title) * 1000000 - + re.exact.test(b.title) * 2000000 - - (parseInt(a.votes) || 0) - - re.word.test(a.title) * 1000000 - - re.exact.test(a.title) * 2000000; - })[0].id; - split[0] = item; - foundItem(); - } else { - pandora.UI.set({ - section: 'items', - item: '' - }); - pandora.Query.fromString('?find=' + pathname); - pandora.URL.replace('?find=' + pathname); - callback(); - } - }); - } - }); - function foundItem() { - pandora.UI.set(Ox.extend({ - section: 'items', - item: item, - itemView: view - }, ['video', 'timeline'].indexOf(view) > -1 ? { - videoView: view - } : {})); - if (time) { - points = time[0].split(','); - if ( - points.length == 2 - && (points = Ox.flatten([points[0], points[1].split('-')]))[2] == '' - ) { - pandora.api.get({ - id: item, - keys: ['duration'] - }, function(result) { - points[2] = result.data.duration.toString(); - foundTime(); - }); - } else { - foundTime(); - } - } else { - if (!pandora.user.ui.videoPoints[item]) { - pandora.UI.set('videoPoints|' + item, { - 'in': 0, out: 0, position: 0 - }); - } - foundTime(); - } - function foundTime() { - if (time) { - // fixme: this is duplicated, see Ox.VideoPlayer() parsePositionInput() - points = points.map(function(point, i) { - var parts = point.split(':').reverse(); - while (parts.length > 3) { - parts.pop(); - } - return parts.reduce(function(prev, curr, i) { - return prev + (parseFloat(curr) || 0) * Math.pow(60, i); - }, 0); - }); - pandora.UI.set('videoPoints|' + item, { - 'in': points.length == 1 ? 0 : points[points.length - 2], - out: points.length == 1 ? 0 : points[points.length - 1], - position: points[0], - }); - points = points.map(function(point) { - return point == -1 ? '' : Ox.formatDuration(point, 3).replace(/\.000$/, ''); - }); - split[split.length - 1] = points[0] + ( - points.length == 1 ? '' : ',' + points[1] + '-' + points[2] - ); - } - pandora.URL.replace(split.join('/')); - // on page load, we have to check if the item is in the previously selected list - // if it is not, the movie browser has to be reloaded - if (pandora.user.ui.list) { - pandora.user.ui.query = { - conditions: [{key: 'list', value: pandora.user.ui.list, operator: ''}], - operator: '&' + // one condition in an & query matches this group + state.find.conditions.splice(state.index, 1); + if (state.find.conditions.length == 1) { + if (state.find.conditions[0].conditions) { + // unwrap single remaining bracketed query + state.find = { + conditions: state.find.conditions[0].conditions, + operator: state.find.conditions[0].operator }; - pandora.api.find({ - query: pandora.user.ui.query, - positions: [pandora.user.ui.item], - sort: [{key: 'id', operator: ''}] - }, function(result) { - if (Ox.isUndefined(result.data.positions[pandora.user.ui.item])) { - pandora.UI.set({list: ''}); - pandora.user.ui.query = {conditions:[], operator: '&'}; - } - callback(); - }); - } else { - callback(); } } } } - }; - - function saveURL() { - previousURL = document.location.pathname + document.location.search; + return state; + }); } - function updateURL() { + function getListsState(find) { + // A list is selected if exactly one condition in an & query has "list" + // as key and "==" as operator + var index, state = ''; + if (find.operator == '&') { + index = oneCondition(find.conditions, 'list', '=='); + if (index > -1) { + state = find.conditions[index].value; + } + } + return state; + } + + function getState() { + return { + type: pandora.user.ui.section == 'items' + ? pandora.site.itemsSection + : pandora.user.ui.section, + item: pandora.user.ui.item, + view: !pandora.user.ui.item + ? pandora.user.ui.listView + : pandora.user.ui.itemView, + sort: !pandora.user.ui.item + ? pandora.user.ui.listSort + : pandora.isClipView(pandora.user.ui.itemView) + ? pandora.user.ui.itemSort : [], + find: !pandora.user.ui.item + ? pandora.user.ui.find + : '' + }; + } + + function oneCondition(conditions, key, operator, includeSubconditions) { + // If exactly one condition has the given key and operator + // (including or excluding conditions where all subconditions match) + // returns the corresponding index, otherwise returns -1 + var indices = Ox.map(conditions, function(condition, i) { + return ( + condition.conditions + ? includeSubconditions && everyCondition(condition.conditions, key, operator) + : condition.key == key && condition.operator == operator + ) ? i : null; + }); + return indices.length == 1 ? indices[0] : -1; + } + + function setState(state) { + Ox.print('STATE:', state) + var previousUI = pandora.UI.getPrevious(); + // var previousUI = Ox.clone(pandora.user.ui); + Ox.Request.cancel(); + $('video').each(function() { + $(this).trigger('stop'); + }); + pandora.user.ui._groupsState = getGroupsState(pandora.user.ui.find); + pandora.user.ui._findState = getFindState(pandora.user.ui.find, pandora.user.ui.list, pandora.user.ui._groupsState); + if (Ox.isEmpty(state)) { + if (pandora.user.ui.showHome) { + pandora.$ui.home = pandora.ui.home().showScreen(); + /* + Ox.print('LIST', pandora.user.ui.list) + pandora.user.ui.list && pandora.Query.fromString( + 'find=list:' + pandora.user.ui.list + ); + */ + } else { + pandora.UI.set({ + section: 'items', + item: '' + }); + } + } else if (state.page) { + if (state.page == 'home') { + //pandora.$ui.home = pandora.ui.home().showScreen(); + pandora.$ui.home = pandora.ui.home().fadeInScreen(); + } else if ([ + 'about', 'contact', 'faq', 'news', 'software', 'terms', 'tour' + ].indexOf(state.page) > -1) { + pandora.$ui.siteDialog = pandora.ui.siteDialog(state.page).open(); + } else if (state.page == 'help') { + pandora.$ui.helpDialog = pandora.ui.helpDialog().open(); + } else if (['signup', 'signin'].indexOf(state.page) > -1) { + if (pandora.user.level == 'guest') { + pandora.ui.accountDialog(state.page).open(); + } else { + pandora.URL.replace('/'); + } + } else if (['preferences', 'signout'].indexOf(state.page) > -1) { + if (pandora.user.level == 'guest') { + pandora.URL.replace('/'); + } else if (state.page == 'preferences') { + pandora.ui.preferencesDialog().open(); + } else { + pandora.ui.accountSignoutDialog().open(); + } + } else if (state.page == 'api') { + document.location.href = '/api/'; + } + } else { + pandora.UI.set({ + section: state.type == pandora.site.itemsSection ? 'items' : state.type, + item: state.item, + }); + + state.find && pandora.UI.set({ + find: state.find, + list: getListsState(state.find) + }); + + if (state.view) { + pandora.UI.set( + !pandora.user.ui.item + ? 'lists.' + pandora.user.ui.list + '.view' + : 'itemView', + state.view + ); + } + + pandora.user.ui._groupsState = getGroupsState(pandora.user.ui.find); + Ox.print('_groupsState =', pandora.user.ui._groupsState); + pandora.user.ui._findState = getFindState(pandora.user.ui.find, pandora.user.ui.list, pandora.user.ui._groupsState); + + if (['video', 'timeline'].indexOf(pandora.user.ui.itemView) > -1) { + if (state.span) { + pandora.UI.set('videoPoints.' + pandora.user.ui.item, { + position: state.span[0], + 'in': state.span[1] || 0, + out: state.span[2] || 0 + }); + } else if (!pandora.user.ui.videoPoints[pandora.user.ui.item]) { + pandora.UI.set('videoPoints.' + pandora.user.ui.item, { + position: 0, + 'in': 0, + out: 0 + }); + } + } + + state.sort && pandora.UI.set( + !pandora.user.ui.item + ? 'lists.' + pandora.user.ui.list + '.sort' + : 'itemSort', + state.sort + ); + + if (!pandora.$ui.appPanel) { + return; + } + + if (pandora.user.ui.section != previousUI.section) { + // new section + pandora.$ui.appPanel.replaceElement(1, pandora.$ui.mainPanel = pandora.ui.mainPanel()); + } else if (!pandora.user.ui.item && !previousUI.item) { + // list to list + Ox.print('pUI', previousUI); + var isClipView = pandora.isClipView(), + list = pandora.user.ui.lists[pandora.user.ui.list], + previousList = previousUI.lists[previousUI.list], + wasClipView = pandora.isClipView(previousList.view); + if (pandora.user.ui.list != previousUI.list) { + pandora.$ui.findElement.replaceWith(pandora.$ui.findElement = pandora.ui.findElement()); + } + if (list.view != previousList.view) { + pandora.$ui.mainMenu.checkItem('viewMenu_movies_' + list.view); + pandora.$ui.viewSelect.options({value: list.view}); + if (isClipView != wasClipView) { + pandora.$ui.mainMenu.replaceMenu('sortMenu', pandora.getSortMenu()); + pandora.$ui.sortSelect.replaceWith(pandora.$ui.sortSelect = pandora.ui.sortSelect()); + if (isClipView && !wasClipView) { + pandora.UI.set('lists.' + pandora.user.ui.list + '.selected', []); + } + } + } + if (!Ox.isEqual(list.sort, previousList.sort)) { + pandora.$ui.mainMenu.checkItem('sortMenu_sortmovies_' + list.sort[0].key); + pandora.$ui.mainMenu.checkItem('sortMenu_ordermovies_' + (( + list.sort[0].operator || pandora.getSortOperator(list.sort[0].key) + ) == '+' ? 'ascending' : 'descending')); + pandora.$ui.sortSelect.options({value: list.sort[0].key}); + } + pandora.$ui.leftPanel.replaceElement(2, pandora.$ui.info = pandora.ui.info()); + if (Ox.isEqual(pandora.user.ui.find, previousUI.find)) { + pandora.$ui.contentPanel.replaceElement(1, pandora.$ui.list = pandora.ui.list()); + } else { + pandora.user.ui._groupsState.forEach(function(data, i) { + if (!Ox.isEqual(data.find, previousUI._groupsState[i].find)) { + pandora.$ui.groups[i].reloadList(); + } + }); + pandora.$ui.contentPanel.replaceElement(1, pandora.$ui.list = pandora.ui.list()); + //pandora.$ui.mainPanel.replaceElement(1, pandora.$ui.rightPanel = pandora.ui.rightPanel()); + } + // fixme: should list selection and deselection happen here? + // (home and menu may cause a list switch) + } else if (!pandora.user.ui.item || !previousUI.item) { + // list to item or item to list + pandora.$ui.leftPanel.replaceElement(2, pandora.$ui.info = pandora.ui.info()); + pandora.$ui.mainPanel.replaceElement(1, pandora.$ui.rightPanel = pandora.ui.rightPanel()); + } else { + // item to item + if (pandora.user.ui.item != previousUI.item) { + pandora.$ui.leftPanel.replaceElement(2, pandora.$ui.info = pandora.ui.info()); + } + pandora.$ui.contentPanel.replaceElement(1, pandora.ui.item()); + } + if ( + previousUI.item + && ['video', 'timeline'].indexOf(previousUI.itemView) > -1 + ) { + var $item = pandora.$ui[ + previousUI.itemView == 'video' ? 'player' : 'editor' + ]; + $item && pandora.UI.set( + 'videoPoints.' + previousUI.item + '.position', + $item.options('position') + ); + } + + } + pandora.user.ui.showHome = false; + + } + + function updateUI() { + // remove later var previousUI = pandora.UI.getPrevious(); Ox.Request.cancel(); $('video').each(function() { @@ -228,15 +424,15 @@ pandora.URL = (function() { var isClipView = pandora.isClipView(), list = pandora.user.ui.lists[pandora.user.ui.list], previousList = previousUI.lists[previousUI.list], - wasClipView = pandora.isClipView(previousList.listView); - if (list.listView != previousList.listView) { - pandora.$ui.mainMenu.checkItem('viewMenu_movies_' + list.listView); - pandora.$ui.viewSelect.options({value: list.listView}); + wasClipView = pandora.isClipView(previousList.view); + if (list.view != previousList.view) { + pandora.$ui.mainMenu.checkItem('viewMenu_movies_' + list.view); + pandora.$ui.viewSelect.options({value: list.view}); if (isClipView != wasClipView) { pandora.$ui.mainMenu.replaceMenu('sortMenu', pandora.getSortMenu()); pandora.$ui.sortSelect.replaceWith(pandora.$ui.sortSelect = pandora.ui.sortSelect()); if (isClipView && !wasClipView) { - pandora.UI.set('lists|' + pandora.user.ui.list + '|selected', []); + pandora.UI.set('lists.' + pandora.user.ui.list + '.selected', []); } } } @@ -248,7 +444,7 @@ pandora.URL = (function() { pandora.$ui.sortSelect.options({value: list.sort[0].key}); } pandora.$ui.leftPanel.replaceElement(2, pandora.$ui.info = pandora.ui.info()); - if (Ox.isEqual(pandora.user.ui.query, previousUI.query)) { + if (Ox.isEqual(pandora.user.ui.find, previousUI.find)) { pandora.$ui.contentPanel.replaceElement(1, pandora.$ui.list = pandora.ui.list()); } else { pandora.$ui.mainPanel.replaceElement(1, pandora.$ui.rightPanel = pandora.ui.rightPanel()); @@ -274,15 +470,140 @@ pandora.URL = (function() { previousUI.itemView == 'video' ? 'player' : 'editor' ]; $item && pandora.UI.set( - 'videoPoints|' + previousUI.item + '|position', + 'videoPoints.' + previousUI.item + '.position', $item.options('position') ); } }); } - return { + that.init = function() { + var itemsSection = pandora.site.itemsSection, + findKeys, sortKeys = {}, spanType = {}, views = {}; + + views[itemsSection] = { + list: Ox.merge( + // listView is the default view + [pandora.user.ui.listView], + Ox.map(pandora.site.listViews, function(view) { + return view.id == pandora.user.ui.listView ? null : view.id; + }) + ), + item: Ox.merge( + // itemView is the default view, + // videoView is the default view if there is a duration + [pandora.user.ui.itemView, pandora.user.ui.videoView], + pandora.site.itemViews.map(function(view) { + return [ + 'info', pandora.user.ui.videoView + ].indexOf(view.id) > -1 ? null : view.id; + }) + ) + }; + + sortKeys[itemsSection] = {list: {}, item: {}}; + views[itemsSection].list.forEach(function(view) { + sortKeys[itemsSection].list[view] = Ox.merge( + pandora.isClipView(view) ? Ox.clone(pandora.site.clipKeys) : [], + // listSort[0].key is the default sort key + [Ox.getObjectById(pandora.site.sortKeys, pandora.user.ui.listSort[0].key)], + Ox.map(pandora.site.sortKeys, function(key) { + return key.id == pandora.user.ui.listSort[0].key ? null : key; + }) + ); + }); + views[itemsSection].item.forEach(function(view) { + if (pandora.isClipView(view, true)) { + sortKeys[itemsSection].item[view] = Ox.merge( + // itemSort[0].key is the default sort key + [Ox.getObjectById(pandora.site.clipKeys, pandora.user.ui.itemSort[0].key)], + Ox.map(pandora.site.clipKeys, function(key) { + return key.id == pandora.user.ui.itemSort ? null : key; + }) + ); + } + }); + + spanType[itemsSection] = { + list: { + map: 'location', + calendar: 'date' + }, + item: { + video: 'duration', + timeline: 'duration', + map: 'location', + calendar: 'date' + } + }; + + findKeys = Ox.merge([{id: 'list', type: 'string'}], pandora.site.itemKeys); + + self.URL = Ox.URL({ + findKeys: findKeys, + getItem: pandora.getItemByIdOrTitle, + getSpan: pandora.getMetadataByIdOrName, + pages: [ + 'about', 'api', 'contact', 'faq', 'help', 'home', 'news', + 'preferences', 'signin', 'signout', 'signup', + 'software', 'terms', 'tour' + ], + sortKeys: sortKeys, + spanType: spanType, + types: [pandora.site.itemName.plural.toLowerCase(), 'edits', 'texts'], + views: views + }); + + return that; + + }; + + // on page load, this sets the state from the URL + that.parse = function(callback) { + if (document.location.pathname.substr(0, 4) == 'url=') { + document.location.href = decodeURI(document.location.pathname.substr(4)); + } else { + self.URL.parse(function(state) { + setState(state); + callback(); + }); + } + return that; + }; + + // sets the URL to the previous URL + that.pop = function() { + self.URL.pop(); + }; + + // pushes a new URL (as string or from state) + that.push = function(url) { + Ox.print('push', arguments[0]) + if (url) { + self.URL.push(url, setState); + } else { + var state = getState(); + Ox.print('&&&&&&&', state) + self.URL.push(state); + setState(state); + } + return that; + }; + + // replaces the current URL (as string or from state) + that.replace = function(url) { + if (url) { + self.URL.replace(url, setState) + } else { + self.URL.replace(getState()); + } + return that; + }; + + return that; + + /* parse: function(callback) { var pathname = document.location.pathname.substr(1), search = document.location.search.substr(1); @@ -342,8 +663,8 @@ pandora.URL = (function() { update: function() { this.set(pandora.Query.toString()); - }, + } - }; + */ }()); diff --git a/static/js/pandora/pandora.js b/static/js/pandora/pandora.js index 029d9434..e1e34f92 100644 --- a/static/js/pandora/pandora.js +++ b/static/js/pandora/pandora.js @@ -298,16 +298,15 @@ pandora.getGroupsSizes = function() { pandora.getInfoHeight = function() { // fixme: new, check if it can be used more - var isVideoPreview, list + var isVideoPreview if (!pandora.user.ui.item) { - list = pandora.user.ui.lists[pandora.user.ui.list]; - isVideoPreview = list.selected.length && !pandora.isClipView(list.listView); + isVideoPreview = pandora.user.ui.listSelection.length && !pandora.isClipView(); } else { - isVideoPreview = !pandora.isClipView(pandora.user.ui.itemView, true); + isVideoPreview = !pandora.isClipView(); } return pandora.user.ui.showInfo * Math.min( isVideoPreview - ? pandora.user.ui.sidebarSize / (16/9) + 16 + ? Math.round(pandora.user.ui.sidebarSize / (16/9)) + 16 : pandora.user.ui.sidebarSize, window.innerHeight - 109 // 20 menu + 24 bar + 64 (4 closed folders) + 1 resizebar ); @@ -329,7 +328,6 @@ pandora.getItemByIdOrTitle = function(str, callback) { }, function(result) { var id = ''; if (result.data.items.length) { - Ox.print('AAAAAA', result.data.items) var items = Ox.map(result.data.items, function(item) { // test if exact match or word match var sort = new RegExp('^' + str + '$', 'i').test(item.title) ? 2000000 @@ -338,7 +336,6 @@ pandora.getItemByIdOrTitle = function(str, callback) { // fixme: remove the (...|| 0) check once the backend sends correct data }); if (items.length) { - Ox.print('BBBBBB', items) id = items.sort(function(a, b) { return b.sort - a.sort; })[0].id; @@ -458,24 +455,24 @@ pandora.getMetadataByIdOrName = function(item, view, str, callback) { }; pandora.getSortMenu = function() { - var list = pandora.user.ui.lists[pandora.user.ui.list], - isClipView = pandora.isClipView(list.listView); + var ui = pandora.user.ui, + isClipView = pandora.isClipView(ui.listView); return { id: 'sortMenu', title: 'Sort', items: [ { id: 'sortmovies', title: 'Sort ' + (isClipView ? 'Clips' : pandora.site.itemName.plural) + ' by', items: [ { group: 'sortmovies', min: 1, max: 1, items: Ox.merge(isClipView ? Ox.merge(pandora.site.clipKeys.map(function(key) { return Ox.extend({ - checked: list.sort[0].key == key.id + checked: ui.listSort[0].key == key.id }, key); }), {}) : [], pandora.site.sortKeys.map(function(key) { return Ox.extend({ - checked: list.sort[0].key == key.id + checked: ui.listSort[0].key == key.id }, key); })) } ] }, { id: 'ordermovies', title: 'Order ' + (isClipView ? 'Clips' : pandora.site.itemName.plural), items: [ { group: 'ordermovies', min: 1, max: 1, items: [ - { id: 'ascending', title: 'Ascending', checked: (list.sort[0].operator || pandora.getSortOperator(list.sort[0].key)) == '+' }, - { id: 'descending', title: 'Descending', checked: (list.sort[0].operator || pandora.getSortOperator(list.sort[0].key)) == '-' } + { id: 'ascending', title: 'Ascending', checked: (ui.listSort[0].operator || pandora.getSortOperator(ui.listSort[0].key)) == '+' }, + { id: 'descending', title: 'Descending', checked: (ui.listSort[0].operator || pandora.getSortOperator(ui.listSort[0].key)) == '-' } ]} ] }, { id: 'advancedsort', title: 'Advanced Sort...', keyboard: 'shift control s' }, @@ -548,7 +545,10 @@ pandora.getVideoPartsAndPoints = function(durations, points) { }; pandora.isClipView = function(view, item) { - view = view || pandora.user.ui.lists[pandora.user.ui.list].listView; + if (arguments.length == 0) { + item = pandora.user.ui.item; + view = !item ? pandora.user.ui.listView : pandora.user.ui.itemView; + } return ( !item ? ['calendar', 'clip', 'map'] : ['calendar', 'clips', 'map'] ).indexOf(view) > -1; @@ -569,6 +569,7 @@ pandora.signout = function(data) { }; pandora.reloadGroups = function(i) { + // fixme: no longer needed var query = pandora.user.ui.query, view = pandora.user.ui.lists[pandora.user.ui.list].listView; if (view == 'clip') { @@ -688,10 +689,6 @@ pandora.resizeFolders = function() { }); }; -pandora.saveVideoPosition = function() { - //alert(JSON.stringify(['videoPosition|' + old.user.ui.item, pandora.$ui[old.user.ui.itemView == 'player' ? 'player' : 'editor'].options('position')])); -}; - pandora.selectList = function() { if (pandora.user.ui.list) { pandora.api.findLists({ diff --git a/static/js/pandora/ui/backButton.js b/static/js/pandora/ui/backButton.js index 830d8425..6820375d 100644 --- a/static/js/pandora/ui/backButton.js +++ b/static/js/pandora/ui/backButton.js @@ -10,7 +10,6 @@ pandora.ui.backButton = function() { .bindEvent({ click: function() { pandora.UI.set({item: null}); - pandora.URL.update(); } }); return that; diff --git a/static/js/pandora/ui/browser.js b/static/js/pandora/ui/browser.js index e4a77a36..1f1ff7fe 100644 --- a/static/js/pandora/ui/browser.js +++ b/static/js/pandora/ui/browser.js @@ -44,23 +44,25 @@ pandora.ui.browser = function() { draggable: true, id: 'list', item: function(data, sort, size) { - var icons = pandora.user.ui.icons, - ratio = icons == 'posters' ? data.posterRatio : 1; + var ui = pandora.user.ui, + ratio = ui.icons == 'posters' + ? (ui.showSitePoster ? 5/8 : data.posterRatio) : 1, size = size || 64; return { height: ratio <= 1 ? size : size / ratio, id: data.id, info: data[['title', 'director'].indexOf(sort[0].key) > -1 ? 'year' : sort[0].key], title: data.title + (data.director ? ' (' + data.director + ')' : ''), - url: icons == 'posters' - ? '/' + data.id + '/poster' + size + '.jpg' - : '/' + data.id + '/icon' + size + '.jpg', + url: '/' + data.id + '/' + ( + ui.icons == 'posters' + ? (ui.showSitePoster ? 'siteposter' : 'poster') : 'icon' + ) + size + '.jpg', width: ratio >= 1 ? size : size * ratio }; }, items: function(data, callback) { pandora.api.find(Ox.extend(data, { - query: pandora.user.ui.query + query: pandora.user.ui.find }), callback); }, keys: ['director', 'id', 'posterRatio', 'title', 'year'], @@ -69,7 +71,7 @@ pandora.ui.browser = function() { orientation: 'horizontal', selected: [pandora.user.ui.item], size: 64, - sort: pandora.user.ui.lists[pandora.user.ui.list].sort, + sort: pandora.user.ui.listSort, unique: 'id' }) .bindEvent({ @@ -77,8 +79,10 @@ pandora.ui.browser = function() { that.scrollToSelection(); }, select: function(data) { - pandora.UI.set('lists|' + pandora.user.ui.list + '|selected', data.ids); - pandora.URL.set(data.ids[0]); + pandora.UI.set({ + 'listSelection': data.ids, + 'item': data.ids[0] + }); }, toggle: function(data) { pandora.UI.set({showMovies: !data.collapsed}); @@ -90,6 +94,17 @@ pandora.ui.browser = function() { } }); pandora.enableDragAndDrop(that, false); + pandora.UI.bind({ + icons: function(value) { + that.options({ + borderRadius: value == 'posters' ? 0 : 8, + defaultRatio: value == 'posters' ? 5/8 : 1 + }).reloadList(true); + }, + showSitePoster: function() { + that.reloadList(true); + } + }); } that.update = function() { pandora.$ui.contentPanel.replaceElement(0, pandora.$ui.browser = pandora.ui.browser()); diff --git a/static/js/pandora/ui/contentPanel.js b/static/js/pandora/ui/contentPanel.js index 28a087e8..1ee38775 100644 --- a/static/js/pandora/ui/contentPanel.js +++ b/static/js/pandora/ui/contentPanel.js @@ -28,6 +28,14 @@ pandora.ui.contentPanel = function() { ], orientation: 'vertical' }); + pandora.UI.bind({ + listView: function() { + that.replaceElement(1, pandora.$ui.list = pandora.ui.list()); + }, + itemView: function() { + that.replaceElement(1, pandora.$ui.item = pandora.ui.item()); + } + }); return that; }; diff --git a/static/js/pandora/ui/filter.js b/static/js/pandora/ui/filter.js index 377289b7..ab6104ff 100644 --- a/static/js/pandora/ui/filter.js +++ b/static/js/pandora/ui/filter.js @@ -18,8 +18,8 @@ pandora.ui.filter = function(list) { type: 'list' }), list: list ? null : { - sort: pandora.user.ui.lists[pandora.user.ui.list].sort, - view: pandora.user.ui.lists[pandora.user.ui.list].listView + sort: pandora.user.ui.listSort, + view: pandora.user.ui.listView }, query: list ? list.query : pandora.user.ui.query, sortKeys: pandora.site.sortKeys, @@ -49,8 +49,8 @@ pandora.ui.filter = function(list) { }); } else { - pandora.user.ui.query = data.query; - pandora.URL.update(); + pandora.UI.set({find: data.query}); + pandora.URL.push(); //reload(); } } diff --git a/static/js/pandora/ui/findElement.js b/static/js/pandora/ui/findElement.js index 23a8bfa8..2a33e7eb 100644 --- a/static/js/pandora/ui/findElement.js +++ b/static/js/pandora/ui/findElement.js @@ -1,8 +1,8 @@ // vim: et:ts=4:sw=4:sts=4:ft=javascript pandora.ui.findElement = function() { - var findIndex = pandora.user.ui.find.index, - findKey = pandora.user.ui.find.key, - findValue = pandora.user.ui.find.value; + var findIndex = pandora.user.ui._findState.index, + findKey = pandora.user.ui._findState.key, + findValue = pandora.user.ui._findState.value; var that = Ox.FormElementGroup({ elements: Ox.merge(pandora.user.ui.list ? [ pandora.$ui.findListSelect = Ox.Select({ @@ -78,20 +78,21 @@ pandora.ui.findElement = function() { && pandora.$ui.findListSelect.value() == 'list', key = pandora.$ui.findSelect.value(), conditions = data.value ? [{ - key: key == 'all' ? '' : key, + key: key, value: data.value, - operator: '' + operator: '=' }] : []; if (findInList) { - pandora.user.ui.query = { + pandora.UI.set('find', { conditions: Ox.merge([{ key: 'list', value: pandora.user.ui.list, - operator: '' + operator: '==' }], conditions), operator: '&' - } - data.value && findIndex == 0 && pandora.user.ui.query.conditions.reverse(); + }); + // fixme: what was this? + // data.value && findIndex == 0 && pandora.user.ui.find.conditions.reverse(); } else { if (pandora.user.ui.list) { Ox.forEach(pandora.$ui.folderList, function($list) { @@ -99,12 +100,12 @@ pandora.ui.findElement = function() { }); pandora.UI.set({list: ''}); } - pandora.user.ui.query = { + pandora.UI.set('find', { conditions: conditions, operator: '' - } + }); } - pandora.URL.set(pandora.Query.toString()); + pandora.URL.push(); } }) ]), @@ -115,7 +116,7 @@ pandora.ui.findElement = function() { margin: '4px' }); function autocompleteFunction() { - return pandora.user.ui.query.conditions.length ? function(value, callback) { + return pandora.user.ui.find.conditions.length ? function(value, callback) { var elementValue = that.value(), key = elementValue[pandora.user.ui.list ? 1 : 0], findKey = Ox.getObjectById(pandora.site.findKeys, key); diff --git a/static/js/pandora/ui/folders.js b/static/js/pandora/ui/folders.js index 1fc0bcee..8d28216f 100644 --- a/static/js/pandora/ui/folders.js +++ b/static/js/pandora/ui/folders.js @@ -49,7 +49,7 @@ pandora.ui.folders = function() { type: data.id == 'new' ? 'static' : 'smart' }, function(result) { var id = result.data.id; - pandora.UI.set(['lists', id].join('|'), pandora.site.user.ui.lists['']); // fixme: necessary? + pandora.UI.set('lists.' + id, pandora.site.user.ui.lists['']); // fixme: necessary? pandora.URL.set('?find=list:' + id) Ox.Request.clearCache(); // fixme: remove $list.reloadList().bindEventOnce({ @@ -220,7 +220,7 @@ pandora.ui.folders = function() { }, toggle: function(data) { data.collapsed && pandora.$ui.folderList[folder.id].loseFocus(); - pandora.UI.set('showFolder|items|' + folder.id, !data.collapsed); + pandora.UI.set('showFolder.items.' + folder.id, !data.collapsed); pandora.resizeFolders(); } }); diff --git a/static/js/pandora/ui/foldersList.js b/static/js/pandora/ui/foldersList.js index 51402c2b..e42a7ebe 100644 --- a/static/js/pandora/ui/foldersList.js +++ b/static/js/pandora/ui/foldersList.js @@ -29,9 +29,11 @@ pandora.ui.folderList = function(id) { width: 16 }, { + /* format: function(value) { return value.split('/').join(': '); }, + */ id: 'id', operator: '+', unique: true, @@ -261,7 +263,7 @@ pandora.ui.folderList = function(id) { type: event.keys == '' ? 'static' : 'smart' }, function(result) { var id = result.data.id; - pandora.UI.set(['lists', id].join('|'), pandora.site.user.ui.lists['']); // fixme: necessary? + pandora.UI.set('lists.' + id, pandora.site.user.ui.lists['']); // fixme: necessary? pandora.URL.set('?find=list:' + id) Ox.Request.clearCache(); // fixme: remove that.reloadList().bindEventOnce({ @@ -319,7 +321,7 @@ pandora.ui.folderList = function(id) { pandora.api.removeList({ id: data.ids[0] }, function(result) { - pandora.UI.set(['lists', data.ids[0]].join('|'), null); + pandora.UI.set('lists.' + data.ids[0], null); Ox.Request.clearCache(); // fixme: remove that.reloadList(); }); @@ -376,13 +378,25 @@ pandora.ui.folderList = function(id) { id != id_ && $list.options('selected', []); }); } - pandora.URL.set(data.ids.length ? '?find=list:' + data.ids[0] : ''); + // pandora.URL.push(data.ids.length ? '/list==' + data.ids[0] : '') /* pandora.UI.set({ item: '', list: data.ids.length ? data.ids[0] : '' - }); + }) + pandora.URL.push(); */ + pandora.UI.set({ + item: '', + list: data.ids.length ? data.ids[0] : '', + find: { + conditions: data.ids.length ? [ + {key: 'list', value: data.ids[0], operator: '=='} + ] : [], + operator: '&' + } + }) + pandora.URL.push(); }, submit: function(data) { data_ = {id: data.id}; diff --git a/static/js/pandora/ui/group.js b/static/js/pandora/ui/group.js index 0d769deb..0c606016 100644 --- a/static/js/pandora/ui/group.js +++ b/static/js/pandora/ui/group.js @@ -1,6 +1,5 @@ // vim: et:ts=4:sw=4:sts=4:ft=javascript pandora.ui.group = function(id) { - //Ox.print('group', id, Ox.getPositionById(pandora.user.ui.groups, id)) var i = Ox.getPositionById(pandora.user.ui.groups, id), group = Ox.getObjectById(pandora.site.groups, id), panelWidth = pandora.$ui.document.width() - (pandora.user.ui.showSidebar * pandora.user.ui.sidebarSize) - 1, @@ -32,7 +31,6 @@ pandora.ui.group = function(id) { .css({ float: 'left', width: pandora.user.ui.groupsSizes[i] - 64 - Ox.UI.SCROLLBAR_SIZE, - //background: 'red', textOverflow: 'ellipsis', overflowX: 'hidden' }) @@ -62,14 +60,14 @@ pandora.ui.group = function(id) { delete data.keys; return pandora.api.find(Ox.extend(data, { group: id, - query: pandora.user.ui.groupsData[i].query + query: pandora.user.ui._groupsState[i].find }), callback); //} else { // callback({data: {items: data.keys ? [] : 0}}); //} }, scrollbarVisible: true, - selected: pandora.user.ui.groupsData[i].selected, + selected: pandora.user.ui._groupsState[i].selected, sort: [{ key: pandora.user.ui.groups[i].sort[0].key, operator: pandora.user.ui.groups[i].sort[0].operator @@ -80,52 +78,61 @@ pandora.ui.group = function(id) { pandora.$ui.list.triggerEvent('paste', data); }, select: function(data) { + // FIXME: cant index be an empty array, instead of -1? var conditions = data.ids.map(function(value) { return { key: id, value: value, - operator: '=' + operator: '==' }; }), - index = pandora.user.ui.groupsData[i].index; + index = pandora.user.ui._groupsState[i].index, + find = Ox.clone(pandora.user.ui.find, true); if (Ox.isArray(index)) { // this group had multiple selections and the | query // was on the top level, i.e. not bracketed - pandora.user.ui.query = { + find = { conditions: conditions, - operator: conditions.length > 1 ? '|' : '' + operator: conditions.length > 1 ? '|' : '&' } } else { if (index == -1) { // this group had no selection, i.e. no query - index = pandora.user.ui.query.conditions.length; - if (pandora.user.ui.query.operator == '|') { - pandora.user.ui.query = { - conditions: [pandora.user.ui.query], + index = find.conditions.length; + if (find.operator == '|') { + find = { + conditions: [find], operator: '&' }; index = 1; } else { - pandora.user.ui.query.operator = index ? '&' : ''; + find.operator = '&'; } } if (conditions.length == 0) { - pandora.user.ui.query.conditions.splice(index, 1); - if (pandora.user.ui.query.conditions.length == 1) { - pandora.user.ui.query.operator = ''; + // nothing selected + find.conditions.splice(index, 1); + if (find.conditions.length == 1) { + find.operator = '&'; } } else if (conditions.length == 1) { - pandora.user.ui.query.conditions[index] = conditions[0]; + // one item selected + find.conditions[index] = conditions[0]; } else { - pandora.user.ui.query.conditions[index].conditions = conditions; - pandora.user.ui.query.conditions[index].operator = '|'; - delete pandora.user.ui.query.conditions[index].key; - delete pandora.user.ui.query.conditions[index].value; + // multiple items selected + find.conditions[index].conditions = conditions; + find.conditions[index].operator = '|'; + delete find.conditions[index].key; + delete find.conditions[index].value; } } + /* pandora.Query.updateGroups(); pandora.URL.push(pandora.Query.toString()); pandora.reloadGroups(i); + */ + pandora.UI.set('find', find); + pandora.URL.push(); }, sort: function(data) { Ox.print('SORT', data) @@ -154,9 +161,9 @@ pandora.ui.group = function(id) { i_ = Ox.getPositionById(pandora.user.ui.groups, id_); if (i_ == -1) { // new group was not part of old group set - if (pandora.user.ui.groupsData[i].selected.length) { + if (pandora.user.ui._groupsState[i].selected.length) { // if group with selection gets replaced, reload - pandora.user.ui.query.conditions.splice(pandora.user.ui.groupsData[i].index, 1); + pandora.user.ui.find.conditions.splice(pandora.user.ui._groupsState[i].index, 1); pandora.Query.updateGroups(); pandora.URL.push(pandora.Query.toString()); pandora.reloadGroups(i); @@ -169,9 +176,9 @@ pandora.ui.group = function(id) { // if part of the existing query works as a group selection in the new group } else { // swap two existing groups - var groupsData = Ox.clone(pandora.user.ui.groupsData[i]); - pandora.user.ui.groupsData[i] = pandora.user.ui.groupsData[i_]; - pandora.user.ui.groupsData[i_] = groupsData; + var groupsData = Ox.clone(pandora.user.ui._groupsState[i]); + pandora.user.ui._groupsState[i] = pandora.user.ui._groupsState[i_]; + pandora.user.ui._groupsState[i_] = groupsData; groups[i] = makeGroup(id_, pandora.user.ui.groups[i_].sort); groups[i_] = makeGroup(id, pandora.user.ui.groups[i].sort); pandora.UI.set({groups: groups}); @@ -187,8 +194,8 @@ pandora.ui.group = function(id) { sort: sort || [{key: group.type == 'integer' ? 'name' : 'items', operator: '-'}] }; } - function replaceGroup(i, id, query) { - // if query is passed, selected items will be derived from it + function replaceGroup(i, id, find) { + // if find is passed, selected items will be derived from it var isOuter = i % 4 == 0; pandora.$ui[isOuter ? 'browser' : 'groupsInnerPanel'].replaceElement( isOuter ? i / 2 : i - 1, @@ -202,7 +209,6 @@ pandora.ui.group = function(id) { pandora.ui.groups = function() { var $groups = []; - //pandora.user.queryGroups = []; pandora.user.ui.groups.forEach(function(group, i) { $groups[i] = pandora.ui.group(group.id); }); diff --git a/static/js/pandora/ui/home.js b/static/js/pandora/ui/home.js index 8892f571..08b74714 100644 --- a/static/js/pandora/ui/home.js +++ b/static/js/pandora/ui/home.js @@ -59,7 +59,7 @@ pandora.ui.home = function() { }) .bind({ click: function() { - pandora.URL.pushPrevious(); + pandora.URL.pop(); that.fadeOutScreen(); } }) @@ -107,7 +107,7 @@ pandora.ui.home = function() { click: function() { var folder = pandora.getListData().folder; folder && pandora.$ui.folderList[folder].options({selected: []}); - pandora.URL.set('/?find=' + $findInput.value()); + pandora.URL.push('/*=' + $findInput.value()); that.fadeOutScreen(); } }) @@ -127,7 +127,7 @@ pandora.ui.home = function() { }) .bindEvent({ click: function() { - pandora.URL.pushPrevious(); + pandora.URL.push(); that.fadeOutScreen(); } }) @@ -147,7 +147,7 @@ pandora.ui.home = function() { }) .bindEvent({ click: function() { - pandora.URL.set('/signup'); + pandora.URL.push('/signup'); that.fadeOutScreen(); } }), @@ -166,7 +166,7 @@ pandora.ui.home = function() { }) .bindEvent({ click: function() { - pandora.URL.set('/signin'); + pandora.URL.push('/signin'); that.fadeOutScreen(); } }), @@ -185,7 +185,7 @@ pandora.ui.home = function() { }) .bindEvent({ click: function() { - pandora.URL.set('/preferences'); + pandora.URL.push('/preferences'); that.fadeOutScreen(); } }), @@ -204,7 +204,7 @@ pandora.ui.home = function() { }) .bindEvent({ click: function() { - pandora.URL.set('/about'); + pandora.URL.push('/about'); that.fadeOutScreen(); } }) @@ -270,4 +270,4 @@ pandora.ui.home = function() { return that; -}; \ No newline at end of file +}; diff --git a/static/js/pandora/ui/info.js b/static/js/pandora/ui/info.js index 4b71a50d..d341b4b8 100644 --- a/static/js/pandora/ui/info.js +++ b/static/js/pandora/ui/info.js @@ -1,7 +1,10 @@ // vim: et:ts=4:sw=4:sts=4:ft=javascript pandora.ui.info = function() { - var list = pandora.user.ui.lists[pandora.user.ui.list], - id = pandora.user.ui.item || (list.selected.length ? list.selected[list.selected.length - 1] : null), + var id = pandora.user.ui.item || ( + pandora.user.ui.listSelection.length + ? pandora.user.ui.listSelection[pandora.user.ui.listSelection.length - 1] + : null + ), view = getView(), that = Ox.Element() .css({overflowX: 'hidden', overflowY: 'auto'}) @@ -13,7 +16,7 @@ pandora.ui.info = function() { }); Ox.print('INFO', view) if (view == 'list') { - that.empty().append(pandora.$ui.listInfo = pandora.ui.listInfo(list)); + that.empty().append(pandora.$ui.listInfo = pandora.ui.listInfo(pandora.user.ui.list)); } else if (view == 'poster') { pandora.api.get({id: id, keys: ['director', 'posterRatio', 'title']}, function(result) { var ratio = result.data.posterRatio, @@ -75,7 +78,7 @@ pandora.ui.listInfo = function(data) { .attr({src: !pandora.user.ui.list ? '/static/png/icon256.png' : Ox.UI.getImageURL('symbolIcon')}) .css(getIconCSS()) .appendTo(that); - $('