From 19f6c7d82fd5c297ccdafe002527b47046a629d5 Mon Sep 17 00:00:00 2001 From: rolux Date: Mon, 3 Jan 2011 06:44:38 +0000 Subject: [PATCH] improvent to groups and context browser --- pandora/item/managers.py | 2 +- pandora/item/views.py | 76 +++++ pandora/templates/site.json | 99 ++++--- static/js/pandora.js | 553 ++++++++++++++++++------------------ 4 files changed, 414 insertions(+), 316 deletions(-) diff --git a/pandora/item/managers.py b/pandora/item/managers.py index 06f0d3ba2..aea31ec93 100644 --- a/pandora/item/managers.py +++ b/pandora/item/managers.py @@ -10,7 +10,7 @@ import models def keyType(key): if key in ('released', ): return "date" - if key in ('year', 'cast.length'): + if key in ('cast.length', ): return "int" if key in ('rating', 'votes'): return "float" diff --git a/pandora/item/views.py b/pandora/item/views.py index b10514b8b..916ae6a04 100644 --- a/pandora/item/views.py +++ b/pandora/item/views.py @@ -147,6 +147,7 @@ Positions response = json_response({}) if 'group' in query: + ''' if 'sort' in query: if len(query['sort']) == 1 and query['sort'][0]['key'] == 'items': if query['group'] == "year": @@ -169,6 +170,8 @@ Positions query['sort'][i]['key'] = name_sort elif query['sort'][i]['key'] == 'items': query['sort'][i]['key'] = items + print query['sort'] + print '---------------------------------------------------------' qs = _order_query(qs, query['sort'], prefix='') if 'ids' in query: #FIXME: this does not scale for larger results @@ -181,6 +184,40 @@ Positions response['data']['items'] = [{'name': i[name], 'items': i[items]} for i in qs] else: response['data']['items'] = qs.count() + ''' + if 'sort' in query: + if len(query['sort']) == 1 and query['sort'][0]['key'] == 'items': + if query['group'] == "year": + order_by = query['sort'][0]['operator'] == '-' and 'items' or '-items' + else: + order_by = query['sort'][0]['operator'] == '-' and '-items' or 'items' + if query['group'] != "keyword": + order_by = (order_by, 'value_sort') + else: + order_by = (order_by,) + else: + order_by = query['sort'][0]['operator'] == '-' and '-value_sort' or 'value_sort' + order_by = (order_by, 'items') + else: + order_by = ('-value_sort', 'items') + response['data']['items'] = [] + items = 'items' + item_qs = query['qs'] + qs = models.Facet.objects.filter(key=query['group']).filter(item__id__in=item_qs) + qs = qs.values('value').annotate(items=Count('id')).order_by(*order_by) + + if 'ids' in query: + #FIXME: this does not scale for larger results + response['data']['positions'] = {} + ids = [j['value'] for j in qs] + response['data']['positions'] = _get_positions(ids, query['ids']) + + elif 'range' in data: + qs = qs[query['range'][0]:query['range'][1]] + response['data']['items'] = [{'name': i['value'], 'items': i[items]} for i in qs] + else: + response['data']['items'] = qs.count() + elif 'ids' in query: #FIXME: this does not scale for larger results qs = _order_query(query['qs'], query['sort']) @@ -223,6 +260,45 @@ Positions actions.register(find) +def autocomplete(request): + ''' + param data + key + value + operator '', '^', '$' + range + return + ''' + data = json.loads(request.POST['data']) + if not 'range' in data: + data['range'] = [0, 10] + + #FIXME: key and sort have to be defined in site.json + if data['key'] == 'title': + qs = models.Item.objects.filter(find__key='title', find__value__icontains=data['value']) + qs = qs.order_by('-sort__votes') + qs = qs[data['range'][0]:data['range'][1]] + response = json_response({}) + response['data']['items'] = [i.get('title') for i in qs] + else: + qs = models.Facet.objects.filter(key=data['key']) + op = data.get('operator', '') + if op == '': + qs = qs.filter(value__icontains=data['value']) + elif op == '^': + qs = qs.filter(value__istartswith=data['value']) + elif op == '$': + qs = qs.filter(value__iendswith=data['value']) + qs = qs.values('value').annotate(items=Count('id')).order_by('-items') + qs = qs[data['range'][0]:data['range'][1]] + response = json_response({}) + response['data']['items'] = [i['value'] for i in qs] + + print response + return render_to_json_response(response) +actions.register(autocomplete) + + def getItem(request): ''' param data diff --git a/pandora/templates/site.json b/pandora/templates/site.json index d753435f7..95556053d 100644 --- a/pandora/templates/site.json +++ b/pandora/templates/site.json @@ -18,7 +18,19 @@ {"id": "summary", "title": "Summary"}, {"id": "dialog", "title": "Dialog"} ], - "groups": ["director", "country", "year", "language", "genre"], + "groups": [ + {"id": "director", "title": "Director"}, + {"id": "country", "title": "Country"}, + {"id": "year", "title": "Year"}, + {"id": "language", "title": "Language"}, + {"id": "genre", "title": "Genre"}, + {"id": "writer", "title": "Writer"}, + {"id": "producer", "title": "Producer"}, + {"id": "cinematographer", "title": "Cinematographer"}, + {"id": "editor", "title": "Editor"}, + {"id": "actor", "title": "Actor"}, + {"id": "keyword", "title": "Keyword"} + ], "itemName": { "singular": "Movie", "plural": "Movies" @@ -61,48 +73,48 @@ {"id": "featured", "title": "Featured Lists"} ], "sortKeys": [ - {"id": "title", "title": "Title", "operator": "", "align": "left", "width": 180, "removable": false}, - {"id": "director", "title": "Director", "operator": "", "align": "left", "width": 180, "removable": false}, - {"id": "country", "title": "Country", "operator": "", "align": "left", "width": 120}, - {"id": "year", "title": "Year", "operator": "-", "align": "right", "width": 60}, - {"id": "language", "title": "Language", "operator": "", "align": "left", "width": 120}, - {"id": "runtime", "title": "Runtime", "operator": "-", "align": "right", "width": 60}, - {"id": "writer", "title": "Writer", "operator": "", "align": "left", "width": 180}, - {"id": "producer", "title": "Producer", "operator": "", "align": "left", "width": 180}, - {"id": "cinematographer", "title": "Cinematographer", "operator": "", "align": "left", "width": 180}, - {"id": "editor", "title": "Editor", "operator": "", "align": "left", "width": 180}, - {"id": "actors", "title": "Number of Actors", "operator": "-", "align": "right", "width": 60}, - {"id": "genre", "title": "Genre", "operator": "", "align": "left", "width": 120}, - {"id": "keywords", "title": "Number of Keywords", "operator": "-", "align": "right", "width": 60}, - {"id": "summary", "title": "Words in Summary", "operator": "-", "align": "right", "width": 60}, - {"id": "trivia", "title": "Words in Trivia", "operator": "-", "align": "right", "width": 60}, - {"id": "releasedate", "title": "Release Date", "operator": "-", "align": "left", "width": 90}, - {"id": "budget", "title": "Budget", "operator": "-", "align": "right", "width": 90}, - {"id": "gross", "title": "Gross", "operator": "-", "align": "right", "width": 90}, - {"id": "profit", "title": "Profit", "operator": "-", "align": "right", "width": 90}, - {"id": "rating", "title": "Rating", "operator": "-", "align": "right", "width": 60}, - {"id": "votes", "title": "Votes", "operator": "-", "align": "right", "width": 90}, - {"id": "id", "title": "ID", "operator": "", "align": "left", "width": 90}, - {"id": "aspectratio", "title": "Aspect Ratio", "operator": "-", "align": "left", "width": 90}, - {"id": "duration", "title": "Duration", "operator": "-", "align": "right", "width": 90}, - {"id": "color", "title": "Color", "operator": "", "align": "left", "width": 90}, - {"id": "saturation", "title": "Saturation", "operator": "-", "align": "right", "width": 60}, - {"id": "brightness", "title": "Brightness", "operator": "-", "align": "right", "width": 60}, - {"id": "volume", "title": "Volume", "operator": "-", "align": "right", "width": 60}, - {"id": "clips", "title": "Clips", "operator": "-", "align": "right", "width": 60}, - {"id": "cuts", "title": "Cuts", "operator": "-", "align": "right", "width": 60}, - {"id": "cutsperminute", "title": "Cuts per Minute", "operator": "-", "align": "right", "width": 60}, - {"id": "words", "title": "Words", "operator": "-", "align": "right", "width": 60}, - {"id": "wordsperminute", "title": "Words per Minute", "operator": "-", "align": "right", "width": 60}, - {"id": "resolution", "title": "Resolution", "operator": "-", "align": "left", "width": 90}, - {"id": "pixels", "title": "Pixels", "operator": "-", "align": "right", "width": 90}, - {"id": "size", "title": "Size", "operator": "-", "align": "right", "width": 90}, - {"id": "bitrate", "title": "Bitrate", "operator": "-", "align": "right", "width": 90}, - {"id": "files", "title": "Files", "operator": "-", "align": "right", "width": 60}, - {"id": "filename", "title": "Filename", "operator": "", "align": "left", "width": 180}, - {"id": "published", "title": "Date Published", "operator": "-", "align": "left", "width": 90}, - {"id": "modified", "title": "Date Modified", "operator": "-", "align": "left", "width": 90}, - {"id": "popularity", "title": "Popularity", "operator": "-", "align": "left", "width": 60} + {"id": "title", "title": "Title", "width": 180, "removable": false, "type": "title", "autocompleteSortKey": "votes"}, + {"id": "director", "title": "Director", "width": 180, "removable": false, "type": "person"}, + {"id": "country", "title": "Country", "width": 120, "type": "text"}, + {"id": "year", "title": "Year", "width": 60, "type": "year"}, + {"id": "language", "title": "Language", "width": 120, "type": "text"}, + {"id": "runtime", "title": "Runtime", "width": 60, "type": "integer"}, + {"id": "writer", "title": "Writer", "width": 180, "type": "person"}, + {"id": "producer", "title": "Producer", "width": 180, "type": "person"}, + {"id": "cinematographer", "title": "Cinematographer", "width": 180, "type": "person"}, + {"id": "editor", "title": "Editor", "width": 180, "type": "person"}, + {"id": "actors", "title": "Number of Actors", "width": 60, "type": "person"}, + {"id": "genre", "title": "Genre", "width": 120, "type": "text"}, + {"id": "keyword", "title": "Number of Keywords", "width": 60, "type": "integer"}, + {"id": "summary", "title": "Words in Summary", "width": 60, "type": "words"}, + {"id": "trivia", "title": "Words in Trivia", "width": 60, "type": "words"}, + {"id": "releasedate", "title": "Release Date", "width": 90, "type": "date"}, + {"id": "budget", "title": "Budget", "width": 90, "type": "integer"}, + {"id": "gross", "title": "Gross", "width": 90, "type": "integer"}, + {"id": "profit", "title": "Profit", "width": 90, "type": "integer"}, + {"id": "rating", "title": "Rating", "width": 60, "type": "float"}, + {"id": "votes", "title": "Votes", "width": 90, "type": "integer"}, + {"id": "id", "title": "ID", "width": 90, "type": "string"}, + {"id": "aspectratio", "title": "Aspect Ratio", "width": 90, "type": "float"}, + {"id": "duration", "title": "Duration", "width": 90, "type": "float"}, + {"id": "color", "title": "Color", "width": 90, "type": "float"}, + {"id": "saturation", "title": "Saturation", "width": 60, "type": "float"}, + {"id": "brightness", "title": "Brightness", "width": 60, "type": "float"}, + {"id": "volume", "title": "Volume", "width": 60, "type": "float"}, + {"id": "clips", "title": "Clips", "width": 60, "type": "integer"}, + {"id": "cuts", "title": "Cuts", "width": 60, "type": "integer"}, + {"id": "cutsperminute", "title": "Cuts per Minute", "width": 60, "type": "float"}, + {"id": "words", "title": "Words", "width": 60, "type": "integer"}, + {"id": "wordsperminute", "title": "Words per Minute", "width": 60, "type": "float"}, + {"id": "resolution", "title": "Resolution", "width": 90, "type": "integer"}, + {"id": "pixels", "title": "Pixels", "width": 90, "type": "integer"}, + {"id": "size", "title": "Size", "width": 90, "type": "integer"}, + {"id": "bitrate", "title": "Bitrate", "width": 90, "type": "integer"}, + {"id": "files", "title": "Files", "width": 60, "type": "integer"}, + {"id": "filename", "title": "Filename", "width": 180, "type": "text"}, + {"id": "published", "title": "Date Published", "width": 90, "type": "date"}, + {"id": "modified", "title": "Date Modified", "width": 90, "type": "date"}, + {"id": "popularity", "title": "Popularity", "type": "float"} ], "totals": [ {"id": "items"}, @@ -118,6 +130,7 @@ "ui": { "columns": ["id", "title", "director", "country", "year", "language", "genre"], "findQuery": {"conditions": [], "operator": ""}, + "groups": ["director", "country", "year", "language", "genre"], "groupsQuery": {"conditions": [], "operator": "|"}, "groupsSize": 176, "item": "", diff --git a/static/js/pandora.js b/static/js/pandora.js index ee4dff8e0..85b931f75 100755 --- a/static/js/pandora.js +++ b/static/js/pandora.js @@ -50,7 +50,7 @@ var pandora = new Ox.App({ }); }); - Query.fromString(location.hash.substr(1)); + //Query.fromString(location.hash.substr(1)); URL.parse(); window.onpopstate = function() { @@ -71,7 +71,8 @@ var pandora = new Ox.App({ } } else { Ox.print('app.$ui.window.resize'); - app.$ui.editor.options({ + app.$ui.browser.scrollToSelection(); + app.user.ui.itemView == 'timeline' && app.$ui.editor.options({ height: app.$ui.document.height() - 20 - 24 - app.$ui.contentPanel.size(0) - 1 - 16, width: app.$ui.document.width() - @@ -474,7 +475,6 @@ var pandora = new Ox.App({ $.each($bins, function(i, bin) { that.append(bin); }); - //alert(JSON.stringify(that.id)) return that; }, appPanel: function() { @@ -503,10 +503,26 @@ var pandora = new Ox.App({ } return that; }, - browser: function(mode) { - if (mode == 'list') { + backButton: function() { + var that = Ox.Button({ + title: 'Back to Movies', + width: 96 + }).css({ + float: 'left', + margin: '4px' + }) + .bindEvent({ + click: function(event, data) { + URL.set(Query.toString()); + } + }); + return that; + }, + browser: function() { + var that; + if (!app.user.ui.item) { app.$ui.groups = ui.groups(); - var that = new Ox.SplitPanel({ + that = new Ox.SplitPanel({ elements: [ { element: app.$ui.groups[0], @@ -529,8 +545,9 @@ var pandora = new Ox.App({ list.size(); }); }); - } else if (mode == 'item') { + } else { var that = new Ox.IconList({ + centered: true, id: 'list', item: function(data, sort, size) { var ratio = data.poster.width / data.poster.height; @@ -558,8 +575,19 @@ var pandora = new Ox.App({ size: 64, sort: app.user.ui.sort, unique: 'id' + }) + .bindEvent({ + open: function(event, data) { + that.scrollToSelection(); + }, + select: function(event, data) { + URL.set(data.ids[0]); + } }); } + that.update = function() { + app.$ui.contentPanel.replace(0, app.$ui.browser = ui.browser()); + } return that; }, contentPanel: function() { @@ -567,7 +595,7 @@ var pandora = new Ox.App({ elements: app.user.ui.item == '' ? [ { collapsible: true, - element: app.$ui.browser = ui.browser('list') + element: app.$ui.browser = ui.browser() .bindEvent('resize', function(event, data) { Ox.print('resizing groups...') $.each(app.$ui.groups, function(i, list) { @@ -584,7 +612,7 @@ var pandora = new Ox.App({ ] : [ { collapsible: true, - element: app.$ui.browser = ui.browser('item'), + element: app.$ui.browser = ui.browser(), size: 112 + ($.browser.mozilla ? 16 : 12) // fixme: should be app.ui.scrollbarSize }, { @@ -617,43 +645,13 @@ var pandora = new Ox.App({ app.user.ui.findQuery.conditions[0].key = key; } app.$ui.mainMenu.checkItem('findMenu_find_' + key); - app.$ui.findInput.focus(); + app.$ui.findInput.options({ + autocomplete: autocompleteFunction() + }).focus(); + Ox.print(app.$ui.findInput.options('autocomplete').toString()) }), app.$ui.findInput = new Ox.Input({ - autocomplete: function(value, callback) { - var key = 'title'; - var findKey = Ox.getObjectById(app.config.findKeys, key); - Ox.print('autocomplete', key, value); - value === '' && Ox.print('Warning: autocomplete function should never be called with empty value'); - if ('autocomplete' in findKey && findKey.autocomplete) { - pandora.api.find({ - keys: [key], - query: { - conditions: [ - { - key: key, - value: value, - operator: '' - } - ], - operator: '' - }, - sort: [ - { - key: key, - operator: '' - } - ], - range: [0, 10] - }, function(result) { - callback($.map(result.data.items, function(v) { - return v.title; - })); - }); - } else { - callback(); - } - }, + autocomplete: autocompleteFunction(), autocompleteSelect: true, autocompleteSelectHighlight: true, autocompleteSelectSubmit: true, @@ -662,7 +660,8 @@ var pandora = new Ox.App({ width: 192 }) .bindEvent('submit', function(event, data) { - var key = app.user.ui.findQuery.conditions[0].key, + var key = app.user.ui.findQuery.conditions.length ? + app.user.ui.findQuery.conditions[0].key : '', query; Ox.print('key', key); app.user.ui.findQuery.conditions = [ @@ -700,97 +699,181 @@ var pandora = new Ox.App({ float: 'right', margin: '4px' }); + function autocompleteFunction() { + return app.user.ui.findQuery.conditions.length ? function(value, callback) { + var key = app.user.ui.findQuery.conditions[0].key, + findKey = Ox.getObjectById(app.config.findKeys, key); + Ox.print('autocomplete', key, value); + value === '' && Ox.print('Warning: autocomplete function should never be called with empty value'); + if ('autocomplete' in findKey && findKey.autocomplete) { + pandora.api.autocomplete({ + key: key, + range: [0, 20], + value: value + }, function(result) { + //alert(JSON.stringify(result)) + callback(result.data.items); + }); + /* + pandora.api.find({ + keys: [key], + query: { + conditions: [ + { + key: key, + value: value, + operator: '' + } + ], + operator: '' + }, + sort: [ + { + key: key, + operator: '' + } + ], + range: [0, 10] + }, function(result) { + callback($.map(result.data.items, function(v) { + return v[key]; + })); + }); + */ + } else { + callback(); + } + } : null; + } return that; }, + group: function(id) { + var i = app.user.ui.groups.indexOf(id), + panelWidth = app.$ui.document.width() - app.user.ui.listsSize - 1, + title = Ox.getObjectById(app.config.groups, id).title, + width = 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 + } + ], + id: 'group_' + id, + request: function(data, callback) { + Ox.print('sending request', data) + delete data.keys; + return pandora.api.find($.extend(data, { + group: id, + query: Query.toObject(id) + }), callback); + }, + sort: [ + { + key: id == 'year' ? 'name' : 'items', + operator: '-' + } + ] + }) + .bindEvent('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: '=' + }; + }); + query = Query.toObject(); + app.$ui.list.options({ + request: function(data, callback) { + return pandora.api.find($.extend(data, { + query: query + }), callback); + } + }); + $.each(app.ui.groups, function(i_, group_) { + if (i_ != i) { + Ox.print('setting groups request', i, i_) + app.$ui.groups[i_].options({ + request: function(data, callback) { + delete data.keys; + return pandora.api.find($.extend(data, { + group: group_.id, + query: Query.toObject(group_.id) + }), callback); + } + }); + } + }); + history.pushState({}, '', Query.toString(query)); + }); + 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, + index = app.user.ui.groups.indexOf(id_); + replaceGroup(i, id_); + index > -1 && replaceGroup(index, id); + function replaceGroup(i, id) { + app.user.ui.groups[i] = id; + if (i == 0 || i == 4) { + app.$ui.browser.replace(i / 2, app.$ui.groups[i] = ui.group(id)); + } else { + app.$ui.groupsInnerPanel.replace(i - 1, app.$ui.groups[i] = ui.group(id)); + } + app.ui.groups[i] = getGroupObject(id); + } + }) + .appendTo(that.$bar.$element); + 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 = getGroupWidth(i, panelWidth); + return { + id: id, + element: that, + query: { + conditions: [], + operator: '|' + }, + size: width.list, + title: title + }; + } + return that; + }, groups: function() { - var $groups = [], - panelWidth = app.$ui.document.width() - app.user.ui.listsSize - 1; - app.ui.groups = $.map(app.config.groups, function(id, i) { - var title = Ox.getObjectById(app.config.sortKeys, id).title, - width = getGroupWidth(i, panelWidth); - return { - id: id, - element: $groups[i] = 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 - } - ], - id: 'group_' + id, - request: function(data, callback) { - Ox.print('sending request', data) - delete data.keys; - return pandora.api.find($.extend(data, { - group: id, - query: Query.toObject(id) - }), callback); - }, - sort: [ - { - key: id == 'year' ? 'name' : 'items', - operator: '-' - } - ] - }) - .bindEvent('select', function(event, data) { - Ox.print('-- select', i) - var group = app.ui.groups[i], - query; - app.ui.groups[i].query.conditions = $.map(data.ids, function(v) { - return { - key: group.id, - value: v, - operator: '=' - }; - }); - query = Query.toObject(); - Ox.print('-- data, query', data, query) - app.$ui.list.options({ - request: function(data, callback) { - return pandora.api.find($.extend(data, { - query: query - }), callback); - } - }); - Ox.print('ZZZ') - $.each(app.ui.groups, function(i_, group_) { - if (i_ != i) { - Ox.print('setting groups request', i, i_) - app.$ui.groups[i_].options({ - request: function(data, callback) { - delete data.keys; - return pandora.api.find($.extend(data, { - group: group_.id, - query: Query.toObject(group_.id) - }), callback); - } - }); - } - }); - history.pushState({}, '', '/#' + Query.toString(query)); - }), - query: { - conditions: [], - operator: '|' - }, - size: width.list, - title: title - }; - }); + var $groups = []; + app.ui.groups = []; + app.user.ui.groups.forEach(function(id, i) { + $groups[i] = ui.group(id, i) + }); return $groups; }, groupsInnerPanel: function() { @@ -833,7 +916,7 @@ var pandora = new Ox.App({ ); return that; }, - item: function(id, view) { // fixme: params are not necessary + item: function() { var that = new Ox.Element('div'); elements = []; getItem(); @@ -878,7 +961,7 @@ var pandora = new Ox.App({ posterFrame: parseInt(video.duration / 2), subtitles: subtitles, videoHeight: video.height, - videoId: id, + videoId: app.user.ui.item, videoWidth: video.width, videoSize: 'small', videoURL: video.url, @@ -919,11 +1002,10 @@ var pandora = new Ox.App({ }); } that.display = function() { - //alert('display') app.$ui.contentPanel.replaceElements([ { collapsible: true, - element: app.$ui.browser = ui.browser('item'), + element: app.$ui.browser = ui.browser(), resizable: false, size: 112 + ($.browser.mozilla ? 16 : 12) }, @@ -935,111 +1017,6 @@ var pandora = new Ox.App({ } return that; }, - /* - item_: function(id, view) { - var $item; - //location.hash = '!' + id; - //app.user.ui.mode = 'item'; - app.$ui.mainMenu.enableItem('openmovie'); - app.$ui.mainMenu.checkItem('viewMenu_openmovie_' + view); - //FIXME: there should be a menu function for this - if (view == 'timeline') { - pandora.api.getItem(id, function(result) { - item_debug = result.data.item; - var video = result.data.item.stream, - cuts = result.data.item.layers.cuts || {}, - subtitles = result.data.item.layers.subtitles || [{ - 'in': 5, - 'out': 10, - 'text': 'This subtitle is just a test...' - }]; - video.height = 96; - video.width = parseInt(video.height * video.aspectRatio / 2) * 2; - video.url = video.baseUrl + '/' + video.height + 'p.' + ($.support.video.webm ? 'webm' : 'mp4'); - //app.$ui.contentPanel.size(0, 80); - app.$ui.contentPanel.replaceElements([ - { - collapsible: true, - element: app.$ui.browser = new Ox.Element('div').options({id: 'browser'}), - resizable: false, - size: 80 - }, - { - element: app.$ui.timelinePanel = new Ox.SplitPanel({ - elements: [ - { - element: app.$ui.editor = new Ox.VideoEditor({ - cuts: cuts, - duration: video.duration, - find: '', - frameURL: function(position) { - return '/' + id + '/frame/' + video.width.toString() + '/' + position.toString() + '.jpg' - }, - height: app.$ui.contentPanel.size(1), - id: 'editor', - largeTimeline: true, - matches: [], - points: [0, 0], - position: 0, - posterFrame: parseInt(video.duration / 2), - subtitles: subtitles, - videoHeight: video.height, - videoId: id, - videoWidth: video.width, - videoSize: 'small', - videoURL: video.url, - width: app.$ui.document.width() - app.$ui.mainPanel.size(0) - 1 - 256 - 1 - }) - .bindEvent('resize', function(event, data) { - Ox.print('RESIZE:', data) - app.$ui.editor.options({ - width: data - }); - }), - size: 'auto' - }, - { - collapsible: true, - element: app.$ui.annotations = ui.annotations(), - size: 256 - } - ], - orientation: 'horizontal' - }), - size: 'auto' - } - ]); - app.$ui.rightPanel - .bindEvent('resize', function(event, data) { - Ox.print('rightPanel resize', data, app.$ui.item.size(1)) - app.$ui.editor.options({ - width: data - app.$ui.item.size(1) - 1 - }); - }); - app.$ui.window.resize(function() { - app.$ui.editor.options({ - height: app.$ui.document.height() - 20 - 24 - app.$ui.contentPanel.size(0) - 1 - 16, - width: app.$ui.document.width() - app.$ui.mainPanel.size(0) - app.$ui.timelinePanel.size(1) - 2 - }); - }); - }); - } else if (view == 'info') { - pandora.api.getItem(id, function(result) { - item_debug = result.data.item; - var item = result.data.item; - var $item = new Ox.Container(); - $item.append(app.template.info.tmpl(item)); - app.$ui.rightPanel.replace(1, $item); - app.$ui.rightPanel - .bindEvent('resize', function(event, data) { - app.$ui.editor.options({ - width: data - app.$ui.timelinePanel.size(1) - 1 - }); - }); - }); - } - }, - */ leftPanel: function() { var that = new Ox.SplitPanel({ elements: [ @@ -1087,8 +1064,10 @@ var pandora = new Ox.App({ that = new Ox.TextList({ columns: $.map(app.config.sortKeys, function(key, i) { return $.extend({ - visible: $.inArray(key.id, app.user.ui.columns) > -1, - unique: key.id == 'id' + align: getAlignment(key.id), + operator: getSortOperator(key.id), + unique: key.id == 'id', + visible: $.inArray(key.id, app.user.ui.columns) > -1 }, key); }), columnsMovable: true, @@ -1653,7 +1632,7 @@ var pandora = new Ox.App({ app.$ui.list.sortList(app.user.ui.sort[0].key, id == 'ascending' ? '' : '-'); } else if (data.id == 'sortmovies') { var id = data.checked[0].id, - operator = Ox.getObjectById(app.config.sortKeys, id).operator; + operator = getSortOperator(id); app.$ui.mainMenu.checkItem('sortMenu_ordermovies_' + (operator === '' ? 'ascending' : 'descending')); app.$ui.sortSelect.selectItem(id); app.$ui.list.sortList(id, operator); @@ -2023,11 +2002,10 @@ var pandora = new Ox.App({ app.$ui.map.triggerResize(); } } else { - if (app.user.ui.itemView == 'timeline') { - app.$ui.editor.options({ - width: data - app.$ui.item.size(1) - 1 - }); - } + app.$ui.browser.scrollToSelection(); + app.user.ui.itemView == 'timeline' && app.$ui.editor.options({ + width: data - app.$ui.item.size(1) - 1 + }); } }); return that; @@ -2141,11 +2119,12 @@ var pandora = new Ox.App({ }) .bindEvent('change', function(event, data) { var id = data.selected[0].id, - operator = Ox.getObjectById(app.config.sortKeys, id).operator; - app.user.ui.listView = id; + operator = getSortOperator(id); + app.user.ui.sort[0].key = id; app.$ui.mainMenu.checkItem('sortMenu_sortmovies_' + id); app.$ui.mainMenu.checkItem('sortMenu_ordermovies_' + (operator === '' ? 'ascending' : 'descending')); app.$ui.list.sortList(id, operator); + URL.set(Query.toString()); }); return that; }, @@ -2187,14 +2166,16 @@ var pandora = new Ox.App({ }, toolbar: function() { var that = new Ox.Bar({ - size: 24 - }) - .append( - app.$ui.viewSelect = ui.viewSelect() - ) - .css({ - zIndex: 2 // fixme: remove later - }); + size: 24 + }).css({ + zIndex: 2 // fixme: remove later + }); + app.user.ui.item && that.append( + app.$ui.backButton = ui.backButton() + ); + that.append( + app.$ui.viewSelect = ui.viewSelect() + ); !app.user.ui.item && that.append( app.$ui.sortSelect = ui.sortSelect() ); @@ -2217,10 +2198,10 @@ var pandora = new Ox.App({ }) : $.map(app.config.itemViews, function(view) { return $.extend($.extend({}, view), { checked: app.user.ui.itemView == view.id, - title: 'View ' + view.title + title: view.title }); }), - width: 144 + width: !app.user.ui.item ? 144 : 96 }) .css({ float: 'left', @@ -2231,6 +2212,7 @@ var pandora = new Ox.App({ app.user.ui.listView = id; app.$ui.mainMenu.checkItem('viewMenu_movies_' + id); app.$ui.contentPanel.replace(1, app.$ui.list = ui.list(id)); + URL.set(Query.toString()); } : function(event, data) { var id = data.selected[0].id; app.user.ui.itemView = id; @@ -2271,6 +2253,12 @@ var pandora = new Ox.App({ callback(value); } + function getAlignment(key) { + return ['person', 'string', 'text', 'title'].indexOf( + Ox.getObjectById(app.config.sortKeys, key).type + ) > -1 ? 'left' : 'right'; + } + function getGroupWidth(pos, panelWidth) { var width = {}; width.list = Math.floor(panelWidth / 5) + (panelWidth % 5 > pos); @@ -2278,6 +2266,12 @@ var pandora = new Ox.App({ return width; } + function getSortOperator(key) { + return ['person', 'string', 'text', 'title'].indexOf( + Ox.getObjectById(app.config.sortKeys, key).type + ) > -1 ? '' : '-'; + } + function resizeGroups(width) { var widths = $.map(app.ui.groups, function(v, i) { return getGroupWidth(i, width); @@ -2398,7 +2392,7 @@ var pandora = new Ox.App({ return { fromString: function(str) { - var query = Ox.unserialize(str), + var query = Ox.unserialize(str.substr(1)), sort = []; if ('find' in query) { app.user.ui.findQuery = parseFind(query.find); @@ -2409,7 +2403,7 @@ var pandora = new Ox.App({ app.user.ui.sort = $.map(query.sort.split(','), function(v, i) { var hasOperator = '+-'.indexOf(v[0]) > -1, key = hasOperator ? query.sort.substr(1) : query.sort, - operator = hasOperator ? v[0].replace('+', '') : Ox.getObjectById(app.config.sortKeys, key).operator; + operator = hasOperator ? v[0].replace('+', '') : getSortOperator(key); return { key: key, operator: operator @@ -2445,7 +2439,7 @@ var pandora = new Ox.App({ toString: function() { Ox.print('tS', app.user.ui.find) - return Ox.serialize({ + return '?' + Ox.serialize({ find: constructFind(Query.toObject()), sort: app.user.ui.sort[0].operator + app.user.ui.sort[0].key, view: app.user.ui.listView @@ -2464,6 +2458,11 @@ var pandora = new Ox.App({ } }, regexps = { + '^\\?': function(url) { + Query.fromString(url); + app.user.ui.section = 'items'; + app.user.ui.item = ''; + }, '^(|about|faq|home|news|software|terms|tour)$': function(url) { app.user.ui.section = 'site'; app.user.ui.sitePage = url; @@ -2504,7 +2503,8 @@ var pandora = new Ox.App({ }, parse: function() { - url = document.location.pathname.substr(1) + document.location.hash; + url = document.location.pathname.substr(1) + + document.location.search + document.location.hash; $.each(regexps, function(re, fn) { Ox.print(url, 're', re) re = new RegExp(re); @@ -2517,12 +2517,21 @@ var pandora = new Ox.App({ update: function() { URL.parse(); - if (!old.user.ui.item && app.user.ui.item) { - //ui.toolbar.display(); - app.$ui.rightPanel.replace(0, app.$ui.toolbar = ui.toolbar()); - ui.item(app.user.ui.item, app.user.ui.itemView).display(); - } else if (old.user.ui.item && !app.user.ui.item) { - ui.list(app.user.ui.listView).display(); + if (!old.user.ui.item) { + if (!app.user.ui.item) { + + } else { + //ui.toolbar.display(); + app.$ui.rightPanel.replace(0, app.$ui.toolbar = ui.toolbar()); + ui.item().display(); + } + } else { + if (!app.user.ui.item) { + alert('return') + ui.list(app.user.ui.listView).display(); + } else { + app.$ui.contentPanel.replace(1, ui.item()); + } } }