').css({ float: 'left', width: '122px', height: '14px', margin: '2px' }).html('Foo')
+ ).append(
+ $('
').css({ float: 'left', width: '40px', height: '14px', margin: '2px', textAlign: 'right' }).html('23')
+ )
+ );
+ });
+ $.each($bins, function(i, bin) {
+ that.append(bin);
+ });
+ return that;
+};
+
+
+
diff --git a/static/js/pandora/ui/filter.js b/static/js/pandora/ui/filter.js
new file mode 100644
index 000000000..e936916ce
--- /dev/null
+++ b/static/js/pandora/ui/filter.js
@@ -0,0 +1,21 @@
+// vim: et:ts=4:sw=4:sts=4:ft=js
+pandora.ui.filter = function() {
+ var that = new Ox.Filter({
+ findKeys: $.map(app.config.itemKeys, function(key) {
+ return {
+ autocomplete: key.autocomplete,
+ autocompleteSortKey: key.autocompleteSortKey,
+ format: key.format,
+ id: key.id,
+ title: key.title,
+ type: key.type == 'layer' ? Ox.getObjectById(
+ app.config.layers, key.id
+ ).type : key.type
+ };
+ }),
+ sortKeys: app.ui.sortKeys,
+ viewKeys: app.config.listViews
+ });
+ return that;
+};
+
diff --git a/static/js/pandora/ui/filterDialog.js b/static/js/pandora/ui/filterDialog.js
new file mode 100644
index 000000000..c30ca0d7d
--- /dev/null
+++ b/static/js/pandora/ui/filterDialog.js
@@ -0,0 +1,41 @@
+// vim: et:ts=4:sw=4:sts=4:ft=js
+pandora.ui.filterDialog = function() {
+ var that = new Ox.Dialog({
+ buttons: [
+ new Ox.Button({
+ id: 'debug',
+ title: 'Debug',
+ })
+ .bindEvent({
+ click: function() {
+ alert(JSON.stringify(app.$ui.filter.options('query')));
+ }
+ }),
+ new Ox.Button({
+ id: 'cancel',
+ title: 'Cancel'
+ })
+ .bindEvent({
+ click: function() {
+ app.$ui.filterDialog.close();
+ }
+ }),
+ new Ox.Button({
+ id: 'save',
+ title: 'Save'
+ })
+ .bindEvent({
+ click: function() {
+ app.$ui.filterDialog.close();
+ }
+ })
+ ],
+ content: app.$ui.filter = new pandora.ui.filter(),
+ height: 264,
+ keys: {enter: 'save', escape: 'cancel'},
+ title: 'Advanced Find',
+ width: 616 + Ox.UI.SCROLLBAR_SIZE
+ });
+ return that;
+};
+
diff --git a/static/js/pandora/ui/findElement.js b/static/js/pandora/ui/findElement.js
new file mode 100644
index 000000000..02da85bf3
--- /dev/null
+++ b/static/js/pandora/ui/findElement.js
@@ -0,0 +1,127 @@
+// vim: et:ts=4:sw=4:sts=4:ft=js
+pandora.ui.findElement = function() {
+ var findKey = '',
+ findValue = '';
+ if (app.user.ui.findQuery.conditions.length == 1) {
+ findKey = app.user.ui.findQuery.conditions[0].key;
+ findValue = app.user.ui.findQuery.conditions[0].value;
+ }
+ var that = new Ox.FormElementGroup({
+ elements: $.merge(app.user.ui.list ? [
+ app.$ui.findListSelect = new Ox.Select({
+ items: [
+ {id: 'all', title: 'Find: All ' + app.config.itemName.plural},
+ {id: 'list', title: 'Find: This List'}
+ ],
+ overlap: 'right',
+ type: 'image'
+ })
+ .bindEvent({
+ change: function(event, data) {
+ var key = data.selected[0].id;
+ app.$ui.findInput.options({
+ autocomplete: autocompleteFunction()
+ }).focus();
+ }
+ }),
+ ] : [], [
+ app.$ui.findSelect = new Ox.Select({
+ id: 'select',
+ items: $.merge($.merge([{
+ id: 'all',
+ title: 'Find: All'
+ }], $.map(app.ui.findKeys, function(key, i) {
+ return {
+ id: key.id,
+ checked: key.id == findKey,
+ title: 'Find: ' + key.title
+ };
+ })), [{}, {
+ id: 'advanced',
+ title: 'Find: Advanced'
+ }]),
+ overlap: 'right',
+ width: 112
+ })
+ .bindEvent({
+ change: function(event, data) {
+ var key = data.selected[0].id;
+ if (key == 'advanced') {
+ app.$ui.filterDialog = pandora.ui.filterDialog().open();
+ } else {
+ if (!app.user.ui.findQuery.conditions.length) { // fixme: can this case happen at all?
+ app.user.ui.findQuery.conditions = [{key: key, value: '', operator: ''}];
+ } else {
+ app.user.ui.findQuery.conditions[0].key = key;
+ }
+ app.$ui.mainMenu.checkItem('findMenu_find_' + key);
+ app.$ui.findInput.options({
+ autocomplete: autocompleteFunction()
+ }).focus();
+ }
+ }
+ }),
+ app.$ui.findInput = new Ox.Input({
+ autocomplete: autocompleteFunction(),
+ autocompleteSelect: true,
+ autocompleteSelectHighlight: true,
+ autocompleteSelectSubmit: true,
+ clear: true,
+ id: 'input',
+ value: findValue,
+ width: 192
+ })
+ .bindEvent({
+ submit: function(event, data) {
+ var key = app.user.ui.findQuery.conditions.length ?
+ app.user.ui.findQuery.conditions[0].key : '';
+ if (app.user.ui.list && that.value()[0].id == 'all') {
+ $.each(app.$ui.folderList, function(k, $list) {
+ $list.options({selected: []});
+ });
+ pandora.UI.set({list: ''});
+ app.user.ui.listQuery = {conditions: [], operator: ''};
+ }
+ app.user.ui.findQuery.conditions = [{
+ key: key == 'all' ? '' : key,
+ value: data.value,
+ operator: ''
+ }];
+ pandora.URL.set(pandora.Query.toString());
+ }
+ })
+ ]),
+ id: 'findElement'
+ })
+ .css({
+ float: 'right',
+ margin: '4px'
+ });
+ function autocompleteFunction() {
+ return app.user.ui.findQuery.conditions.length ? function(value, callback) {
+ var elementValue = that.value(),
+ key = elementValue[app.user.ui.list ? 1 : 0].id,
+ findKey = Ox.getObjectById(app.ui.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) {
+ pandora.api.autocomplete({
+ key: key,
+ query: elementValue[0].id == 'list' ? app.user.ui.listQuery : {conditions: [], operator: ''},
+ range: [0, 20],
+ sort: [{
+ key: 'votes',
+ operator: '-'
+ }],
+ value: value
+ }, function(result) {
+ callback(result.data.items);
+ });
+ } else {
+ callback([]);
+ }
+ } : null;
+ }
+ return that;
+};
+
diff --git a/static/js/pandora/ui/flipbook.js b/static/js/pandora/ui/flipbook.js
new file mode 100644
index 000000000..71068622a
--- /dev/null
+++ b/static/js/pandora/ui/flipbook.js
@@ -0,0 +1,26 @@
+// vim: et:ts=4:sw=4:sts=4:ft=js
+pandora.ui.flipbook = function(item) {
+ var that = new Ox.Flipbook({
+ }).bindEvent('click', function(event, data) {
+ pandora.UI.set('videoPosition|' + item, data.position);
+ pandora.URL.set(item + '/timeline');
+ });
+ pandora.api.getItem(item, function(result) {
+ var duration = result.data.item.duration,
+ posterFrame = result.data.item.posterFrame || parseInt(duration/2),
+ steps = 24,
+ framePrefix = '/' + item + '/frame/' + that.width() + '/',
+ frames = {};
+ Ox.range(0, duration, duration/steps).forEach(function(position) {
+ position = parseInt(position);
+ frames[position] = framePrefix + position + '.jpg';
+ });
+ that.options({
+ frames: frames,
+ icon: framePrefix + posterFrame + '.jpg',
+ duration: duration
+ });
+ });
+ return that;
+};
+
diff --git a/static/js/pandora/ui/folderBrowser.js b/static/js/pandora/ui/folderBrowser.js
new file mode 100644
index 000000000..f9f8c2625
--- /dev/null
+++ b/static/js/pandora/ui/folderBrowser.js
@@ -0,0 +1,17 @@
+// vim: et:ts=4:sw=4:sts=4:ft=js
+pandora.ui.folderBrowser = function(id) {
+ var that = new Ox.SplitPanel({
+ elements: [
+ {
+ element: pandora.ui.folderBrowserBar(),
+ size: 24
+ },
+ {
+ element: app.$ui.folderList[id] = pandora.ui.folderBrowserList(id)
+ }
+ ],
+ orientation: 'vertical'
+ });
+ return that;
+};
+
diff --git a/static/js/pandora/ui/folderBrowserBar.js b/static/js/pandora/ui/folderBrowserBar.js
new file mode 100644
index 000000000..82aa02095
--- /dev/null
+++ b/static/js/pandora/ui/folderBrowserBar.js
@@ -0,0 +1,17 @@
+// vim: et:ts=4:sw=4:sts=4:ft=js
+pandora.ui.folderBrowserBar = function(id) {
+ var that = new Ox.Bar({
+ size: 24
+ });
+ app.$ui.findListInput = new Ox.Input({
+ placeholder: 'Find User',
+ width: 184 - Ox.UI.SCROLLBAR_SIZE
+ })
+ .css({
+ margin: '4px',
+ align: 'right'
+ })
+ .appendTo(that);
+ return that;
+};
+
diff --git a/static/js/pandora/ui/folderBrowserList.js b/static/js/pandora/ui/folderBrowserList.js
new file mode 100644
index 000000000..a432badae
--- /dev/null
+++ b/static/js/pandora/ui/folderBrowserList.js
@@ -0,0 +1,664 @@
+// vim: et:ts=4:sw=4:sts=4:ft=js
+pandora.ui.folderBrowserList = function(id) {
+ var columnWidth = (app.user.ui.sidebarSize - Ox.UI.SCROLLBAR_SIZE - 88) / 2,
+ i = Ox.getPositionById(app.ui.sectionFolders[app.user.ui.section], id),
+ that = new Ox.TextList({
+ columns: [
+ {
+ format: function() {
+ return $('
')
+ .attr({
+ src: Ox.UI.PATH + 'png/icon16.png'
+ });
+ },
+ id: 'id',
+ operator: '+',
+ title: $('
')
+ .attr({
+ src: Ox.UI.PATH + 'png/icon16.png'
+ })
+ .css({
+ width: '10px',
+ height: '10px',
+ padding: '3px 2px 1px 2px',
+ }),
+ unique: true,
+ visible: true,
+ width: 16
+ },
+ {
+ id: 'user',
+ operator: '+',
+ title: 'User',
+ visible: true,
+ width: Math.floor(columnWidth)
+ },
+ {
+ id: 'name',
+ operator: '+',
+ title: 'List',
+ visible: true,
+ width: Math.ceil(columnWidth)
+ },
+ {
+ align: 'right',
+ id: 'items',
+ operator: '-',
+ title: 'Items',
+ visible: true,
+ width: 40
+ },
+ {
+ clickable: function(data) {
+ return data.type == 'smart';
+ },
+ format: function(value) {
+ return $('
')
+ .attr({
+ src: Ox.UI.getImagePath('symbolFind.svg')
+ })
+ .css({
+ width: '10px',
+ height: '10px',
+ padding: '3px 2px 1px 2px', // fixme: strange
+ opacity: value == 'static' ? 0.1 : 1
+ });
+ },
+ id: 'type',
+ operator: '+',
+ title: $('
')
+ .attr({
+ src: Ox.UI.getImagePath('symbolFind.svg')
+ })
+ .css({
+ width: '10px',
+ height: '10px',
+ padding: '3px 2px 1px 2px',
+ }),
+ visible: true,
+ width: 16
+ },
+ {
+ clickable: true,
+ format: function(value) {
+ return $('
')
+ .attr({
+ src: Ox.UI.getImagePath(
+ 'symbol' + (id == 'favorite' ? 'Check' : 'Star') + '.svg'
+ )
+ })
+ .css({
+ width: '10px',
+ height: '10px',
+ padding: '3px 2px 1px 2px',
+ opacity: id == 'favorite' ? (value ? 1 : 0.1) :
+ (value == 'featured' ? 1 : 0.1)
+ });
+ },
+ id: id == 'favorite' ? 'subscribed' : 'status',
+ operator: '+',
+ title: $('
')
+ .attr({
+ src: Ox.UI.getImagePath(
+ 'symbol' + (id == 'favorite' ? 'Check' : 'Star') + '.svg'
+ )
+ })
+ .css({
+ width: '10px',
+ height: '10px',
+ padding: '3px 2px 1px 2px'
+ }),
+ visible: true,
+ width: 16
+ },
+ ],
+ columnsVisible: true,
+ items: function(data, callback) {
+ var query = id == 'favorite' ? {conditions: [
+ {key: 'user', value: app.user.username, operator: '!'},
+ {key: 'status', value: 'public', operator: '='}
+ ], operator: '&'} : {conditions: [
+ {key: 'status', value: 'public', operator: '='},
+ {key: 'status', value: 'featured', operator: '='}
+ ], operator: '|'};
+ return pandora.api.findLists($.extend(data, {
+ query: query
+ }), callback);
+ },
+ pageLength: 1000,
+ // fixme: select if previously selected
+ // selected: app.user.ui.list ? [app.user.ui.list] : [],
+ sort: [
+ {key: 'name', operator: '+'}
+ ]
+ })
+ .bindEvent({
+ click: function(event, data) {
+ if (data.key == 'type') {
+ alert('...');
+ } else if (data.key == 'subscribed') {
+ var subscribed = that.value(data.id, 'subscribed');
+ pandora.api[subscribed ? 'unsubscribeFromList' : 'subscribeToList']({
+ id: data.id,
+ }, function(result) {
+ that.value(data.id, 'subscribed', !subscribed);
+ });
+ } else if (data.key == 'status') {
+ pandora.api.editList({
+ id: data.id,
+ status: that.value(data.id, 'status') == 'featured' ? 'public' : 'featured'
+ }, function(result) {
+ Ox.print('result', result)
+ if (result.data.user == app.user.username || result.data.subscribed) {
+ Ox.Request.clearCache(); // fixme: remove
+ app.$ui.folderList[
+ result.data.user == app.user.username ? 'personal' : 'favorite'
+ ].reloadList();
+ }
+ that.value(data.id, 'status', result.data.status);
+ });
+ }
+ },
+ init: function(event, data) {
+ app.ui.sectionFolders[app.user.ui.section][i].items = data.items;
+ app.$ui.folder[i].$content.css({
+ height: 40 + data.items * 16 + 'px'
+ });
+ app.$ui.folderList[id].css({
+ height: 16 + data.items * 16 + 'px'
+ });
+ pandora.resizeFolders();
+ },
+ paste: function(event, data) {
+ app.$ui.list.triggerEvent('paste', data);
+ },
+ select: function(event, data) {
+ // fixme: duplicated
+ if (data.ids.length) {
+ $.each(app.$ui.folderList, function(id_, $list) {
+ id != id_ && $list.options('selected', []);
+ });
+ pandora.UI.set({list: data.ids[0]});
+ pandora.URL.set('?find=list:' + data.ids[0]);
+ } else {
+ pandora.UI.set({list: ''});
+ pandora.URL.set('');
+ }
+ }
+ });
+ return that;
+};
+
+pandora.ui.folderList = function(id) {
+ var i = Ox.getPositionById(app.ui.sectionFolders[app.user.ui.section], id),
+ that;
+ if (app.user.ui.section == 'site') {
+ that = new Ox.TextList({
+ columns: [
+ {
+ format: function() {
+ return $('
')
+ .attr({
+ src: Ox.UI.PATH + 'png/icon16.png'
+ })
+ },
+ id: 'id',
+ operator: '+',
+ unique: true,
+ visible: true,
+ width: 16
+ },
+ {
+ id: 'title',
+ operator: '+',
+ visible: true,
+ width: app.user.ui.sidebarSize - 16
+ }
+ ],
+ items: function(data, callback) {
+ var result = {data: {}};
+ if (!data.range) {
+ result.data.items = Ox.getObjectById(app.ui.sectionFolders.site, id).items.length;
+ } else {
+ result.data.items = Ox.getObjectById(app.ui.sectionFolders.site, id).items;
+ }
+ callback(result);
+ },
+ max: 1,
+ min: 1,
+ sort: [{key: '', operator: ''}]
+ })
+ .bindEvent({
+ select: function(event, data) {
+ // fixme: duplicated
+ $.each(app.$ui.folderList, function(id_, $list) {
+ id != id_ && $list.options('selected', []);
+ })
+ pandora.URL.set((id == 'admin' ? 'admin/' : '' ) + data.ids[0]);
+ },
+ });
+ } else if (app.user.ui.section == 'items') {
+ that = new Ox.TextList({
+ columns: [
+ {
+ format: function() {
+ return $('
').attr({
+ src: Ox.UI.PATH + 'png/icon16.png'
+ });
+ },
+ id: 'user',
+ operator: '+',
+ visible: true,
+ width: 16
+ },
+ {
+ format: function(value) {
+ return value.split('/').join(': ');
+ },
+ id: 'id',
+ operator: '+',
+ unique: true,
+ visible: id == 'favorite',
+ width: app.user.ui.sidebarWidth - 88
+ },
+ {
+ editable: function(data) {
+ return data.user == app.user.username;
+ },
+ id: 'name',
+ input: {
+ autovalidate: pandora.ui.autovalidateListname
+ },
+ operator: '+',
+ visible: id != 'favorite',
+ width: app.user.ui.sidebarWidth - 88
+ },
+ {
+ align: 'right',
+ id: 'items',
+ operator: '-',
+ visible: true,
+ width: 40
+ },
+ {
+ clickable: function(data) {
+ return data.type == 'smart';
+ },
+ format: function(value) {
+ return $('
')
+ .attr({
+ src: Ox.UI.getImagePath('symbolFind.svg')
+ })
+ .css({
+ width: '10px',
+ height: '10px',
+ padding: '3px 2px 1px 2px',
+ opacity: value == 'static' ? 0.1 : 1
+ });
+ },
+ id: 'type',
+ operator: '+',
+ visible: true,
+ width: 16
+ },
+ {
+ clickable: id == 'personal',
+ format: function(value) {
+ //var symbols = {private: 'Publish', public: 'Publish', featured: 'Star'};
+ return $('
')
+ .attr({
+ src: Ox.UI.getImagePath(
+ 'symbol' + (value == 'featured' ? 'Star' : 'Publish') + '.svg'
+ )
+ })
+ .css({
+ width: '10px',
+ height: '10px',
+ padding: '3px 2px 1px 2px',
+ opacity: value == 'private' ? 0.1 : 1
+ })
+ },
+ id: 'status',
+ operator: '+',
+ visible: true,
+ width: 16
+ }
+ ],
+ items: function(data, callback) {
+ var query;
+ if (id == 'personal') {
+ query = {conditions: [
+ {key: 'user', value: app.user.username, operator: '='},
+ {key: 'status', value: 'featured', operator: '!'}
+ ], operator: '&'};
+ } else if (id == 'favorite') {
+ query = {conditions: [
+ {key: 'subscribed', value: true, operator: '='},
+ {key: 'status', value: 'featured', operator: '!'},
+ ], operator: '&'};
+ } else if (id == 'featured') {
+ query = {conditions: [{key: 'status', value: 'featured', operator: '='}], operator: '&'};
+ }
+ return pandora.api.findLists($.extend(data, {
+ query: query
+ }), callback);
+ },
+ max: 1,
+ min: 0,
+ pageLength: 1000,
+ sort: [
+ {key: 'position', operator: '+'}
+ ],
+ sortable: id == 'personal' || id == 'favorite' || app.user.level == 'admin'
+ })
+ .css({
+ left: 0,
+ top: 0,
+ width: app.user.ui.sidebarWidth + 'px',
+ })
+ .bind({
+ dragenter: function(e) {
+ //Ox.print('DRAGENTER', e)
+ }
+ })
+ .bindEvent({
+ click: function(event, data) {
+ var $list = app.$ui.folderList[id];
+ if (data.key == 'type') {
+ app.$ui.filterDialog = pandora.ui.filterDialog().open();
+ } else if (data.key == 'status') {
+ pandora.api.editList({
+ id: data.id,
+ status: $list.value(data.id, data.key) == 'private' ? 'public' : 'private'
+ }, function(result) {
+ $list.value(result.data.id, 'status', result.data.status);
+ });
+ }
+ },
+ 'delete': function(event, data) {
+ var $list = app.$ui.folderList[id];
+ app.user.ui.listQuery.conditions = [];
+ pandora.URL.set(pandora.Query.toString());
+ $list.options({selected: []});
+ if (id == 'personal') {
+ pandora.api.removeList({
+ id: data.ids[0]
+ }, function(result) {
+ // fixme: is this the best way to delete a ui preference?
+ delete app.user.ui.lists[data.ids[0]];
+ pandora.UI.set({lists: app.user.ui.lists});
+ Ox.Request.clearCache(); // fixme: remove
+ $list.reloadList();
+ });
+ } else if (id == 'favorite') {
+ pandora.api.unsubscribeFromList({
+ id: data.ids[0]
+ }, function(result) {
+ Ox.Request.clearCache(); // fixme: remove
+ $list.reloadList();
+ });
+ } else if (id == 'featured' && app.user.level == 'admin') {
+ pandora.api.editList({
+ id: data.ids[0],
+ status: 'public'
+ }, function(result) {
+ // fixme: duplicated
+ if (result.data.user == app.user.username || result.data.subscribed) {
+ Ox.Request.clearCache(); // fixme: remove
+ app.$ui.folderList[
+ result.data.user == app.user.username ? 'personal' : 'favorite'
+ ].reloadList();
+ }
+ $list.reloadList();
+ });
+ }
+ },
+ init: function(event, data) {
+ app.ui.sectionFolders[app.user.ui.section][i].items = data.items;
+ app.$ui.folder[i].$content.css({
+ height: data.items * 16 + 'px'
+ });
+ app.$ui.folderList[id].css({
+ height: data.items * 16 + 'px'
+ });
+ pandora.resizeFolders();
+ },
+ move: function(event, data) {
+ /*
+ data.ids.forEach(function(id, pos) {
+ app.user.ui.lists[id].position = pos;
+ });
+ */
+ pandora.api.sortLists({
+ section: id,
+ ids: data.ids
+ });
+ },
+ paste: function(event, data) {
+ app.$ui.list.triggerEvent('paste', data);
+ },
+ select: function(event, data) {
+ if (data.ids.length) {
+ $.each(app.$ui.folderList, function(id_, $list) {
+ id != id_ && $list.options('selected', []);
+ })
+ pandora.URL.set('?find=list:' + data.ids[0]);
+ } else {
+ pandora.URL.set('?find=');
+ }
+ },
+ submit: function(event, data) {
+ data_ = {id: data.id};
+ data_[data.key] = data.value;
+ pandora.api.editList(data_, function(result) {
+ if (result.data.id != data.id) {
+ app.$ui.folderList[id].value(data.id, 'name', result.data.name);
+ app.$ui.folderList[id].value(data.id, 'id', result.data.id);
+ pandora.URL.set('?find=list:' + result.data.id);
+ }
+ });
+ }
+ });
+ }
+ return that;
+};
+
+pandora.ui.folders = function() {
+ var that = new Ox.Element()
+ .css({overflowX: 'hidden', overflowY: 'auto'})
+ .bindEvent({
+ resize: function(event, data) {
+ pandora.resizeFolders();
+ }
+ });
+ var counter = 0;
+ //var $sections = [];
+ app.$ui.folder = [];
+ app.$ui.folderBrowser = {};
+ app.$ui.folderList = {};
+ if (app.user.ui.section == 'site') {
+ $.each(app.ui.sectionFolders.site, function(i, folder) {
+ var height = (Ox.getObjectById(app.ui.sectionFolders.site, folder.id).items.length * 16);
+ app.$ui.folder[i] = new Ox.CollapsePanel({
+ id: folder.id,
+ collapsed: !app.user.ui.showFolder.site[folder.id],
+ size: 16,
+ title: folder.title
+ })
+ .bindEvent({
+ toggle: function(event, data) {
+
+ }
+ });
+ //alert(JSON.stringify(Ox.getObjectById(app.ui.sectionFolders.site, folder.id)))
+ app.$ui.folder[i].$content.css({
+ height: height + 'px'
+ })
+ //.appendTo(that);
+ app.$ui.folderList[folder.id] = pandora.ui.folderList(folder.id)
+ .css({
+ height: height + 'px'
+ })
+ .appendTo(app.$ui.folder[i].$content);
+ app.$ui.folder.forEach(function($folder) {
+ that.append($folder);
+ });
+ });
+ //pandora.resizeFolders();
+ } else if (app.user.ui.section == 'items') {
+ $.each(app.ui.sectionFolders.items, function(i, folder) {
+ var extras = [];
+ if (folder.id == 'personal' && app.user.level != 'guest') {
+ extras = [new Ox.Select({
+ items: [
+ { id: 'new', title: 'New List...' },
+ { id: 'newfromselection', title: 'New List from Current Selection...', disabled: true },
+ { id: 'newsmart', title: 'New Smart List...' },
+ { id: 'newfromresults', title: 'New Smart List from Current Results...', disabled: true },
+ {},
+ { id: 'addselection', title: 'Add Selection to List...' }
+ ],
+ max: 0,
+ min: 0,
+ selectable: false,
+ type: 'image'
+ })
+ .bindEvent({
+ click: function(event, data) {
+ var $list = app.$ui.folderList[folder.id],
+ id;
+ if (data.id == 'new' || data.id == 'newsmart') {
+ pandora.api.addList({
+ name: 'Untitled',
+ status: 'private',
+ type: data.id == 'new' ? 'static' : 'smart'
+ }, function(result) {
+ id = result.data.id;
+ pandora.UI.set(['lists', id].join('|'), app.config.user.ui.lists['']); // fixme: necessary?
+ pandora.URL.set('?find=list:' + id)
+ Ox.Request.clearCache(); // fixme: remove
+ $list.reloadList().bindEventOnce({
+ load: function(event, data) {
+ $list.gainFocus()
+ .options({selected: [id]})
+ .editCell(id, 'name');
+ }
+ });
+ });
+ }
+ }
+ })];
+ } else if (folder.id == 'favorite' && app.user.level != 'guest') {
+ extras = [new Ox.Button({
+ selectable: true,
+ style: 'symbol',
+ title: 'Edit',
+ tooltip: 'Manage Favorite Lists',
+ type: 'image'
+ })
+ .bindEvent({
+ change: function(event, data) {
+ Ox.Request.clearCache(); // fixme: remove
+ app.ui.sectionFolders.items[i].showBrowser = !app.ui.sectionFolders.items[i].showBrowser;
+ if (app.ui.sectionFolders.items[i].showBrowser) {
+ app.$ui.folderList.favorite.replaceWith(
+ app.$ui.folderBrowser.favorite = pandora.ui.folderBrowser('favorite')
+ );
+ } else {
+ app.$ui.folderBrowser.favorite.replaceWith(
+ app.$ui.folderList.favorite = pandora.ui.folderList('favorite')
+ );
+ }
+ pandora.resizeFolders();
+ }
+ })];
+ } else if (folder.id == 'featured' && app.user.level == 'admin') {
+ extras = [new Ox.Button({
+ selectable: true,
+ style: 'symbol',
+ title: 'Edit',
+ tooltip: 'Manage Featured Lists',
+ type: 'image'
+ })
+ .bindEvent({
+ change: function(event, data) {
+ Ox.Request.clearCache(); // fixme: remove
+ app.ui.sectionFolders.items[i].showBrowser = !app.ui.sectionFolders.items[i].showBrowser;
+ if (app.ui.sectionFolders.items[i].showBrowser) {
+ app.$ui.folderList.featured.replaceWith(
+ app.$ui.folderBrowser.featured = pandora.ui.folderBrowser('featured'));
+ } else {
+ app.$ui.folderBrowser.featured.replaceWith(
+ app.$ui.folderList.featured = pandora.ui.folderList('featured')
+ );
+ }
+ pandora.resizeFolders();
+ }
+ })];
+ }
+ app.$ui.folder[i] = new Ox.CollapsePanel({
+ id: folder.id,
+ collapsed: !app.user.ui.showFolder.items[folder.id],
+ extras: extras,
+ size: 16,
+ title: folder.title
+ })
+ .bindEvent({
+ // fixme: duplicated
+ click: function(event, data) {
+ var $list = app.$ui.folderList[i],
+ hasFocus, id;
+ if (data.id == 'new' || data.id == 'newsmart') {
+ pandora.api.addList({
+ name: 'Untitled',
+ status: 'private',
+ type: data.id == 'new' ? 'static' : 'smart'
+ }, function(result) {
+ id = result.data.id;
+ pandora.URL.set('?find=list:' + id)
+ Ox.Request.clearCache(); // fixme: remove
+ $list.reloadList().bindEventOnce({
+ load: function(event, data) {
+ $list.gainFocus()
+ .options({selected: [id]})
+ .editCell(id, 'name');
+ }
+ });
+ });
+ } else if (data.id == 'browse') {
+ alert('??')
+ /*
+ app.$ui.sectionList[1].replaceWith(app.$ui.publicLists = pandora.ui.publicLists());
+ app.ui.showAllPublicLists = true;
+ */
+ }
+ },
+ toggle: function(event, data) {
+ data.collapsed && app.$ui.folderList[folder.id].loseFocus();
+ pandora.UI.set('showFolder|items|' + folder.id, !data.collapsed);
+ pandora.resizeFolders();
+ }
+ });
+ //$sections.push(app.$ui.section[i]);
+ app.$ui.folderList[folder.id] = pandora.ui.folderList(folder.id)
+ .bindEventOnce({
+ init: function(event, data) {
+ Ox.print('init', i, counter)
+ if (++counter == 3) {
+ app.$ui.folder.forEach(function($folder) {
+ that.append($folder);
+ });
+ pandora.resizeFolders();
+ pandora.selectList(); //fixme: doesn't work
+ }
+ }
+ })
+ .appendTo(app.$ui.folder[i].$content);
+ });
+ }
+ that.toggle = function() {
+
+ }
+ return that;
+};
+
diff --git a/static/js/pandora/ui/folders.js b/static/js/pandora/ui/folders.js
new file mode 100644
index 000000000..a09e00e6c
--- /dev/null
+++ b/static/js/pandora/ui/folders.js
@@ -0,0 +1,199 @@
+// vim: et:ts=4:sw=4:sts=4:ft=js
+pandora.ui.folders = function() {
+ var that = new Ox.Element()
+ .css({overflowX: 'hidden', overflowY: 'auto'})
+ .bindEvent({
+ resize: function(event, data) {
+ pandora.resizeFolders();
+ }
+ });
+ var counter = 0;
+ //var $sections = [];
+ app.$ui.folder = [];
+ app.$ui.folderBrowser = {};
+ app.$ui.folderList = {};
+ if (app.user.ui.section == 'site') {
+ $.each(app.ui.sectionFolders.site, function(i, folder) {
+ var height = (Ox.getObjectById(app.ui.sectionFolders.site, folder.id).items.length * 16);
+ app.$ui.folder[i] = new Ox.CollapsePanel({
+ id: folder.id,
+ collapsed: !app.user.ui.showFolder.site[folder.id],
+ size: 16,
+ title: folder.title
+ })
+ .bindEvent({
+ toggle: function(event, data) {
+
+ }
+ });
+ //alert(JSON.stringify(Ox.getObjectById(app.ui.sectionFolders.site, folder.id)))
+ app.$ui.folder[i].$content.css({
+ height: height + 'px'
+ })
+ //.appendTo(that);
+ app.$ui.folderList[folder.id] = pandora.ui.folderList(folder.id)
+ .css({
+ height: height + 'px'
+ })
+ .appendTo(app.$ui.folder[i].$content);
+ app.$ui.folder.forEach(function($folder) {
+ that.append($folder);
+ });
+ });
+ //pandora.resizeFolders();
+ } else if (app.user.ui.section == 'items') {
+ $.each(app.ui.sectionFolders.items, function(i, folder) {
+ var extras = [];
+ if (folder.id == 'personal' && app.user.level != 'guest') {
+ extras = [new Ox.Select({
+ items: [
+ { id: 'new', title: 'New List...' },
+ { id: 'newfromselection', title: 'New List from Current Selection...', disabled: true },
+ { id: 'newsmart', title: 'New Smart List...' },
+ { id: 'newfromresults', title: 'New Smart List from Current Results...', disabled: true },
+ {},
+ { id: 'addselection', title: 'Add Selection to List...' }
+ ],
+ max: 0,
+ min: 0,
+ selectable: false,
+ type: 'image'
+ })
+ .bindEvent({
+ click: function(event, data) {
+ var $list = app.$ui.folderList[folder.id],
+ id;
+ if (data.id == 'new' || data.id == 'newsmart') {
+ pandora.api.addList({
+ name: 'Untitled',
+ status: 'private',
+ type: data.id == 'new' ? 'static' : 'smart'
+ }, function(result) {
+ id = result.data.id;
+ pandora.UI.set(['lists', id].join('|'), app.config.user.ui.lists['']); // fixme: necessary?
+ pandora.URL.set('?find=list:' + id)
+ Ox.Request.clearCache(); // fixme: remove
+ $list.reloadList().bindEventOnce({
+ load: function(event, data) {
+ $list.gainFocus()
+ .options({selected: [id]})
+ .editCell(id, 'name');
+ }
+ });
+ });
+ }
+ }
+ })];
+ } else if (folder.id == 'favorite' && app.user.level != 'guest') {
+ extras = [new Ox.Button({
+ selectable: true,
+ style: 'symbol',
+ title: 'Edit',
+ tooltip: 'Manage Favorite Lists',
+ type: 'image'
+ })
+ .bindEvent({
+ change: function(event, data) {
+ Ox.Request.clearCache(); // fixme: remove
+ app.ui.sectionFolders.items[i].showBrowser = !app.ui.sectionFolders.items[i].showBrowser;
+ if (app.ui.sectionFolders.items[i].showBrowser) {
+ app.$ui.folderList.favorite.replaceWith(
+ app.$ui.folderBrowser.favorite = pandora.ui.folderBrowser('favorite')
+ );
+ } else {
+ app.$ui.folderBrowser.favorite.replaceWith(
+ app.$ui.folderList.favorite = pandora.ui.folderList('favorite')
+ );
+ }
+ pandora.resizeFolders();
+ }
+ })];
+ } else if (folder.id == 'featured' && app.user.level == 'admin') {
+ extras = [new Ox.Button({
+ selectable: true,
+ style: 'symbol',
+ title: 'Edit',
+ tooltip: 'Manage Featured Lists',
+ type: 'image'
+ })
+ .bindEvent({
+ change: function(event, data) {
+ Ox.Request.clearCache(); // fixme: remove
+ app.ui.sectionFolders.items[i].showBrowser = !app.ui.sectionFolders.items[i].showBrowser;
+ if (app.ui.sectionFolders.items[i].showBrowser) {
+ app.$ui.folderList.featured.replaceWith(
+ app.$ui.folderBrowser.featured = pandora.ui.folderBrowser('featured'));
+ } else {
+ app.$ui.folderBrowser.featured.replaceWith(
+ app.$ui.folderList.featured = pandora.ui.folderList('featured')
+ );
+ }
+ pandora.resizeFolders();
+ }
+ })];
+ }
+ app.$ui.folder[i] = new Ox.CollapsePanel({
+ id: folder.id,
+ collapsed: !app.user.ui.showFolder.items[folder.id],
+ extras: extras,
+ size: 16,
+ title: folder.title
+ })
+ .bindEvent({
+ // fixme: duplicated
+ click: function(event, data) {
+ var $list = app.$ui.folderList[i],
+ hasFocus, id;
+ if (data.id == 'new' || data.id == 'newsmart') {
+ pandora.api.addList({
+ name: 'Untitled',
+ status: 'private',
+ type: data.id == 'new' ? 'static' : 'smart'
+ }, function(result) {
+ id = result.data.id;
+ pandora.URL.set('?find=list:' + id)
+ Ox.Request.clearCache(); // fixme: remove
+ $list.reloadList().bindEventOnce({
+ load: function(event, data) {
+ $list.gainFocus()
+ .options({selected: [id]})
+ .editCell(id, 'name');
+ }
+ });
+ });
+ } else if (data.id == 'browse') {
+ alert('??')
+ /*
+ app.$ui.sectionList[1].replaceWith(app.$ui.publicLists = pandora.ui.publicLists());
+ app.ui.showAllPublicLists = true;
+ */
+ }
+ },
+ toggle: function(event, data) {
+ data.collapsed && app.$ui.folderList[folder.id].loseFocus();
+ pandora.UI.set('showFolder|items|' + folder.id, !data.collapsed);
+ pandora.resizeFolders();
+ }
+ });
+ //$sections.push(app.$ui.section[i]);
+ app.$ui.folderList[folder.id] = pandora.ui.folderList(folder.id)
+ .bindEventOnce({
+ init: function(event, data) {
+ Ox.print('init', i, counter)
+ if (++counter == 3) {
+ app.$ui.folder.forEach(function($folder) {
+ that.append($folder);
+ });
+ pandora.resizeFolders();
+ pandora.selectList(); //fixme: doesn't work
+ }
+ }
+ })
+ .appendTo(app.$ui.folder[i].$content);
+ });
+ }
+ that.toggle = function() {
+
+ };
+ return that;
+};
diff --git a/static/js/pandora/ui/foldersList.js b/static/js/pandora/ui/foldersList.js
new file mode 100644
index 000000000..266ddd4c7
--- /dev/null
+++ b/static/js/pandora/ui/foldersList.js
@@ -0,0 +1,274 @@
+// vim: et:ts=4:sw=4:sts=4:ft=js
+pandora.ui.folderList = function(id) {
+ var i = Ox.getPositionById(app.ui.sectionFolders[app.user.ui.section], id),
+ that;
+ if (app.user.ui.section == 'site') {
+ that = new Ox.TextList({
+ columns: [
+ {
+ format: function() {
+ return $('
')
+ .attr({
+ src: Ox.UI.PATH + 'png/icon16.png'
+ })
+ },
+ id: 'id',
+ operator: '+',
+ unique: true,
+ visible: true,
+ width: 16
+ },
+ {
+ id: 'title',
+ operator: '+',
+ visible: true,
+ width: app.user.ui.sidebarSize - 16
+ }
+ ],
+ items: function(data, callback) {
+ var result = {data: {}};
+ if (!data.range) {
+ result.data.items = Ox.getObjectById(app.ui.sectionFolders.site, id).items.length;
+ } else {
+ result.data.items = Ox.getObjectById(app.ui.sectionFolders.site, id).items;
+ }
+ callback(result);
+ },
+ max: 1,
+ min: 1,
+ sort: [{key: '', operator: ''}]
+ })
+ .bindEvent({
+ select: function(event, data) {
+ // fixme: duplicated
+ $.each(app.$ui.folderList, function(id_, $list) {
+ id != id_ && $list.options('selected', []);
+ })
+ pandora.URL.set((id == 'admin' ? 'admin/' : '' ) + data.ids[0]);
+ },
+ });
+ } else if (app.user.ui.section == 'items') {
+ that = new Ox.TextList({
+ columns: [
+ {
+ format: function() {
+ return $('
').attr({
+ src: Ox.UI.PATH + 'png/icon16.png'
+ });
+ },
+ id: 'user',
+ operator: '+',
+ visible: true,
+ width: 16
+ },
+ {
+ format: function(value) {
+ return value.split('/').join(': ');
+ },
+ id: 'id',
+ operator: '+',
+ unique: true,
+ visible: id == 'favorite',
+ width: app.user.ui.sidebarWidth - 88
+ },
+ {
+ editable: function(data) {
+ return data.user == app.user.username;
+ },
+ id: 'name',
+ input: {
+ autovalidate: pandora.ui.autovalidateListname
+ },
+ operator: '+',
+ visible: id != 'favorite',
+ width: app.user.ui.sidebarWidth - 88
+ },
+ {
+ align: 'right',
+ id: 'items',
+ operator: '-',
+ visible: true,
+ width: 40
+ },
+ {
+ clickable: function(data) {
+ return data.type == 'smart';
+ },
+ format: function(value) {
+ return $('
')
+ .attr({
+ src: Ox.UI.getImagePath('symbolFind.svg')
+ })
+ .css({
+ width: '10px',
+ height: '10px',
+ padding: '3px 2px 1px 2px',
+ opacity: value == 'static' ? 0.1 : 1
+ });
+ },
+ id: 'type',
+ operator: '+',
+ visible: true,
+ width: 16
+ },
+ {
+ clickable: id == 'personal',
+ format: function(value) {
+ //var symbols = {private: 'Publish', public: 'Publish', featured: 'Star'};
+ return $('
')
+ .attr({
+ src: Ox.UI.getImagePath(
+ 'symbol' + (value == 'featured' ? 'Star' : 'Publish') + '.svg'
+ )
+ })
+ .css({
+ width: '10px',
+ height: '10px',
+ padding: '3px 2px 1px 2px',
+ opacity: value == 'private' ? 0.1 : 1
+ })
+ },
+ id: 'status',
+ operator: '+',
+ visible: true,
+ width: 16
+ }
+ ],
+ items: function(data, callback) {
+ var query;
+ if (id == 'personal') {
+ query = {conditions: [
+ {key: 'user', value: app.user.username, operator: '='},
+ {key: 'status', value: 'featured', operator: '!'}
+ ], operator: '&'};
+ } else if (id == 'favorite') {
+ query = {conditions: [
+ {key: 'subscribed', value: true, operator: '='},
+ {key: 'status', value: 'featured', operator: '!'},
+ ], operator: '&'};
+ } else if (id == 'featured') {
+ query = {conditions: [{key: 'status', value: 'featured', operator: '='}], operator: '&'};
+ }
+ return pandora.api.findLists($.extend(data, {
+ query: query
+ }), callback);
+ },
+ max: 1,
+ min: 0,
+ pageLength: 1000,
+ sort: [
+ {key: 'position', operator: '+'}
+ ],
+ sortable: id == 'personal' || id == 'favorite' || app.user.level == 'admin'
+ })
+ .css({
+ left: 0,
+ top: 0,
+ width: app.user.ui.sidebarWidth + 'px',
+ })
+ .bind({
+ dragenter: function(e) {
+ //Ox.print('DRAGENTER', e)
+ }
+ })
+ .bindEvent({
+ click: function(event, data) {
+ var $list = app.$ui.folderList[id];
+ if (data.key == 'type') {
+ app.$ui.filterDialog = ui.filterDialog().open();
+ } else if (data.key == 'status') {
+ pandora.api.editList({
+ id: data.id,
+ status: $list.value(data.id, data.key) == 'private' ? 'public' : 'private'
+ }, function(result) {
+ $list.value(result.data.id, 'status', result.data.status);
+ });
+ }
+ },
+ 'delete': function(event, data) {
+ var $list = app.$ui.folderList[id];
+ app.user.ui.listQuery.conditions = [];
+ pandora.URL.set(pandora.Query.toString());
+ $list.options({selected: []});
+ if (id == 'personal') {
+ pandora.api.removeList({
+ id: data.ids[0]
+ }, function(result) {
+ // fixme: is this the best way to delete a ui preference?
+ delete app.user.ui.lists[data.ids[0]];
+ pandora.UI.set({lists: app.user.ui.lists});
+ Ox.Request.clearCache(); // fixme: remove
+ $list.reloadList();
+ });
+ } else if (id == 'favorite') {
+ pandora.api.unsubscribeFromList({
+ id: data.ids[0]
+ }, function(result) {
+ Ox.Request.clearCache(); // fixme: remove
+ $list.reloadList();
+ });
+ } else if (id == 'featured' && app.user.level == 'admin') {
+ pandora.api.editList({
+ id: data.ids[0],
+ status: 'public'
+ }, function(result) {
+ // fixme: duplicated
+ if (result.data.user == app.user.username || result.data.subscribed) {
+ Ox.Request.clearCache(); // fixme: remove
+ app.$ui.folderList[
+ result.data.user == app.user.username ? 'personal' : 'favorite'
+ ].reloadList();
+ }
+ $list.reloadList();
+ });
+ }
+ },
+ init: function(event, data) {
+ app.ui.sectionFolders[app.user.ui.section][i].items = data.items;
+ app.$ui.folder[i].$content.css({
+ height: data.items * 16 + 'px'
+ });
+ app.$ui.folderList[id].css({
+ height: data.items * 16 + 'px'
+ });
+ pandora.resizeFolders();
+ },
+ move: function(event, data) {
+ /*
+ data.ids.forEach(function(id, pos) {
+ app.user.ui.lists[id].position = pos;
+ });
+ */
+ pandora.api.sortLists({
+ section: id,
+ ids: data.ids
+ });
+ },
+ paste: function(event, data) {
+ app.$ui.list.triggerEvent('paste', data);
+ },
+ select: function(event, data) {
+ if (data.ids.length) {
+ $.each(app.$ui.folderList, function(id_, $list) {
+ id != id_ && $list.options('selected', []);
+ })
+ pandora.URL.set('?find=list:' + data.ids[0]);
+ } else {
+ pandora.URL.set('?find=');
+ }
+ },
+ submit: function(event, data) {
+ data_ = {id: data.id};
+ data_[data.key] = data.value;
+ pandora.api.editList(data_, function(result) {
+ if (result.data.id != data.id) {
+ app.$ui.folderList[id].value(data.id, 'name', result.data.name);
+ app.$ui.folderList[id].value(data.id, 'id', result.data.id);
+ pandora.URL.set('?find=list:' + result.data.id);
+ }
+ });
+ }
+ });
+ }
+ return that;
+};
diff --git a/static/js/pandora/ui/group.js b/static/js/pandora/ui/group.js
new file mode 100644
index 000000000..aa73f4fca
--- /dev/null
+++ b/static/js/pandora/ui/group.js
@@ -0,0 +1,170 @@
+// vim: et:ts=4:sw=4:sts=4:ft=js
+pandora.ui.group = function(id, query) {
+ //Ox.print('group', id, query);
+ /*
+ query && query.conditions.length && alert($.map(query.conditions, function(v) {
+ return v.value;
+ }));
+ */
+ //alert(id + ' ' + JSON.stringify(pandora.Query.toObject(id)))
+ var i = app.user.ui.groups.indexOf(id),
+ panelWidth = app.$ui.document.width() - (app.user.ui.showSidebar * app.user.ui.sidebarSize) - 1,
+ title = Ox.getObjectById(app.config.groups, id).title,
+ width = pandora.getGroupWidth(i, panelWidth),
+ that = new Ox.TextList({
+ columns: [
+ {
+ align: 'left',
+ id: 'name',
+ operator: id == 'year' ? '-' : '+',
+ title: title,
+ unique: true,
+ visible: true,
+ width: width.column
+ },
+ {
+ align: 'right',
+ id: 'items',
+ operator: '-',
+ title: '#',
+ visible: true,
+ width: 40
+ }
+ ],
+ columnsVisible: true,
+ id: 'group_' + id,
+ items: function(data, callback) {
+ //Ox.print('sending request', data)
+ delete data.keys;
+ //alert(id + " pandora.Query.toObject " + JSON.stringify(pandora.Query.toObject(id)) + ' ' + JSON.stringify(data))
+ return pandora.api.find($.extend(data, {
+ group: id,
+ query: pandora.Query.toObject(id)
+ }), callback);
+ },
+ scrollbarVisible: true,
+ selected: query ? $.map(query.conditions, function(v) {
+ return v.value;
+ }) : [],
+ sort: [
+ {
+ key: id == 'year' ? 'name' : 'items',
+ operator: '-'
+ }
+ ]
+ })
+ .bindEvent({
+ paste: function(event, data) {
+ app.$ui.list.triggerEvent('paste', data);
+ },
+ select: function(event, data) {
+ var group = app.ui.groups[i],
+ query;
+ app.ui.groups[i].query.conditions = $.map(data.ids, function(v) {
+ return {
+ key: id,
+ value: v,
+ operator: '='
+ };
+ });
+ reloadGroups(i);
+ }
+ });
+ new Ox.Select({
+ items: $.map(app.config.groups, function(v) {
+ return {
+ checked: v.id == id,
+ id: v.id,
+ title: v.title
+ }
+ }),
+ max: 1,
+ min: 1,
+ type: 'image'
+ })
+ .bindEvent('change', function(event, data) {
+ var id_ = data.selected[0].id,
+ i_ = app.user.ui.groups.indexOf(id_);
+ if (i_ == -1) {
+ // new group was not part of old group set
+ if (app.ui.groups[i].query.conditions.length) {
+ // if group with selection gets replaced, reload
+ app.ui.groups[i].query.conditions = [];
+ reloadGroups(i);
+ }
+ app.ui.groups[i] = getGroupObject(id_);
+ app.user.ui.groups[i] = id_;
+ pandora.UI.set({groups: app.user.ui.groups});
+ replaceGroup(i, id_);
+ } else {
+ // swap two existing groups
+ var group = $.extend({}, app.ui.groups[i]);
+ app.ui.groups[i] = app.ui.groups[i_];
+ app.ui.groups[i_] = group;
+ app.user.ui.groups[i] = id_;
+ app.user.ui.groups[i_] = id;
+ pandora.UI.set({groups: app.user.ui.groups});
+ replaceGroup(i, id_, app.ui.groups[i].query);
+ replaceGroup(i_, id, app.ui.groups[i_].query);
+ }
+ function replaceGroup(i, id, query) {
+ // if query is passed, selected items will be derived from it
+ var isOuter = i % 4 == 0;
+ app.$ui[isOuter ? 'browser' : 'groupsInnerPanel'].replaceElement(
+ isOuter ? i / 2 : i - 1,
+ app.$ui.groups[i] = pandora.ui.group(id, query)
+ );
+ }
+ })
+ .appendTo(that.$bar.$element);
+ if (!query) {
+ // if query is set, group object has already been taken care of
+ app.ui.groups[i] = getGroupObject(id);
+ }
+ function getGroupObject(id) {
+ var i = app.user.ui.groups.indexOf(id),
+ title = Ox.getObjectById(app.config.groups, id).title,
+ width = pandora.getGroupWidth(i, panelWidth);
+ return {
+ id: id,
+ element: that,
+ query: {
+ conditions: [],
+ operator: '|'
+ },
+ size: width.list,
+ title: title
+ };
+ }
+ return that;
+};
+
+pandora.ui.groups = function() {
+ var $groups = [];
+ app.ui.groups = [];
+ app.user.ui.groups.forEach(function(id, i) {
+ $groups[i] = pandora.ui.group(id);
+ });
+ return $groups;
+};
+
+pandora.ui.groupsInnerPanel = function() {
+ var that = new Ox.SplitPanel({
+ elements: [
+ {
+ element: app.$ui.groups[1],
+ size: app.ui.groups[1].size
+ },
+ {
+ element: app.$ui.groups[2],
+ },
+ {
+ element: app.$ui.groups[3],
+ size: app.ui.groups[3].size
+ }
+ ],
+ orientation: 'horizontal'
+ });
+ return that;
+};
+
diff --git a/static/js/pandora/ui/info.js b/static/js/pandora/ui/info.js
new file mode 100644
index 000000000..25d0b0f00
--- /dev/null
+++ b/static/js/pandora/ui/info.js
@@ -0,0 +1,50 @@
+// vim: et:ts=4:sw=4:sts=4:ft=js
+pandora.ui.info = function() {
+ var that = new Ox.Element()
+ .append(
+ app.$ui.infoStill = new Ox.Element()
+ .css({
+ position: 'absolute',
+ left: 0,
+ top: 0,
+ height: '96px'
+ })
+ )
+ .append(
+ app.$ui.infoTimeline = new Ox.Element('
')
+ .css({
+ position: 'absolute',
+ left: 0,
+ bottom: 0,
+ height: '16px',
+ })
+ )
+ .bindEvent({
+ toggle: function(event, data) {
+ UI.set({showInfo: !data.collapsed});
+ pandora.resizeFolders();
+ }
+ });
+ if(app.user.ui.item) {
+ pandora.api.getItem(app.user.ui.item, function(result) {
+ app.ui.infoRatio = result.data.item.stream.aspectRatio;
+ var width = that.width() || 256,
+ height = width / app.ui.infoRatio + 16;
+ app.$ui.infoStill.removeElement();
+ app.$ui.infoStill = pandora.ui.flipbook(app.user.ui.item)
+ .appendTo(that.$element);
+ app.$ui.infoStill.css({
+ 'height': (height-16) + 'px'
+ });
+ that.css({
+ height: height + 'px'
+ });
+ pandora.resizeFolders();
+ !app.user.ui.showInfo && app.$ui.leftPanel.css({bottom: -height});
+ app.$ui.leftPanel.size(2, height );
+ });
+ app.$ui.infoTimeline.attr('src', '/'+app.user.ui.item+'/timeline.16.png')
+ }
+ return that;
+};
+
diff --git a/static/js/pandora/ui/item.js b/static/js/pandora/ui/item.js
new file mode 100644
index 000000000..a5196b1a1
--- /dev/null
+++ b/static/js/pandora/ui/item.js
@@ -0,0 +1,202 @@
+// vim: et:ts=4:sw=4:sts=4:ft=js
+pandora.ui.item = function() {
+ var that;
+ if (app.user.ui.itemView == 'info' || app.user.ui.itemView == 'files') {
+ that = new Ox.Element();
+ } else if (app.user.ui.itemView == 'player') {
+ that = new Ox.Element();
+ } else if (app.user.ui.itemView == 'timeline') {
+ that = new Ox.Element();
+ }
+ pandora.api.getItem(app.user.ui.item, function(result) {
+ if (app.user.ui.itemView == 'info') {
+ //Ox.print('result.data.item', result.data.item)
+ if (app.user.level == 'admin') {
+ var $form,
+ $edit = new Ox.Element()
+ .append($form = new Ox.FormElementGroup({
+ elements: Ox.map(app.config.itemKeys, function(key) {
+ return new Ox.Input({
+ id: key.id,
+ label: key.title,
+ labelWidth: 100,
+ value: result.data.item[key.id],
+ type: 'text',
+ width: 500
+ });
+ }),
+ separators: [
+ {title: '', width: 0}
+ ]
+ }))
+ .append(new Ox.Button({
+ title: 'Save',
+ type: 'text'
+ }).bindEvent({
+ click: function(event, data) {
+ var values = $form.value();
+ var changed = {};
+ Ox.map(app.config.itemKeys, function(key, i) {
+ if(values[i] && values[i] != ''+result.data.item[key.id]) {
+ if(Ox.isArray(key.type) && key.type[0] == 'string')
+ changed[key.id] = values[i].split(', ');
+ else
+ changed[key.id] = values[i];
+ }
+ });
+ if(changed) {
+ pandora.api.editItem(Ox.extend(changed, {id: app.user.ui.item}), function(result) {
+ //fixme just reload parts that need reloading
+ window.location.reload();
+ });
+ }
+ }
+ }));
+ app.$ui.contentPanel.replaceElement(1, app.$ui.item = $edit);
+ } else {
+ $.get('/static/html/itemInfo.html', {}, function(template) {
+ //Ox.print(template);
+ app.$ui.contentPanel.replaceElement(1,
+ app.$ui.item = new Ox.Element()
+ .append($.tmpl(template, result.data.item))
+ );
+ });
+ }
+
+ } else if (app.user.ui.itemView == 'player') {
+ var video = result.data.item.stream,
+ subtitles = result.data.item.layers.subtitles,
+ format = $.support.video.supportedFormat(video.formats);
+ video.height = video.profiles[0]
+ video.width = parseInt(video.height * video.aspectRatio / 2) * 2;
+ video.url = video.baseUrl + '/' + video.height + 'p.' + format;
+ app.$ui.contentPanel.replaceElement(1, app.$ui.player = new Ox.VideoPanelPlayer({
+ annotationsSize: app.user.ui.annotationsSize,
+ duration: video.duration,
+ height: app.$ui.contentPanel.size(1),
+ position: app.user.ui.videoPosition[app.user.ui.item] || 0,
+ showAnnotations: app.user.ui.showAnnotations,
+ showControls: app.user.ui.showControls,
+ subtitles: subtitles,
+ videoHeight: video.height,
+ videoId: app.user.ui.item,
+ videoWidth: video.width,
+ videoSize: app.user.ui.videoScreen,
+ videoURL: video.url,
+ width: app.$ui.document.width() - app.$ui.mainPanel.size(0) - 1
+ }).bindEvent({
+ change: function(event, data) {
+ // showAnnotations, showControls, videoScreen
+ pandora.UI.set('videoSize' in data ? {
+ videoScreen: data.videoSize
+ } : data);
+ },
+ enterfullscreen: pandora.enterFullscreen,
+ exitfullscreen: pandora.exitFullscreen,
+ resize: function(event, data) {
+ app.$ui.player.options({
+ height: data
+ });
+ }
+ }));
+ } else if (app.user.ui.itemView == 'timeline') {
+ var layers = [],
+ video = result.data.item.stream,
+ cuts = result.data.item.cuts || {},
+ format = $.support.video.supportedFormat(video.formats);
+ subtitles = result.data.item.layers.subtitles;
+ video.height = video.profiles[0];
+ video.width = parseInt(video.height * video.aspectRatio / 2) * 2;
+ video.url = video.baseUrl + '/' + video.height + 'p.' + format;
+ $.each(app.config.layers, function(i, layer) {
+ layers[i] = $.extend({}, layer, {items: result.data.item.layers[layer.id]});
+ });
+ app.$ui.contentPanel.replaceElement(1, app.$ui.editor = new Ox.VideoEditor({
+ annotationsSize: app.user.ui.annotationsSize,
+ cuts: cuts,
+ duration: video.duration,
+ find: '',
+ getFrameURL: function(position) {
+ return '/' + app.user.ui.item + '/frame/' + video.width.toString() + '/' + position.toString() + '.jpg'
+ },
+ getLargeTimelineImageURL: function(i) {
+ return '/' + app.user.ui.item + '/timelines/timeline.64.' + i + '.png';
+ },
+ getSmallTimelineImageURL: function(i) {
+ return '/' + app.user.ui.item + '/timelines/timeline.16.' + i + '.png';
+ },
+ height: app.$ui.contentPanel.size(1),
+ id: 'editor',
+ 'in': 0,
+ layers: layers,
+ out: 0,
+ position: app.user.ui.videoPosition[app.user.ui.item] || 0,
+ posterFrame: parseInt(video.duration / 2),
+ showAnnotations: app.user.ui.showAnnotations,
+ showLargeTimeline: true,
+ // fixme: layers have value, subtitles has text?
+ subtitles: subtitles.map(function(subtitle) {
+ return {'in': subtitle['in'], out: subtitle.out, text: subtitle.value};
+ }),
+ videoHeight: video.height,
+ videoId: app.user.ui.item,
+ videoWidth: video.width,
+ videoSize: app.user.ui.videoSize,
+ video: video.url,
+ width: app.$ui.document.width() - app.$ui.mainPanel.size(0) - 1
+ }).bindEvent({
+ resize: function(event, data) {
+ app.$ui.editor.options({
+ height: data
+ });
+ },
+ togglesize: function(event, data) {
+ pandora.UI.set({videoSize: data.size});
+ },
+ addAnnotation: function(event, data) {
+ Ox.print('addAnnotation', data);
+ data.item = app.user.ui.item;
+ data.value = 'Click to edit';
+ pandora.api.addAnnotation(data, function(result) {
+ app.$ui.editor.addAnnotation(data.layer, result.data);
+ });
+ },
+ removeAnnotations: function(event, data) {
+ pandora.api.removeAnnotations(data, function(result) {
+ //fixme: check for errors
+ app.$ui.editor.removeAnnotations(data.layer, data.ids);
+ });
+ },
+ updateAnnotation: function(event, data) {
+ //fixme: check that edit was successfull
+ Ox.print('updateAnnotation', data);
+ pandora.api.editAnnotation(data);
+ }
+ }));
+ that.bindEvent('resize', function(event, data) {
+ //Ox.print('resize item', data)
+ app.$ui.editor.options({
+ height: data
+ });
+ });
+ /*
+ app.$ui.rightPanel.bindEvent('resize', function(event, data) {
+ Ox.print('... rightPanel resize', data, app.$ui.timelinePanel.size(1))
+ app.$ui.editor.options({
+ width: data - app.$ui.timelinePanel.size(1) - 1
+ });
+ });
+ */
+ } else if (app.user.ui.itemView == 'files') {
+ app.$ui.contentPanel.replaceElement(1,
+ app.$ui.item = new Ox.FilesView({
+ id: result.data.item.id
+ })
+ );
+ }
+ var director = result.data.item.director?' ('+result.data.item.director.join(', ')+')':'';
+ app.$ui.total.html(result.data.item.title + director);
+ });
+ return that;
+};
+
diff --git a/static/js/pandora/ui/leftPanel.js b/static/js/pandora/ui/leftPanel.js
new file mode 100644
index 000000000..c34ed9346
--- /dev/null
+++ b/static/js/pandora/ui/leftPanel.js
@@ -0,0 +1,53 @@
+// vim: et:ts=4:sw=4:sts=4:ft=js
+pandora.ui.leftPanel = function() {
+ var that = new Ox.SplitPanel({
+ elements: [
+ {
+ element: app.$ui.sectionbar = pandora.ui.sectionbar('buttons'),
+ size: 24
+ },
+ {
+ element: app.$ui.folders = pandora.ui.folders()
+ },
+ {
+ collapsed: !app.user.ui.showInfo,
+ collapsible: true,
+ element: app.$ui.info = pandora.ui.info(),
+ size: app.user.ui.sidebarSize / app.ui.infoRatio + 16
+ }
+ ],
+ id: 'leftPanel',
+ orientation: 'vertical'
+ })
+ .bindEvent({
+ resize: function(event, data) {
+ var infoSize = Math.round(data / app.ui.infoRatio) + 16;
+ app.user.ui.sidebarSize = data;
+ if (data < app.ui.sectionButtonsWidth && app.$ui.sectionButtons) {
+ app.$ui.sectionButtons.removeElement();
+ delete app.$ui.sectionButtons;
+ app.$ui.sectionbar.append(app.$ui.sectionSelect = pandora.ui.sectionSelect());
+ } else if (data >= app.ui.sectionButtonsWidth && app.$ui.sectionSelect) {
+ app.$ui.sectionSelect.removeElement();
+ delete app.$ui.sectionSelect;
+ app.$ui.sectionbar.append(app.$ui.sectionButtons = pandora.ui.sectionButtons());
+ }
+ !app.user.ui.showInfo && app.$ui.leftPanel.css({bottom: -infoSize});
+ app.$ui.leftPanel.size(2, infoSize);
+ pandora.resizeFolders();
+ },
+ resizeend: function(event, data) {
+ pandora.UI.set({sidebarSize: data});
+ },
+ toggle: function(event, data) {
+ pandora.UI.set({showSidebar: !data.collapsed});
+ if (data.collapsed) {
+ $.each(app.$ui.folderList, function(k, $list) {
+ $list.loseFocus();
+ });
+ }
+ }
+ });
+ return that;
+};
+
diff --git a/static/js/pandora/ui/list.js b/static/js/pandora/ui/list.js
new file mode 100644
index 000000000..0c1aa76fc
--- /dev/null
+++ b/static/js/pandora/ui/list.js
@@ -0,0 +1,425 @@
+// vim: et:ts=4:sw=4:sts=4:ft=js
+pandora.ui.list = function(view) { // fixme: remove view argument
+ var that, $map;
+ //Ox.print('constructList', view);
+ if (view == 'list') {
+ /*
+ keys = Ox.unique($.merge(
+ $.map(app.user.ui.lists[app.user.ui.list].columns, function(id) {
+ return Ox.getObjectById(app.config.sortKeys, id);
+ }),
+ app.config.sortKeys
+ ));
+ Ox.print('$$$$', keys)
+ */
+ that = new Ox.TextList({
+ columns: $.map(app.ui.sortKeys, function(key, i) {
+ var position = app.user.ui.lists[app.user.ui.list].columns.indexOf(key.id);
+ return {
+ align: ['string', 'text'].indexOf(
+ Ox.isArray(key.type) ? key.type[0]: key.type
+ ) > -1 ? 'left' : 'right',
+ defaultWidth: key.columnWidth,
+ format: key.format,
+ id: key.id,
+ operator: pandora.getSortOperator(key.id),
+ position: position,
+ removable: !key.columnRequired,
+ title: key.title,
+ type: key.type,
+ unique: key.id == 'id',
+ visible: position > -1,
+ width: app.user.ui.lists[app.user.ui.list].columnWidth[key.id] || key.columnWidth
+ };
+ }),
+ columnsMovable: true,
+ columnsRemovable: true,
+ columnsResizable: true,
+ columnsVisible: true,
+ id: 'list',
+ items: function(data, callback) {
+ //Ox.print('data, pandora.Query.toObject', data, pandora.Query.toObject())
+ pandora.api.find($.extend(data, {
+ query: pandora.Query.toObject()
+ }), callback);
+ },
+ scrollbarVisible: true,
+ sort: app.user.ui.lists[app.user.ui.list].sort
+ })
+ .bindEvent({
+ columnchange: function(event, data) {
+ var columnWidth = {}
+ pandora.UI.set(['lists', app.user.ui.list, 'columns'].join('|'), data.ids);
+ /*
+ data.ids.forEach(function(id) {
+ columnWidth[id] =
+ app.user.ui.lists[app.user.ui.list].columnWidth[id] ||
+ Ox.getObjectById(app.ui.sortKeys, id).width
+ });
+ pandora.UI.set(['lists', app.user.ui.list, 'columnWidth'].join('|'), columnWidth);
+ */
+ },
+ columnresize: function(event, data) {
+ pandora.UI.set(['lists', app.user.ui.list, 'columnWidth', data.id].join('|'), data.width);
+ },
+ resize: function(event, data) { // this is the resize event of the split panel
+ that.size();
+ },
+ sort: function(event, data) {
+ pandora.UI.set(['lists', app.user.ui.list, 'sort'].join('|'), [data]);
+ }
+ });
+ } else if (view == 'icons') {
+ that = new Ox.IconList({
+ id: 'list',
+ item: function(data, sort, size) {
+ var ratio = data.poster.width / data.poster.height;
+ size = size || 128;
+ 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.length ? ' (' + data.director.join(', ') + ')' : ''),
+ url: data.poster.url.replace(/jpg/, size + '.jpg'),
+ width: ratio >= 1 ? size : size * ratio
+ };
+ },
+ items: function(data, callback) {
+ //Ox.print('data, pandora.Query.toObject', data, pandora.Query.toObject())
+ pandora.api.find($.extend(data, {
+ query: pandora.Query.toObject()
+ }), callback);
+ },
+ keys: ['director', 'id', 'poster', 'title', 'year'],
+ size: 128,
+ sort: app.user.ui.lists[app.user.ui.list].sort,
+ unique: 'id'
+ })
+ } else if (view == 'map') {
+ that = new Ox.SplitPanel({
+ elements: [
+ {
+ element: new Ox.SplitPanel({
+ elements: [
+ {
+ element: new Ox.Toolbar({
+ orientation: 'horizontal',
+ size: 24
+ })
+ .append(
+ app.$ui.findMapInput = new Ox.Input({
+ clear: true,
+ id: 'findMapInput',
+ placeholder: 'Find on Map',
+ width: 192
+ })
+ .css({
+ float: 'right',
+ margin: '4px'
+ })
+ .bindEvent({
+ submit: function(event, data) {
+ app.$ui.map.find(data.value, function(data) {
+ app.$ui.mapStatusbar.html(data.geoname + ' ' + JSON.stringify(data.points))
+ });
+ }
+ })
+ ),
+ size: 24
+ },
+ {
+ element: app.$ui.map = new Ox.Map({
+ places: [
+ {
+ geoname: 'Beirut, Lebanon',
+ name: 'Beirut',
+ points: {
+ 'center': [33.8886284, 35.4954794],
+ 'northeast': [33.8978909, 35.5114868],
+ 'southwest': [33.8793659, 35.479472]
+ }
+ },
+ {
+ geoname: 'Berlin, Germany',
+ name: 'Berlin',
+ points: {
+ 'center': [52.506701, 13.4246065],
+ 'northeast': [52.675323, 13.760909],
+ 'southwest': [52.338079, 13.088304]
+ }
+ },
+ {
+ geoname: 'Mumbai, Maharashtra, India',
+ name: 'Bombay',
+ points: {
+ 'center': [19.07871865, 72.8778187],
+ 'northeast': [19.2695223, 72.9806562],
+ 'southwest': [18.887915, 72.7749812]
+ }
+ }
+ ]
+ })
+ .bindEvent({
+ select: function(event, data) {
+ app.$ui.mapStatusbar.html(data.geoname + ' ' + JSON.stringify(data.points))
+ }
+ }),
+ id: 'map',
+ size: 'auto'
+ },
+ {
+ element: app.$ui.mapStatusbar = new Ox.Toolbar({
+ orientation: 'horizontal',
+ size: 16
+ })
+ .css({
+ fontSize: '9px',
+ padding: '2px 4px 0 0',
+ textAlign: 'right'
+ }),
+ size: 16
+ }
+ ],
+ orientation: 'vertical'
+ }),
+ },
+ {
+ element: new Ox.Element(),
+ id: 'place',
+ size: 128 + 16 + 12
+ }
+ ],
+ orientation: 'horizontal'
+ })
+ .bindEvent('resize', function() {
+ app.$ui.map.resize();
+ });
+ } else {
+ $list = new Ox.Element('
')
+ .css({
+ width: '100px',
+ height: '100px',
+ background: 'red'
+ });
+ }
+
+ ['list', 'icons'].indexOf(view) > -1 && that.bind({
+ dragstart: function(e) {
+ app.$ui.folderList.forEach(function($list, i) {
+ $list.addClass('OxDrop');
+ });
+ },
+ dragend: function(e) {
+ app.$ui.folderList.forEach(function($list, i) {
+ $list.removeClass('OxDrop');
+ });
+ },
+ }).bindEvent({
+ closepreview: function(event, data) {
+ app.$ui.previewDialog.close();
+ delete app.$ui.previewDialog;
+ },
+ copy: function(event, data) {
+ Ox.Clipboard.copy({
+ items: data.ids,
+ text: $.map(data.ids, function(id) {
+ return app.$ui.list.value(id, 'title');
+ }).join('\n')
+ });
+ },
+ 'delete': function(event, data) {
+ getListData().editable && pandora.api.removeListItems({
+ list: app.user.ui.list,
+ items: data.ids
+ }, reloadList);
+ },
+ init: function(event, data) {
+ app.$ui.total.html(pandora.ui.status('total', data));
+ data = [];
+ $.each(app.config.totals, function(i, v) {
+ data[v.id] = 0;
+ });
+ app.$ui.selected.html(pandora.ui.status('selected', data));
+ },
+ open: function(event, data) {
+ var id = data.ids[0],
+ title = that.value(id, 'title');
+ pandora.URL.set(title, id);
+ },
+ openpreview: function(event, data) {
+ app.requests.preview && pandora.api.cancel(app.requests.preview);
+ app.requests.preview = pandora.api.find({
+ keys: ['director', 'id', 'poster', 'title'],
+ query: {
+ conditions: $.map(data.ids, function(id, i) {
+ return {
+ key: 'id',
+ value: id,
+ operator: '='
+ }
+ }),
+ operator: '|'
+ }
+ }, function(result) {
+ var documentHeight = app.$ui.document.height(),
+ item = result.data.items[0],
+ title = item.title + (item.director ? ' (' + item.director + ')' : ''),
+ dialogHeight = documentHeight - 100,
+ dialogWidth;
+ app.ui.previewRatio = item.poster.width / item.poster.height,
+ dialogWidth = parseInt((dialogHeight - 48) * app.ui.previewRatio);
+ if ('previewDialog' in app.$ui) {
+ app.$ui.previewDialog.options({
+ title: title
+ });
+ app.$ui.previewImage.animate({
+ opacity: 0
+ }, 100, function() {
+ app.$ui.previewDialog.size(dialogWidth, dialogHeight, function() {
+ app.$ui.previewImage
+ .attr({
+ src: item.poster.url
+ })
+ .one('load', function() {
+ app.$ui.previewImage
+ .css({
+ width: dialogWidth + 'px',
+ height: (dialogHeight - 48 - 2) + 'px', // fixme: why -2 ?
+ opacity: 0
+ })
+ .animate({
+ opacity: 1
+ }, 100);
+ });
+ });
+ });
+ //Ox.print(app.$ui.document.height(), dialogWidth, 'x', dialogHeight, dialogWidth / (dialogHeight - 48), item.poster.width, 'x', item.poster.height, item.poster.width / item.poster.height)
+ } else {
+ app.$ui.previewImage = $('
')
+ .attr({
+ src: item.poster.url
+ })
+ .css({
+ position: 'absolute',
+ width: dialogWidth + 'px',
+ height: (dialogHeight - 48 - 2) + 'px', // fixme: why -2 ?
+ left: 0,
+ top: 0,
+ right: 0,
+ bottom: 0,
+ margin: 'auto',
+ });
+ app.$ui.previewDialog = new Ox.Dialog({
+ buttons: [
+ new Ox.Button({
+ title: 'Close',
+ }).bindEvent({
+ click: function() {
+ app.$ui.previewDialog.close();
+ delete app.$ui.previewDialog;
+ app.$ui.list.closePreview();
+ }
+ })
+ ],
+ content: app.$ui.previewImage,
+ height: dialogHeight,
+ id: 'previewDialog',
+ minHeight: app.ui.previewRatio >= 1 ? 128 / app.ui.previewRatio + 48 : 176,
+ minWidth: app.ui.previewRatio >= 1 ? 128 : 176 * app.ui.previewRatio,
+ padding: 0,
+ title: title,
+ width: dialogWidth
+ })
+ .bindEvent('resize', function(event, data) {
+ var dialogRatio = data.width / (data.height - 48),
+ height, width;
+ if (dialogRatio < app.ui.previewRatio) {
+ width = data.width;
+ height = width / app.ui.previewRatio;
+ } else {
+ height = (data.height - 48 - 2);
+ width = height * app.ui.previewRatio;
+ }
+ app.$ui.previewImage.css({
+ width: width + 'px',
+ height: height + 'px', // fixme: why -2 ?
+ })
+ })
+ .open();
+ //app.$ui.previewImage = $image;
+ //Ox.print(app.$document.height(), dialogWidth, 'x', dialogHeight, dialogWidth / (dialogHeight - 48), item.poster.width, 'x', item.poster.height, item.poster.width / item.poster.height)
+ }
+ });
+ },
+ paste: function(event, data) {
+ data.items && getListData().editable && pandora.api.addListItems({
+ list: app.user.ui.list,
+ items: data.items
+ }, reloadList);
+ },
+ select: function(event, data) {
+ var $still, $timeline;
+ app.ui.selectedMovies = data.ids;
+ if (data.ids.length) {
+ app.$ui.mainMenu.enableItem('copy');
+ app.$ui.mainMenu.enableItem('openmovie');
+ } else {
+ app.$ui.mainMenu.disableItem('copy');
+ app.$ui.mainMenu.disableItem('openmovie');
+ }
+ if (data.ids.length == 1) {
+ pandora.api.getItem(data.ids[0], function(result) {
+ app.ui.infoRatio = result.data.item.stream.aspectRatio;
+ var height = app.$ui.info.width() / app.ui.infoRatio + 16;
+ if(app.$ui.infoStill) app.$ui.infoStill.removeElement();
+ app.$ui.infoStill = pandora.ui.flipbook(data.ids[0])
+ .appendTo(app.$ui.info.$element);
+ app.$ui.infoStill.css({
+ 'height': (height - 16) + 'px'
+ });
+ !app.user.ui.showInfo && app.$ui.leftPanel.css({bottom: -height});
+ app.$ui.leftPanel.size(2, height);
+ app.$ui.info.animate({
+ height: height + 'px'
+ }, 250, function() {
+ pandora.resizeFolders();
+ });
+ });
+ app.$ui.infoTimeline.attr('src', '/'+data.ids[0]+'/timeline.16.png')
+ }
+ pandora.api.find({
+ query: {
+ conditions: $.map(data.ids, function(id, i) {
+ return {
+ key: 'id',
+ value: id,
+ operator: '='
+ }
+ }),
+ operator: '|'
+ }
+ }, function(result) {
+ app.$ui.selected.html(pandora.ui.status('selected', result.data));
+ });
+ },
+ sort: function(event, data) {
+ /* some magic has already set user.ui.sort
+ Ox.print(':', user.ui.sort[0])
+ if (data.key != user.ui.sort[0].key) {
+ app.$ui.mainMenu.checkItem('sort_sortmovies_' + data.key);
+ }
+ if (data.operator != user.ui.sort[0].operator) {
+ app.$ui.mainMenu.checkItem('sort_ordermovies_' + data.operator === '' ? 'ascending' : 'descending');
+ }
+ user.ui.sort[0] = data;
+ */
+ app.$ui.mainMenu.checkItem('sortMenu_sortmovies_' + data.key);
+ app.$ui.mainMenu.checkItem('sortMenu_ordermovies_' + (data.operator === '' ? 'ascending' : 'descending'));
+ }
+ });
+ that.display = function() { // fixme: used?
+ app.$ui.rightPanel.replaceElement(1, app.$ui.contentPanel = pandora.ui.contentPanel());
+ };
+ return that;
+};
+
diff --git a/static/js/pandora/ui/mainPanel.js b/static/js/pandora/ui/mainPanel.js
new file mode 100644
index 000000000..452aeead9
--- /dev/null
+++ b/static/js/pandora/ui/mainPanel.js
@@ -0,0 +1,21 @@
+// vim: et:ts=4:sw=4:sts=4:ft=js
+pandora.ui.mainPanel = function() {
+ var that = new Ox.SplitPanel({
+ elements: [
+ {
+ collapsible: true,
+ collapsed: !app.user.ui.showSidebar,
+ element: app.$ui.leftPanel = pandora.ui.leftPanel(),
+ resizable: true,
+ resize: [192, 256, 320, 384],
+ size: app.user.ui.sidebarSize
+ },
+ {
+ element: app.$ui.rightPanel = pandora.ui.rightPanel()
+ }
+ ],
+ orientation: 'horizontal'
+ })
+ return that;
+};
+
diff --git a/static/js/pandora/ui/menu.js b/static/js/pandora/ui/menu.js
new file mode 100644
index 000000000..6a3e71f07
--- /dev/null
+++ b/static/js/pandora/ui/menu.js
@@ -0,0 +1,538 @@
+// vim: et:ts=4:sw=4:sts=4:ft=js
+pandora.ui.mainMenu = function() {
+ var isGuest = app.user.level == 'guest',
+ that = new Ox.MainMenu({
+ extras: [
+ $('
').html('beta').css({marginRight: '8px', color: 'rgb(128, 128, 128)'}),
+ app.$ui.loadingIcon = new Ox.LoadingIcon({
+ size: 'medium'
+ })
+ ],
+ id: 'mainMenu',
+ menus: [
+ { id: app.config.site.id + 'Menu', title: app.config.site.name, items: [
+ { id: 'home', title: 'Home' },
+ {},
+ { id: 'about', title: 'About ' + app.config.site.name },
+ { id: 'news', title: app.config.site.name + ' News' },
+ { id: 'tour', title: 'Take a Tour' },
+ { id: 'faq', title: 'Frequently Asked Questions' },
+ { id: 'terms', title: 'Terms of Service' },
+ {},
+ { id: 'software', title: 'Software', items: [
+ { id: 'about', title: 'About' },
+ { id: 'download', title: 'Download' },
+ { id: 'report', title: 'Report a Bug' }
+ ] },
+ {},
+ { id: 'contact', title: 'Contact ' + app.config.site.name }
+ ] },
+ { id: 'userMenu', title: 'User', items: [
+ { id: 'username', title: 'User: ' + (isGuest ? 'not logged in' : app.user.username), disabled: true },
+ {},
+ { id: 'preferences', title: 'Preferences...', disabled: isGuest, keyboard: 'control ,' },
+ {},
+ { id: 'register', title: 'Register...', disabled: !isGuest },
+ { id: 'loginlogout', title: isGuest ? 'Login...' : 'Logout...' }
+ ] },
+ { id: 'listMenu', title: 'List', items: [
+ { id: 'history', title: 'History', items: [
+ { id: 'allmovies', title: 'All ' + app.config.itemName.plural }
+ ] },
+ { id: 'lists', title: 'View List', items: [
+ { id: 'favorites', title: 'Favorites' }
+ ] },
+ { id: 'features', title: 'View Feature', items: [
+ { id: 'situationistfilm', title: 'Situationist Film' },
+ { id: 'timelines', title: 'Timelines' }
+ ] },
+ {},
+ { 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 ' + app.config.itemName.singular + ' to List...', 'Add Selected ' + app.config.itemName.plural + ' to List...'], disabled: true },
+ {},
+ { id: 'setposterframe', title: 'Set Poster Frame', disabled: true }
+ ]},
+ { id: 'editMenu', title: 'Edit', items: [
+ { id: 'undo', title: 'Undo', disabled: true, keyboard: 'control z' },
+ { id: 'redo', title: 'Redo', disabled: true, keyboard: 'shift control z' },
+ {},
+ { id: 'cut', title: 'Cut', disabled: true, keyboard: 'control x' },
+ { id: 'copy', title: 'Copy', disabled: true, keyboard: 'control c' },
+ { id: 'paste', title: 'Paste', disabled: true, keyboard: 'control v' },
+ { id: 'delete', title: 'Delete', disabled: true, keyboard: 'delete' },
+ {},
+ { id: 'selectall', title: 'Select All', disabled: true, keyboard: 'control a' },
+ { id: 'selectnone', title: 'Select None', disabled: true, keyboard: 'shift control a' },
+ { id: 'invertselection', title: 'Invert Selection', disabled: true, keyboard: 'alt control a' }
+ ] },
+ { id: 'viewMenu', title: 'View', items: [
+ { id: 'movies', title: 'View ' + app.config.itemName.plural, items: [
+ { group: 'viewmovies', min: 0, max: 1, items: $.map(app.config.listViews, function(view, i) {
+ return $.extend({
+ checked: app.user.ui.lists[app.user.ui.list].listView == view.id,
+ }, view);
+ }) },
+ ]},
+ { id: 'icons', title: 'Icons', items: [
+ { id: 'poster', title: 'Poster' },
+ { id: 'still', title: 'Still' },
+ { id: 'timeline', title: 'Timeline' }
+ ] },
+ { id: 'info', title: 'Info', items: [
+ { id: 'poster', title: 'Poster' },
+ { id: 'video', title: 'Video' }
+ ] },
+ {},
+ { id: 'openmovie', title: ['Open ' + app.config.itemName.singular, 'Open ' + app.config.itemName.plural], disabled: true, items: [
+ { group: 'movieview', min: 0, max: 1, items: $.map(app.config.itemViews, function(view, i) {
+ return $.extend({
+ checked: app.user.ui.itemView == view.id,
+ }, view);
+ }) },
+ ]},
+ {},
+ { id: 'lists', title: 'Hide Lists', keyboard: 'shift l' },
+ { id: 'info', title: 'Hide Info', keyboard: 'shift i' },
+ { id: 'groups', title: 'Hide Groups', keyboard: 'shift g' },
+ { id: 'movies', title: 'Hide ' + app.config.itemName.plural, disabled: true, keyboard: 'shift m' }
+ ]},
+ { id: 'sortMenu', title: 'Sort', items: [
+ { id: 'sortmovies', title: 'Sort ' + app.config.itemName.plural + ' by', items: [
+ { group: 'sortmovies', min: 1, max: 1, items: $.map(app.ui.sortKeys, function(key, i) {
+ return $.extend({
+ checked: app.user.ui.lists[app.user.ui.list].sort[0].key == key.id,
+ }, key);
+ }) }
+ ] },
+ { id: 'ordermovies', title: 'Order ' + app.config.itemName.plural, items: [
+ { group: 'ordermovies', min: 1, max: 1, items: [
+ { id: 'ascending', title: 'Ascending', checked: app.user.ui.lists[app.user.ui.list].sort[0].operator === '' },
+ { id: 'descending', title: 'Descending', checked: app.user.ui.lists[app.user.ui.list].sort[0].operator == '-' }
+ ]}
+ ] },
+ { id: 'advancedsort', title: 'Advanced Sort...', keyboard: 'shift control s' },
+ {},
+ { id: 'groupsstuff', title: 'Groups Stuff' }
+ ] },
+ { id: 'findMenu', title: 'Find', items: [
+ { id: 'find', title: 'Find', items: [
+ { group: 'find', min: 1, max: 1, items: $.map(app.ui.findKeys, function(key, i) {
+ return $.extend({
+ checked: app.user.ui.findQuery.conditions.length &&
+ (app.user.ui.findQuery.conditions[0].key == key.id ||
+ (app.user.ui.findQuery.conditions[0].key === '' && key.id == 'all')),
+ }, key)
+ }) }
+ ] },
+ { id: 'advancedfind', title: 'Advanced Find...', keyboard: 'shift control f' }
+ ] },
+ { id: 'dataMenu', title: 'Data', items: [
+ { id: 'titles', title: 'Manage Titles...' },
+ { id: 'names', title: 'Manage Names...' },
+ {},
+ { id: 'posters', title: 'Manage Stills...' },
+ { id: 'posters', title: 'Manage Posters...' },
+ {},
+ { id: 'places', title: 'Manage Places...' },
+ { id: 'events', title: 'Manage Events...' },
+ {},
+ { id: 'users', title: 'Manage Users...' },
+ { id: 'lists', title: 'Manage Lists...' },
+ ] },
+ { id: 'codeMenu', title: 'Code', items: [
+ { id: 'download', title: 'Download' },
+ { id: 'contribute', title: 'Contribute' },
+ { id: 'report', title: 'Report a Bug' },
+ ] },
+ { id: 'helpMenu', title: 'Help', items: [
+ { id: 'help', title: app.config.site.name + ' Help', keyboard: 'shift ?' }
+ ] },
+ { id: 'debugMenu', title: 'Debug', items: [
+ { id: 'query', title: 'Show pandora.Query' },
+ { id: 'resetui', title: 'Reset UI Settings'}
+ ] },
+ { id: 'testMenu', title: 'Test', items: [
+ { group: 'foogroup', items: [
+ { id: 'item1', title: 'Item 1' },
+ { id: 'item2', title: 'Item 2' }
+ ] }
+ ] }
+ ]
+ })
+ .bindEvent({
+ change: function(event, data) {
+ if (data.id == 'find') {
+ var id = data.checked[0].id;
+ app.$ui.findSelect.selectItem(id);
+ } else if (data.id == 'movieview') {
+ var view = data.checked[0].id;
+ var id = document.location.pathname.split('/')[1];
+ if (view == 'info')
+ url(id + '/info');
+ else
+ url(id);
+ } else if (data.id == 'ordermovies') {
+ var id = data.checked[0].id;
+ app.$ui.list.sortList(app.user.ui.lists[app.user.ui.list].sort[0].key, id == 'ascending' ? '' : '-');
+ } else if (data.id == 'sortmovies') {
+ var id = data.checked[0].id,
+ operator = pandora.getSortOperator(id);
+ app.$ui.mainMenu.checkItem('sortMenu_ordermovies_' + (operator === '' ? 'ascending' : 'descending'));
+ app.$ui.sortSelect.selectItem(id);
+ app.$ui.list.sortList(id, operator);
+ pandora.URL.set(pandora.Query.toString());
+ } else if (data.id == 'viewmovies') {
+ var view = data.checked[0].id;
+ url('#view=' + view);
+ }
+ },
+ click: function(event, data) {
+ if (data.id == 'about') {
+ var $dialog = new Ox.Dialog({
+ buttons: [
+ new Ox.Button({
+ id: 'close',
+ title: 'Close'
+ }).bindEvent({
+ click: function() {
+ $dialog.close();
+ }
+ })
+ ],
+ id: 'about',
+ title: 'About'
+ }).open();
+ } else if (data.id == 'home') {
+ var $dialog = new Ox.Dialog({
+ buttons: [
+ new Ox.Button({
+ id: 'close',
+ title: 'Close'
+ }).bindEvent({
+ click: function() {
+ $dialog.close();
+ }
+ })
+ ],
+ height: 498,
+ id: 'home',
+ keys: {enter: 'close', escape: 'close'},
+ title: app.config.site.name,
+ width: 800
+ }).open();
+ } else if (data.id == 'register') {
+ app.$ui.accountDialog = pandora.ui.accountDialog('register').open();
+ } else if (data.id == 'loginlogout') {
+ app.$ui.accountDialog = (app.user.level == 'guest' ?
+ pandora.ui.accountDialog('login') : pandora.ui.accountLogoutDialog()).open();
+ } else if (data.id == 'places') {
+ app.$ui.placesDialog = pandora.ui.placesDialog().open();
+ /*
+ var $manage = new Ox.SplitPanel({
+ elements: [
+ {
+ collapsible: true,
+ element: new Ox.SplitPanel({
+ elements: [
+ {
+ element: new Ox.Toolbar({
+ orientation: 'horizontal',
+ size: 44
+ }).append(
+ app.$ui.findPlacesElement = new Ox.FormElementGroup({
+ elements: [
+ app.$ui.findPlacesSelect = new 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(event, data) {
+ app.$ui.findPlacesSelect.loseFocus();
+ app.$ui.findPlacesInput.options({
+ placeholder: data.selected[0].title
+ });
+ }
+ }),
+ app.$ui.findPlacesInput = new Ox.Input({
+ clear: true,
+ id: 'findPlacesInput',
+ placeholder: 'Find: Name',
+ width: 234
+ })
+ ],
+ id: 'findPlacesElement'
+ })
+ .css({
+ float: 'left',
+ margin: '4px'
+ })
+ ).append(
+ app.$ui.sortPlacesSelect = new 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: new Ox.Element('div')
+ },
+ {
+ element: new Ox.Toolbar({
+ orientation: 'horizontal',
+ size: 16
+ }),
+ size: 16
+ }
+ ],
+ orientation: 'vertical'
+ }),
+ size: 256
+ },
+ {
+ element: new Ox.SplitPanel({
+ elements: [
+ {
+ element: new Ox.Toolbar({
+ orientation: 'horizontal',
+ size: 24
+ }).append(
+ app.$ui.labelsButton = new Ox.Button({
+ id: 'labelsButton',
+ title: [
+ {id: 'show', title: 'Show Labels'},
+ {id: 'hide', title: 'Hide Labels'}
+ ],
+ width: 96
+ })
+ .css({
+ float: 'left',
+ margin: '4px'
+ })
+ ).append(
+ app.$ui.findMapInput = new Ox.Input({
+ clear: true,
+ id: 'findMapInput',
+ placeholder: 'Find on Map',
+ width: 192
+ })
+ .css({
+ float: 'right',
+ margin: '4px'
+ })
+ .bindEvent({
+ submit: function(event, data) {
+ app.$ui.map.find(data.value, function(location) {
+
+ app.$ui.placeNameInput.options({
+ disabled: false,
+ value: location.name
+ });
+ app.$ui.placeAliasesInput.options({
+ disabled: false
+ });
+ app.$ui.placeGeonameLabel.options({
+ disabled: false,
+ title: location.names.join(', ')
+ });
+ app.$ui.removePlaceButton.options({
+ disabled: false
+ });
+ app.$ui.addPlaceButton.options({
+ disabled: false
+ });
+
+ });
+ }
+ })
+ ),
+ size: 24
+ },
+ {
+ element: app.$ui.map = new 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) {
+ app.$ui.placeNameInput.options({
+ disabled: false,
+ value: location.name
+ });
+ app.$ui.placeAliasesInput.options({
+ disabled: false
+ });
+ app.$ui.placeGeonameLabel.options({
+ disabled: false,
+ title: location.names.join(', ')
+ });
+ app.$ui.removePlaceButton.options({
+ disabled: false
+ });
+ app.$ui.addPlaceButton.options({
+ disabled: false
+ });
+ }
+ })
+ },
+ {
+ element: app.$ui.bottomBar = new Ox.Toolbar({
+ orientation: 'horizontal',
+ size: 24
+ })
+ .append(
+ app.$ui.placeNameInput = new Ox.Input({
+ disabled: true,
+ id: 'placeName',
+ placeholder: 'Name',
+ width: 128
+ })
+ .css({
+ float: 'left',
+ margin: '4px 0 0 4px'
+ })
+ )
+ .append(
+ app.$ui.placeAliasesInput = new Ox.Input({
+ disabled: true,
+ id: 'aliases',
+ placeholder: 'Aliases',
+ width: 128
+ })
+ .css({
+ float: 'left',
+ margin: '4px 0 0 4px'
+ })
+ )
+ .append(
+ app.$ui.placeGeonameLabel = new Ox.Label({
+ disabled: true,
+ id: 'placeGeoname',
+ title: 'Geoname',
+ width: parseInt(app.$ui.document.width() * 0.8) - 256 - 256 - 32 - 24
+ })
+ .css({
+ float: 'left',
+ margin: '4px 0 0 4px'
+ })
+ )
+ .append(
+ app.$ui.addPlaceButton = new Ox.Button({
+ disabled: true,
+ id: 'addPlaceButton',
+ title: 'add',
+ type: 'image'
+ })
+ .css({
+ float: 'right',
+ margin: '4px 4px 0 0'
+ })
+ )
+ .append(
+ app.$ui.removePlaceButton = new 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 = new Ox.Dialog({
+ buttons: [
+ {
+ click: function() {
+ $dialog.close();
+ },
+ id: 'close',
+ title: 'Close',
+ value: 'Close'
+ }
+ ],
+ height: parseInt(app.$ui.document.height() * 0.8),
+ id: 'places',
+ minHeight: 400,
+ minWidth: 600,
+ padding: 0,
+ title: 'Manage Places',
+ width: parseInt(app.$ui.document.width() * 0.8)
+ }).css({
+ overflow: 'hidden'
+ }).append($manage).open();
+ */
+ } else if (data.id == 'query') {
+ var $dialog = new Ox.Dialog({
+ buttons: [
+ new Ox.Button({
+ id: 'close',
+ title: 'Close'
+ }).bindEvent({
+ click: function() {
+ $dialog.close();
+ }
+ })
+ ],
+ content: new Ox.Element()
+ .html([
+ 'Query: ' + JSON.stringify(pandora.Query.toObject()),
+ 'findQuery: ' + JSON.stringify(app.user.ui.findQuery),
+ 'listQuery: ' + JSON.stringify(app.user.ui.listQuery)
+ ].join('
')),
+ height: 200,
+ keys: {enter: 'close', escape: 'close'},
+ width: 400
+ }).open();
+ } else if (data.id == 'resetui') {
+ pandora.api.resetUI({}, function() {
+ app.$ui.appPanel.reload();
+ });
+ }
+ }
+ });
+ return that;
+};
+
diff --git a/static/js/pandora/ui/placesDialog.js b/static/js/pandora/ui/placesDialog.js
new file mode 100644
index 000000000..c1e441e27
--- /dev/null
+++ b/static/js/pandora/ui/placesDialog.js
@@ -0,0 +1,67 @@
+// vim: et:ts=4:sw=4:sts=4:ft=js
+pandora.ui.placesDialog = function() {
+ var height = Math.round(document.height * 0.8),
+ width = Math.round(document.width * 0.8),
+ that = new Ox.Dialog({
+ buttons: [
+ new Ox.Button({
+ id: 'done',
+ title: 'Done'
+ }).bindEvent({
+ click: function() {
+ that.close();
+ }
+ })
+ ],
+ content: app.$ui.placesElement = new Ox.ListMap({
+ height: height - 48,
+ places: function(data, callback) {
+ return pandora.api.findPlaces($.extend(data, {
+ query: {conditions: [], operator: ''}
+ }), callback);
+ },
+ width: width
+ })
+ .bindEvent({
+ addplace: function(event, data) {
+ Ox.print('ADDPLACE', data)
+ pandora.api.addPlace(data.place, function(result) {
+ var id = result.data.id;
+ Ox.print("ID", result.data.id, result)
+ Ox.Request.clearCache(); // fixme: remove
+ Ox.print('AAAAA')
+ app.$ui.placesElement
+ .reloadList()
+ .bindEventOnce({
+ loadlist: function() {
+ app.$ui.placesElement
+ .focusList()
+ .options({selected: [id]});
+ }
+ });
+ });
+ },
+ removeplace: function(event, data) {
+ pandora.api.removePlace(data.id, function(result) {
+ // fixme: duplicated
+ Ox.Request.clearCache(); // fixme: remove
+ app.$ui.placesElement
+ .reloadList()
+ .bindEventOnce({
+ loadlist: function(event, data) {
+ app.$ui.placesElement
+ .focusList();
+ }
+ });
+ });
+ }
+ }),
+ height: height,
+ keys: {enter: 'done', escape: 'done'},
+ padding: 0,
+ title: 'Manage Places',
+ width: width
+ });
+ return that;
+};
+
diff --git a/static/js/pandora/ui/player.js b/static/js/pandora/ui/player.js
new file mode 100644
index 000000000..e69de29bb
diff --git a/static/js/pandora/ui/publicLists.js b/static/js/pandora/ui/publicLists.js
new file mode 100644
index 000000000..952f84375
--- /dev/null
+++ b/static/js/pandora/ui/publicLists.js
@@ -0,0 +1,25 @@
+// vim: et:ts=4:sw=4:sts=4:ft=js
+pandora.ui.publicListsDialog = function() { // fixme: unused
+ var that = new Ox.Dialog({
+ buttons: [
+ new Ox.Button({
+ id: 'done',
+ title: 'Done'
+ }).bindEvent({
+ click: function() {
+ that.close();
+ }
+ })
+ ],
+ content: pandora.ui.publicListsList(),
+ height: 320,
+ keys: {enter: 'close', escape: 'close'},
+ padding: 0,
+ title: 'Public Lists',
+ width: 420
+ })
+ .css({
+ position: 'absolute'
+ });
+ return that;
+};
diff --git a/static/js/pandora/ui/rightPanel.js b/static/js/pandora/ui/rightPanel.js
new file mode 100644
index 000000000..c1aa62aeb
--- /dev/null
+++ b/static/js/pandora/ui/rightPanel.js
@@ -0,0 +1,56 @@
+// vim: et:ts=4:sw=4:sts=4:ft=js
+pandora.ui.rightPanel = function() {
+ var that;
+ if (app.user.ui.section == 'site') {
+ that = new Ox.Element()
+ .html(app.user.ui.sitePage)
+ .bindEvent({
+ resize: function(event, data) {
+
+ }
+ });
+ pandora.api.getPage(app.user.ui.sitePage, function(result) {
+ that.html(result.data.body).css({'overflow-y':'auto'});
+ });
+ } else if (app.user.ui.section == 'items') {
+ that = new Ox.SplitPanel({
+ elements: [
+ {
+ element: app.$ui.toolbar = pandora.ui.toolbar(),
+ size: 24
+ },
+ {
+ element: app.$ui.contentPanel = pandora.ui.contentPanel()
+ },
+ {
+ element: app.$ui.statusbar = pandora.ui.statusbar(),
+ size: 16
+ }
+ ],
+ id: 'rightPanel',
+ orientation: 'vertical'
+ })
+ .bindEvent({
+ resize: function(event, data) {
+ //Ox.print('???? resize rightPanel', event, data)
+ if (!app.user.ui.item) {
+ resizeGroups(data);
+ app.$ui.list.size();
+ if (app.user.ui.lists[app.user.ui.list].listView == 'map') {
+ app.$ui.map.resize();
+ }
+ } else {
+ app.$ui.browser.scrollToSelection();
+ app.user.ui.itemView == 'player' && app.$ui.player.options({
+ width: data
+ });
+ app.user.ui.itemView == 'timeline' && app.$ui.editor.options({
+ width: data
+ });
+ }
+ }
+ });
+ }
+ return that;
+};
+
diff --git a/static/js/pandora/ui/sectionButtons.js b/static/js/pandora/ui/sectionButtons.js
new file mode 100644
index 000000000..336b170ba
--- /dev/null
+++ b/static/js/pandora/ui/sectionButtons.js
@@ -0,0 +1,28 @@
+// vim: et:ts=4:sw=4:sts=4:ft=js
+pandora.ui.sectionButtons = function() {
+ var that = new Ox.ButtonGroup({
+ buttons: [
+ {id: 'site', selected: app.user.ui.section == 'site', title: app.config.site.name},
+ {id: 'items', selected: app.user.ui.section == 'items', title: app.config.itemName.plural},
+ {id: 'texts', selected: app.user.ui.section == 'texts', title: 'Texts'},
+ {id: 'admin', selected: app.user.ui.section == 'admin', title: 'Admin'}
+ ],
+ id: 'sectionButtons',
+ selectable: true
+ }).css({
+ float: 'left',
+ margin: '4px'
+ })
+ .bindEvent({
+ change: function(event, data) {
+ var section = data.selected[0];
+ if (section == 'site') {
+ pandora.URL.set(app.user.ui.sitePage);
+ } else if (section == 'items') {
+ pandora.URL.set(pandora.Query.toString());
+ }
+ }
+ });
+ return that;
+};
+
diff --git a/static/js/pandora/ui/sectionSelect.js b/static/js/pandora/ui/sectionSelect.js
new file mode 100644
index 000000000..fda181427
--- /dev/null
+++ b/static/js/pandora/ui/sectionSelect.js
@@ -0,0 +1,21 @@
+// vim: et:ts=4:sw=4:sts=4:ft=js
+pandora.ui.sectionSelect = function() {
+ // fixme: duplicated
+ var that = new Ox.Select({
+ id: 'sectionSelect',
+ items: [
+ {checked: app.user.ui.section == 'site', id: 'site', title: app.config.site.name},
+ {checked: app.user.ui.section == 'items', id: 'items', title: app.config.itemName.plural},
+ {checked: app.user.ui.section == 'texts', id: 'texts', title: 'Texts'},
+ {checked: app.user.ui.section == 'admin', id: 'admin', title: 'Admin'}
+ ]
+ }).css({
+ float: 'left',
+ margin: '4px'
+ })
+ .bindEvent({
+
+ });
+ return that;
+};
+
diff --git a/static/js/pandora/ui/sectionbar.js b/static/js/pandora/ui/sectionbar.js
new file mode 100644
index 000000000..bf2b1c51a
--- /dev/null
+++ b/static/js/pandora/ui/sectionbar.js
@@ -0,0 +1,16 @@
+// vim: et:ts=4:sw=4:sts=4:ft=js
+pandora.ui.sectionbar = function(mode) {
+ var that = new Ox.Bar({
+ size: 24
+ })
+ .append(
+ mode == 'buttons' ?
+ app.$ui.sectionButtons = pandora.ui.sectionButtons() :
+ app.$ui.sectionSelect = pandora.ui.sectionSelect()
+ );
+ that.toggle = function() {
+
+ };
+ return that;
+};
+
diff --git a/static/js/pandora/ui/sortSelect.js b/static/js/pandora/ui/sortSelect.js
new file mode 100644
index 000000000..6e86c809f
--- /dev/null
+++ b/static/js/pandora/ui/sortSelect.js
@@ -0,0 +1,36 @@
+// vim: et:ts=4:sw=4:sts=4:ft=js
+pandora.ui.sortSelect = function() {
+ var that = new Ox.Select({
+ id: 'sortSelect',
+ items: $.map(app.ui.sortKeys, function(key) {
+ //Ox.print('????', app.user.ui.lists[app.user.ui.list].sort.key, key.id)
+ return $.extend($.extend({}, key), {
+ checked: app.user.ui.lists[app.user.ui.list].sort[0].key == key.id,
+ title: 'Sort by ' + key.title
+ });
+ }),
+ width: 144
+ })
+ .css({
+ float: 'left',
+ margin: '4px 0 0 4px'
+ })
+ .bindEvent({
+ change: function(event, data) {
+ var id = data.selected[0].id,
+ operator = pandora.getSortOperator(id);
+ /*
+ app.user.ui.lists[app.user.ui.list].sort[0] = {
+ key: id,
+ operator: operator
+ };
+ */
+ app.$ui.mainMenu.checkItem('sortMenu_sortmovies_' + id);
+ app.$ui.mainMenu.checkItem('sortMenu_ordermovies_' + (operator === '' ? 'ascending' : 'descending'));
+ app.$ui.list.sortList(id, operator);
+ pandora.URL.set(pandora.Query.toString());
+ }
+ });
+ return that;
+};
+
diff --git a/static/js/pandora/ui/status.js b/static/js/pandora/ui/status.js
new file mode 100644
index 000000000..a91cd8cea
--- /dev/null
+++ b/static/js/pandora/ui/status.js
@@ -0,0 +1,13 @@
+// vim: et:ts=4:sw=4:sts=4:ft=js
+pandora.ui.status = function(key, data) {
+ var that = Ox.toTitleCase(key) + ': ' + [
+ Ox.formatNumber(data.items) + ' movie' + (data.items != 1 ? 's' : ''),
+ Ox.formatDuration(data.runtime, 'medium'),
+ data.files + ' file' + (data.files != 1 ? 's' : ''),
+ Ox.formatDuration(data.duration, 'short'),
+ Ox.formatValue(data.size, 'B'),
+ Ox.formatValue(data.pixels, 'px')
+ ].join(', ');
+ return that;
+};
+
diff --git a/static/js/pandora/ui/statusbar.js b/static/js/pandora/ui/statusbar.js
new file mode 100644
index 000000000..9d74e1b80
--- /dev/null
+++ b/static/js/pandora/ui/statusbar.js
@@ -0,0 +1,27 @@
+// vim: et:ts=4:sw=4:sts=4:ft=js
+pandora.ui.statusbar = function() {
+ var that = new Ox.Bar({
+ size: 16
+ })
+ .css({
+ textAlign: 'center'
+ })
+ .append(
+ new Ox.Element()
+ .css({
+ marginTop: '2px',
+ fontSize: '9px'
+ })
+ .append(
+ app.$ui.total = new Ox.Element('span')
+ )
+ .append(
+ new Ox.Element('span').html(' — ')
+ )
+ .append(
+ app.$ui.selected = new Ox.Element('span')
+ )
+ );
+ return that;
+};
+
diff --git a/static/js/pandora/ui/toolbar.js b/static/js/pandora/ui/toolbar.js
new file mode 100644
index 000000000..e991fdd76
--- /dev/null
+++ b/static/js/pandora/ui/toolbar.js
@@ -0,0 +1,25 @@
+// vim: et:ts=4:sw=4:sts=4:ft=js
+pandora.ui.toolbar = function() {
+ var that = new Ox.Bar({
+ size: 24
+ }).css({
+ zIndex: 2 // fixme: remove later
+ });
+ app.user.ui.item && that.append(
+ app.$ui.backButton = pandora.ui.backButton()
+ );
+ that.append(
+ app.$ui.viewSelect = pandora.ui.viewSelect()
+ );
+ !app.user.ui.item && that.append(
+ app.$ui.sortSelect = pandora.ui.sortSelect()
+ );
+ that.append(
+ app.$ui.findElement = pandora.ui.findElement()
+ );
+ that.display = function() {
+ app.$ui.rightPanel.replaceElement(0, app.$ui.toolbar = pandora.ui.toolbar()); // fixme: remove later
+ }
+ return that;
+};
+
diff --git a/static/js/pandora/ui/viewSelect.js b/static/js/pandora/ui/viewSelect.js
new file mode 100644
index 000000000..fa9148b99
--- /dev/null
+++ b/static/js/pandora/ui/viewSelect.js
@@ -0,0 +1,37 @@
+// vim: et:ts=4:sw=4:sts=4:ft=js
+pandora.ui.viewSelect = function() {
+ var that = new Ox.Select({
+ id: 'viewSelect',
+ items: !app.user.ui.item ? $.map(app.config.listViews, function(view) {
+ return $.extend($.extend({}, view), {
+ checked: app.user.ui.lists[app.user.ui.list].listView == view.id,
+ title: 'View ' + view.title
+ });
+ }) : $.map(app.config.itemViews, function(view) {
+ return $.extend($.extend({}, view), {
+ checked: app.user.ui.itemView == view.id,
+ title: 'View: ' + view.title
+ });
+ }),
+ width: !app.user.ui.item ? 144 : 128
+ })
+ .css({
+ float: 'left',
+ margin: '4px 0 0 4px'
+ })
+ .bindEvent({
+ change: !app.user.ui.item ? function(event, data) {
+ var id = data.selected[0].id;
+ app.$ui.mainMenu.checkItem('viewMenu_movies_' + id);
+ pandora.UI.set(['lists', app.user.ui.list, 'listView'].join('|'), id);
+ pandora.URL.set(pandora.Query.toString());
+ } : function(event, data) {
+ var id = data.selected[0].id;
+ //pandora.UI.set({itemView: id});
+ pandora.URL.set(app.user.ui.item + '/' + id);
+ // app.$ui.contentPanel.replaceElement(1, app.$ui.item = pandora.ui.item());
+ }
+ });
+ return that;
+};
+
diff --git a/static/json/pandora.json b/static/json/pandora.json
new file mode 100644
index 000000000..9da403b48
--- /dev/null
+++ b/static/json/pandora.json
@@ -0,0 +1,41 @@
+[
+ "js/pandora/pandora.js",
+ "js/pandora/URL.js",
+ "js/pandora/Query.js",
+ "js/pandora/autovalidate.js",
+ "js/pandora/UI.js",
+ "js/pandora/ui/info.js",
+ "js/pandora/ui/rightPanel.js",
+ "js/pandora/ui/folderBrowserList.js",
+ "js/pandora/ui/group.js",
+ "js/pandora/ui/toolbar.js",
+ "js/pandora/ui/statusbar.js",
+ "js/pandora/ui/player.js",
+ "js/pandora/ui/sectionButtons.js",
+ "js/pandora/ui/item.js",
+ "js/pandora/ui/folderBrowser.js",
+ "js/pandora/ui/publicLists.js",
+ "js/pandora/ui/filter.js",
+ "js/pandora/ui/status.js",
+ "js/pandora/ui/sectionbar.js",
+ "js/pandora/ui/folders.js",
+ "js/pandora/ui/mainPanel.js",
+ "js/pandora/ui/sortSelect.js",
+ "js/pandora/ui/menu.js",
+ "js/pandora/ui/viewSelect.js",
+ "js/pandora/ui/browser.js",
+ "js/pandora/ui/list.js",
+ "js/pandora/ui/foldersList.js",
+ "js/pandora/ui/findElement.js",
+ "js/pandora/ui/filterDialog.js",
+ "js/pandora/ui/account.js",
+ "js/pandora/ui/folderBrowserBar.js",
+ "js/pandora/ui/sectionSelect.js",
+ "js/pandora/ui/placesDialog.js",
+ "js/pandora/ui/contentPanel.js",
+ "js/pandora/ui/backButton.js",
+ "js/pandora/ui/leftPanel.js",
+ "js/pandora/ui/appPanel.js",
+ "js/pandora/ui/flipbook.js",
+ "js/pandora/ui/editor.js"
+]
\ No newline at end of file