From b22225413d69e63e0d7953856a9dc0312e132bab Mon Sep 17 00:00:00 2001 From: rlx <0x0073@0x2620.org> Date: Sun, 4 Sep 2011 12:43:59 +0000 Subject: [PATCH] support drag and drop from (item view) list browser --- static/js/pandora/pandora.js | 192 +++++++++++++ static/js/pandora/ui/browser.js | 2 + static/js/pandora/ui/list.js | 464 ++++++++++---------------------- 3 files changed, 337 insertions(+), 321 deletions(-) diff --git a/static/js/pandora/pandora.js b/static/js/pandora/pandora.js index 3da7cf8..c323a87 100644 --- a/static/js/pandora/pandora.js +++ b/static/js/pandora/pandora.js @@ -1,5 +1,197 @@ // vim: et:ts=4:sw=4:sts=4:ft=javascript +pandora.enableDragAndDrop = function($list, canMove) { + + var drag = {}, + $tooltip = Ox.Tooltip({ + animate: false + }); + + $list.bindEvent({ + draganddropstart: function(data) { + Ox.print('DRAGSTART', pandora.getListData()); + drag.action = 'copy'; + drag.ids = $list.options('selected'), + drag.item = drag.ids.length == 1 + ? $list.value(drag.ids[0], 'title') + : drag.ids.length; + drag.source = pandora.getListData(), + drag.targets = {}; + Ox.forEach(pandora.$ui.folderList, function($list) { + $list.addClass('OxDroppable').find('.OxItem').each(function() { + var $item = $(this), + id = $item.data('id'), + data = $list.value(id); + drag.targets[id] = Ox.extend({ + editable: data.user == pandora.user.username + && data.type == 'static', + selected: $item.is('.OxSelected') + }, data); + if (!drag.targets[id].selected && drag.targets[id].editable) { + $item.addClass('OxDroppable'); + } + }); + }); + $tooltip.options({ + title: getTitle(data._event) + }).show(data._event); + canMove && Ox.UI.$window.bind({ + keydown: keydown, + keyup: keyup + }); + }, + draganddrop: function(data) { + $tooltip.options({ + title: getTitle(data._event) + }).show(data._event); + }, + draganddropenter: function(data) { + var $parent = $(data._event.target).parent(), + $item = $parent.is('.OxItem') ? $parent : $parent.parent(), + $list = $item.parent().parent().parent().parent(); + if ($list.is('.OxDroppable')) { + $item.addClass('OxDrop'); + drag.target = drag.targets[$item.data('id')]; + } else { + drag.target = null; + } + }, + draganddropleave: function(data) { + var $parent = $(data._event.target).parent(), + $item = $parent.is('.OxItem') ? $parent : $parent.parent(); + if ($item.is('.OxDroppable')) { + $item.removeClass('OxDrop'); + drag.target = null; + } + }, + draganddropend: function(data) { + Ox.print(data, drag, '------------'); + canMove && Ox.UI.$window.unbind({ + keydown: keydown, + keyup: keyup + }); + if (drag.target && drag.target.editable && !drag.target.selected) { + if (drag.action == 'copy' || ( + drag.action == 'move' && drag.source.editable + )) { + if (drag.action == 'move') { + pandora.api.removeListItems({ + list: pandora.user.ui.list, + items: data.ids + }, pandora.reloadList); + } + pandora.api.addListItems({ + list: drag.target.id, + items: data.ids + }, function() { + Ox.Request.clearCache(); // fixme: remove + pandora.api.find({ + query: { + conditions: [{key: 'list', value: drag.target.id, operator: '='}], + operator: '' + } + }, function(result) { + var folder = drag.target.status != 'featured' ? 'personal' : 'featured'; + //Ox.print(drag.source.status, '//////', drag.target.status) + pandora.$ui.folderList[folder].value( + drag.target.id, 'items', + result.data.items + ); + cleanup(250); + }); + }); + } + } else { + cleanup(0); + } + function cleanup(ms) { + drag = {}; + setTimeout(function() { + $('.OxDroppable').removeClass('OxDroppable'); + $('.OxDrop').removeClass('OxDrop'); + $tooltip.hide(); + }, ms); + } + } + }); + + function getTitle(e) { + var image, text; + if (drag.action == 'move' && drag.source.user != pandora.user.username) { + image = 'symbolClose' + text = 'You can only remove ' + pandora.site.itemName.plural.toLowerCase() + + '
from your own lists.'; + } else if (drag.action == 'move' && drag.source.type == 'smart') { + image = 'symbolClose'; + text = 'You can\'t remove ' + pandora.site.itemName.plural.toLowerCase() + + '
from smart lists.'; + } else if (drag.target && drag.target.user != pandora.user.username) { + image = 'symbolClose' + text = 'You can only ' + drag.action + ' ' + pandora.site.itemName.plural.toLowerCase() + + '
to your own lists'; + } else if (drag.target && drag.target.type == 'smart') { + image = 'symbolClose' + text = 'You can\'t ' + drag.action + ' ' + pandora.site.itemName.plural.toLowerCase() + + '
to smart lists'; + } else { + image = drag.action == 'copy' ? 'symbolAdd' : 'symbolRemove'; + text = Ox.toTitleCase(drag.action) + ' ' + ( + Ox.isString(drag.item) + ? '"' + drag.item + '"' + : drag.item + ' ' + pandora.site.itemName[ + drag.item == 1 ? 'singular' : 'plural' + ].toLowerCase() + ) + '
to ' + ( + drag.target && !drag.target.selected + ? 'the list "' + drag.target.name + '"' + : 'another list' + ); + } + return $('
') + .append( + $('
') + .css({ + float: 'left', + width: '16px', + height: '16px', + padding: '2px', + border: '2px solid rgb(192, 192, 192)', + borderRadius: '12px', + margin: '3px 2px 2px 2px' + }) + .append( + $('') + .attr({src: Ox.UI.getImageURL(image)}) + .css({width: '16px', height: '16px'}) + ) + ) + .append( + $('
') + .css({ + float: 'left', + margin: '1px 2px 2px 2px', + fontSize: '11px', + whiteSpace: 'nowrap' + }) + .html(text) + ) + } + + function keydown(e) { + if (e.metaKey) { + drag.action = 'move'; + $tooltip.options({title: getTitle()}).show(); + } + } + function keyup(e) { + if (drag.action == 'move') { + drag.action = 'copy'; + $tooltip.options({title: getTitle()}).show(); + } + } + +}; + pandora.enterFullscreen = function() { pandora.$ui.appPanel.size(0, 0); pandora.user.ui.showSidebar && pandora.$ui.mainPanel.size(0, 0); diff --git a/static/js/pandora/ui/browser.js b/static/js/pandora/ui/browser.js index 1f09858..cd56640 100644 --- a/static/js/pandora/ui/browser.js +++ b/static/js/pandora/ui/browser.js @@ -41,6 +41,7 @@ pandora.ui.browser = function() { borderRadius: pandora.user.ui.icons == 'posters' ? 0 : 8, centered: true, defaultRatio: pandora.user.ui.icons == 'posters' ? 5/8 : 1, + draggable: true, id: 'list', item: function(data, sort, size) { var icons = pandora.user.ui.icons, @@ -88,6 +89,7 @@ pandora.ui.browser = function() { } } }); + pandora.enableDragAndDrop(that, false); } that.update = function() { pandora.$ui.contentPanel.replaceElement(0, pandora.$ui.browser = pandora.ui.browser()); diff --git a/static/js/pandora/ui/list.js b/static/js/pandora/ui/list.js index 36e8140..29dddf9 100644 --- a/static/js/pandora/ui/list.js +++ b/static/js/pandora/ui/list.js @@ -517,337 +517,159 @@ pandora.ui.list = function() { // fixme: remove view argument }); } - var drag = {}; + if (['list', 'icons'].indexOf(view) > -1) { - var $tooltip = Ox.Tooltip({ - animate: false - }); + pandora.enableDragAndDrop(that, true); - function getTitle(e) { - var image, text; - if (drag.action == 'move' && drag.source.user != pandora.user.username) { - image = 'symbolClose' - text = 'You can only remove ' + pandora.site.itemName.plural.toLowerCase() - + '
from your own lists.'; - } else if (drag.action == 'move' && drag.source.type == 'smart') { - image = 'symbolClose'; - text = 'You can\'t remove ' + pandora.site.itemName.plural.toLowerCase() - + '
from smart lists.'; - } else if (drag.target && drag.target.user != pandora.user.username) { - image = 'symbolClose' - text = 'You can only ' + drag.action + ' ' + pandora.site.itemName.plural.toLowerCase() - + '
to your own lists'; - } else if (drag.target && drag.target.type == 'smart') { - image = 'symbolClose' - text = 'You can\'t ' + drag.action + ' ' + pandora.site.itemName.plural.toLowerCase() - + '
to smart lists'; - } else { - image = drag.action == 'copy' ? 'symbolAdd' : 'symbolRemove'; - text = Ox.toTitleCase(drag.action) + ' ' + ( - Ox.isString(drag.item) - ? '"' + drag.item + '"' - : drag.item + ' ' + pandora.site.itemName[ - drag.item == 1 ? 'singular' : 'plural' - ].toLowerCase() - ) + '
to ' + ( - drag.target && !drag.target.selected - ? 'the list "' + drag.target.name + '"' - : 'another list' - ); - } - return $('
') - .append( - $('
') - .css({ - float: 'left', - width: '16px', - height: '16px', - padding: '2px', - border: '2px solid rgb(192, 192, 192)', - borderRadius: '12px', - margin: '3px 2px 2px 2px' - }) - .append( - $('') - .attr({src: Ox.UI.getImageURL(image)}) - .css({width: '16px', height: '16px'}) - ) - ) - .append( - $('
') - .css({ - float: 'left', - margin: '1px 2px 2px 2px', - fontSize: '11px', - whiteSpace: 'nowrap' - }) - .html(text) - ) - } - - function keydown(e) { - if (e.metaKey) { - drag.action = 'move'; - $tooltip.options({title: getTitle()}).show(); - } - } - function keyup(e) { - if (drag.action == 'move') { - drag.action = 'copy'; - $tooltip.options({title: getTitle()}).show(); - } - } - - ['list', 'icons'].indexOf(view) > -1 && that.bindEvent({ - closepreview: function(data) { - pandora.$ui.previewDialog.close(); - preview = false; - //delete pandora.$ui.previewDialog; - }, - copy: function(data) { - Ox.Clipboard.copy({ - items: data.ids, - text: $.map(data.ids, function(id) { - return pandora.$ui.list.value(id, 'title'); - }).join('\n') - }); - }, - 'delete': function(data) { - pandora.getListData().editable && pandora.api.removeListItems({ - list: pandora.user.ui.list, - items: data.ids - }, pandora.reloadList); - }, - draganddropstart: function(data) { - Ox.print('DRAGSTART', pandora.getListData()); - drag.action = 'copy'; - drag.ids = that.options('selected'), - drag.item = drag.ids.length == 1 - ? that.value(drag.ids[0], 'title') - : drag.ids.length; - drag.source = pandora.getListData(), - drag.targets = {}; - Ox.forEach(pandora.$ui.folderList, function($list) { - $list.addClass('OxDroppable').find('.OxItem').each(function() { - var $item = $(this), - id = $item.data('id'), - data = $list.value(id); - Ox.print('DATA', data) - drag.targets[id] = Ox.extend({ - editable: data.user == pandora.user.username - && data.type == 'static', - selected: $item.is('.OxSelected') - }, data); - if (!drag.targets[id].selected && drag.targets[id].editable) { - $item.addClass('OxDroppable'); + that.bindEvent({ + closepreview: function(data) { + pandora.$ui.previewDialog.close(); + preview = false; + //delete pandora.$ui.previewDialog; + }, + copy: function(data) { + Ox.Clipboard.copy({ + items: data.ids, + text: $.map(data.ids, function(id) { + return pandora.$ui.list.value(id, 'title'); + }).join('\n') + }); + }, + 'delete': function(data) { + pandora.getListData().editable && pandora.api.removeListItems({ + list: pandora.user.ui.list, + items: data.ids + }, pandora.reloadList); + }, + init: function(data) { + pandora.$ui.total.html(pandora.ui.status('total', data)); + data = []; + $.each(pandora.site.totals, function(i, v) { + data[v.id] = 0; + }); + pandora.$ui.selected.html(pandora.ui.status('selected', data)); + }, + open: function(data) { + var id = data.ids[0], + title = that.value(id, 'title'); + pandora.URL.set(title, id); + }, + openpreview: function(data) { + pandora.requests.preview && pandora.api.cancel(pandora.requests.preview); + pandora.requests.preview = pandora.api.find({ + keys: ['director', 'id', 'posterRatio', 'title'], + query: { + conditions: $.map(data.ids, function(id, i) { + return { + key: 'id', + value: id, + operator: '=' + } + }), + operator: '|' + } + }, function(result) { + var item = result.data.items[0], + title = item.title + ' (' + item.director + ')' + ratio = item.posterRatio, + windowWidth = window.innerWidth * 0.8, + windowHeight = window.innerHeight * 0.8, + windowRatio = windowWidth / windowHeight, + width = Math.round(ratio > windowRatio ? windowWidth : windowHeight * ratio), + height = Math.round(ratio < windowRatio ? windowHeight : windowWidth / ratio); + pandora.$ui.previewImage = $('') + .attr({src: '/' + item.id + '/poster128.jpg'}) + .css({width: width + 'px', height: height + 'px'}) + $('').load(function() { + pandora.$ui.previewImage.attr({src: $(this).attr('src')}); + }) + .attr({src: '/' + item.id + '/poster1024.jpg'}); + if (!preview) { + if (!pandora.$ui.previewDialog) { + pandora.$ui.previewDialog = Ox.Dialog({ + closeButton: true, + content: pandora.$ui.previewImage, + fixedRatio: true, + focus: false, + height: height, + maximizeButton: true, + title: title, + width: width + }) + .bindEvent({ + close: function() { + that.closePreview(); + preview = false; + }, + resize: function(event) { + pandora.$ui.previewImage.css({ + width: event.width + 'px', + height: event.height + 'px' + }); + } + }) + .open(); + } else { + pandora.$ui.previewDialog.options({ + content: pandora.$ui.previewImage, + height: height, + title: title, + width: width + }) + .open(); + } + preview = true; + } else { + pandora.$ui.previewDialog.options({ + content: pandora.$ui.previewImage, + title: title, + }) + .setSize(width, height); } }); - }); - $tooltip.options({ - title: getTitle(data._event) - }).show(data._event); - Ox.UI.$window.bind({ - keydown: keydown, - keyup: keyup - }); - }, - draganddrop: function(data) { - $tooltip.options({ - title: getTitle(data._event) - }).show(data._event); - }, - draganddropenter: function(data) { - var $parent = $(data._event.target).parent(), - $item = $parent.is('.OxItem') ? $parent : $parent.parent(); - $list = $item.parent().parent().parent().parent(); - if ($list.is('.OxDroppable')) { - $item.addClass('OxDrop'); - drag.target = drag.targets[$item.data('id')]; - } else { - drag.target = null; - } - }, - draganddropleave: function(data) { - var $parent = $(data._event.target).parent(), - $item = $parent.is('.OxItem') ? $parent : $parent.parent(); - if ($item.is('.OxDroppable')) { - $item.removeClass('OxDrop'); - drag.target = null; - } - }, - draganddropend: function(data) { - Ox.print(data, drag, '------------'); - Ox.UI.$window.unbind({ - keydown: keydown, - keyup: keyup - }); - if (drag.target && drag.target.editable && !drag.target.selected) { - if (drag.action == 'copy' || ( - drag.action == 'move' && drag.source.editable - )) { - if (drag.action == 'move') { - pandora.api.removeListItems({ - list: pandora.user.ui.list, - items: data.ids - }, pandora.reloadList); - } - pandora.api.addListItems({ - list: drag.target.id, - items: data.ids - }, function() { - Ox.Request.clearCache(); // fixme: remove - pandora.api.find({ - query: { - conditions: [{key: 'list', value: drag.target.id, operator: '='}], - operator: '' - } - }, function(result) { - var folder = drag.target.status != 'featured' ? 'personal' : 'featured'; - //Ox.print(drag.source.status, '//////', drag.target.status) - pandora.$ui.folderList[folder].value( - drag.target.id, 'items', - result.data.items - ); - cleanup(500); - }); - }); - } - } else { - cleanup(0); - } - function cleanup(ms) { - drag = {}; - setTimeout(function() { - $('.OxDroppable').removeClass('OxDroppable'); - $('.OxDrop').removeClass('OxDrop'); - $tooltip.hide(); - }, ms); - } - }, - init: function(data) { - pandora.$ui.total.html(pandora.ui.status('total', data)); - data = []; - $.each(pandora.site.totals, function(i, v) { - data[v.id] = 0; - }); - pandora.$ui.selected.html(pandora.ui.status('selected', data)); - }, - open: function(data) { - var id = data.ids[0], - title = that.value(id, 'title'); - pandora.URL.set(title, id); - }, - openpreview: function(data) { - pandora.requests.preview && pandora.api.cancel(pandora.requests.preview); - pandora.requests.preview = pandora.api.find({ - keys: ['director', 'id', 'posterRatio', 'title'], - query: { - conditions: $.map(data.ids, function(id, i) { - return { - key: 'id', - value: id, - operator: '=' - } - }), - operator: '|' - } - }, function(result) { - var item = result.data.items[0], - title = item.title + ' (' + item.director + ')' - ratio = item.posterRatio, - windowWidth = window.innerWidth * 0.8, - windowHeight = window.innerHeight * 0.8, - windowRatio = windowWidth / windowHeight, - width = Math.round(ratio > windowRatio ? windowWidth : windowHeight * ratio), - height = Math.round(ratio < windowRatio ? windowHeight : windowWidth / ratio); - pandora.$ui.previewImage = $('') - .attr({src: '/' + item.id + '/poster128.jpg'}) - .css({width: width + 'px', height: height + 'px'}) - $('').load(function() { - pandora.$ui.previewImage.attr({src: $(this).attr('src')}); - }) - .attr({src: '/' + item.id + '/poster1024.jpg'}); - if (!preview) { - if (!pandora.$ui.previewDialog) { - pandora.$ui.previewDialog = Ox.Dialog({ - closeButton: true, - content: pandora.$ui.previewImage, - fixedRatio: true, - focus: false, - height: height, - maximizeButton: true, - title: title, - width: width - }) - .bindEvent({ - close: function() { - that.closePreview(); - preview = false; - }, - resize: function(event) { - pandora.$ui.previewImage.css({ - width: event.width + 'px', - height: event.height + 'px' - }); - } - }) - .open(); - } else { - pandora.$ui.previewDialog.options({ - content: pandora.$ui.previewImage, - height: height, - title: title, - width: width - }) - .open(); - } - preview = true; + }, + paste: function(data) { + data.items && pandora.getListData().editable && pandora.api.addListItems({ + list: pandora.user.ui.list, + items: data.items + }, pandora.reloadList); + }, + select: function(data) { + var $still, $timeline; + pandora.UI.set(['lists', pandora.user.ui.list, 'selected'].join('|'), data.ids); + //pandora.user.ui.lists[pandora.user.ui.list].selected = data.ids; + if (data.ids.length) { + pandora.$ui.mainMenu.enableItem('copy'); + pandora.$ui.mainMenu.enableItem('openmovie'); } else { - pandora.$ui.previewDialog.options({ - content: pandora.$ui.previewImage, - title: title, - }) - .setSize(width, height); + pandora.$ui.mainMenu.disableItem('copy'); + pandora.$ui.mainMenu.disableItem('openmovie'); } - }); - }, - paste: function(data) { - data.items && pandora.getListData().editable && pandora.api.addListItems({ - list: pandora.user.ui.list, - items: data.items - }, pandora.reloadList); - }, - select: function(data) { - var $still, $timeline; - pandora.UI.set(['lists', pandora.user.ui.list, 'selected'].join('|'), data.ids); - //pandora.user.ui.lists[pandora.user.ui.list].selected = data.ids; - if (data.ids.length) { - pandora.$ui.mainMenu.enableItem('copy'); - pandora.$ui.mainMenu.enableItem('openmovie'); - } else { - pandora.$ui.mainMenu.disableItem('copy'); - pandora.$ui.mainMenu.disableItem('openmovie'); + pandora.$ui.leftPanel.replaceElement(2, pandora.$ui.info = pandora.ui.info(data.ids[0])); + pandora.api.find({ + query: { + conditions: $.map(data.ids, function(id, i) { + return { + key: 'id', + value: id, + operator: '=' + } + }), + operator: '|' + } + }, function(result) { + pandora.$ui.selected.html(pandora.ui.status('selected', result.data)); + }); } - pandora.$ui.leftPanel.replaceElement(2, pandora.$ui.info = pandora.ui.info(data.ids[0])); - pandora.api.find({ - query: { - conditions: $.map(data.ids, function(id, i) { - return { - key: 'id', - value: id, - operator: '=' - } - }), - operator: '|' - } - }, function(result) { - pandora.$ui.selected.html(pandora.ui.status('selected', result.data)); - }); - } - }); + }); + + } + that.display = function() { // fixme: used? pandora.$ui.rightPanel.replaceElement(1, pandora.$ui.contentPanel = pandora.ui.contentPanel()); }; + return that; + };