diff options
Diffstat (limited to 'web/scripts.js')
-rw-r--r-- | web/scripts.js | 684 |
1 files changed, 684 insertions, 0 deletions
diff --git a/web/scripts.js b/web/scripts.js new file mode 100644 index 00000000..c420dcdb --- /dev/null +++ b/web/scripts.js @@ -0,0 +1,684 @@ +var ws=null; +var pageTitle; + +function initWS() { + if(typeof(pageMID)!="undefined" && pageMID>0) { + var url; + if(typeof(juickDebug)!="undefined") { + url="wss://ws.juick.com/_replies"; + } else { + url="wss://ws.juick.com/"+pageMID; + } + if(typeof(hash)!="undefined" && hash) { + url+="?hash="+hash; + } + + ws = new WebSocket(url); + ws.onopen = function() { + console.log('online'); + if($('#wsthread').length==0) { + var d=$('<div id="wsthread"/>'); + d.on('click',onclickNextReply); + d.appendTo("body"); + pageTitle=document.title; + } + }; + ws.onclose = function() { + console.log('offline'); + ws=null; + setTimeout(function() { + initWS(); + },2000); + }; + ws.onmessage = function(msg) { + if(msg.data==' ') { + ws.send(' '); + } else { + try { + var jsonMsg=$.parseJSON(msg.data); + console.log('data: '+msg.data); + wsIncomingReply(jsonMsg); + } catch(err) { + console.log(err); + } + } + }; + setInterval(wsSendKeepAlive, 90000); + } +} + +function wsSendKeepAlive() { + if(ws) { + ws.send(' '); + } +} + +function wsShutdown() { + if(ws) { + ws.onclose=function(){}; + ws.close(); + } +} + +function wsIncomingReply(msg) { + var p; + if(msg.replyto>0) { + p=$('#'+msg.replyto); + if(p.length==0) { + p=null; + } + } + + var li=$('<li class="msg reply-new" id="'+msg.rid+'" onclick="onclickNewReply(this)" onmouseover="onclickNewReply(this)">'); + li.html('<div class="msg-avatar"><a href="/'+msg.user.uname+'/"><img src="//i.juick.com/a/'+msg.user.uid+'.png"/></a></div>'+ + '<div class="msg-cont">'+ + '<div class="msg-menu"><a href="#" onclick="showMessageLinksDialog('+msg.mid+','+msg.rid+'); return false"></a></div>'+ + '<div class="msg-header"><a href="/'+msg.user.uname+'/">@'+msg.user.uname+'</a>:</div>'+ + '<div class="msg-ts"><a href="/'+msg.mid+'#'+msg.rid+'" title="'+msg.timestamp+' GMT">'+msg.timestamp+'</a></div>'+ + '<div class="msg-txt">'+msg.body+'</div>'+ + '<div class="msg-links"><a href="#" onclick="return showCommentForm('+msg.mid+','+msg.rid+')">Ответить</a></div>'+ + '<div class="msg-comment" style="display: none"></div>'+ + '</div>'); + + if(p) { + li.css('margin-left',parseInt(p.css('margin-left'))+20+'px'); + p.after(li); + } else { + $('#replies').append(li); + } + + updateRepliesCounter(); +} + +function onclickNewReply(e) { + var li=$(e); + li.removeClass('reply-new'); + li.off('click'); + li.off('mouseover'); + updateRepliesCounter(); +} + +function onclickNextReply() { + var li=$('#replies>li.reply-new:first'); + if(li.length) { + li.removeClass('reply-new'); + li.off('click'); + li.get(0).scrollIntoView(); + updateRepliesCounter(); + } +} + +function updateRepliesCounter() { + var replies=$('#replies>li.reply-new').length; + if(replies>0) { + $('#wsthread').text(replies).css('display','block'); + document.title='['+replies+'] '+pageTitle; + } else { + $('#wsthread').css('display','none'); + document.title=pageTitle; + } +} + +/******************************************************************************/ +/******************************************************************************/ +/******************************************************************************/ + +function postformListener(formEl,ev) { + if(ev.ctrlKey && (ev.keyCode==10 || ev.keyCode==13)) { + if(!formEl.onsubmit || formEl.onsubmit()) { + formEl.submit(); + } + } +} + +function unfoldPostForm() { + if(window.location.pathname==="/" && window.location.hash==="#post") { + $('#newmessage>div').css('display','block'); + $('#newmessage textarea').css('min-height','70px'); + $('#newmessage textarea')[0].focus(); + } +} + +function onsubmitNewMessage() { + if($('#newmessage .tags').val().length==0) { + openDialog('<p class="dialogtxt">Пожалуйста, введите теги сообщения</p>'); + return false; + } else if($('#newmessage textarea').val().length==0) { + openDialog('<p class="dialogtxt">Пожалуйста, введите текст сообщения</p>'); + return false; + } + return true; +} + +function showMoreReplies(id) { + $('#'+id+' .msg-comments').hide(); + + var replies=$('#replies>li'); + var flagshow=0; + for(var i=0; i<replies.length; i++) { + if(flagshow==1) { + if(replies[i].style.display=="none") { + replies[i].style.display="block"; + } else { + break; + } + } + if(replies[i].id==id) { + flagshow=1; + } + } + return false; +} + +function showCommentForm(mid,rid) { + if($('#replies #'+rid+' textarea').length==0) { + var c=$('#replies #'+rid+' .msg-comment'); + c.wrap('<form action="/comment" method="POST" enctype="multipart/form-data"/>'); + c.before('<input type="hidden" name="mid" value="'+mid+'"/><input type="hidden" name="rid" value="'+rid+'"/>'); + c.append('<div class="ta-wrapper"><textarea name="body" rows="1" class="reply narrow" placeholder="Add a comment..." onkeypress="postformListener(this.form,event)"></textarea><div class="attach-photo" onclick="attachCommentPhoto(this)"/></div><input type="submit" value="OK"/>'); + } + // $('#replies #'+rid+' .msg-links').hide(); + $('#replies #'+rid+' .msg-comment').show(); + $('#replies #'+rid+' textarea')[0].focus(); + $('#replies #'+rid+' textarea').autoResize({ + extraSpace: 0, + minHeight: 1 + }); + return false; +} + +function showCommentFooter(e) { + var a=$(e).closest("article"); + if(a.find("footer.comm").length==0) { + a.append('<form action="/comment" method="POST" enctype="multipart/form-data"><input type="hidden" name="mid" value="'+a.data('mid')+'"/><footer class="comm"><div class="ta-wrapper"><textarea name="body" rows="1" class="reply narrow" placeholder="Написать комментарий..." onkeypress="postformListener(this.form,event)"></textarea><div class="attach-photo" onclick="attachCommentPhoto(this)"/></div><input type="submit" value="OK"/></footer></form>'); + a.find('textarea').autoResize({ + extraSpace: 0, + minHeight: 1 + }); + } + a.find('textarea')[0].focus(); + return false; +} + +function attachCommentPhoto(div) { + if($(div).children().length===0) { + var inp=$('<input type="file" name="attach" accept="image/jpeg,image/png" style="visibility: hidden"/>'); + inp.on('change',function() { + $(this).parent().attr('class','attach-photo-active'); + }); + inp.trigger('click'); + $(div).append(inp); + } else { + $(div).empty(); + $(div).attr('class','attach-photo'); + } +} + +function attachMessagePhoto(div) { + var f=$(div).closest('form'); + if(f.find('input:file').length===0) { + var inp=$('<input type="file" name="attach" accept="image/jpeg,image/png" style="float: left; width: 0; height: 0; visibility: hidden"/>'); + inp.on('change',function() { + $(div).text("загрузить (✓)"); + }); + f.append(inp); + inp.trigger('click'); + } else { + f.find('input:file').remove(); + $(div).text("загрузить"); + } +} + +function unfoldReply() { + if((0+window.location.hash.substring(1))>0) { + var el=$(window.location.hash); + while(el.is(":hidden")) { + el=el.prev(); + } + showMoreReplies(el.attr('id')); + window.location.replace(window.location.hash); + } +} + +function showMessageLinksDialog(mid,rid) { + var hlink="http://juick.com/"+mid; + var mlink="#"+mid; + if(rid>0) { + hlink+="#"+rid; + mlink+="/"+rid; + } + var hlinkenc=encodeURIComponent(hlink); + + var html="<div class=\"dialogshare\">Ссылка на сообщение:"; + html+="<div onclick=\"$(this).selectText()\" class=\"dialogl\">"+hlink+"</div>"; + html+="Номер сообщения:"; + html+="<div onclick=\"$(this).selectText()\" class=\"dialogl\">"+mlink+"</div>"; + html+="Поделиться:<ul>"; + html+="<li><a href=\"https://www.facebook.com/sharer/sharer.php?u="+hlinkenc+"\" onclick=\"return openSocialWindow(this)\"></a></li>"; + html+="<li><a href=\"https://twitter.com/intent/tweet?url="+hlinkenc+"\" onclick=\"return openSocialWindow(this)\" style=\"background-position: -32px 0;\"></a></li>"; + html+="<li><a href=\"https://vk.com/share.php?url="+hlinkenc+"\" onclick=\"return openSocialWindow(this)\" style=\"background-position: -64px 0;\"></a></li>"; + html+="<li><a href=\"https://plus.google.com/share?url="+hlinkenc+"\" onclick=\"return openSocialWindow(this)\" style=\"background-position: -96px 0;\"></a></li>"; + html+="</ul></div>"; + + openDialog(html); +} + +function showPhotoDialog(fname) { + var width=$(window).width(); + var height=$(window).height()*0.9; + if(width<640) { + return true; + } else if(width<1280) { + openDialog("<a href=\"//i.juick.com/photos-1024/"+fname+"\"><img src=\"//i.juick.com/photos-512/"+fname+"\"/></a>"); + $('#dialogw img').css('max-height',height+'px'); + return false; + } else { + openDialog("<a href=\"//i.juick.com/p/"+fname+"\"><img src=\"//i.juick.com/photos-1024/"+fname+"\"/></a>"); + $('#dialogw img').css('max-height',height+'px'); + return false; + } +} + +function openDialog(html) { + var dhtml="<table id=\"dialogt\"><tr><td><div id=\"dialogb\" onclick=\"closeDialog()\"></div><div id=\"dialogw\"><div id=\"dialogc\" onclick=\"closeDialog()\"></div>"; + dhtml+=html; + dhtml+="</div></td></tr></table>"; + $('body').append(dhtml); +} + +function closeDialog() { + $('#dialogb').remove(); + $('#dialogt').remove(); +} + +function openSocialWindow(a) { + var w=window.open(a.href,'juickshare','width=640,height=400'); + if(window.focus) w.focus(); + return false; +} + +function checkUsername() { + var uname=$('#username').val(); + $.ajax('http://api.juick.com/users?uname='+uname).done(function() { + $('#username').css('background','#FFCCCC'); + }).fail(function() { + $('#username').css('background','#CCFFCC'); + }); +} + +/******************************************************************************/ + +function openDialogLogin() { + var html='<div class="dialoglogin"><p>Пожалуйста, представьтесь:' + +'<a href="/_fblogin" id="signfb">Facebook</a> ' + +'<a href="/_vklogin" id="signvk">ВКонтакте</a></p>' + +'<p>Уже зарегистрированы?</p>' + +'<form action="/login" method="POST">' + +'<input class="signinput" type="text" name="username" placeholder="Имя пользователя"/><br/>' + +'<input class="signinput" type="password" name="password" placeholder="Пароль"/><br/>' + +'<input class="signsubmit" type="submit" value="OK"/>' + +'</form></div>'; + openDialog(html); + return false; +} + +/******************************************************************************/ + +function likeMessage(e,mid) { + $.ajax({ + url: 'http://juick.com/like?mid='+mid, + type: 'POST' + }).done(function() { + $(e).closest("article").append("<p>OK!</p>"); + }).fail(function() { + $(e).closest("article").append("<p>Ошибка</p>"); + }); + return false; +} + +/******************************************************************************/ + +function setPopular(e,mid,popular) { + $.ajax('http://api.juick.com/messages/set_popular?mid='+mid+'&popular='+popular+'&hash='+hash).done(function() { + var a=$(e).closest("article"); + a.append("<p>OK!</p>"); + }); + return false; +} + +function setPrivacy(e,mid) { + $.ajax('http://api.juick.com/messages/set_privacy?mid='+mid+'&hash='+hash).done(function() { + var a=$(e).closest("article"); + a.append("<p>OK!</p>"); + }); + return false; +} + +/******************************************************************************/ + +function readerLinkReplace(e) { + var a=$(e); + a.attr('href','/_out?lid='+a.data('lid')); +} + +/******************************************************************************/ + +jQuery.fn.selectText = function(){ + var d = document; + if (d.body.createTextRange) { + var range = d.body.createTextRange(); + range.moveToElementText(this[0]); + range.select(); + } else if (window.getSelection) { + var selection = window.getSelection(); + var range = d.createRange(); + range.selectNodeContents(this[0]); + selection.removeAllRanges(); + selection.addRange(range); + } +}; + +/* + * jQuery.fn.autoResize 1.14 + */ + +(function($){ + + var uid = 'ar' + +new Date, + + defaults = autoResize.defaults = { + onResize: function(){}, + onBeforeResize: function(){ + return 123 + }, + onAfterResize: function(){ + return 555 + }, + animate: { + duration: 200, + complete: function(){} + }, + extraSpace: 50, + minHeight: 'original', + maxHeight: 500, + minWidth: 'original', + maxWidth: 500 + }; + + autoResize.cloneCSSProperties = [ + 'lineHeight', 'textDecoration', 'letterSpacing', + 'fontSize', 'fontFamily', 'fontStyle', 'fontWeight', + 'textTransform', 'textAlign', 'direction', 'wordSpacing', 'fontSizeAdjust', + 'paddingTop', 'paddingLeft', 'paddingBottom', 'paddingRight', 'width' + ]; + + autoResize.cloneCSSValues = { + position: 'absolute', + top: -9999, + left: -9999, + opacity: 0, + overflow: 'hidden' + }; + + autoResize.resizableFilterSelector = [ + 'textarea:not(textarea.' + uid + ')', + 'input:not(input[type])', + 'input[type=text]', + 'input[type=password]', + 'input[type=email]', + 'input[type=url]' + ].join(','); + + autoResize.AutoResizer = AutoResizer; + + $.fn.autoResize = autoResize; + + function autoResize(config) { + this.filter(autoResize.resizableFilterSelector).each(function(){ + new AutoResizer( $(this), config ); + }); + return this; + } + + function AutoResizer(el, config) { + + if (el.data('AutoResizer')) { + el.data('AutoResizer').destroy(); + } + + config = this.config = $.extend({}, autoResize.defaults, config); + this.el = el; + + this.nodeName = el[0].nodeName.toLowerCase(); + + this.originalHeight = el.height(); + this.previousScrollTop = null; + + this.value = el.val(); + + if (config.maxWidth === 'original') config.maxWidth = el.width(); + if (config.minWidth === 'original') config.minWidth = el.width(); + if (config.maxHeight === 'original') config.maxHeight = el.height(); + if (config.minHeight === 'original') config.minHeight = el.height(); + + if (this.nodeName === 'textarea') { + el.css({ + resize: 'none', + overflowY: 'hidden' + }); + } + + el.data('AutoResizer', this); + + // Make sure onAfterResize is called upon animation completion + config.animate.complete = (function(f){ + return function() { + config.onAfterResize.call(el); + return f.apply(this, arguments); + }; + }(config.animate.complete)); + + this.bind(); + + } + + AutoResizer.prototype = { + + bind: function() { + + var check = $.proxy(function(){ + this.check(); + return true; + }, this); + + this.unbind(); + + this.el + .bind('keyup.autoResize', check) + //.bind('keydown.autoResize', check) + .bind('change.autoResize', check) + .bind('paste.autoResize', function() { + setTimeout(function() { + check(); + }, 0); + }); + + if (!this.el.is(':hidden')) { + this.check(null, true); + } + + }, + + unbind: function() { + this.el.unbind('.autoResize'); + }, + + createClone: function() { + + var el = this.el, + clone = this.nodeName === 'textarea' ? el.clone() : $('<span/>'); + + this.clone = clone; + + $.each(autoResize.cloneCSSProperties, function(i, p){ + clone[0].style[p] = el.css(p); + }); + + clone + .removeAttr('name') + .removeAttr('id') + .addClass(uid) + .attr('tabIndex', -1) + .css(autoResize.cloneCSSValues); + + if (this.nodeName === 'textarea') { + clone.height('auto'); + } else { + clone.width('auto').css({ + whiteSpace: 'nowrap' + }); + } + + }, + + check: function(e, immediate) { + + if (!this.clone) { + this.createClone(); + this.injectClone(); + } + + var config = this.config, + clone = this.clone, + el = this.el, + value = el.val(); + + // Do nothing if value hasn't changed + if (value === this.prevValue) { + return true; + } + this.prevValue = value; + + if (this.nodeName === 'input') { + + clone.text(value); + + // Calculate new width + whether to change + var cloneWidth = clone.width(), + newWidth = (cloneWidth + config.extraSpace) >= config.minWidth ? + cloneWidth + config.extraSpace : config.minWidth, + currentWidth = el.width(); + + newWidth = Math.min(newWidth, config.maxWidth); + + if ( + (newWidth < currentWidth && newWidth >= config.minWidth) || + (newWidth >= config.minWidth && newWidth <= config.maxWidth) + ) { + + config.onBeforeResize.call(el); + config.onResize.call(el); + + el.scrollLeft(0); + + if (config.animate && !immediate) { + el.stop(1,1).animate({ + width: newWidth + }, config.animate); + } else { + el.width(newWidth); + config.onAfterResize.call(el); + } + + } + + return; + + } + + // TEXTAREA + + clone.width(el.width()).height(0).val(value).scrollTop(10000); + + var scrollTop = clone[0].scrollTop; + + // Don't do anything if scrollTop hasen't changed: + if (this.previousScrollTop === scrollTop) { + return; + } + + this.previousScrollTop = scrollTop; + + if (scrollTop + config.extraSpace >= config.maxHeight) { + el.css('overflowY', ''); + scrollTop = config.maxHeight; + immediate = true; + } else if (scrollTop <= config.minHeight) { + scrollTop = config.minHeight; + } else { + el.css('overflowY', 'hidden'); + scrollTop += config.extraSpace; + } + + config.onBeforeResize.call(el); + config.onResize.call(el); + + // Either animate or directly apply height: + if (config.animate && !immediate) { + el.stop(1,1).animate({ + height: scrollTop + }, config.animate); + } else { + el.height(scrollTop); + config.onAfterResize.call(el); + } + + }, + + destroy: function() { + this.unbind(); + this.el.removeData('AutoResizer'); + this.clone.remove(); + delete this.el; + delete this.clone; + }, + + injectClone: function() { + ( + autoResize.cloneContainer || + (autoResize.cloneContainer = $('<arclones/>').appendTo('body')) + ).append(this.clone); + } + + }; + +})(jQuery); + +/******************************************************************************/ + +$(document).ready(function() { + $('textarea').autoResize({ + extraSpace: 0, + minHeight: 1 + }); + + $('textarea.reply').click(function () { + $(this).addClass("narrow"); + $(this).after('<div class="attach-photo" onclick="attachCommentPhoto(this)"/>'); + $(this).parent().after('<input type="submit" value="OK"/>'); + $(this).off('click'); + }); + + $('textarea.replypm').click(function () { + $(this).addClass("narrowpm"); + $(this).parent().after('<input type="submit" value="OK"/>'); + $(this).off('click'); + }); + + unfoldPostForm(); + unfoldReply(); + $(window).bind('hashchange',unfoldPostForm); + $(window).bind('hashchange',unfoldReply); + + $(window).on('beforeunload',wsShutdown); +}); |