function escapeHTML(str) {
return str.replace(/[&<>"'`=\/]/g, function(s) {
return {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": ''',
'/': '/',
'`': '`',
'=': '='
}[s];
});
}
//Pagination
var paginate = function(pagination, options) {
var type = options.hash.type || 'middle';
var ret = '';
var pageCount = Number(pagination.pageCount);
var page = Number(pagination.page);
var limit;
if (options.hash.limit) limit = +options.hash.limit;
//page pageCount
var newContext = {};
switch (type) {
case 'middle':
if (typeof limit === 'number') {
var i = 0;
var leftCount = Math.ceil(limit / 2) - 1;
var rightCount = limit - leftCount - 1;
if (page + rightCount > pageCount)
leftCount = limit - (pageCount - page) - 1;
if (page - leftCount < 1)
leftCount = page - 1;
var start = page - leftCount;
while (i < limit && i < pageCount) {
newContext = { n: start };
if (start === page) newContext.active = true;
ret = ret + options.fn(newContext);
start++;
i++;
}
}
else {
for (var i = 1; i <= pageCount; i++) {
newContext = { n: i };
if (i === page) newContext.active = true;
ret = ret + options.fn(newContext);
}
}
break;
case 'previous':
if (page === 1) {
newContext = { disabled: true, n: 1 }
}
else {
newContext = { n: page - 1 }
}
ret = ret + options.fn(newContext);
break;
case 'next':
newContext = {};
if (page === pageCount) {
newContext = { disabled: true, n: pageCount }
}
else {
newContext = { n: page + 1 }
}
ret = ret + options.fn(newContext);
break;
case 'first':
if (page === 1) {
newContext = { disabled: true, n: 1 }
}
else {
newContext = { n: 1 }
}
ret = ret + options.fn(newContext);
break;
case 'last':
if (page === pageCount) {
newContext = { disabled: true, n: pageCount }
}
else {
newContext = { n: pageCount }
}
ret = ret + options.fn(newContext);
break;
}
return ret;
};
class API {
static request(post, base, method, params, callback) {
$.ajax({
url: '/api/' + base + '/' + method,
method: post ? 'POST' : 'GET',
data: params,
success: cb => {
if(cb.error === 'null')
callback(true, null, cb.warnings, cb);
else
callback(false, this.responsify(cb.error), cb.warnings, cb);
},
error: cb => callback(false, null, null, cb)
});
}
static responsify(response) {
var r = (type, text) => ({type: type, text: text});
return {
not_logged_in: r('error', 'Not logged in (✖╭╮✖)'),
invalid_request: r('error', 'Invalid request 【ツ】'),
video_not_found: r('error', 'Video not found. Perhaps it has already been deleted'),
insufficient_permissions: r('error', 'Insufficient permissions ┌∩┐(◣_◢)┌∩┐'),
no_tags_specified: r('error', 'No tags specified')
}[response];
}
}
//CSRF Token AjaxSetup
$(function() {
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="_token"]').attr('content')
}
});
});
class Video {
constructor() {
let match = location.href.match(/(\d+)(?!.*\/.)/);
if(!match) return;
this.id = match[1];
this.user = $('.fa-info-circle').next().children().text().trim();
this.tags = $.makeArray($('#tag-display').children().children()).map(el => el.innerText).filter(tag => !!tag);
this.api = 'video';
this.apiBase = this.api + '/' + this.id;
}
tag(tags, callback) {
var _this = this;
function preCallback(success, error, warnings, cb) {
if(success) {
_this.tags = [];
_this.tags = cb.tags.map(tag => tag.name);
}
callback(success, error, warnings, cb);
}
tags.length ? API.request(true, this.apiBase, 'tag', {tags: tags}, preCallback) : callback(false, API.responsify('no_tags_specified'), null, null);
}
untag(tag, callback) {
var _this = this;
function preCallback(success, error, warnings, cb) {
if(success) {
_this.tags = [];
_this.tags = cb.tags.map(tag => tag.name);
}
callback(success, error, warnings, cb);
}
tag = tag.trim();
!!tag ? API.request(true, this.apiBase, 'untag', {tag: tag}, preCallback) : callback(false, API.responsify('invalid_request'), null, null);
}
delete(reason, callback) {
reason = reason.trim();
!!reason ? API.request(true, this.apiBase, 'delete', {reason: reason}, callback) : callback(false, API.responsify('invalid_request'), null, null);
}
}
function flash(type, message) {
var html = '
:REPLACE:
';
var alerts = $('.flashcontainer > .flash-inner');
if(type === 'error') type = 'danger';
alerts.append(html.replace(/:TYPE:/, type).replace(/:REPLACE:/, message));
alertrm(jQuery);
}
window.requestAnimFrame = (function(){
return window.requestAnimationFrame
|| window.webkitRequestAnimationFrame
|| window.mozRequestAnimationFrame
|| function(callback) { window.setTimeout(callback, 1000 / 60);};
})();
if (typeof video !== 'undefined') {
video = new Video();
if(!video.id) video = null;
// the variable is defined
var videoElem = document.getElementById('video');
videoElem.play();
videoElem.addEventListener('mouseover', function() { this.controls = true; });
videoElem.volume = 0.3;
videoElem.volume = localStorage.getItem("volume") || 1;
videoElem.addEventListener("volumechange", ev => {
localStorage.setItem("volume", ev.target.volume);
});
if(videoElem !== null) {
if(localStorage.getItem('background') == undefined) {
localStorage.setItem('background', 'true');
}
var background = localStorage.getItem('background') === 'true';
var canvas = document.getElementById('bg');
var context = canvas.getContext('2d');
var cw = canvas.width = canvas.clientWidth | 0;
var ch = canvas.height = canvas.clientHeight | 0;
function animationLoop() {
if(videoElem.paused || videoElem.ended || !background)
return;
context.drawImage(videoElem, 0, 0, cw, ch);
window.requestAnimFrame(animationLoop);
}
videoElem.addEventListener('play', animationLoop);
/*$(window).keypress(function(e) {
/* if (e.which == 32) {
/* if (videoElem.paused)
/* videoElem.play();
/* else
/* videoElem.pause();
/* }
});*/
}
};
$('#togglebg').on('click', function (e) {
e.preventDefault();
background = !background;
localStorage.setItem('background', background.toString());
if(background)
$(canvas).css('display', 'block');
else
$(canvas).css('display', 'none');
animationLoop();
});
$("[data-toggle=popover]").popover({
html: true,
content: function() {
return $('#popover-content').html();
}
});
$('body').on('click', function (e) {
$('[data-toggle="popover"]').each(function () {
//the 'is' for buttons that trigger popups
//the 'has' for icons within a button that triggers a popup
if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
$(this).popover('hide');
}
});
});
(function ($) {
function updaterow(ctx, video) {
if($('video').length) {
var info = [];
if(video.interpret) {
info.push(' Artist: ' + video.interpret);
}
if(video.songtitle) {
info.push(' Songtitle: ' + video.songtitle);
}
if(video.imgsource) {
info.push(' Video Source: ' + video.imgsource);
}
if(video.category.name) {
info.push(' Category: ' + video.category.name);
}
$('span.fa-info-circle').attr('data-content', info.join('
'));
}
else {
var row = ctx.parents('tr');
row.find('span').show();
row.find('input, select').hide();
row.find('.vinterpret').html(video.interpret || '');
row.find('.vsongtitle').html(video.songtitle || '');
row.find('.vimgsource').html(video.imgsource || '');
row.find('.vcategory').html('' + video.category.name + '');
}
}
var indexform = $('.indexform, #webmedit');
$('.indexedit').find('input, select').hide();
if(indexform.length) {
var row = $('tr');
row.on('dblclick touchdown', function(e) {
var self = $(this);
self.find('input, select').show();
self.find('span').hide();
});
}
indexform.on('submit', function (e) {
var self = $(this);
e.preventDefault();
$.ajax({
type: 'POST',
url: self.attr('action'),
data: self.serialize()
}).done(function (data) {
flash('success', 'Video successfully updated');
updaterow(self, data);
self.find('#webmeditmodal');
}).fail(function(){
flash('error', 'Error updating video');
self.find('#webmeditmodal');
});
});
})(jQuery);
(function ($) {
$(':not(form)[data-confirm]').on('click touchdown', function () {
return confirm($(this).data('confirm'));
});
})(jQuery);
var alertrm = function ($) {
$('.alert').each(function (index) {
$(this).delay(3000 + index * 1000).slideUp(300, function() { $(this).remove(); });
});
};
alertrm(jQuery);
//upload
$(function() {
if(!/\/upload/.test(location.href))
return;
var defaultPreview = $('#dragndrop-text').html();
var defaultDragNDropColor = $('#dragndrop').css('color');
var defaultDragNDropBorderColor = $('#dragndrop').css('border-left-color');
var defaultDragNDropBackgroundColor = $('#dragndrop').css('background-color');
var counter = 0;
var currentFile;
var jqXHR;
var tags = $('#tags_upload');
var nsfwCheckbox = $('#nsfw');
function applyDefaultDragNDropCSS() {
$('#dragndrop').css({
'color': defaultDragNDropColor,
'border-color': defaultDragNDropBorderColor,
'background-color': defaultDragNDropBackgroundColor
});
}
function humanFileSize(size) {
var i = Math.floor(Math.log(size) / Math.log(1024));
return (size / Math.pow(1024, i)).toFixed(2) + ' ' + ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'][i];
}
function dragndropLinkClickHandler(e) {
e.preventDefault();
$('input[type="file"]').trigger('click');
}
function restoreDefaultPreview() {
$('#dragndrop-link').on('click', dragndropLinkClickHandler);
$('#dragndrop-link').attr('href', '#');
$('#dragndrop-text').html(defaultPreview);
}
function createPreview(file) {
$('#dragndrop-link').removeAttr('href').off('click');
$('#dragndrop-text').html('' + file.name + ' — ' + humanFileSize(file.size) + ' — ');
$('#video_preview').prop('volume', 0);
$('#dragndrop-clear').on('click', function(e) {
e.preventDefault();
e.stopPropagation();
currentFile = null;
$(this).off('click');
applyDefaultDragNDropCSS();
restoreDefaultPreview();
if(jqXHR && jqXHR.statusText != "abort") {
jqXHR.abort();
jqXHR = null;
}
});
}
function checkFile(file) {
var maxFileSize = 1e8;
var tooBig = file.size > maxFileSize;
var invalid = file.type !== "video/webm";
if((tooBig && $('#dragndrop').data('uploadlimit')) || invalid) {
flash('error', invalid ? 'Invalid file' : `File too big. Max ${humanFileSize(maxFileSize)}`);
applyDefaultDragNDropCSS();
return false;
}
return true;
}
function submitForm(videotitle, interpret, songtitle, imgsource, category, tags, file) {
var lastState = {
'loaded': 0,
'secondsElapsed': 0
};
var speed = [];
var lastSpeedIndex = 0;
function interval() {
var avgSpeed = 0;
var length = speed.length;
var i;
for(i = lastSpeedIndex; i < length; i++)
avgSpeed += speed[i];
avgSpeed = avgSpeed / (i - lastSpeedIndex);
lastSpeedIndex = i;
$('#upload-stats').text('Speed: ' + humanFileSize(Math.floor(avgSpeed)) + '/s Uploaded: ' + humanFileSize(lastState.loaded));
}
var statsInterval;
var formData = new FormData();
formData.append('videotitle', videotitle);
formData.append('interpret', interpret);
formData.append('songtitle', songtitle);
formData.append('imgsource', imgsource);
formData.append('category', category);
formData.append('tags', tags);
formData.append('file', file);
$('.progress-striped, #upload-stats').css('opacity', 0).slideDown('fast').animate({opacity: 1}, {queue: false, duration: 'fast'});
jqXHR = $.ajax({
url: '/api/upload',
type: 'POST',
data: formData,
processData: false,
contentType: false,
success: function(cb) {
switch(cb.error) {
case 'null':
if(cb.video_id) {
flash('success', 'Upload successful: /' + cb.video_id + '. Redirect in 3 seconds...');
setTimeout(function() {
location.href = '/' + cb.video_id;
}, 3000);
}
else
flash('error', 'Upload failed');
break;
case 'invalid_request':
flash('error', 'Invalid request');
break;
case 'not_logged_in':
flash('error', 'Not logged in');
break;
case 'uploadlimit_reached':
flash('error', 'Uploadlimit reached');
break;
case 'invalid_file':
flash('error', 'Invalid file');
break;
case 'file_too_big':
flash('error', 'File too big. Check the max upload size.');
break;
case 'already_exists':
if(cb.video_id)
flash('error', 'Video already exists: /' + cb.video_id + '');
else
flash('error', 'Video already existed but has been deleted');
break;
case 'erroneous_file_encoding':
flash('error', 'Erroneous file encoding. Try reencoding it');
break;
default:
flash('error', 'Upload failed');
break;
}
if(cb.error != 'null') {
$('.progress-bar-custom').css('background-color', 'red');
$('.progress-bar-custom').text('Upload failed');
}
$('#upload-stats').text('Speed: ' + humanFileSize(Math.floor(speed.average())) + '/s Uploaded: ' + humanFileSize(currentFile.size));
},
error: function(jqXHR, status, error) {
jqXHR = null;
if(error == 'abort') {
flash('info', 'Upload aborted');
return;
}
flash('error', 'Upload failed');
$('.progress-bar-custom').css('background-color', 'red');
$('.progress-bar-custom').text('Upload failed');
},
complete: function() {
clearInterval(statsInterval);
},
xhr: function() {
var xhr = $.ajaxSettings.xhr();
var started_at = new Date();
$('.progress-bar-custom').css('background-color', 'rgba(47, 196, 47, 1)');
xhr.upload.onprogress = function(e) {
var percentage = Math.floor(e.loaded / e.total * 100);
var secondsElapsed = (new Date().getTime() - started_at.getTime()) / 1000;
var bytesPerSecond = (e.loaded - lastState.loaded) / (secondsElapsed - lastState.secondsElapsed);
$('.progress-bar-custom').css('width', percentage + '%');
$('.progress-bar-custom').text(percentage + '%');
lastState.secondsElapsed = secondsElapsed;
lastState.loaded = e.loaded;
speed.push(bytesPerSecond);
if(!statsInterval) {
interval();
statsInterval = setInterval(interval, 500);
}
};
return xhr;
}
});
}
$('input[type="file"]').on('change', function(e) {
if(!this.files.length)
return;
var file = this.files[0];
if(checkFile(file)) {
currentFile = file;
createPreview(file);
}
$(this).wrap('