pandora/static/js/editPanel.js

407 lines
17 KiB
JavaScript
Raw Normal View History

'use strict';
pandora.ui.editPanel = function() {
2013-07-13 23:08:01 +00:00
var ui = pandora.user.ui,
edit,
listSizes = [
144 + Ox.UI.SCROLLBAR_SIZE,
280 + Ox.UI.SCROLLBAR_SIZE,
416 + Ox.UI.SCROLLBAR_SIZE
],
listSize = listSizes[ui.clipColumns],
smallTimelineCanvas,
smallTimelineContext,
that = Ox.Element();
2013-07-14 18:57:31 +00:00
ui.edit ? renderEdit() : renderEdits();
2013-07-13 23:08:01 +00:00
2013-08-07 14:32:17 +00:00
function editsKey(key) {
return 'edits.' + ui.edit.replace(/\./g, '\\.') + '.' + key;
2013-07-13 23:08:01 +00:00
}
function enableDragAndDrop() {
pandora.enableDragAndDrop(
Ox.UI.elements[that.find('.OxIconList').data('oxid')],
edit.editable
);
}
2013-07-13 23:08:01 +00:00
function getSmallTimelineURL() {
var fps = 25,
width = Math.floor(edit.duration * fps),
height = 64;
smallTimelineCanvas = Ox.$('<canvas>').attr({width: width, height: height})[0];
smallTimelineContext = smallTimelineCanvas.getContext('2d');
return smallTimelineCanvas.toDataURL();
}
function getVideos() {
var videos = {};
pandora.site.video.resolutions.forEach(function(resolution) {
videos[resolution] = Ox.flatten(edit.clips.map(function(clip) {
return pandora.getClipVideos(clip, resolution);
}));
});
return videos;
2013-07-13 23:08:01 +00:00
}
2013-07-14 18:57:31 +00:00
function renderEdit() {
pandora.api.getEdit({id: ui.edit}, function(result) {
2013-07-13 23:08:01 +00:00
edit = result.data;
// fixme: duration should come from backend
edit.duration = 0;
edit.clips.forEach(function(clip) {
clip.position = edit.duration;
edit.duration += clip.duration;
});
updateSmallTimelineURL();
2013-07-13 23:08:01 +00:00
pandora.$ui.mainPanel.replaceElement(1,
2013-07-14 09:28:08 +00:00
that = pandora.$ui.editPanel = Ox.VideoEditPanel({
2013-07-14 14:59:04 +00:00
clips: Ox.clone(edit.clips),
2013-07-14 09:28:08 +00:00
clipSize: listSize,
2013-07-13 23:08:01 +00:00
clipSort: ui.clipSort,
clipSortOptions: [/*...*/],
2013-08-07 14:32:17 +00:00
clipView: ui.editView,
2013-07-13 23:08:01 +00:00
duration: edit.duration,
editable: edit.editable,
enableSubtitles: ui.videoSubtitles,
fullscreen: false,
2013-07-15 11:32:36 +00:00
getClipImageURL: function(id, width, height) {
var clip = Ox.getObjectById(edit.clips, id);
return '/' + clip.item + '/' + height + 'p' + clip['in'] + '.jpg';
},
2013-07-13 23:08:01 +00:00
getLargeTimelineURL: function(type, i, callback) {
pandora.getLargeEditTimelineURL(edit, type, i, callback);
},
height: pandora.$ui.appPanel.size(1),
2013-08-07 14:32:17 +00:00
'in': ui.edits[ui.edit]['in'],
2013-07-13 23:08:01 +00:00
loop: ui.videoLoop,
muted: ui.videoMuted,
2013-08-07 14:32:17 +00:00
out: ui.edits[ui.edit].out,
position: ui.edits[ui.edit].position,
2013-07-13 23:08:01 +00:00
resolution: ui.videoResolution,
scaleToFill: ui.videoScale == 'fill',
// selected: ...
showClips: ui.showClips,
showTimeline: ui.showTimeline,
smallTimelineURL: getSmallTimelineURL(),
sort: ui.clipSort,
sortOptions: [
2013-07-14 14:59:04 +00:00
{id: 'index', title: Ox._('Sort Manually'), operator: '+'}
2013-07-13 23:08:01 +00:00
].concat(
pandora.site.clipKeys.map(function(key) {
return Ox.extend(Ox.clone(key), {
title: Ox._(('Sort by Clip {0}'), [Ox._(key.title)])
});
})
).concat(
pandora.site.sortKeys.map(function(key) {
return Ox.extend(Ox.clone(key), {
title: Ox._('Sort by {0}', [Ox._(key.title)])
});
})
),
timeline: ui.videoTimeline,
video: getVideos(),
volume: ui.videoVolume,
width: pandora.$ui.document.width() - pandora.$ui.mainPanel.size(0) - 1
})
.bindEvent({
2013-07-13 23:08:01 +00:00
copy: function(data) {
pandora.clipboard.copy(data.ids.map(function(id) {
2013-08-02 19:38:18 +00:00
var clip = Ox.getObjectById(edit.clips, id);
return clip.annotation || clip.item + '/' + clip['in'] + '-' + clip.out;
2013-07-14 18:57:31 +00:00
}), 'clip');
2013-07-13 23:08:01 +00:00
},
copyadd: function(data) {
pandora.clipboard.add(data.ids.map(function(id) {
2013-08-02 19:38:18 +00:00
var clip = Ox.getObjectById(edit.clips, id);
return clip.annotation || clip.item + '/' + clip['in'] + '-' + clip.out;
}), 'clip');
2013-07-13 23:08:01 +00:00
},
2013-08-03 14:09:21 +00:00
cut: function(data) {
if (edit.editable) {
pandora.clipboard.copy(data.ids.map(function(id) {
2013-08-03 14:09:21 +00:00
var clip = Ox.getObjectById(edit.clips, id);
return clip.annotation || clip.item + '/' + clip['in'] + '-' + clip.out;
}), 'clip');
pandora.doHistory('cut', data.ids, ui.edit, function(result) {
Ox.Request.clearCache('getEdit');
updateClips(result.data.clips);
});
}
},
cutadd: function(data) {
if (edit.editable) {
pandora.clipboard.add(data.ids.map(function(id) {
2013-08-03 14:09:21 +00:00
var clip = Ox.getObjectById(edit.clips, id);
return clip.annotation || clip.item + '/' + clip['in'] + '-' + clip.out;
}), 'clip');
pandora.doHistory('cut', data.ids, ui.edit, function(result) {
Ox.Request.clearCache('getEdit');
updateClips(result.data.clips);
});
}
},
'delete': function(data) {
if (edit.editable) {
pandora.doHistory('delete', data.ids, ui.edit, function(result) {
Ox.Request.clearCache('getEdit');
updateClips(result.data.clips);
});
}
},
2013-07-13 23:08:01 +00:00
edit: function(data) {
var args = {id: data.id},
index = Ox.getIndexById(edit.clips, data.id),
clip = edit.clips[index];
if (data.key == 'duration') {
data.key = 'out';
data.value += clip['in'];
}
2013-07-13 23:08:01 +00:00
pandora.api.get({id: clip.item, keys: ['duration']}, function(result) {
data.value = Math.min(data.value, result.data.duration);
args[data.key] = data.value;
if (data.key == 'in' && data.value > clip.out) {
args.out = args['in'];
} else if (data.key == 'out' && data.value < clip['in']) {
args['in'] = args.out;
}
pandora.api.editClip(args, function(result) {
if (result.status.code == 200) {
edit.clips[index] = result.data;
that.updateClip(data.id, result.data);
updateVideos();
} else {
Ox.print('failed to edit clip', result);
}
2013-07-13 23:08:01 +00:00
});
});
},
2013-07-14 15:36:49 +00:00
loop: function(data) {
pandora.UI.set({videoLoop: data.loop});
},
2013-07-13 23:08:01 +00:00
move: function(data) {
pandora.api.orderClips({
2013-07-13 23:08:01 +00:00
edit: edit.id,
ids: data.ids
}, function(result) {
2013-07-13 23:08:01 +00:00
Ox.Request.clearCache('getEdit');
orderClips(data.ids);
2013-07-13 23:08:01 +00:00
});
},
muted: function(data) {
2013-07-14 15:36:49 +00:00
pandora.UI.set({videoMuted: data.muted});
2013-07-13 23:08:01 +00:00
},
2013-07-14 15:10:19 +00:00
open: function(data) {
2013-08-07 14:32:17 +00:00
pandora.UI.set(editsKey('clip'), data.ids[0]);
2013-07-14 15:10:19 +00:00
},
2013-07-13 23:08:01 +00:00
paste: function() {
2013-08-03 14:09:21 +00:00
var clips;
if (pandora.clipboard.type() == 'clip') {
clips = pandora.clipboard.paste().map(function(clip) {
2013-08-03 14:09:21 +00:00
var split = clip.split('/'),
item = split[0],
points = split[1].split('-');
return Ox.extend({
item: item
}, points.length == 1 ? {
annotation: clip
} : {
'in': parseFloat(points[0]),
out: parseFloat(points[1])
});
});
pandora.doHistory('paste', clips, ui.edit, function(result) {
Ox.Request.clearCache('getEdit');
2013-07-13 23:08:01 +00:00
updateClips(edit.clips.concat(result.data.clips));
});
}
},
playing: function(data) {
2013-07-14 15:10:19 +00:00
var set = {};
2013-08-07 14:32:17 +00:00
set[editsKey('clip')] = '';
set[editsKey('position')] = data.position;
2013-07-14 15:10:19 +00:00
pandora.UI.set(set);
2013-07-13 23:08:01 +00:00
},
position: function(data) {
2013-07-14 15:10:19 +00:00
var set = {};
2013-08-07 14:32:17 +00:00
set[editsKey('clip')] = '';
set[editsKey('position')] = data.position;
2013-07-14 15:10:19 +00:00
pandora.UI.set(set);
2013-07-13 23:08:01 +00:00
},
2013-07-14 09:28:08 +00:00
resize: function(data) {
// sidebar resize
that.options({width: data.size});
},
2013-07-13 23:08:01 +00:00
resizeclips: function(data) {
2013-07-14 15:36:49 +00:00
pandora.UI.set({clipsSize: data.clipsSize});
2013-07-13 23:08:01 +00:00
},
resolution: function(data) {
2013-07-14 15:36:49 +00:00
pandora.UI.set({videoResolution: data.resolution});
2013-07-13 23:08:01 +00:00
},
scale: function(data) {
2013-07-14 15:36:49 +00:00
pandora.UI.set({videoScale: data.scale});
2013-07-13 23:08:01 +00:00
},
2013-07-14 10:11:18 +00:00
size: function(data) {
2013-07-14 15:36:49 +00:00
pandora.UI.set({clipSize: data.size});
2013-07-14 10:11:18 +00:00
},
sort: function(data) {
2013-07-14 15:36:49 +00:00
pandora.UI.set({clipSort: data});
2013-07-14 14:59:04 +00:00
var key = data[0].key;
if (key == 'position') {
key = 'in';
}
if ([
'id', 'index', 'in', 'out', 'duration',
'title', 'director', 'year', 'videoRatio'
].indexOf(key) > -1) {
2013-07-14 14:59:04 +00:00
edit.clips = Ox.sortBy(edit.clips, key);
2013-07-14 17:44:30 +00:00
if (data[0].operator == '-') {
2013-07-14 14:59:04 +00:00
edit.clips.reverse();
}
updateClips(edit.clips);
} else {
pandora.api.sortClips({
edit: edit.id,
sort: data
}, function(result) {
edit.clips.forEach(function(clip) {
clip['sort'] = result.data.clips.indexOf(clip.id);
});
edit.clips = Ox.sortBy(edit.clips, 'sort');
2013-07-14 14:59:04 +00:00
updateClips(edit.clips);
});
}
2013-07-14 10:11:18 +00:00
},
2013-07-13 23:08:01 +00:00
subtitles: function(data) {
2013-07-14 15:36:49 +00:00
pandora.UI.set({videoSubtitles: data.subtitles});
2013-07-13 23:08:01 +00:00
},
timeline: function(data) {
2013-07-14 15:36:49 +00:00
pandora.UI.set({videoTimeline: data.timeline});
2013-07-13 23:08:01 +00:00
},
toggleclips: function(data) {
2013-07-14 15:36:49 +00:00
pandora.UI.set({showClips: data.showClips});
2013-07-13 23:08:01 +00:00
},
toggletimeline: function(data) {
2013-07-14 15:36:49 +00:00
pandora.UI.set({showTimeline: data.showTimeline});
2013-07-13 23:08:01 +00:00
},
2013-07-14 10:11:18 +00:00
view: function(data) {
2013-08-07 14:32:17 +00:00
pandora.UI.set({editView: data.view});
data.view == 'grid' && enableDragAndDrop();
2013-07-14 10:11:18 +00:00
},
2013-07-13 23:08:01 +00:00
volume: function(data) {
2013-07-14 15:36:49 +00:00
pandora.UI.set({videoVolume: data.volume});
2013-07-13 23:08:01 +00:00
},
2013-07-14 09:28:08 +00:00
pandora_showclips: function(data) {
that.options({showClips: data.value});
2013-07-13 23:08:01 +00:00
},
pandora_showtimeline: function(data) {
that.options({showTimeline: data.value});
},
pandora_videotimeline: function(data) {
that.options({timeline: data.value});
}
})
2013-07-13 23:08:01 +00:00
);
2013-08-07 14:32:17 +00:00
ui.editView == 'grid' && enableDragAndDrop();
});
}
2013-07-14 18:57:31 +00:00
function renderEdits() {
2013-07-14 17:22:26 +00:00
that = Ox.IconList({
borderRadius: 16,
defaultRatio: 1,
draggable: true,
item: function(data, sort, size) {
size = size || 128;
var ui = pandora.user.ui,
url = '/edit/' + data.id + '/icon'+size+'.jpg?' + data.modified,
info = Ox.formatDuration(data.duration);
return {
height: size,
id: data.id,
title: data.name,
info: info,
url: url,
width: size,
}
},
items: function(data, callback) {
pandora.api.findEdits(data, callback);
return Ox.clone(data, true);
},
keys: ['id', 'modified', 'name', 'duration'],
size: 128,
sort: [{key: 'id', operator: '+'}],
unique: 'id'
})
.addClass('OxMedia')
.bindEvent({
open: function(data) {
pandora.UI.set('edit', data.ids[0]);
}
});
}
function orderClips(ids) {
edit.clips.forEach(function(clip) {
clip.index = ids.indexOf(clip.id);
});
edit.clips = Ox.sortBy(edit.clips, 'index');
2013-07-14 11:04:13 +00:00
updateVideos();
}
2013-07-13 23:08:01 +00:00
function updateClips(clips) {
edit.clips = clips;
edit.duration = 0;
edit.clips.forEach(function(clip) {
clip.position = edit.duration;
edit.duration += clip.duration;
});
2013-07-13 23:08:01 +00:00
that.options({
2013-07-14 14:59:04 +00:00
clips: Ox.clone(clips),
2013-07-13 23:08:01 +00:00
smallTimelineURL: getSmallTimelineURL(),
video: getVideos()
});
2013-07-13 23:08:01 +00:00
updateSmallTimelineURL();
}
2013-07-13 23:08:01 +00:00
function updateSmallTimelineURL() {
var fps = 25;
Ox.serialForEach(edit.clips, function(clip) {
var callback = Ox.last(arguments);
pandora.getLargeClipTimelineURL(clip.item, clip['in'], clip.out, ui.videoTimeline, function(url) {
var image = Ox.$('<img>')
.on({
load: function() {
smallTimelineContext.drawImage(image, Math.floor(clip.position * fps), 0);
that.options({smallTimelineURL: smallTimelineCanvas.toDataURL()});
callback();
}
})
.attr({
src: url
})[0];
});
});
}
2013-07-12 14:44:33 +00:00
2013-07-14 18:57:31 +00:00
function updateVideos() {
edit.duration = 0;
edit.clips.forEach(function(clip) {
clip.position = edit.duration;
edit.duration += clip.duration;
});
that.options({
smallTimelineURL: getSmallTimelineURL(),
video: getVideos()
});
updateSmallTimelineURL();
}
return that;
2013-07-13 23:08:01 +00:00
};