diff --git a/app/Http/Controllers/tmp/test.png b/app/Http/Controllers/tmp/test.png index 0f87524..b9f0b72 100644 Binary files a/app/Http/Controllers/tmp/test.png and b/app/Http/Controllers/tmp/test.png differ diff --git a/public/njum/css/cstms.css b/public/njum/css/cstms.css index fce362d..71c98a8 100644 --- a/public/njum/css/cstms.css +++ b/public/njum/css/cstms.css @@ -1683,6 +1683,11 @@ div.comment_header { font-size: 1.6rem; } +span.laz0r { + font-size: 1.6rem; + font-weight: bold; +} + @-webkit-keyframes shoop { 0% { top: 16px } 2% { top: 17px } diff --git a/public/z0mb/js/blahscript.js b/public/z0mb/js/blahscript.js new file mode 100644 index 0000000..2cb53c8 --- /dev/null +++ b/public/z0mb/js/blahscript.js @@ -0,0 +1,1383 @@ + + +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 = ''; + 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).addClass( 'fader-in' ).removeClass('fader-out'); + else + $(canvas).addClass( 'fader-out' ).removeClass('fader-in'); + 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/video/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('
').closest('form').get(0).reset(); + $(this).unwrap(); + }); + $('#dragndrop-link').on('click', dragndropLinkClickHandler); + $(document).on('dragenter', function(e) { + e.preventDefault(); + counter++; + var dt = e.originalEvent.dataTransfer; + if(dt.types != null && (dt.types.indexOf ? dt.types.indexOf('Files') === 0 : dt.types.contains('application/x-moz-file'))) { + $('#dragndrop').css({ + 'color': '#BBB', + 'border-color': '#656464', + 'background-color': '#323234' + }); + } + }).on('dragleave', function() { + counter--; + if(counter === 0) + applyDefaultDragNDropCSS(); + }).on('dragover', function(e) { + e.preventDefault(); + }).on('drop', function(e) { + e.preventDefault(); + if(!$(e.target).is('#dragndrop-text')) { + applyDefaultDragNDropCSS(); + } + }); + $('#dragndrop-text').on('dragover', function(e) { + var dt = e.originalEvent.dataTransfer; + var effect = dt.effectAllowed; + dt.dropEffect = 'move' === effect || 'linkMove' === effect ? 'move' : 'copy'; + }).on('drop', function(e) { + if(!e.originalEvent.dataTransfer.files.length) + return; + if(jqXHR && jqXHR.statusText != "abort") { + jqXHR.abort(); + currentFile = null; + restoreDefaultPreview(); + } + var file = e.originalEvent.dataTransfer.files[0]; + applyDefaultDragNDropCSS(); + if(checkFile(file)) { + currentFile = file; + createPreview(file); + counter = 0; + } + }); + $('button#btn-upload').on('click', function() { + if(!currentFile) { + flash('error', 'No file selected'); + return; + } + if(jqXHR && (jqXHR.readyState == 0 || jqXHR.readyState == 1 || jqXHR.readyState == 3)) { + flash('info', 'Already uploading'); + return; + } + submitForm($('#videotitle').val(), $('#interpret').val(), $('#songtitle').val(), $('#imgsource').val(), $('#category').val(), tags.tagsinput('items'), currentFile); + }); + tags.on('itemRemoved', function(e) { + if(e.item === 'nsfw') { + nsfwCheckbox.prop('checked', false); + $(this).tagsinput('add', 'sfw'); + } + else if(e.item === 'sfw') { + nsfwCheckbox.prop('checked', true); + $(this).tagsinput('add', 'nsfw'); + } + }); + nsfwCheckbox.on('change', function() { + if(this.checked) { + tags.tagsinput('remove', 'sfw'); + tags.tagsinput('add', 'nsfw'); + } + else { + tags.tagsinput('remove', 'nsfw'); + tags.tagsinput('add', 'sfw'); + } + }); + nsfwCheckbox.trigger('change'); +}); + +var figure = $(".video-index").hover( hoverVideo, hideVideo ); + +function hoverVideo(e) { + $('#video-index', this).get(0).play(); +} + +function hideVideo(e) { + $('#video-index', this).get(0).pause(); +} + +//$('#video').hover(function toggleControls() { +// if (this.hasAttribute("controls")) { +// this.removeAttribute("controls") +// } else { +// this.setAttribute("controls", "controls") +// } +//}) + +//enable bootstrap tooltips and timeago +$(function () { + var s = $.timeago.settings; + var str = s.strings; + s.refreshMillis = 1000; + s.allowFuture = true; + s.localeTitle = true; + //same format as laravel diffForHumans() + str.seconds = "%d seconds"; + str.minute = "1 minute"; + str.hour = "1 hour"; + str.hours = "%d hours"; + str.day = "1 day"; + str.month = "1 month"; + str.year = "1 year"; + str.suffixFromNow = null; + $('time.timeago').timeago(); + $('[data-toggle="tooltip"]').tooltip(); +}); + + function getNext() { + var next = $('#next'); + if(next.css('visibility') != 'hidden') { + next.get(0).click(); + } + } + + function getPrev() { + var prev = $('#prev'); + if(prev.css('visibility') != 'hidden') { + prev.get(0).click(); + } + } + + //Key Bindings + $(document).on('keydown', function(e) { + if(e.defaultPrevented || e.target.nodeName.match(/\b(input|textarea)\b/i) || e.ctrlKey || e.altKey || e.shiftKey) + return; + + //arrow keys + else if(e.keyCode == 39) + getNext(); + else if(e.keyCode == 37) + getPrev(); + + //gamer-style + else if(e.keyCode == 65) + getPrev(); + else if(e.keyCode == 68) + getNext(); + + //vi style + else if(e.keyCode == 72) + getPrev(); + else if(e.keyCode == 76) + getNext(); + + else if(e.keyCode == 82) //click random + $('#prev').next().get(0).click(); + + else if(e.keyCode == 70) //add fav + $('#fav').get(0).click(); + + /*else if(e.keyCode == 87 || e.keyCode == 38) + videoElem.volume(videoElem.volume() + 0.1); + + else if(e.keyCode == 83 || e.keyCode == 40) + videoElem.volume(videoElem.volume() - 0.1); + + else if(e.keyCode == 32) + video.paused() ? video.play() : video.pause();*/ + }); + +(function ($) { + var favBtn = $('#fav'); + var hiddenfavbtn = $('#hidden-fav'); + favBtn.on('click touchdown', function (e) { + e.preventDefault(); + $.ajax({ + type: 'GET', + url: hiddenfavbtn.attr('href') + }).done(function () { + var icon = favBtn.find('i'); + if(icon.hasClass('fa-heart-o')) { + icon.removeClass('fa-heart-o'); + icon.addClass('fa-heart'); + } else { + icon.removeClass('fa-heart'); + icon.addClass('fa-heart-o'); + } + }); + }) +})(jQuery); + +$(function() { + function get_loc(e) { + return [ + (e.clientX + $('div#thumb').width() >= $(window).width() - 10) ? e.pageX - 5 - $('div#thumb').width() : e.pageX + 5, + (e.clientY + $('div#thumb').height() >= $(window).height() - 10) ? e.pageY - 5 - $('div#thumb').height() : e.pageY + 5 + ]; + } + + $('[data-thumb]').on('mouseenter', function(e) { + var id = $(this).data('thumb'); + var lnk = '/thumbs/' + id + '.gif'; + var loc = get_loc(e); + $(document.body).prepend('
'); + $('div#thumb').prepend(''); + $('img#thumb').text('Loading...'); + $('div#thumb').css({ + 'position': 'absolute', + 'left': loc[0], + 'top': loc[1], + 'z-index': '5', + 'border': '1px white solid', + 'box-shadow': '5px 5px 7px 0px rgba(0,0,0,0.75)', + 'color': 'white', + 'background-color': '#181818' + }); + var img = $('img#thumb'); + var thumb = $(''); + thumb.load(function() { + img.attr("src", $(this).attr("src")); + loc = get_loc(e); + $('div#thumb').css({ + 'left': loc[0], + 'top': loc[1] + }); + }); + thumb.attr("src", lnk); + }).on('mousemove', function(e) { + $('div#thumb').css({ + 'left': get_loc(e)[0], + 'top': get_loc(e)[1] + }); + }).on('mouseleave', function() { + $('#thumb').remove(); + }); +}); + + // Filter + var filter = $('#filter'), + submitfilter = $('#submitfilter'); + submitfilter.on('click touchdown', function(e) { + e.preventDefault(); + $.ajax({ + type: 'POST', + url: submitfilter.attr('href'), + data: filter.serialize() + }).done(function() { + flash('success', 'Filter successfully updated'); + $('#filterselectmodal').modal('hide'); + }).fail(function(data) { + flash('error', 'Error updating filter'); + }); + }); + + //Tags + let tagsinput = $('#tags'), + submit = $('#submittags'), + tagdisplay = $('#tag-display'); + + function tagmd() { + let elReplace = (el, regex, fn) => el.innerHTML = el.innerHTML.replace(regex, fn); + tagdisplay.children().children(':first-of-type').each((i, el) => { + elReplace(el, /^nsfw$/i, x => '' + x + ''); + elReplace(el, /^sfw$/i, x => '' + x + ''); + }); + } + tagmd(); + + function tagDeleteHandler(e) { + e.preventDefault(); + if(!confirm('Do you really want to delete this tag?')) return; + video.untag($(this).siblings().text(), (success, error, warnings, cb) => { + if(success) { + flash('success', 'Tag successfully deleted'); + let tags = []; + for(let tag of cb.tags) + tags.push('' + escapeHTML(tag.name) + ' '); + tagdisplay.empty(); + tagdisplay.append(tags.join(" ")); + $('.delete-tag').on('click', tagDeleteHandler); + tagmd(); + } + else + flash('error', 'Error deleting tag'); + }); + } + + $('.delete-tag').on('click', tagDeleteHandler); + + $('#tags, #filter, #tags_upload').on('itemAdded', e => setTimeout(() => $(e.currentTarget).siblings('.bootstrap-tagsinput').children('input').val(''), 0)); + + tagsinput.on('beforeItemAdd', e => { + for(let tag of video.tags) { + if(tag.toLowerCase() === e.item.toLowerCase()) { + e.cancel = true; + flash('info', 'Tag already exists'); + return; + } + } + }); + submit.on('click touchdown', e => { + e.preventDefault(); + video.tag(tagsinput.tagsinput('items'), (success, error, warnings, cb) => { + if(success) { + $('#tag-add-toggle').prop('checked', false); + var tags = []; + for(let tag of cb.tags) + tags.push('' + escapeHTML(tag.name) + '' + (cb.can_edit_video ? ' ' : '') + ''); + tagdisplay.empty(); + tagdisplay.append(tags.join(" ")); + tagsinput.tagsinput('removeAll'); + $('.delete-tag').on('click', tagDeleteHandler); + tagmd(); + } + else + flash('error', 'Error saving tag(s)'); + }); + }); + +$('.scrollable').on('wheel', function(e) { + if(e.ctrlKey || e.altKey || e.shiftKey) + return; + e.preventDefault(); + e.originalEvent.deltaY > 0 ? getNext() : getPrev(); + }); + +$(function() { + $('.delete_video').on('click', function(e) { + e.preventDefault(); + do { + var reason = prompt('Reason for deleting video ' + video.id + ' by ' + video.user); + if(reason === null) + return; + reason = reason.trim(); + } while(!reason); + video.delete(reason, (success, error, warnings) => { + if(success) { + flash('success', 'Video deleted. Redirect in 3 seconds...'); + setTimeout(() => location.href = '/', 3000); + for(let warn of warnings) + flash('warning', warn); + } + else + flash('error', 'Error deleting video'); + }); + }); +}); + + +// Notifications +var messagesBadge = $('ul.navbar-right > li > a > span.badge'); +var activeMessage; +if(messagesBadge.text() > 0) { + messagesBadge.css('visibility', 'visible'); +} + +if(/\/user\/.+\/comments/i.test(location.href)) { + //Comment View + (function($) { + if(typeof Handlebars == "undefined") return; // only on profilelayout + + Handlebars.registerHelper('paginate', paginate); + + var comlist = Handlebars.compile($('#comlist').html()); + var pagination = Handlebars.compile($('#paginationtmpl').html()); + var jsondata = {}; + var username = location.href.match(/\/user\/(.+)\/comments/i)[1]; + + var getMessages = function(url) { + var baseUrl = '/api/comments'; + if(!url) url = baseUrl; + + $.getJSON(url, { 'username': username }) + .done(function(data) { + $('.spinner').hide(); + jsondata = data; + $('#list').html(comlist(data)); + $('time.timeago').timeago(); + $('time[data-toggle="tooltip"]').tooltip(); + var page = { + pagination: { + page: data.current_page, + pageCount: data.last_page + } + }; + + $('#pagination').html(pagination(page)); + + $('#pagination a').on('click touchdown', function(e) { + e.preventDefault(); + getMessages(baseUrl + '?page=' + $(this).data('page')); + }); + }); + }; + getMessages(); + })(jQuery); +} +else { + (function($) { + if(typeof Handlebars == "undefined" || !$('#msglist').length) return; // only on profilelayout + + Handlebars.registerHelper('paginate', paginate); + + + var msglist = Handlebars.compile($('#msglist').html()); + var msgtmpl = Handlebars.compile($('#msgtmpl').html()); + var pagination = Handlebars.compile($('#paginationtmpl').html()); + var jsondata = {}; + + var getMessages = function(url) { + var baseUrl = '/api/messages'; + if(!url) url = baseUrl; + + $.getJSON(url) + .done(function(data) { + $('.spinner').hide(); + jsondata = data; + $('#list').html(msglist(data)); + if(typeof activeMessage != "undefined") $('#listitems a[data-id="' + activeMessage + '"]').addClass('active'); + + var page = { + pagination: { + page: data.current_page, + pageCount: data.last_page + } + }; + + $('#pagination').html(pagination(page)); + + $('#pagination a').on('click touchdown', function(e) { + e.preventDefault(); + getMessages(baseUrl + '?page=' + $(this).data('page')); + }); + + $('#listitems a').on('click touchdown', function(e) { + e.preventDefault(); + var self = $(this); + var i = self.data('index'); + activeMessage = $(this).data('id'); + + $('#message').html(msgtmpl(jsondata.data[i])); + if(!jsondata.data[i].read) { + + $.post('/api/messages/read','m_ids[]=' + self.data('id')) + .done(function(data) { + self.removeClass('list-group-item-info'); + messagesBadge.text(messagesBadge.text() - 1); + if(messagesBadge.text() <= 0) { + messagesBadge.css('visibility', 'hidden'); + } + }); + + } + $('a').removeClass('active'); + self.addClass('active'); + $('time.timeago').timeago(); + $('time[data-toggle="tooltip"]').tooltip(); + }); + }); + }; + getMessages(); + })(jQuery); +} + +function readAll() { + $.ajax({ + url: '/api/messages/readall', + success: function(data) { + if(data == 1) { + flash('success', 'Marked all messages as read'); + $('.list-group-item-info').removeClass('list-group-item-info'); + messagesBadge.text('0'); + messagesBadge.css('visibility', 'hidden'); + } + else { + flash('error', 'Failed to mark all messages as read'); + } + }, + error: function(jqxhr, status, error) { + flash('error', 'Failed to mark all messages as read'); + } + }); +} + +$('ul.dropdown-menu').on('click touchdown', function(e) { + e.stopPropagation(); +}); + +function deleteComment(self) { + var comment = self.closest('div[data-id]'); + var id = comment.data('id'); + var username = $(comment.children('.panel-footer').children('a')[0]).text(); + do { + var reason = prompt('Reason for deleting comment ' + id + ' by ' + username); + if(reason === null) + return; + reason = reason.trim(); + } while(!reason); + $.ajax({ + url: '/api/comments/' + id + '/delete', + method: 'POST', + data: { reason: reason }, + success: function(retval) { + if(retval == 'success') { + flash('success', 'Comment deleted'); + comment.removeClass('panel-default').addClass('panel-danger'); + comment.find('.panel-footer').children('a[onclick="deleteComment($(this))"]').replaceWith(''); + comment.find('.panel-footer > a[onclick="editComment($(this))"]').remove(); + } + else if(retval == 'invalid_request') flash('error', 'Invalid request'); + else if(retval == 'not_logged_in') flash('error', 'Not logged in'); + else if(retval == 'insufficient_permissions') flash('error', 'Insufficient permissions'); + else flash('error', 'Error deleting comment'); + }, + error: function(jqxhr, status, error) { + flash('error', 'Error deleting comment'); + } + }); +} + +function restoreComment(self) { + var comment = self.closest('div[data-id]'); + var id = comment.data('id'); + var username = $(comment.children('.panel-footer').children('a')[0]).text(); + do { + var reason = prompt('Reason for restoring comment ' + id + ' by ' + username); + if(reason === null) + return; + reason = reason.trim(); + } while(!reason); + $.ajax({ + url: '/api/comments/' + id + '/restore', + method: 'POST', + data: { reason: reason }, + success: function(retval) { + if(retval == 'success') { + flash('success', 'Comment restored'); + comment.removeClass('panel-danger').addClass('panel-default'); + comment.find('.panel-footer').children('a[onclick]').replaceWith(' '); + } + else if(retval == 'invalid_request') flash('error', 'Invalid request'); + else if(retval == 'not_logged_in') flash('error', 'Not logged in'); + else if(retval == 'insufficient_permissions') flash('error', 'Insufficient permissions'); + else if(retval == 'comment_not_deleted') flash('error', 'Comment is not deleted'); + else flash('error', 'Error restoring comment'); + }, + error: function(jqxhr, status, error) { + flash('error', 'Error restoring comment'); + } + }); +} + +function editComment(self) { + var comment = self.closest('div[data-id]'); + var body = comment.find('.panel-body'); + var id = comment.data('id'); + $.ajax({ + url: '/api/comments/' + id, + success: function(retval) { + if(retval.error == 'null') { + var textarea = $('