fix issues with automatically opening annotation folders; add annotations option to video player to make find work for all layers
This commit is contained in:
parent
61402492c6
commit
94cfbdb45c
7 changed files with 108 additions and 30 deletions
|
@ -20,6 +20,7 @@ Ox.CollapsePanel = function(options, self) {
|
||||||
self = self || {};
|
self = self || {};
|
||||||
var that = Ox.Panel({}, self)
|
var that = Ox.Panel({}, self)
|
||||||
.defaults({
|
.defaults({
|
||||||
|
animate: true,
|
||||||
collapsed: false,
|
collapsed: false,
|
||||||
extras: [],
|
extras: [],
|
||||||
size: 16,
|
size: 16,
|
||||||
|
@ -92,11 +93,18 @@ Ox.CollapsePanel = function(options, self) {
|
||||||
!self.options.collapsed && that.$content.css({
|
!self.options.collapsed && that.$content.css({
|
||||||
marginTop: -that.$content.height() + 'px'
|
marginTop: -that.$content.height() + 'px'
|
||||||
}).show();
|
}).show();
|
||||||
that.$content.animate({
|
if (self.options.animate) {
|
||||||
marginTop: marginTop + 'px'
|
that.$content.animate({
|
||||||
}, 250, function() {
|
marginTop: marginTop + 'px'
|
||||||
|
}, 250, function() {
|
||||||
|
self.options.collapsed && that.$content.hide();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
that.$content.css({
|
||||||
|
marginTop: marginTop + 'px'
|
||||||
|
});
|
||||||
self.options.collapsed && that.$content.hide();
|
self.options.collapsed && that.$content.hide();
|
||||||
});
|
}
|
||||||
that.triggerEvent('toggle', {
|
that.triggerEvent('toggle', {
|
||||||
collapsed: self.options.collapsed
|
collapsed: self.options.collapsed
|
||||||
});
|
});
|
||||||
|
@ -110,7 +118,8 @@ Ox.CollapsePanel = function(options, self) {
|
||||||
if (key == 'collapsed') {
|
if (key == 'collapsed') {
|
||||||
// will be toggled again in toggleCollapsed
|
// will be toggled again in toggleCollapsed
|
||||||
self.options.collapsed = !self.options.collapsed;
|
self.options.collapsed = !self.options.collapsed;
|
||||||
self.$button.trigger('click');
|
self.$button.toggle();
|
||||||
|
toggleCollapsed();
|
||||||
} else if (key == 'title') {
|
} else if (key == 'title') {
|
||||||
self.$title.html(self.options.title);
|
self.$title.html(self.options.title);
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,10 @@ Ox.AnnotationFolder = function(options, self) {
|
||||||
})
|
})
|
||||||
.options(options || {});
|
.options(options || {});
|
||||||
|
|
||||||
|
if (self.options.selected) {
|
||||||
|
self.options.collapsed = false;
|
||||||
|
}
|
||||||
|
|
||||||
self.annotations = getAnnotations();
|
self.annotations = getAnnotations();
|
||||||
self.points = getPoints();
|
self.points = getPoints();
|
||||||
self.position = self.options.position;
|
self.position = self.options.position;
|
||||||
|
@ -526,8 +530,11 @@ Ox.AnnotationFolder = function(options, self) {
|
||||||
if (value === '') {
|
if (value === '') {
|
||||||
self.editing = false;
|
self.editing = false;
|
||||||
}
|
}
|
||||||
|
value && Ox.print('----------------- select item in folder', value, self.options.collapsed)
|
||||||
if (value && self.options.collapsed) {
|
if (value && self.options.collapsed) {
|
||||||
toggleLayer();
|
self.$panel.options({animate: false});
|
||||||
|
self.$panel.options({collapsed: false});
|
||||||
|
self.$panel.options({animate: true});
|
||||||
}
|
}
|
||||||
self.$annotations.options({selected: value});
|
self.$annotations.options({selected: value});
|
||||||
} else if (key == 'sort') {
|
} else if (key == 'sort') {
|
||||||
|
|
|
@ -110,6 +110,7 @@ Ox.AnnotationPanel = function(options, self) {
|
||||||
that.triggerEvent('submit', Ox.extend({layer: layer.id}, data));
|
that.triggerEvent('submit', Ox.extend({layer: layer.id}, data));
|
||||||
},
|
},
|
||||||
togglelayer: function(data) {
|
togglelayer: function(data) {
|
||||||
|
self.options.showLayers[layer.id] = !data.collapsed;
|
||||||
that.triggerEvent('togglelayer', Ox.extend({layer: layer.id}, data));
|
that.triggerEvent('togglelayer', Ox.extend({layer: layer.id}, data));
|
||||||
},
|
},
|
||||||
togglewidget: function(data) {
|
togglewidget: function(data) {
|
||||||
|
|
|
@ -74,6 +74,7 @@ Ox.VideoPanel = function(options, self) {
|
||||||
});
|
});
|
||||||
|
|
||||||
self.$video = Ox.VideoPlayer({
|
self.$video = Ox.VideoPlayer({
|
||||||
|
annotations: getAnnotations(),
|
||||||
censored: self.options.censored,
|
censored: self.options.censored,
|
||||||
controlsTop: ['fullscreen', 'title', 'find'],
|
controlsTop: ['fullscreen', 'title', 'find'],
|
||||||
controlsBottom: ['play', 'volume', 'scale', 'timeline', 'position', 'settings'],
|
controlsBottom: ['play', 'volume', 'scale', 'timeline', 'position', 'settings'],
|
||||||
|
@ -127,6 +128,7 @@ Ox.VideoPanel = function(options, self) {
|
||||||
scale: function(data) {
|
scale: function(data) {
|
||||||
that.triggerEvent('scale', data);
|
that.triggerEvent('scale', data);
|
||||||
},
|
},
|
||||||
|
select: selectAnnotation,
|
||||||
subtitles: function(data) {
|
subtitles: function(data) {
|
||||||
that.triggerEvent('subtitles', data);
|
that.triggerEvent('subtitles', data);
|
||||||
},
|
},
|
||||||
|
@ -269,6 +271,14 @@ Ox.VideoPanel = function(options, self) {
|
||||||
that.triggerEvent('position', {position: self.options.position});
|
that.triggerEvent('position', {position: self.options.position});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getAnnotations() {
|
||||||
|
return Ox.flatten(Ox.merge(self.options.layers.map(function(layer) {
|
||||||
|
return layer.items.map(function(item) {
|
||||||
|
return {id: item.id, 'in': item['in'], out: item.out, text: item.value};
|
||||||
|
});
|
||||||
|
}))).sort(sortAnnotations);
|
||||||
|
}
|
||||||
|
|
||||||
function getPlayerHeight() {
|
function getPlayerHeight() {
|
||||||
return self.options.height -
|
return self.options.height -
|
||||||
self.options.showTimeline * 80 - 1;
|
self.options.showTimeline * 80 - 1;
|
||||||
|
@ -330,6 +340,7 @@ Ox.VideoPanel = function(options, self) {
|
||||||
setPoint('in', data['in']);
|
setPoint('in', data['in']);
|
||||||
setPoint('out', data.out);
|
setPoint('out', data.out);
|
||||||
}
|
}
|
||||||
|
self.$annotationPanel.options({selected: self.options.selected});
|
||||||
that.triggerEvent('select', {id: self.options.selected});
|
that.triggerEvent('select', {id: self.options.selected});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -347,6 +358,24 @@ Ox.VideoPanel = function(options, self) {
|
||||||
self.$annotationPanel.options({position: self.options.position});
|
self.$annotationPanel.options({position: self.options.position});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sortAnnotations(a, b) {
|
||||||
|
var ret = 0;
|
||||||
|
if (a['in'] < b['in']) {
|
||||||
|
ret = -1;
|
||||||
|
} else if (a['in'] > b['in']) {
|
||||||
|
ret = 1;
|
||||||
|
} else if (a.out < b.out) {
|
||||||
|
ret = -1;
|
||||||
|
} else if (a.out > b.out) {
|
||||||
|
ret = 1;
|
||||||
|
} else if (a.value < b.value) {
|
||||||
|
ret = -1;
|
||||||
|
} else if (a.value > b.value) {
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
function toggleAnnotations(data) {
|
function toggleAnnotations(data) {
|
||||||
self.options.showAnnotations = !data.collapsed;
|
self.options.showAnnotations = !data.collapsed;
|
||||||
self.$video.options({
|
self.$video.options({
|
||||||
|
|
|
@ -6,12 +6,11 @@
|
||||||
Ox.VideoPlayer <f> Generic Video Player
|
Ox.VideoPlayer <f> Generic Video Player
|
||||||
(options, self) -> <o> Video Player
|
(options, self) -> <o> Video Player
|
||||||
options <o> Options
|
options <o> Options
|
||||||
annotation <[o]> Array of annotation tracks
|
annotations <[]> Array of annotations
|
||||||
name <s> Name of the annotation track
|
id <s> Optional id
|
||||||
data <[o]> Annotation data
|
in <n> In point (sec)
|
||||||
in <n> In point (sec)
|
out <n> Out point (sec)
|
||||||
out <n> Out point (sec)
|
text <s> Text
|
||||||
text <s> Text
|
|
||||||
censored <a|[]> Array of censored ranges
|
censored <a|[]> Array of censored ranges
|
||||||
controlsBottom <[s]|[]> Bottom controls, from left to right
|
controlsBottom <[s]|[]> Bottom controls, from left to right
|
||||||
Can be 'close', fullscreen', 'scale', 'title', 'find', 'open',
|
Can be 'close', fullscreen', 'scale', 'title', 'find', 'open',
|
||||||
|
@ -60,6 +59,7 @@ Ox.VideoPlayer <f> Generic Video Player
|
||||||
showProgress <|false> If true, show buffering progress
|
showProgress <|false> If true, show buffering progress
|
||||||
sizeIsLarge <b|false> If true, initial state of the size control is large
|
sizeIsLarge <b|false> If true, initial state of the size control is large
|
||||||
subtitles <s|[o]|[]> URL or SRT or array of subtitles
|
subtitles <s|[o]|[]> URL or SRT or array of subtitles
|
||||||
|
id <s> Optional id
|
||||||
in <n> In point (sec)
|
in <n> In point (sec)
|
||||||
out <n> Out point (sec)
|
out <n> Out point (sec)
|
||||||
text <s> Text
|
text <s> Text
|
||||||
|
@ -146,6 +146,10 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (Ox.isEmpty(self.options.annotations)) {
|
||||||
|
self.options.annotations = self.options.subtitles;
|
||||||
|
}
|
||||||
|
|
||||||
if (Ox.isObject(self.options.video)) {
|
if (Ox.isObject(self.options.video)) {
|
||||||
self.resolutions = Ox.sort(Object.keys(self.options.video));
|
self.resolutions = Ox.sort(Object.keys(self.options.video));
|
||||||
if (!(self.options.resolution in self.options.video)) {
|
if (!(self.options.resolution in self.options.video)) {
|
||||||
|
@ -1160,13 +1164,17 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
var results = [];
|
var results = [];
|
||||||
if (query.length) {
|
if (query.length) {
|
||||||
query = query.toLowerCase();
|
query = query.toLowerCase();
|
||||||
results = Ox.map(self.options.subtitles, function(subtitle) {
|
results = Ox.map(self.options.annotations, function(annotation) {
|
||||||
return subtitle.text.toLowerCase().indexOf(query) > -1 ? {
|
return Ox.decodeHTML(Ox.stripTags(
|
||||||
'in': subtitle['in'],
|
annotation.text.toLowerCase()
|
||||||
out: subtitle.out
|
)).indexOf(query) > -1 ? {
|
||||||
|
id: annotation.id,
|
||||||
|
'in': annotation['in'],
|
||||||
|
out: annotation.out
|
||||||
} : null;
|
} : null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Ox.print('FIND RESULTS:', results);
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1500,24 +1508,29 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
|
|
||||||
function goToNextResult(direction) {
|
function goToNextResult(direction) {
|
||||||
var found = false,
|
var found = false,
|
||||||
position = 0;
|
result;
|
||||||
if (self.results.length) {
|
if (self.results.length) {
|
||||||
direction == -1 && self.results.reverse();
|
direction == -1 && self.results.reverse();
|
||||||
Ox.forEach(self.results, function(v) {
|
Ox.forEach(self.results, function(v) {
|
||||||
if (direction == 1 ? v['in'] > self.options.position : v.out < self.options.position) {
|
if (
|
||||||
position = v['in'];
|
direction == 1
|
||||||
|
? v['in'] > self.options.position
|
||||||
|
: v.out < self.options.position
|
||||||
|
) {
|
||||||
|
result = v
|
||||||
found = true;
|
found = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
direction == -1 && self.results.reverse();
|
direction == -1 && self.results.reverse();
|
||||||
if (!found) {
|
if (!found) {
|
||||||
position = self.results[direction == 1 ? 0 : self.results.length - 1]['in'];
|
result = self.results[direction == 1 ? 0 : self.results.length - 1];
|
||||||
}
|
}
|
||||||
setPosition(position + self.secondsPerFrame);
|
setPosition(result['in'] + self.secondsPerFrame);
|
||||||
that.triggerEvent('position', {
|
that.triggerEvent('position', {
|
||||||
position: self.options.position
|
position: self.options.position
|
||||||
});
|
});
|
||||||
|
result.id && that.triggerEvent('select', result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2132,7 +2145,12 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
results: self.results
|
results: self.results
|
||||||
});
|
});
|
||||||
if (hasPressedEnter) {
|
if (hasPressedEnter) {
|
||||||
self.results.length ? goToNextResult(1) : self.$findInput.focusInput(true);
|
if (self.results.length) {
|
||||||
|
goToNextResult(1);
|
||||||
|
that.gainFocus();
|
||||||
|
} else {
|
||||||
|
self.$findInput.focusInput(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
that.triggerEvent('find', {find: self.options.find});
|
that.triggerEvent('find', {find: self.options.find});
|
||||||
}
|
}
|
||||||
|
|
|
@ -794,21 +794,21 @@ Video
|
||||||
.OxThemeClassic .OxAnnotationFolder .OxArrayEditable .OxEditableElement.OxSelected .OxHighlight {
|
.OxThemeClassic .OxAnnotationFolder .OxArrayEditable .OxEditableElement.OxSelected .OxHighlight {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
background-image: -moz-repeating-linear-gradient(
|
background-image: -moz-repeating-linear-gradient(
|
||||||
-45deg, rgb(192, 192, 255) 0, rgb(192, 192, 255) 25%,
|
-45deg, transparent 0%, transparent 25%,
|
||||||
rgb(255, 255, 0) 25%, rgb(255, 255, 0) 50%,
|
rgb(255, 255, 0) 25%, rgb(255, 255, 0) 50%,
|
||||||
rgb(192, 192, 255) 50%, rgb(192, 192, 255) 75%,
|
transparent 50%, transparent 75%,
|
||||||
rgb(255, 255, 0) 75%, rgb(255, 255, 0) 100%
|
rgb(255, 255, 0) 75%, rgb(255, 255, 0) 100%
|
||||||
);
|
);
|
||||||
background-image: -o-repeating-linear-gradient(
|
background-image: -o-repeating-linear-gradient(
|
||||||
-45deg, rgb(192, 192, 255) 0, rgb(192, 192, 255) 25%,
|
-45deg, transparent 0%, transparent 25%,
|
||||||
rgb(255, 255, 0) 25%, rgb(255, 255, 0) 50%,
|
rgb(255, 255, 0) 25%, rgb(255, 255, 0) 50%,
|
||||||
rgb(192, 192, 255) 50%, rgb(192, 192, 255) 75%,
|
transparent 50%, transparent 75%,
|
||||||
rgb(255, 255, 0) 75%, rgb(255, 255, 0) 100%
|
rgb(255, 255, 0) 75%, rgb(255, 255, 0) 100%
|
||||||
);
|
);
|
||||||
background-image: -webkit-repeating-linear-gradient(
|
background-image: -webkit-repeating-linear-gradient(
|
||||||
-45deg, rgb(192, 192, 255) 0, rgb(192, 192, 255) 25%,
|
-45deg, transparent 0%, transparent 25%,
|
||||||
rgb(255, 255, 0) 25%, rgb(255, 255, 0) 50%,
|
rgb(255, 255, 0) 25%, rgb(255, 255, 0) 50%,
|
||||||
rgb(192, 192, 255) 50%, rgb(192, 192, 255) 75%,
|
transparent 50%, transparent 75%,
|
||||||
rgb(255, 255, 0) 75%, rgb(255, 255, 0) 100%
|
rgb(255, 255, 0) 75%, rgb(255, 255, 0) 100%
|
||||||
);
|
);
|
||||||
background-size: 4px 4px;
|
background-size: 4px 4px;
|
||||||
|
|
|
@ -75,7 +75,9 @@ Ox.highlightHTML <f> Highlight matches in an HTML string
|
||||||
> Ox.highlightHTML('AT&T', 'amp', 'h')
|
> Ox.highlightHTML('AT&T', 'amp', 'h')
|
||||||
'AT&T'
|
'AT&T'
|
||||||
> Ox.highlightHTML('a <b> c', '<b>', 'h')
|
> Ox.highlightHTML('a <b> c', '<b>', 'h')
|
||||||
'<span class="h">a <span class="h"><b></span> c'
|
'a <span class="h"><b></span> c'
|
||||||
|
> Ox.highlightHTML('a <br> c', 'b', 'h')
|
||||||
|
'a <br> c'
|
||||||
@*/
|
@*/
|
||||||
Ox.highlightHTML = function(html, str, classname, tags) {
|
Ox.highlightHTML = function(html, str, classname, tags) {
|
||||||
var count = 0,
|
var count = 0,
|
||||||
|
@ -83,7 +85,19 @@ Ox.highlightHTML = function(html, str, classname, tags) {
|
||||||
isTag = false,
|
isTag = false,
|
||||||
position,
|
position,
|
||||||
positions = [];
|
positions = [];
|
||||||
tags = Ox.merge(tags || [], ['a', 'b', 'code', 'i', 's', 'sub', 'sup', 'u']);
|
//fixme: default tags should be same as in parseHTML
|
||||||
|
tags = Ox.merge(tags || [], [
|
||||||
|
// inline formatting
|
||||||
|
'b', 'code', 'i', 's', 'sub', 'sup', 'u',
|
||||||
|
// block formatting
|
||||||
|
'blockquote', 'h1', 'h2', 'h3', 'p', 'pre',
|
||||||
|
// lists
|
||||||
|
'li', 'ol', 'ul',
|
||||||
|
// tables
|
||||||
|
'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr',
|
||||||
|
// other
|
||||||
|
'a', 'br', 'img',
|
||||||
|
]);
|
||||||
str = Ox.encodeHTML(str).toLowerCase();
|
str = Ox.encodeHTML(str).toLowerCase();
|
||||||
Ox.forEach(html.toLowerCase(), function(chr, i) {
|
Ox.forEach(html.toLowerCase(), function(chr, i) {
|
||||||
// check for entity or tag start
|
// check for entity or tag start
|
||||||
|
|
Loading…
Reference in a new issue