1
0
mirror of https://github.com/vichan-devel/vichan.git synced 2024-12-01 18:47:20 +01:00
vichan/js/post-hover.js

321 lines
9.5 KiB
JavaScript
Raw Normal View History

2012-03-15 07:05:33 +01:00
/*
* post-hover.js
2012-03-31 02:13:11 +02:00
* https://github.com/savetheinternet/Tinyboard/blob/master/js/post-hover.js
2012-03-15 07:05:33 +01:00
*
* Released under the MIT license
* Copyright (c) 2012 Michael Save <savetheinternet@tinyboard.org>
* Copyright (c) 2013-2014 Marcin Łabanowski <marcin@6irc.net>
* Copyright (c) 2013 Macil Tech <maciltech@gmail.com>
2012-03-15 07:05:33 +01:00
*
* Usage:
* $config['additional_javascript'][] = 'js/jquery.min.js';
* $config['additional_javascript'][] = 'js/post-hover.js';
*
*/
onready(function(){
2015-01-05 06:27:39 +01:00
init_hover = function() {
2014-11-04 00:40:54 +01:00
var link = $(this);
2015-01-05 06:27:39 +01:00
2012-03-15 07:05:33 +01:00
var id;
var matches;
2015-01-05 06:27:39 +01:00
if (link.is('[data-thread]')) {
id = link.attr('data-thread');
}
2014-11-04 00:40:54 +01:00
else if(matches = link.text().match(/^>>(?:>\/([^\/]+)\/)?(\d+)$/)) {
id = matches[2];
}
else {
2013-06-18 19:10:06 +02:00
return;
2012-03-15 07:05:33 +01:00
}
2013-08-04 12:08:10 +02:00
var board = $(this);
while (board.data('board') === undefined) {
board = board.parent();
}
var threadid;
2014-11-04 00:40:54 +01:00
if (link.is('[data-thread]')) threadid = 0;
else threadid = board.attr('id').replace("thread_", "");
2013-08-04 12:08:10 +02:00
board = board.data('board');
var parentboard = board;
2014-11-04 00:40:54 +01:00
if (link.is('[data-thread]')) parentboard = $('form[name="post"] input[name="board"]').val();
else if (matches[1] !== undefined) board = matches[1];
2014-11-04 00:40:54 +01:00
var post = false;
var hovering = false;
2014-11-04 00:40:54 +01:00
link.hover(function(e) {
hovering = true;
2015-01-05 06:27:39 +01:00
var start_hover = function(link) {
2014-11-04 00:40:54 +01:00
if(post.is(':visible') &&
post.offset().top >= $(window).scrollTop() &&
post.offset().top + post.height() <= $(window).scrollTop() + $(window).height()) {
// post is in view
2014-11-04 00:40:54 +01:00
post.addClass('highlighted');
} else {
2014-11-04 00:40:54 +01:00
var newPost = post.clone();
newPost.find('>.reply, >br').remove();
newPost.find('a.post_anchor').remove();
2014-11-04 00:40:54 +01:00
newPost
.attr('id', 'post-hover-' + id)
2013-08-04 12:08:10 +02:00
.attr('data-board', board)
.addClass('post-hover')
.css('border-style', 'solid')
.css('box-shadow', '1px 1px 1px #999')
.css('display', 'block')
.css('position', 'absolute')
.css('font-style', 'normal')
.css('z-index', '100')
2014-11-04 00:40:54 +01:00
.css('left', '0')
2014-11-28 02:15:10 +01:00
.css('margin-left', '')
.addClass('reply').addClass('post')
2015-01-05 06:27:39 +01:00
.appendTo(link.closest('div.post'));
2014-11-04 00:40:54 +01:00
// shrink expanded images
newPost.find('div.file a[data-expanded="true"]').each(function() {
var thumb = $(this).data('src');
$(this).find('img.post-image').attr('src', thumb);
});
// Highlight references to the current post
if (link.hasClass('mentioned-'+id)) {
var postLinks = newPost.find('div.body a:not([rel="nofollow"])');
if (postLinks.length > 1) {
2014-11-06 00:13:06 +01:00
var originalPost = link.closest('div.post').attr('id').replace("reply_", "").replace("inline_", "");
postLinks.each(function() {
if ($(this).text() == ">>"+originalPost) {
$(this).addClass('dashed-underline');
}
});
}
}
2014-11-04 00:40:54 +01:00
var previewWidth = newPost.outerWidth(true);
var widthDiff = previewWidth - newPost.width();
var linkLeft = link.offset().left;
var left, top;
if (linkLeft < $(document).width() * 0.7) {
left = linkLeft + link.width();
if (left + previewWidth > $(window).width()) {
newPost.css('width', $(window).width() - left - widthDiff);
}
} else {
if (previewWidth > linkLeft) {
newPost.css('width', linkLeft - widthDiff);
previewWidth = linkLeft;
}
left = linkLeft - previewWidth;
}
newPost.css('left', left);
top = link.offset().top - 10;
var scrollTop = $(window).scrollTop();
if (link.is("[data-thread]")) {
scrollTop = 0;
top -= $(window).scrollTop();
}
if(top < scrollTop + 15) {
top = scrollTop;
} else if(top > scrollTop + $(window).height() - newPost.height() - 15) {
top = scrollTop + $(window).height() - newPost.height() - 15;
}
if (newPost.height() > $(window).height()) {
top = scrollTop;
}
newPost.css('top', top);
}
};
2015-01-05 06:27:39 +01:00
2014-11-04 00:40:54 +01:00
post = $('[data-board="' + board + '"] div.post#reply_' + id + ', [data-board="' + board + '"]div#thread_' + id);
if(post.length > 0) {
start_hover($(this));
} else {
2015-01-05 06:27:39 +01:00
var url = link.attr('href').replace(/#.*$/, '').replace('.html', '.json');
var dataPromise = getPost(id, url);
dataPromise.done(function (data) {
// reconstruct post from json response
var file_array = [];
var multifile = false;
var add_info = function (data) {
var file = {
'thumb_h': data.tn_h,
'thumb_w': data.tn_w,
'fsize': data.fsize,
'filename': data.filename,
'ext': data.ext,
'tim': data.tim
};
if ('h' in data) {
file.isImage = true; //(or video)
file.h = data.h;
file.w = data.w;
} else {
file.isImage = false;
}
2015-01-05 06:27:39 +01:00
// since response doens't indicate spoilered files,
// we'll just make do by assuming any image with 128*128px thumbnail is spoilered.
// which is probably 99% of the cases anyway.
file.isSpoiler = (data.tn_h == 128 && data.tn_w == 128);
file_array.push(file);
};
var bytesToSize = function (bytes) {
var sizes = ['Bytes', 'KB', 'MB'];
var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
return (i === 0) ? bytes +' '+ sizes[i] : (bytes / Math.pow(1024, i)).toFixed(2) +' ' +sizes[i];
};
// in case no subject
if (!data.sub) data.sub = '';
var $post = $('<div class="post reply hidden" id="reply_'+ data.no +'">')
.append($('<p class="intro"></p>')
.append('<span class="subject">'+ data.sub +'</span> ')
.append('<span class="name">'+ data.name +'</span> ')
.append('<a class="post_no">No.'+ data.no +'</a>')
)
.append($('<div class="body"></div>')
.html(data.com)
)
.css('display', 'none');
if ('filename' in data) {
var $files = $('<div class="files">');
add_info(data);
if ('extra_files' in data) {
multifile = true;
$.each(data.extra_files, function () {
add_info(this);
});
}
2015-01-05 06:27:39 +01:00
$.each(file_array, function () {
var thumb_url;
var file_ext = this.ext;
2015-01-05 06:27:39 +01:00
if (this.isImage && !this.isSpoiler) {
// video files uses jpg for thumbnail
if (this.ext === '.webm' || this.ext === '.mp4' || this.ext === '.jpeg') this.ext = '.jpg';
2015-01-05 06:27:39 +01:00
thumb_url = '/'+ board +'/thumb/' + this.tim + this.ext;
} else {
thumb_url = (this.isSpoiler) ? '/static/spoiler.png' : '/static/file.png';
}
// truncate long filenames
if (this.filename.length > 23) {
this.filename = this.filename.substr(0, 22) + '…';
}
2015-01-05 06:27:39 +01:00
// file infos
var $ele = $('<div class="file">')
.append($('<p class="fileinfo">')
.append('<span>File: </span>')
.append('<a>'+ this.filename + file_ext +'</a>')
2015-01-05 06:27:39 +01:00
.append('<span class="unimportant"> ('+ bytesToSize(this.fsize) +', '+ this.w +'x'+ this.h +')</span>')
);
if (multifile) $ele.addClass('multifile').css('width', this.thumb_w + 30);
2015-01-05 06:27:39 +01:00
// image
var $img = $('<img class="post-image">')
.css('width', this.thumb_w)
.css('height', this.thumb_h)
.attr('src', thumb_url);
$ele.append($img);
$files.append($ele);
});
$post.children('p.intro').after($files);
}
2015-01-05 06:27:39 +01:00
var mythreadid = (data.resto !== 0) ? data.resto : data.no;
if (mythreadid != threadid || parentboard != board) {
// previewing post from external thread/board
if ($('div#thread_'+ mythreadid +'[data-board="'+ board +'"]').length === 0) {
$('form[name="postcontrols"]').prepend('<div class="thread" id="thread_'+ mythreadid +'" data-board="'+ board +'" style="display: none;"></div>');
}
}
2015-01-05 06:27:39 +01:00
if ($('div#thread_'+ mythreadid +'[data-board="'+ board +'"]').children('#reply_'+ data.no).length === 0) {
$('div#thread_'+ mythreadid +'[data-board="'+ board +'"]').prepend($post);
}
post = $('[data-board="' + board + '"] div.post#reply_' + id + ', [data-board="' + board + '"]div#thread_' + id);
if (hovering && post.length > 0) {
start_hover(link);
}
});
}
2012-03-15 07:05:33 +01:00
}, function() {
hovering = false;
2014-11-04 00:40:54 +01:00
if(!post)
return;
2014-11-04 00:40:54 +01:00
post.removeClass('highlighted');
2015-01-05 06:27:39 +01:00
if(post.hasClass('hidden'))
2014-11-04 00:40:54 +01:00
post.css('display', 'none');
$('.post-hover').remove();
2012-03-15 07:05:33 +01:00
});
};
2015-01-05 06:27:39 +01:00
var getPost = (function () {
var cache = {};
return function (targetId, url) {
var deferred = $.Deferred();
var data, post;
var findPost = function (targetId, data) {
var arr = data.posts;
for (var i=0; i<arr.length; i++) {
if (arr[i].no == targetId)
return arr[i];
}
return false;
};
var get = function (targetId, url) {
$.ajax({
url: url,
success: function (response) {
cache[url] = response;
var post = findPost(targetId, response);
deferred.resolve(post);
}
});
};
// check for cached response and check if it's stale
if ((data = cache[url]) !== undefined && (post = findPost(targetId, data))) {
deferred.resolve(post);
} else {
get(targetId, url);
}
return deferred.promise();
};
})();
2012-08-27 15:01:08 +02:00
$('div.body a:not([rel="nofollow"])').each(init_hover);
// allow to work with auto-reload.js, etc.
$(document).on('new_post', function(e, post) {
2012-08-27 15:01:08 +02:00
$(post).find('div.body a:not([rel="nofollow"])').each(init_hover);
2012-03-15 07:05:33 +01:00
});
});