some improvements to Ox.VideoPlayer
This commit is contained in:
parent
57618c850f
commit
a19c271e8f
6 changed files with 213 additions and 49 deletions
|
@ -9,9 +9,23 @@ Ox.load('UI', {
|
||||||
padding: '16px'
|
padding: '16px'
|
||||||
});
|
});
|
||||||
Ox.VideoPlayer({
|
Ox.VideoPlayer({
|
||||||
height: 288,
|
height: 96 * 256/180,
|
||||||
|
timeline: timeline,
|
||||||
|
title: 'Brick',
|
||||||
|
url: url,
|
||||||
|
width: 256
|
||||||
|
}).appendTo(Ox.UI.$body);
|
||||||
|
/*
|
||||||
|
var id = '0133093';
|
||||||
|
var url = 'http://next.0xdb.org/' + id + '/96p.webm?' + Ox.random(1000000);
|
||||||
|
var timeline = 'http://next.0xdb.org/' + id + '/timeline.16.png';
|
||||||
|
Ox.VideoPlayer({
|
||||||
|
height: 96 * 256/230,
|
||||||
timeline: timeline,
|
timeline: timeline,
|
||||||
url: url,
|
url: url,
|
||||||
width: 540
|
width: 256
|
||||||
|
}).css({
|
||||||
|
left: '300px'
|
||||||
}).appendTo(Ox.UI.$body);
|
}).appendTo(Ox.UI.$body);
|
||||||
|
*/
|
||||||
});
|
});
|
||||||
|
|
|
@ -1647,6 +1647,7 @@ Video
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.OxVideoPlayer > .OxBar .OxInputGroup {
|
.OxVideoPlayer > .OxBar .OxInputGroup {
|
||||||
//width: 98px;
|
//width: 98px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,10 @@ Ox.Focus = function() {
|
||||||
_print: function() {
|
_print: function() {
|
||||||
Ox.print(stack);
|
Ox.print(stack);
|
||||||
},
|
},
|
||||||
|
_reset: function() {
|
||||||
|
$('.OxFocus').removeClass('OxFocus');
|
||||||
|
stack = [];
|
||||||
|
},
|
||||||
blur: function(id) {
|
blur: function(id) {
|
||||||
var index = stack.indexOf(id);
|
var index = stack.indexOf(id);
|
||||||
if (index > -1 && index == stack.length - 1) {
|
if (index > -1 && index == stack.length - 1) {
|
||||||
|
|
|
@ -729,12 +729,18 @@ Ox.Input = function(options, self) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
that.focusInput = function() {
|
that.focusInput = function(select) {
|
||||||
|
select = Ox.isUndefined(select) ? true : select;
|
||||||
self.$input.focus();
|
self.$input.focus();
|
||||||
|
if (select) {
|
||||||
cursor(0, self.$input.val().length);
|
cursor(0, self.$input.val().length);
|
||||||
|
} else {
|
||||||
|
cursor(self.$input.val().length);
|
||||||
|
}
|
||||||
return that;
|
return that;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// fixme: deprecate, options are enough
|
||||||
that.value = function() {
|
that.value = function() {
|
||||||
return self.$input.hasClass('OxPlaceholder') ? '' : self.$input.val();
|
return self.$input.hasClass('OxPlaceholder') ? '' : self.$input.val();
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,6 +11,7 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
})
|
})
|
||||||
.options(options || {})
|
.options(options || {})
|
||||||
.css({
|
.css({
|
||||||
|
position: 'absolute',
|
||||||
width: self.options.width + 'px',
|
width: self.options.width + 'px',
|
||||||
height: self.options.height + 'px'
|
height: self.options.height + 'px'
|
||||||
//background: 'red'
|
//background: 'red'
|
||||||
|
@ -27,9 +28,7 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
self.barHeight = 16;
|
self.barHeight = 16;
|
||||||
self.outerBarWidth = self.options.width - 96;
|
self.outerBarWidth = self.options.width - 96;
|
||||||
self.innerBarWidth = self.outerBarWidth - self.barHeight;
|
self.innerBarWidth = self.outerBarWidth - self.barHeight;
|
||||||
self.markerSize = 12;
|
self.markerOffset = -self.innerBarWidth - 8;
|
||||||
self.markerBorderSize = 2;
|
|
||||||
self.markerOffset = -self.innerBarWidth - self.markerSize / 2;
|
|
||||||
|
|
||||||
self.$video = Ox.VideoElement({
|
self.$video = Ox.VideoElement({
|
||||||
height: self.options.height,
|
height: self.options.height,
|
||||||
|
@ -44,10 +43,12 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
loadedmetadata: loadedmetadata,
|
loadedmetadata: loadedmetadata,
|
||||||
paused: function(data) {
|
paused: function(data) {
|
||||||
// called when playback ends
|
// called when playback ends
|
||||||
|
/*
|
||||||
self.$playButton.toggleTitle();
|
self.$playButton.toggleTitle();
|
||||||
self.$positionMarker.css({
|
self.$positionMarkerRing.css({
|
||||||
borderColor: 'rgb(192, 192, 192)'
|
borderColor: 'rgba(255, 255, 255, 0.5)'
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
},
|
},
|
||||||
playing: function(data) {
|
playing: function(data) {
|
||||||
setPosition(data.position);
|
setPosition(data.position);
|
||||||
|
@ -60,7 +61,7 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
if (self.buffered[i][0] > self.buffered[i][1]) {
|
if (self.buffered[i][0] > self.buffered[i][1]) {
|
||||||
self.buffered[i][0] = 0;
|
self.buffered[i][0] = 0;
|
||||||
}
|
}
|
||||||
Ox.print(i, self.buffered[i][0], self.buffered[i][1])
|
//Ox.print(i, self.buffered[i][0], self.buffered[i][1])
|
||||||
}
|
}
|
||||||
self.$buffered.attr({
|
self.$buffered.attr({
|
||||||
src: getBufferedImageURL()
|
src: getBufferedImageURL()
|
||||||
|
@ -72,14 +73,33 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
})
|
})
|
||||||
.appendTo(that);
|
.appendTo(that);
|
||||||
|
|
||||||
|
if (self.options.title) {
|
||||||
|
self.$titlebar = $('<div>')
|
||||||
|
.css({
|
||||||
|
position: 'absolute',
|
||||||
|
width: self.options.width + 'px',
|
||||||
|
height: '15px',
|
||||||
|
paddingTop: '1px',
|
||||||
|
textAlign: 'center'
|
||||||
|
})
|
||||||
|
.css({
|
||||||
|
backgroundImage: '-moz-linear-gradient(top, rgba(64, 64, 64, 0.5), rgba(0, 0, 0, 0.5))'
|
||||||
|
})
|
||||||
|
.css({
|
||||||
|
backgroundImage: '-webkit-linear-gradient(top, rgba(64, 64, 64, 0.5), rgba(0, 0, 0, 0.5))'
|
||||||
|
})
|
||||||
|
.html(self.options.title)
|
||||||
|
.appendTo(that.$element);
|
||||||
|
}
|
||||||
|
|
||||||
self.$loadingIcon = $('<img>')
|
self.$loadingIcon = $('<img>')
|
||||||
.attr({
|
.attr({
|
||||||
src: Ox.UI.getImagePath('symbolLoadingAnimated.svg')
|
src: Ox.UI.getImagePath('symbolLoadingAnimated.svg').replace('/classic/', '/modern/')
|
||||||
})
|
})
|
||||||
.css({
|
.css({
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
left: self.options.width / 2 - 16 + 'px',
|
left: parseInt(self.options.width / 2) - 16 + 'px', // fixme
|
||||||
top: self.options.height / 2 - 16 + 'px',
|
top: parseInt(self.options.height / 2) - 16 + 'px',
|
||||||
width: '32px',
|
width: '32px',
|
||||||
height: '32px'
|
height: '32px'
|
||||||
})
|
})
|
||||||
|
@ -93,6 +113,12 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
width: self.options.width + 'px',
|
width: self.options.width + 'px',
|
||||||
marginTop: self.options.height - self.barHeight + 'px',
|
marginTop: self.options.height - self.barHeight + 'px',
|
||||||
})
|
})
|
||||||
|
.css({
|
||||||
|
backgroundImage: '-moz-linear-gradient(top, rgba(64, 64, 64, 0.5), rgba(0, 0, 0, 0.5))'
|
||||||
|
})
|
||||||
|
.css({
|
||||||
|
backgroundImage: '-webkit-linear-gradient(top, rgba(64, 64, 64, 0.5), rgba(0, 0, 0, 0.5))'
|
||||||
|
})
|
||||||
.appendTo(that);
|
.appendTo(that);
|
||||||
|
|
||||||
self.$buttons = Ox.Element()
|
self.$buttons = Ox.Element()
|
||||||
|
@ -150,9 +176,17 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
float: 'left',
|
float: 'left',
|
||||||
width: self.outerBarWidth + 'px',
|
width: self.outerBarWidth + 'px',
|
||||||
height: self.barHeight + 'px',
|
height: self.barHeight + 'px',
|
||||||
background: 'rgb(0, 0, 0)',
|
background: 'rgba(0, 0, 0, 0.75)',
|
||||||
borderRadius: self.barHeight / 2 + 'px'
|
borderRadius: self.barHeight / 2 + 'px'
|
||||||
})
|
})
|
||||||
|
/*
|
||||||
|
.css({
|
||||||
|
backgroundImage: '-moz-linear-gradient(top, rgba(0, 0, 0, 0.75), rgba(64, 64, 64, 0.75))'
|
||||||
|
})
|
||||||
|
.css({
|
||||||
|
backgroundImage: '-webkit-linear-gradient(top, rgba(0, 0, 0, 0.75), rgba(64, 64, 64, 0.75))'
|
||||||
|
})
|
||||||
|
*/
|
||||||
.appendTo(self.$controls);
|
.appendTo(self.$controls);
|
||||||
|
|
||||||
self.$innerBar = Ox.Element()
|
self.$innerBar = Ox.Element()
|
||||||
|
@ -187,21 +221,36 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
})
|
})
|
||||||
.appendTo(self.$innerBar.$element);
|
.appendTo(self.$innerBar.$element);
|
||||||
|
|
||||||
self.$positionMarker = Ox.Element()
|
self.$positionMarker = $('<div>')
|
||||||
.css({
|
.css({
|
||||||
float: 'left',
|
float: 'left',
|
||||||
width: self.markerSize - self.markerBorderSize * 2 + 'px',
|
width: '14px',
|
||||||
height: self.markerSize - self.markerBorderSize * 2 + 'px',
|
height: '14px',
|
||||||
marginTop: (self.barHeight - self.markerSize) / 2 + 'px',
|
|
||||||
marginLeft: self.markerOffset + 'px',
|
marginLeft: self.markerOffset + 'px',
|
||||||
border: self.markerBorderSize + 'px solid rgb(192, 192, 192)',
|
border: '1px solid rgba(0, 0, 0, 0.5)',
|
||||||
borderRadius: self.markerSize - self.markerBorderSize * 2 + 'px',
|
borderRadius: '8px'
|
||||||
//background: 'rgba(0, 0, 0, 0.5)',
|
|
||||||
boxShadow: '0 0 ' + (self.barHeight - self.markerSize) / 2 + 'px black'
|
|
||||||
})
|
})
|
||||||
.appendTo(self.$outerBar);
|
.append(
|
||||||
|
self.$positionMarkerRing = $('<div>')
|
||||||
|
.css({
|
||||||
|
width: '10px',
|
||||||
|
height: '10px',
|
||||||
|
border: '2px solid rgba(255, 255, 255, 0.5)',
|
||||||
|
borderRadius: '7px',
|
||||||
|
})
|
||||||
|
.append(
|
||||||
|
$('<div>')
|
||||||
|
.css({
|
||||||
|
width: '8px',
|
||||||
|
height: '8px',
|
||||||
|
border: '1px solid rgba(0, 0, 0, 0.5)',
|
||||||
|
borderRadius: '5px',
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.appendTo(self.$outerBar.$element);
|
||||||
|
|
||||||
self.$interfaceBar = Ox.Element()
|
self.$trackInterface = Ox.Element()
|
||||||
.css({
|
.css({
|
||||||
float: 'left',
|
float: 'left',
|
||||||
width: self.outerBarWidth + 'px',
|
width: self.outerBarWidth + 'px',
|
||||||
|
@ -214,7 +263,7 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
animate: false
|
animate: false
|
||||||
});
|
});
|
||||||
|
|
||||||
self.$position = Ox.Element()
|
self.$position = $('<div>')
|
||||||
.css({
|
.css({
|
||||||
float: 'left',
|
float: 'left',
|
||||||
width: '44px',
|
width: '44px',
|
||||||
|
@ -224,7 +273,81 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
textAlign: 'center'
|
textAlign: 'center'
|
||||||
})
|
})
|
||||||
.html(Ox.formatDuration(self.options.position))
|
.html(Ox.formatDuration(self.options.position))
|
||||||
.appendTo(self.$controls)
|
.bind({
|
||||||
|
click: function() {
|
||||||
|
if (!self.$video.paused()) {
|
||||||
|
self.wasPlaying = true;
|
||||||
|
self.$video.pause();
|
||||||
|
self.$playButton.toggleTitle();
|
||||||
|
}
|
||||||
|
self.$position.hide();
|
||||||
|
self.$positionInput
|
||||||
|
.options({
|
||||||
|
value: Ox.formatDuration(self.options.position)
|
||||||
|
})
|
||||||
|
.show()
|
||||||
|
.focusInput(false);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.appendTo(self.$controls.$element)
|
||||||
|
|
||||||
|
self.$positionInput = Ox.Input({
|
||||||
|
value: Ox.formatDuration(self.options.position),
|
||||||
|
width: 48
|
||||||
|
})
|
||||||
|
.css({
|
||||||
|
float: 'left',
|
||||||
|
background: 'rgba(0, 0, 0, 0)',
|
||||||
|
MozBoxShadow: '0 0 0',
|
||||||
|
WebkitBoxShadow: '0 0 0'
|
||||||
|
})
|
||||||
|
.bindEvent({
|
||||||
|
blur: submitPositionInput,
|
||||||
|
change: submitPositionInput,
|
||||||
|
//submit: submitPositionInput
|
||||||
|
})
|
||||||
|
.hide()
|
||||||
|
.appendTo(self.$controls.$element);
|
||||||
|
|
||||||
|
self.$positionInput.children('input').css({
|
||||||
|
width: '42px',
|
||||||
|
height: '16px',
|
||||||
|
padding: '0 3px 0 3px',
|
||||||
|
border: '0px',
|
||||||
|
borderRadius: '8px',
|
||||||
|
fontSize: '9px',
|
||||||
|
color: 'rgb(255, 255, 255)'
|
||||||
|
})
|
||||||
|
.css({
|
||||||
|
background: '-moz-linear-gradient(top, rgba(0, 0, 0, 0.5), rgba(64, 64, 64, 0.5))'
|
||||||
|
})
|
||||||
|
.css({
|
||||||
|
background: '-webkit-linear-gradient(top, rgba(0, 0, 0, 0.5), rgba(64, 64, 64, 0.5))'
|
||||||
|
});
|
||||||
|
|
||||||
|
function submitPositionInput() {
|
||||||
|
self.$positionInput.hide();
|
||||||
|
self.$position.html('').show();
|
||||||
|
setPosition(parsePositionInput(self.$positionInput.options('value')));
|
||||||
|
self.$video.position(self.options.position);
|
||||||
|
if (self.wasPlaying) {
|
||||||
|
self.$video.play();
|
||||||
|
self.$playButton.toggleTitle();
|
||||||
|
self.wasPlaying = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function parsePositionInput(str) {
|
||||||
|
var position,
|
||||||
|
split = str.split(':').reverse();
|
||||||
|
while (split.length > 3) {
|
||||||
|
split.pop();
|
||||||
|
}
|
||||||
|
position = split.reduce(function(prev, curr, i) {
|
||||||
|
return prev + (parseFloat(curr) || 0) * Math.pow(60, i);
|
||||||
|
}, 0)
|
||||||
|
return Ox.limit(position, 0, self.duration);
|
||||||
|
}
|
||||||
|
|
||||||
function getPosition(e) {
|
function getPosition(e) {
|
||||||
// fixme: no offsetX in firefox???
|
// fixme: no offsetX in firefox???
|
||||||
|
@ -235,7 +358,10 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
0, self.duration
|
0, self.duration
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
Ox.print(e.offsetX)
|
/*Ox.print(e.offsetX, Ox.limit(
|
||||||
|
(e.offsetX - self.barHeight / 2) / self.innerBarWidth * self.duration,
|
||||||
|
0, self.duration
|
||||||
|
))*/
|
||||||
return Ox.limit(
|
return Ox.limit(
|
||||||
(e.offsetX - self.barHeight / 2) / self.innerBarWidth * self.duration,
|
(e.offsetX - self.barHeight / 2) / self.innerBarWidth * self.duration,
|
||||||
0, self.duration
|
0, self.duration
|
||||||
|
@ -274,12 +400,19 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function hideControls() {
|
function hideControls() {
|
||||||
|
Ox.print('!!!!!!', self.$positionInput.hasFocus())
|
||||||
|
if (!self.$positionInput.hasFocus()) {
|
||||||
self.controlsTimeout = setTimeout(function() {
|
self.controlsTimeout = setTimeout(function() {
|
||||||
|
// fixme: use class
|
||||||
|
self.$titlebar.animate({
|
||||||
|
opacity: 0
|
||||||
|
}, 250);
|
||||||
self.$controls.animate({
|
self.$controls.animate({
|
||||||
opacity: 0
|
opacity: 0
|
||||||
}, 250);
|
}, 250);
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function hideLoadingIcon() {
|
function hideLoadingIcon() {
|
||||||
self.$loadingIcon.animate({
|
self.$loadingIcon.animate({
|
||||||
|
@ -289,9 +422,9 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
|
|
||||||
function loadedmetadata(data) {
|
function loadedmetadata(data) {
|
||||||
//self.$position.html(Ox.formatDuration(data.video.duration))
|
//self.$position.html(Ox.formatDuration(data.video.duration))
|
||||||
Ox.print('!!!!', data.video.width, data.video.height, data.video.videoWidth, data.video.videoHeight)
|
//Ox.print('!!!!', data.video.width, data.video.height, data.video.videoWidth, data.video.videoHeight)
|
||||||
self.duration = data.video.duration;
|
self.duration = data.video.duration;
|
||||||
Ox.print('DURATION', Ox.formatDuration(self.duration));
|
//Ox.print('DURATION', Ox.formatDuration(self.duration));
|
||||||
hideLoadingIcon();
|
hideLoadingIcon();
|
||||||
that.gainFocus().bindEvent({
|
that.gainFocus().bindEvent({
|
||||||
key_space: function() {
|
key_space: function() {
|
||||||
|
@ -299,38 +432,41 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
togglePlay();
|
togglePlay();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
self.$interfaceBar
|
self.$trackInterface
|
||||||
.bind({
|
.bind({
|
||||||
mousedown: mousedownBar,
|
mousedown: mousedownTrack,
|
||||||
mouseleave: mouseleaveBar,
|
mouseleave: mouseleaveTrack,
|
||||||
mousemove: mousemoveBar,
|
mousemove: mousemoveTrack,
|
||||||
})
|
})
|
||||||
.bindEvent({
|
.bindEvent({
|
||||||
drag: dragBar,
|
drag: dragTrack,
|
||||||
|
dragpause: dragpauseTrack,
|
||||||
|
dragend: dragpauseTrack
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function dragBar(e) {
|
function dragTrack(e) {
|
||||||
setPosition(getPosition(e));
|
setPosition(getPosition(e));
|
||||||
if (self.dragTimeout) {
|
if (self.dragTimeout) {
|
||||||
clearTimeout(self.dragTimeout);
|
clearTimeout(self.dragTimeout);
|
||||||
self.dragTimeout = 0;
|
self.dragTimeout = 0;
|
||||||
}
|
}
|
||||||
self.dragTimeout = setTimeout(function() {
|
|
||||||
self.$video.position(self.options.position);
|
|
||||||
}, 1000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function mousedownBar(e) {
|
function dragpauseTrack(e) {
|
||||||
|
self.$video.position(self.options.position);
|
||||||
|
}
|
||||||
|
|
||||||
|
function mousedownTrack(e) {
|
||||||
setPosition(getPosition(e));
|
setPosition(getPosition(e));
|
||||||
self.$video.position(self.options.position);
|
self.$video.position(self.options.position);
|
||||||
}
|
}
|
||||||
|
|
||||||
function mouseleaveBar(e) {
|
function mouseleaveTrack(e) {
|
||||||
self.$tooltip.hide();
|
self.$tooltip.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
function mousemoveBar(e) {
|
function mousemoveTrack(e) {
|
||||||
self.$tooltip.options({
|
self.$tooltip.options({
|
||||||
title: Ox.formatDuration(getPosition(e))
|
title: Ox.formatDuration(getPosition(e))
|
||||||
}).show(e.clientX, e.clientY);
|
}).show(e.clientX, e.clientY);
|
||||||
|
@ -338,6 +474,9 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
|
|
||||||
function showControls() {
|
function showControls() {
|
||||||
clearTimeout(self.controlsTimeout);
|
clearTimeout(self.controlsTimeout);
|
||||||
|
self.$titlebar.animate({
|
||||||
|
opacity: 1
|
||||||
|
}, 250);
|
||||||
self.$controls.animate({
|
self.$controls.animate({
|
||||||
opacity: 1
|
opacity: 1
|
||||||
}, 250);
|
}, 250);
|
||||||
|
@ -363,8 +502,8 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
|
|
||||||
function togglePlay() {
|
function togglePlay() {
|
||||||
self.$video.togglePlay();
|
self.$video.togglePlay();
|
||||||
self.$positionMarker.css({
|
self.$positionMarkerRing.css({
|
||||||
borderColor: self.$video.paused() ? 'rgb(192, 192, 192)' : 'rgb(255, 255, 255)'
|
borderColor: 'rgba(255, 255, 255, ' + (self.$video.paused() ? 0.5 : 1) + ')'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
height: 256px;
|
height: 256px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script src="../../../../build/js/jquery/jquery.js"></script>
|
<script src="../../../../build/jquery/jquery.js"></script>
|
||||||
<script src="../../../Ox.js"></script>
|
<script src="../../../Ox.js"></script>
|
||||||
<script>
|
<script>
|
||||||
$(function() {
|
$(function() {
|
||||||
|
|
Loading…
Reference in a new issue