diff --git a/pandora/0xdb.json b/pandora/0xdb.json
index 4d2e6d60..769afced 100644
--- a/pandora/0xdb.json
+++ b/pandora/0xdb.json
@@ -564,7 +564,6 @@
"item": "",
"itemSort": [{"key": "clip:position", "operator": ""}],
"itemView": "info",
- "list": "",
"listColumns": ["title", "director", "country", "year", "language", "runtime", "genre"],
"listColumnWidth": {},
"listSelection": [],
diff --git a/static/js/pandora.js b/static/js/pandora.js
index acc12867..53a3ab19 100644
--- a/static/js/pandora.js
+++ b/static/js/pandora.js
@@ -3,9 +3,25 @@
Pandora
***/
+/*
+---- UI Tree ----
+appPanel
+ mainMenu
+ mainPanel
+ leftPanel
+ sectionbar
+ folders
+ info
+ rightPanel
+ toolbar
+ contentPanel
+ browser <-- should be filters or browser
+ list or item
+ statusbar
+*/
+
// fixme: never set pandora.ui.videoPosition to 0 ... set to null a.k.a. delete
// fixme: sort=-director doesn't work
-// fixme: don't reload full right panel on sortSelect
// fixme: clear items cache after login/logout
Ox.load({
@@ -112,7 +128,7 @@ Ox.load({
}
window.onpopstate = function(event) {
- pandora.URL.update();
+ //pandora.URL.update();
};
// set up url controller
diff --git a/static/js/pandora/UI.js b/static/js/pandora/UI.js
index 295428f7..2defb4da 100644
--- a/static/js/pandora/UI.js
+++ b/static/js/pandora/UI.js
@@ -1,55 +1,36 @@
// vim: et:ts=4:sw=4:sts=4:ft=javascript
pandora.UI = (function() {
+
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 = {};
+ set = {},
+ trigger = {};
self.previousUI = Ox.clone(pandora.user.ui, true);
Ox.forEach(obj, function(val, key) {
- var listSettings = pandora.site.listSettings
- if (key == 'list') {
- if (!pandora.user.ui.lists[val]) {
- obj['lists.' + that.encode(val)] = {};
- }
- Ox.forEach(listSettings, function(listSetting, setting) {
- if (!pandora.user.ui.lists[val]) {
- // add default list settings and copy to settings
- obj['lists.' + that.encode(val)][listSetting] = pandora.site.user.ui[setting];
- obj[setting] = pandora.site.user.ui[setting];
- } else {
- // copy list settings to setting
- obj[setting] = pandora.user.ui.lists[val][listSetting];
- }
- });
- Ox.forEach()
- } 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('.'),
+ listSettings = pandora.site.listSettings,
ui = pandora.user.ui;
while (i < keys.length - 1) {
ui = ui[keys[i]];
@@ -62,20 +43,62 @@ pandora.UI = (function() {
ui[keys[i]] = val;
}
if (key[0] != '_') {
- // don't send private keys
+ // don't save or trigger events for private keys
// set[key] = val;
- // fixme: remove later
- set[key.replace(/\./g, '|')] = val;
+ set[key] = val;
+ trigger[key] = val;
+ }
+ if (key == 'find') {
+ // the challenge here is that find may change list,
+ // and list may then change listSort and listView,
+ // which we don't want to trigger, since find triggers
+ var list = pandora.getListsState()
+ pandora.user.ui._list = list;
+ pandora.user.ui._groupsState = pandora.getGroupsState();
+ pandora.user.ui._findState = pandora.getFindState();
+ if (list != self.previousUI.list) {
+ if (!pandora.user.ui.lists[list]) {
+ set['lists.' + that.encode(list)] = {};
+ }
+ Ox.forEach(listSettings, function(listSetting, setting) {
+ if (!pandora.user.ui.lists[list]) {
+ // add default list settings and copy to settings
+ set['lists.' + that.encode(list)][listSetting] = pandora.site.user.ui[setting];
+ set[setting] = pandora.site.user.ui[setting];
+ } else {
+ // copy list settings to setting
+ set[setting] = pandora.user.ui.lists[list][listSetting];
+ }
+ });
+ }
+ } else if (Object.keys(listSettings).indexOf(key) > -1) {
+ // copy setting to list setting
+ set['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
+ set['videoPoints.' + pandora.user.ui.item] = {'in': 0, out: 0, position: 0};
}
}
});
+ Ox.forEach(trigger, function(val, key) {
+ Ox.Event.trigger(key, val);
+ });
+ // fixme: swap later, once the backend accepts dots
+ // Ox.len(set) && pandora.api.setUI(set);
if (Ox.len(set)) {
+ var set_ = {};
Ox.forEach(set, function(val, key) {
- Ox.Event.trigger(key, val);
+ set_[key.replace(/\./g, '|')] = val;
});
- pandora.api.setUI(set);
+ pandora.api.setUI(set_);
}
};
+
return that;
+
}());
diff --git a/static/js/pandora/URL.js b/static/js/pandora/URL.js
index 6be90b30..acb26afa 100644
--- a/static/js/pandora/URL.js
+++ b/static/js/pandora/URL.js
@@ -87,117 +87,6 @@ pandora.URL = (function() {
}
*/
- 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 {
- // 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
- };
- }
- }
- }
- }
- return state;
- });
- }
-
- 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 {
@@ -218,20 +107,6 @@ pandora.URL = (function() {
};
}
- 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();
@@ -240,8 +115,8 @@ pandora.URL = (function() {
$('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);
+ pandora.user.ui._groupsState = pandora.getGroupsState();
+ pandora.user.ui._findState = pandora.getFindState();
if (Ox.isEmpty(state)) {
if (pandora.user.ui.showHome) {
pandora.$ui.home = pandora.ui.home().showScreen();
@@ -292,21 +167,21 @@ pandora.URL = (function() {
state.find && pandora.UI.set({
find: state.find,
- list: getListsState(state.find)
+ list: pandora.getListsState(state.find)
});
if (state.view) {
pandora.UI.set(
!pandora.user.ui.item
- ? 'lists.' + pandora.user.ui.list + '.view'
+ ? 'listView'
: 'itemView',
state.view
);
}
- pandora.user.ui._groupsState = getGroupsState(pandora.user.ui.find);
+ pandora.user.ui._groupsState = pandora.getGroupsState();
Ox.print('_groupsState =', pandora.user.ui._groupsState);
- pandora.user.ui._findState = getFindState(pandora.user.ui.find, pandora.user.ui.list, pandora.user.ui._groupsState);
+ pandora.user.ui._findState = pandora.getFindState();
if (['video', 'timeline'].indexOf(pandora.user.ui.itemView) > -1) {
if (state.span) {
@@ -331,6 +206,7 @@ pandora.URL = (function() {
state.sort
);
+ /*
if (!pandora.$ui.appPanel) {
return;
}
@@ -403,6 +279,7 @@ pandora.URL = (function() {
$item.options('position')
);
}
+ */
}
pandora.user.ui.showHome = false;
@@ -555,7 +432,7 @@ pandora.URL = (function() {
views: views
});
- ['item', 'itemSort', 'itemView', 'list', 'listSort', 'listView'].forEach(function(event) {
+ ['find', 'item', 'itemSort', 'itemView', 'list', 'listSort', 'listView'].forEach(function(event) {
pandora.UI.bind(event, function() {
that.push();
});
diff --git a/static/js/pandora/pandora.js b/static/js/pandora/pandora.js
index e1e34f92..9b9b52fd 100644
--- a/static/js/pandora/pandora.js
+++ b/static/js/pandora/pandora.js
@@ -368,32 +368,6 @@ pandora.getListData = function() {
return data;
};
-pandora.getListMenu = function(lists) {
- return { id: 'listMenu', title: 'List', items: [
- { id: 'history', title: 'History', items: [
- { id: 'allmovies', title: 'All ' + pandora.site.itemName.plural }
- ] },
- { id: 'viewlist', title: 'View List', items: lists ? ['personal', 'favorite', 'featured'].map(function(folder) {
- return { id: folder + 'lists', title: Ox.toTitleCase(folder) + ' Lists', items: [
- { group: folder + 'lists', min: 0, max: 1, items: lists[folder].map(function(list) {
- return { id: 'viewlist' + list.id, title: (folder == 'favorite' ? list.user + ': ' : '') + list.name, checked: list.id == pandora.user.ui.list };
- }) }
- ] };
- }) : [
- { id: 'loading', title: 'Loading...', disabled: true }
- ] },
- {},
- { id: 'newlist', title: 'New List...', keyboard: 'control n' },
- { id: 'newlistfromselection', title: 'New List from Selection...', disabled: true, keyboard: 'shift control n' },
- { id: 'newsmartlist', title: 'New Smart List...', keyboard: 'alt control n' },
- { id: 'newsmartlistfromresults', title: 'New Smart List from Results...', keyboard: 'shift alt control n' },
- {},
- { id: 'addmovietolist', title: ['Add Selected ' + pandora.site.itemName.singular + ' to List...', 'Add Selected ' + pandora.site.itemName.plural + ' to List...'], disabled: true },
- {},
- { id: 'setposterframe', title: 'Set Poster Frame', disabled: true }
- ] };
-};
-
pandora.getMetadataByIdOrName = function(item, view, str, callback) {
// For a given item (or none) and a given view (or any), this takes a string
// and checks if it's an annotation/event/place id or an event/place name,
@@ -454,56 +428,6 @@ pandora.getMetadataByIdOrName = function(item, view, str, callback) {
}
};
-pandora.getSortMenu = function() {
- 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: ui.listSort[0].key == key.id
- }, key);
- }), {}) : [], pandora.site.sortKeys.map(function(key) {
- return Ox.extend({
- 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: (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' },
- {},
- { id: 'sortgroups', title: 'Sort Groups', items: pandora.user.ui.groups.map(function(group) {
- return {
- id: 'sortgroup' + group.id,
- title: 'Sort ' + Ox.getObjectById(pandora.site.groups, group.id).title + ' Group by',
- items: [
- { group: 'sortgroup' + group.id, min: 1, max: 1, items: [
- { id: 'name', title: 'Name', checked: group.sort[0].key == 'name' },
- { id: 'items', title: 'Items', checked: group.sort[0].key == 'items' }
- ] }
- ]
- }
- }) },
- { id: 'ordergroups', title: 'Order Groups', items: pandora.user.ui.groups.map(function(group) {
- return {
- id: 'ordergroup' + group.id,
- title: 'Order ' + Ox.getObjectById(pandora.site.groups, group.id).title + ' Group',
- items: [
- { group: 'ordergroup' + group.id, min: 1, max: 1, items: [
- { id: 'ascending', title: 'Ascending', checked: group.sort[0].operator == '+' },
- { id: 'descending', title: 'Descending', checked: group.sort[0].operator == '-' }
- ] }
- ]
- }
- }) }
- ] };
-};
-
pandora._getSortOperator = function(type) {
return ['hue', 'string', 'text'].indexOf(
Ox.isArray(type) ? type[0] : type
@@ -568,59 +492,6 @@ pandora.signout = function(data) {
pandora.$ui.appPanel.reload();
};
-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') {
- pandora.$ui.list.options({
- items: function(data, callback) {
- return pandora.api.findAnnotations(Ox.extend(data, {
- itemQuery: query
- }), callback);
- }
- });
- } else if (view == 'map') {
- pandora.$ui.map.options({
- places: function(data, callback) {
- return pandora.api.findPlaces(Ox.extend(data, {
- itemQuery: query
- }), callback);
- }
- });
- } else if (view == 'calendar') {
- pandora.$ui.list.options({
- items: function(data, callback) {
- return pandora.api.findEvents(Ox.extend(data, {
- itemQuery: query
- }), callback);
- }
- });
- } else {
- pandora.$ui.list.options({
- items: function(data, callback) {
- return pandora.api.find(Ox.extend(data, {
- query: query
- }), callback);
- }
- });
- }
- Ox.forEach(pandora.user.ui.groups, function(group, i_) {
- if (i_ != i) {
- //Ox.print('setting groups request', i, i_)
- pandora.$ui.groups[i_].options({
- items: function(data, callback) {
- delete data.keys;
- return pandora.api.find(Ox.extend(data, {
- group: group.id,
- query: pandora.user.ui.groupsData[i_].query
- }), callback);
- }
- });
- }
- });
-};
-
pandora.reloadList = function() {
Ox.print('reloadList')
var listData = pandora.getListData();
@@ -628,7 +499,8 @@ pandora.reloadList = function() {
pandora.$ui.groups.forEach(function($group) {
$group.reloadList();
});
- pandora.$ui.list.bindEvent({
+ pandora.$ui.list
+ .bindEvent({
init: function(data) {
// fixme: this will not work for lists in the favorites folder
// (but then it's also unlikely they'll have to be reloaded)
@@ -647,7 +519,6 @@ pandora.reloadList = function() {
pandora.resizeGroups = function(width) {
pandora.user.ui.groupsSizes = pandora.getGroupsSizes();
- Ox.print('{}{}{}', window.innerWidth, window.innerWidth - pandora.user.ui.showSidebar * pandora.user.ui.sidebarSize - 1, pandora.user.ui.groupsSizes)
pandora.$ui.browser
.size(0, pandora.user.ui.groupsSizes[0])
.size(2, pandora.user.ui.groupsSizes[4]);
@@ -666,14 +537,12 @@ pandora.resizeFolders = function() {
columnWidth = {user: parseInt((width - 96) * 0.4)};
columnWidth.name = (width - 96) - columnWidth.user;
}
- //Ox.print('sectionsWidth', width)
Ox.forEach(pandora.$ui.folderList, function($list, id) {
- var i = Ox.getPositionById(pandora.site.sectionFolders[pandora.user.ui.section], id);
- pandora.$ui.folder[i].css({width: width + 'px'});
+ var pos = Ox.getPositionById(pandora.site.sectionFolders[pandora.user.ui.section], id);
+ pandora.$ui.folder[pos].css({width: width + 'px'});
$list.css({width: width + 'px'});
if (pandora.user.ui.section == 'items') {
- if (pandora.site.sectionFolders[pandora.user.ui.section][i].showBrowser) {
- Ox.print('ID', id)
+ if (pandora.site.sectionFolders[pandora.user.ui.section][pos].showBrowser) {
pandora.$ui.findListInput[id].options({
width: width - 24
});
@@ -684,12 +553,13 @@ pandora.resizeFolders = function() {
}
}
if (!pandora.user.ui.showFolder[pandora.user.ui.section][id]) {
- pandora.$ui.folder[i].update();
+ pandora.$ui.folder[pos].update();
}
});
};
pandora.selectList = function() {
+ // fixme: can this be removed?
if (pandora.user.ui.list) {
pandora.api.findLists({
keys: ['status', 'user'],
@@ -710,10 +580,143 @@ pandora.selectList = function() {
.gainFocus();
} else {
pandora.user.ui.list = '';
- //pandora.user.ui.listQuery.conditions = []; // fixme: Query should read from pandora.ui.list, and not need pandora.ui.listQuery to be reset
- //pandora.URL.set(pandora.Query.toString());
}
});
}
};
+(function() {
+
+ // Note: getFindState has to run after getListState and getGroupsState
+
+ 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 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;
+ }
+
+ pandora.getFindState = function() {
+ // 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,
+ find = pandora.user.ui.find,
+ indices,
+ state = {index: -1, key: '*', value: ''};
+ if (find.operator == '&') {
+ // number of conditions that are not list or groups
+ conditions = find.conditions.length
+ - !!pandora.user.ui.list
+ - pandora.user.ui._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;
+ }
+
+ pandora.getGroupsState = function() {
+ // 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
+ var find = pandora.user.ui.find;
+ 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 {
+ // 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
+ };
+ }
+ }
+ }
+ }
+ return state;
+ });
+ }
+
+ pandora.getListsState = function() {
+ // A list is selected if exactly one condition in an & query has "list"
+ // as key and "==" as operator
+ var find = pandora.user.ui.find, index, state = '';
+ if (find.operator == '&') {
+ index = oneCondition(find.conditions, 'list', '==');
+ if (index > -1) {
+ state = find.conditions[index].value;
+ }
+ }
+ return state;
+ };
+
+}());
\ No newline at end of file
diff --git a/static/js/pandora/ui/browser.js b/static/js/pandora/ui/browser.js
index 1f1ff7fe..db5229a4 100644
--- a/static/js/pandora/ui/browser.js
+++ b/static/js/pandora/ui/browser.js
@@ -102,13 +102,10 @@ pandora.ui.browser = function() {
}).reloadList(true);
},
showSitePoster: function() {
- that.reloadList(true);
+ pandora.user.ui.icons == 'poster' && that.reloadList(true);
}
});
}
- that.update = function() {
- pandora.$ui.contentPanel.replaceElement(0, pandora.$ui.browser = pandora.ui.browser());
- }
return that;
};
diff --git a/static/js/pandora/ui/contentPanel.js b/static/js/pandora/ui/contentPanel.js
index 843ae65b..3625558f 100644
--- a/static/js/pandora/ui/contentPanel.js
+++ b/static/js/pandora/ui/contentPanel.js
@@ -32,8 +32,8 @@ pandora.ui.contentPanel = function() {
listView: function() {
that.replaceElement(1, pandora.$ui.list = pandora.ui.list());
},
- item: function() {
- that.replaceElement(1, pandora.$ui.item = pandora.ui.item());
+ item: function(value) {
+ value && that.replaceElement(1, pandora.$ui.item = pandora.ui.item());
},
itemView: function() {
that.replaceElement(1, pandora.$ui.item = pandora.ui.item());
diff --git a/static/js/pandora/ui/findElement.js b/static/js/pandora/ui/findElement.js
index 2a33e7eb..209538a0 100644
--- a/static/js/pandora/ui/findElement.js
+++ b/static/js/pandora/ui/findElement.js
@@ -105,7 +105,6 @@ pandora.ui.findElement = function() {
operator: ''
});
}
- pandora.URL.push();
}
})
]),
@@ -120,12 +119,15 @@ pandora.ui.findElement = function() {
var elementValue = that.value(),
key = elementValue[pandora.user.ui.list ? 1 : 0],
findKey = Ox.getObjectById(pandora.site.findKeys, key);
- Ox.print('!!!!', key, findKey, 'autocomplete' in findKey && findKey.autocomplete)
value === '' && Ox.print('Warning: autocomplete function should never be called with empty value');
- if ('autocomplete' in findKey && findKey.autocomplete) {
+ if (findKey.autocomplete) {
pandora.api.autocomplete({
key: key,
- query: elementValue[0].id == 'list' ? pandora.user.ui.listQuery : {conditions: [], operator: ''},
+ query: {
+ conditions: pandora.$ui.findListSelect.value() == 'list'
+ ? [{key: 'list', value: pandora.user.ui.list, operator: '=='}] : [],
+ operator: '&'
+ },
range: [0, 20],
sort: [{
key: 'votes',
diff --git a/static/js/pandora/ui/folderList.js b/static/js/pandora/ui/folderList.js
index f196cc81..7e87446a 100644
--- a/static/js/pandora/ui/folderList.js
+++ b/static/js/pandora/ui/folderList.js
@@ -1,4 +1,5 @@
// vim: et:ts=4:sw=4:sts=4:ft=javascript
+
pandora.ui.folderList = function(id) {
var i = Ox.getPositionById(pandora.site.sectionFolders[pandora.user.ui.section], id),
that;
@@ -372,30 +373,20 @@ pandora.ui.folderList = function(id) {
pandora.$ui.list.triggerEvent('paste', data);
},
select: function(data) {
- if (data.ids.length) {
+ var list = data.ids.length ? data.ids[0] : '';
+ if (list) {
Ox.forEach(pandora.$ui.folderList, function($list, id_) {
id != id_ && $list.options('selected', []);
});
}
- // 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 ? [
+ conditions: list ? [
{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/folders.js b/static/js/pandora/ui/folders.js
index 8d28216f..cc5c88d4 100644
--- a/static/js/pandora/ui/folders.js
+++ b/static/js/pandora/ui/folders.js
@@ -29,6 +29,7 @@ pandora.ui.folders = function() {
{ id: 'newsmart', title: 'New Smart List...' },
{ id: 'newfromresults', title: 'New Smart List from Current Results...', disabled: true },
{},
+ { id: 'duplicate', title: 'Duplicate List' },
{ id: 'copyselection', title: 'Copy Selection to List...' },
{ id: 'moveselection', title: 'Move Selection to List...' }
],
diff --git a/static/js/pandora/ui/group.js b/static/js/pandora/ui/group.js
index 0c606016..5b9c1254 100644
--- a/static/js/pandora/ui/group.js
+++ b/static/js/pandora/ui/group.js
@@ -132,7 +132,7 @@ pandora.ui.group = function(id) {
pandora.reloadGroups(i);
*/
pandora.UI.set('find', find);
- pandora.URL.push();
+ //pandora.URL.push();
},
sort: function(data) {
Ox.print('SORT', data)
diff --git a/static/js/pandora/ui/infoView.js b/static/js/pandora/ui/infoView.js
index 8f4915cf..b0cb498a 100644
--- a/static/js/pandora/ui/infoView.js
+++ b/static/js/pandora/ui/infoView.js
@@ -517,7 +517,9 @@ pandora.ui.infoView = function(data) {
pandora.UI.bind({
icons: that.reload,
- showSitePoster: that.reload
+ showSitePoster: function() {
+ pandora.user.ui.icons == 'poster' && that.reload();
+ }
});
return that;
diff --git a/static/js/pandora/ui/list.js b/static/js/pandora/ui/list.js
index 9f71f64d..43246430 100644
--- a/static/js/pandora/ui/list.js
+++ b/static/js/pandora/ui/list.js
@@ -689,7 +689,7 @@ pandora.ui.list = function() {
}).reloadList(true);
},
showSitePoster: function() {
- that.reloadList(true);
+ pandora.user.ui.icons == 'poster' && that.reloadList(true);
}
});
}
diff --git a/static/js/pandora/ui/menu.js b/static/js/pandora/ui/menu.js
index e280187e..c2af1c8e 100644
--- a/static/js/pandora/ui/menu.js
+++ b/static/js/pandora/ui/menu.js
@@ -1,5 +1,6 @@
// vim: et:ts=4:sw=4:sts=4:ft=javascript
pandora.ui.mainMenu = function() {
+
var isGuest = pandora.user.level == 'guest',
ui = pandora.user.ui,
that = Ox.MainMenu({
@@ -33,7 +34,7 @@ pandora.ui.mainMenu = function() {
isGuest ? { id: 'signin', title: 'Sign In...' }
: { id: 'signout', title: 'Sign Out...'}
] },
- pandora.getListMenu(),
+ getListMenu(),
{ id: 'editMenu', title: 'Edit', items: [
{ id: 'undo', title: 'Undo', disabled: true, keyboard: 'control z' },
{ id: 'redo', title: 'Redo', disabled: true, keyboard: 'shift control z' },
@@ -104,7 +105,7 @@ pandora.ui.mainMenu = function() {
]}
] }
]},
- pandora.getSortMenu(),
+ getSortMenu(),
{ id: 'findMenu', title: 'Find', items: [
{ id: 'find', title: 'Find', items: [
{ group: 'find', min: 1, max: 1, items: pandora.site.findKeys.map(function(key, i) {
@@ -210,309 +211,12 @@ pandora.ui.mainMenu = function() {
pandora.$ui.postersDialog = pandora.ui.postersDialog(id).open();
} else if (data.id == 'places') {
pandora.$ui.placesDialog = pandora.ui.placesDialog().open();
- /*
- var $manage = Ox.SplitPanel({
- elements: [
- {
- collapsible: true,
- element: Ox.SplitPanel({
- elements: [
- {
- element: Ox.Toolbar({
- orientation: 'horizontal',
- size: 44
- }).append(
- pandora.$ui.findPlacesElement = Ox.FormElementGroup({
- elements: [
- pandora.$ui.findPlacesSelect = Ox.Select({
- id: 'findPlacesSelect',
- items: [
- { id: 'name', title: 'Find: Name' },
- { id: 'region', title: 'Find: Region' },
- { id: 'user', title: 'Find: User' }
- ],
- overlap: 'right',
- type: 'image'
- })
- .bindEvent({
- change: function(data) {
- pandora.$ui.findPlacesSelect.loseFocus();
- pandora.$ui.findPlacesInput.options({
- placeholder: data.selected[0].title
- });
- }
- }),
- pandora.$ui.findPlacesInput = Ox.Input({
- clear: true,
- id: 'findPlacesInput',
- placeholder: 'Find: Name',
- width: 234
- })
- ],
- id: 'findPlacesElement'
- })
- .css({
- float: 'left',
- margin: '4px'
- })
- ).append(
- pandora.$ui.sortPlacesSelect = Ox.Select({
- id: 'sortPlacesSelect',
- items: [
- { id: 'name', title: 'Sort by Name', checked: true },
- { id: 'region', title: 'Sort by Region' },
- { id: 'size', title: 'Sort by Size' },
- { id: 'latitude', title: 'Sort by Latitude' },
- { id: 'longitude', title: 'Sort by Longitude' },
- { id: 'clips', title: 'Sort by Number of Clips' },
- { id: 'user', title: 'Sort by User' },
- { id: 'datecreated', title: 'Sort by Date Added' },
- { id: 'datemodified', title: 'Sort by Date Modified' }
- ],
- width: 246
- })
- .css({
- float: 'left',
- margin: '0 4px 4px 4px'
- })
- ),
- size: 44
- },
- {
- element: Ox.Element('div')
- },
- {
- element: Ox.Toolbar({
- orientation: 'horizontal',
- size: 16
- }),
- size: 16
- }
- ],
- orientation: 'vertical'
- }),
- size: 256
- },
- {
- element: Ox.SplitPanel({
- elements: [
- {
- element: Ox.Toolbar({
- orientation: 'horizontal',
- size: 24
- }).append(
- pandora.$ui.labelsButton = Ox.Button({
- id: 'labelsButton',
- title: [
- {id: 'show', title: 'Show Labels'},
- {id: 'hide', title: 'Hide Labels'}
- ],
- width: 96
- })
- .css({
- float: 'left',
- margin: '4px'
- })
- ).append(
- pandora.$ui.findMapInput = Ox.Input({
- clear: true,
- id: 'findMapInput',
- placeholder: 'Find on Map',
- width: 192
- })
- .css({
- float: 'right',
- margin: '4px'
- })
- .bindEvent({
- submit: function(data) {
- pandora.$ui.map.find(data.value, function(location) {
-
- pandora.$ui.placeNameInput.options({
- disabled: false,
- value: location.name
- });
- pandora.$ui.placeAliasesInput.options({
- disabled: false
- });
- pandora.$ui.placeGeonameLabel.options({
- disabled: false,
- title: location.names.join(', ')
- });
- pandora.$ui.removePlaceButton.options({
- disabled: false
- });
- pandora.$ui.addPlaceButton.options({
- disabled: false
- });
-
- });
- }
- })
- ),
- size: 24
- },
- {
- element: pandora.$ui.map = Ox.Map({
- places: ['Boston', 'Brussels', 'Barcelona', 'Berlin', 'Beirut', 'Bombay', 'Bangalore', 'Beijing']
- })
- .css({
- left: 0,
- top: 0,
- right: 0,
- bottom: 0
- })
- .bindEvent({
- select: function(event, location) {
- pandora.$ui.placeNameInput.options({
- disabled: false,
- value: location.name
- });
- pandora.$ui.placeAliasesInput.options({
- disabled: false
- });
- pandora.$ui.placeGeonameLabel.options({
- disabled: false,
- title: location.names.join(', ')
- });
- pandora.$ui.removePlaceButton.options({
- disabled: false
- });
- pandora.$ui.addPlaceButton.options({
- disabled: false
- });
- }
- })
- },
- {
- element: pandora.$ui.bottomBar = Ox.Toolbar({
- orientation: 'horizontal',
- size: 24
- })
- .append(
- pandora.$ui.placeNameInput = Ox.Input({
- disabled: true,
- id: 'placeName',
- placeholder: 'Name',
- width: 128
- })
- .css({
- float: 'left',
- margin: '4px 0 0 4px'
- })
- )
- .append(
- pandora.$ui.placeAliasesInput = Ox.Input({
- disabled: true,
- id: 'aliases',
- placeholder: 'Aliases',
- width: 128
- })
- .css({
- float: 'left',
- margin: '4px 0 0 4px'
- })
- )
- .append(
- pandora.$ui.placeGeonameLabel = Ox.Label({
- disabled: true,
- id: 'placeGeoname',
- title: 'Geoname',
- width: parseInt(pandora.$ui.document.width() * 0.8) - 256 - 256 - 32 - 24
- })
- .css({
- float: 'left',
- margin: '4px 0 0 4px'
- })
- )
- .append(
- pandora.$ui.addPlaceButton = Ox.Button({
- disabled: true,
- id: 'addPlaceButton',
- title: 'add',
- type: 'image'
- })
- .css({
- float: 'right',
- margin: '4px 4px 0 0'
- })
- )
- .append(
- pandora.$ui.removePlaceButton = Ox.Button({
- disabled: true,
- id: 'removePlaceButton',
- title: 'remove',
- type: 'image'
- })
- .css({
- float: 'right',
- margin: '4px 4px 0 0'
- })
- ),
- size: 24
- }
- ],
- orientation: 'vertical'
- })
- }
- ],
- orientation: 'horizontal'
- }).css({
- top: '24px',
- bottom: '24px',
- }),
- $dialog = Ox.Dialog({
- buttons: [
- {
- click: function() {
- $dialog.close();
- },
- id: 'close',
- title: 'Close',
- value: 'Close'
- }
- ],
- height: parseInt(pandora.$ui.document.height() * 0.8),
- id: 'places',
- minHeight: 400,
- minWidth: 600,
- padding: 0,
- title: 'Manage Places',
- width: parseInt(pandora.$ui.document.width() * 0.8)
- }).css({
- overflow: 'hidden'
- }).append($manage).open();
- */
} else if (data.id == 'events') {
pandora.$ui.eventsDialog = pandora.ui.eventsDialog().open();
} else if (data.id == 'users') {
pandora.$ui.eventsDialog = pandora.ui.usersDialog().open();
} else if (data.id == 'lists') {
pandora.$ui.eventsDialog = pandora.ui.listsDialog().open();
- } else if (data.id == 'query') {
- var $dialog = Ox.Dialog({
- buttons: [
- Ox.Button({
- id: 'close',
- title: 'Close'
- }).bindEvent({
- click: function() {
- $dialog.close();
- }
- })
- ],
- content: Ox.Element()
- .css({padding: '16px'})
- .html([
- 'Query: ' + JSON.stringify(pandora.Query.toObject()),
- 'findQuery: ' + JSON.stringify(pandora.user.ui.findQuery),
- 'listQuery: ' + JSON.stringify(pandora.user.ui.listQuery)
- ].join('
')),
- height: 192,
- keys: {enter: 'close', escape: 'close'},
- title: 'Query',
- width: 384
- }).open();
} else if (data.id == 'resetgroups') {
pandora.UI.set({
groups: pandora.site.user.ui.groups
@@ -528,6 +232,90 @@ pandora.ui.mainMenu = function() {
}
});
+ function getListMenu(lists) {
+ return { id: 'listMenu', title: 'List', items: Ox.merge(
+ ['personal', 'favorite', 'featured'].map(function(folder) {
+ return {
+ id: folder + 'lists',
+ title: Ox.toTitleCase(folder) + ' Lists',
+ items: [{
+ group: folder + 'lists',
+ min: 0,
+ max: 1,
+ items: lists ? lists[folder].map(function(list) {
+ return {
+ id: 'viewlist' + list.id,
+ title: (folder == 'favorite' ? list.user + ': ' : '') + list.name,
+ checked: list.id == pandora.user.ui.list
+ };
+ }) : [{id: 'loading', title: 'Loading...', disabled: true}]
+ }]
+ };
+ }),
+ [
+ {},
+ { id: 'newlist', title: 'New List...', keyboard: 'control n' },
+ { id: 'newlistfromselection', title: 'New List from Selection...', disabled: true, keyboard: 'shift control n' },
+ { id: 'newsmartlist', title: 'New Smart List...', keyboard: 'alt control n' },
+ { id: 'newsmartlistfromresults', title: 'New Smart List from Results...', keyboard: 'shift alt control n' },
+ {},
+ { id: 'addmovietolist', title: ['Add Selected ' + pandora.site.itemName.singular + ' to List...', 'Add Selected ' + pandora.site.itemName.plural + ' to List...'], disabled: true },
+ {},
+ { id: 'setposterframe', title: 'Set Poster Frame', disabled: true }
+ ]
+ )};
+ };
+
+ function getSortMenu() {
+ 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: ui.listSort[0].key == key.id
+ }, key);
+ }), {}) : [], pandora.site.sortKeys.map(function(key) {
+ return Ox.extend({
+ 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: (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' },
+ {},
+ { id: 'sortgroups', title: 'Sort Groups', items: pandora.user.ui.groups.map(function(group) {
+ return {
+ id: 'sortgroup' + group.id,
+ title: 'Sort ' + Ox.getObjectById(pandora.site.groups, group.id).title + ' Group by',
+ items: [
+ { group: 'sortgroup' + group.id, min: 1, max: 1, items: [
+ { id: 'name', title: 'Name', checked: group.sort[0].key == 'name' },
+ { id: 'items', title: 'Items', checked: group.sort[0].key == 'items' }
+ ] }
+ ]
+ }
+ }) },
+ { id: 'ordergroups', title: 'Order Groups', items: pandora.user.ui.groups.map(function(group) {
+ return {
+ id: 'ordergroup' + group.id,
+ title: 'Order ' + Ox.getObjectById(pandora.site.groups, group.id).title + ' Group',
+ items: [
+ { group: 'ordergroup' + group.id, min: 1, max: 1, items: [
+ { id: 'ascending', title: 'Ascending', checked: group.sort[0].operator == '+' },
+ { id: 'descending', title: 'Descending', checked: group.sort[0].operator == '-' }
+ ] }
+ ]
+ }
+ }) }
+ ] };
+ }
+
// fixme: the sidebar makes the same requests.
// is it ok to make them twice, or should the sidebar trigger the menu replace?
@@ -556,7 +344,7 @@ pandora.ui.mainMenu = function() {
lists[folder] = result.data.items;
if (++counter == 3) {
Ox.print('--------------------------------------------', lists)
- pandora.$ui.mainMenu.replaceMenu('listMenu', pandora.getListMenu(lists));
+ pandora.$ui.mainMenu.replaceMenu('listMenu', getListMenu(lists));
}
});
});
diff --git a/static/js/pandora/ui/rightPanel.js b/static/js/pandora/ui/rightPanel.js
index 6a940b51..87560932 100644
--- a/static/js/pandora/ui/rightPanel.js
+++ b/static/js/pandora/ui/rightPanel.js
@@ -58,8 +58,21 @@ pandora.ui.rightPanel = function() {
});
}
pandora.UI.bind({
- list: function() {
- that.replaceElement(1, pandora.$ui.contentPanel = pandora.ui.contentPanel());
+ find: function() {
+ var previousUI = pandora.UI.getPrevious();
+ if (pandora.user.ui.list == previousUI.list) {
+ pandora.$ui.list.reloadList();
+ pandora.user.ui._groupsState.forEach(function(data, i) {
+ if (!Ox.isEqual(data.selected, previousUI._groupsState[i].selected)) {
+ pandora.$ui.groups[i].options({selected: data.selected});
+ }
+ if (!Ox.isEqual(data.find, previousUI._groupsState[i].find)) {
+ pandora.$ui.groups[i].reloadList();
+ }
+ });
+ } else {
+ that.replaceElement(1, pandora.$ui.contentPanel = pandora.ui.contentPanel());
+ }
},
itemView: function(value) {
if (pandora.isClipView() != pandora.isClipView(pandora.UI.getPrevious('itemView'))) {
diff --git a/static/js/pandora/ui/sortSelect.js b/static/js/pandora/ui/sortSelect.js
index 089a4ba2..d429fc6b 100644
--- a/static/js/pandora/ui/sortSelect.js
+++ b/static/js/pandora/ui/sortSelect.js
@@ -38,7 +38,7 @@ pandora.ui.sortSelect = function() {
listSort: function(value) {
that.selectItem(value[0].key);
},
- item: function(valye) {
+ item: function(value) {
},
itemSort: function(value) {